diff mbox

[ARM] : PR67745: Fix function alignment after __attribute__ 2/2

Message ID 5614C412.5080400@st.com
State New
Headers show

Commit Message

Christian Bruel Oct. 7, 2015, 7:04 a.m. UTC
The ARM target can switch different alignment requirements between the 
thumb or arm, thanks to the attribute ((target)). Using 
FUNCTION_BOUNDARY that now depends on the switchable target_flag.

The previous attempt to fix this was to use the set_current_function 
hook to reset DECL_ALIGN. On a second thought I found this not 
satisfactory because this hook is called multiple time between passes, 
whereas the setting only needs to be done once.

Instead, this patch resets the function's DECL_ALIGN in 
allocate_struct_function, when not enforced by the user or the language, 
after the attributes are processed.

Tested for arm-none-eabi (with the 1/2 part 
https://gcc.gnu.org/ml/gcc-patches/2015-09/msg02198.html)

Bootstraped for x86_64-unknown-linux-gnu and tested (c+,c++,fortran)

Comments ? OK for trunk ?

thanks

Christian

Comments

Bernd Schmidt Oct. 7, 2015, 10:18 a.m. UTC | #1
On 10/07/2015 09:04 AM, Christian Bruel wrote:
> +	  /* Similarly, relayout function's alignment if not forced.  */
> +	  if (!DECL_USER_ALIGN (fndecl)
> +	      && (TREE_CODE (fntype) != METHOD_TYPE
> +		  || TARGET_PTRMEMFUNC_VBIT_LOCATION != ptrmemfunc_vbit_in_pfn))
> +	    DECL_ALIGN (fndecl) = FUNCTION_BOUNDARY;
>   	}

That's a very odd-looking condition. Why the vbit location test?


Bernd
Christian Bruel Oct. 7, 2015, 10:45 a.m. UTC | #2
On 10/07/2015 12:18 PM, Bernd Schmidt wrote:
> On 10/07/2015 09:04 AM, Christian Bruel wrote:
>> +	  /* Similarly, relayout function's alignment if not forced.  */
>> +	  if (!DECL_USER_ALIGN (fndecl)
>> +	      && (TREE_CODE (fntype) != METHOD_TYPE
>> +		  || TARGET_PTRMEMFUNC_VBIT_LOCATION != ptrmemfunc_vbit_in_pfn))
>> +	    DECL_ALIGN (fndecl) = FUNCTION_BOUNDARY;
>>    	}
>
> That's a very odd-looking condition. Why the vbit location test?

This is for member functions to make sure that the lsb address is 
reserved for the virtual function bit.

see cp/decl.c:

   /* If pointers to member functions use the least significant bit to
      indicate whether a function is virtual, ensure a pointer
      to this function will have that bit clear.  */
   if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
       && TREE_CODE (type) == METHOD_TYPE
       && DECL_ALIGN (decl) < 2 * BITS_PER_UNIT)
     DECL_ALIGN (decl) = 2 * BITS_PER_UNIT;

This happens for instance on i386 that aligns member functions on 2 
bytes, bigger than the one byte required boundary. So we cannot 
re-layout bellow that.
Bernd Schmidt Oct. 7, 2015, 5:37 p.m. UTC | #3
On 10/07/2015 12:45 PM, Christian Bruel wrote:
>
>
> On 10/07/2015 12:18 PM, Bernd Schmidt wrote:
>> On 10/07/2015 09:04 AM, Christian Bruel wrote:
>>> +      /* Similarly, relayout function's alignment if not forced.  */
>>> +      if (!DECL_USER_ALIGN (fndecl)
>>> +          && (TREE_CODE (fntype) != METHOD_TYPE
>>> +          || TARGET_PTRMEMFUNC_VBIT_LOCATION !=
>>> ptrmemfunc_vbit_in_pfn))
>>> +        DECL_ALIGN (fndecl) = FUNCTION_BOUNDARY;
>>>        }
>>
>> That's a very odd-looking condition. Why the vbit location test?
>
> This is for member functions to make sure that the lsb address is
> reserved for the virtual function bit.
>
> see cp/decl.c:
>
>    /* If pointers to member functions use the least significant bit to
>       indicate whether a function is virtual, ensure a pointer
>       to this function will have that bit clear.  */
>    if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
>        && TREE_CODE (type) == METHOD_TYPE
>        && DECL_ALIGN (decl) < 2 * BITS_PER_UNIT)
>      DECL_ALIGN (decl) = 2 * BITS_PER_UNIT;
>
> This happens for instance on i386 that aligns member functions on 2
> bytes, bigger than the one byte required boundary. So we cannot
> re-layout bellow that.

Hmm, at least that would need to be spelled out in a comment, but I 
think this would better be abstracted as

#define MINIMUM_FUNCTION_BOUNDARY(FN) \
  ....
in a header file, and used in both places.


Bernd
Jeff Law Oct. 7, 2015, 5:40 p.m. UTC | #4
On 10/07/2015 01:04 AM, Christian Bruel wrote:
> The ARM target can switch different alignment requirements between the
> thumb or arm, thanks to the attribute ((target)). Using
> FUNCTION_BOUNDARY that now depends on the switchable target_flag.
>
> The previous attempt to fix this was to use the set_current_function
> hook to reset DECL_ALIGN. On a second thought I found this not
> satisfactory because this hook is called multiple time between passes,
> whereas the setting only needs to be done once.
>
> Instead, this patch resets the function's DECL_ALIGN in
> allocate_struct_function, when not enforced by the user or the language,
> after the attributes are processed.
>
> Tested for arm-none-eabi (with the 1/2 part
> https://gcc.gnu.org/ml/gcc-patches/2015-09/msg02198.html)
>
> Bootstraped for x86_64-unknown-linux-gnu and tested (c+,c++,fortran)
>
> Comments ? OK for trunk ?
Bernd seems pretty engaged at this point.  I'll just add I like this 
much more than the prior approaches.

jeff
Bernd Schmidt Oct. 7, 2015, 5:50 p.m. UTC | #5
On 10/07/2015 07:37 PM, Bernd Schmidt wrote:
> On 10/07/2015 12:45 PM, Christian Bruel wrote:

>> On 10/07/2015 12:18 PM, Bernd Schmidt wrote:
>>> On 10/07/2015 09:04 AM, Christian Bruel wrote:
>>>> +      /* Similarly, relayout function's alignment if not forced.  */
>>>> +      if (!DECL_USER_ALIGN (fndecl)
>>>> +          && (TREE_CODE (fntype) != METHOD_TYPE
>>>> +          || TARGET_PTRMEMFUNC_VBIT_LOCATION !=
>>>> ptrmemfunc_vbit_in_pfn))
>>>> +        DECL_ALIGN (fndecl) = FUNCTION_BOUNDARY;
>>>>        }

Hmm, more questions are coming to mind - are other places that set 
DECL_ALIGN for functions redundant after this change? It looks like the 
main place where it's set is make_node_stat where it's also set to 
FUNCTION_BOUNDARY. That's small enough not to bother changing it, but it 
raises another issue: we don't allocate a struct function for mere 
declarations, so does that mean they can have an incorrect DECL_ALIGN?


Bernd
Christian Bruel Oct. 8, 2015, 1:14 p.m. UTC | #6
On 10/07/2015 07:50 PM, Bernd Schmidt wrote:
> On 10/07/2015 07:37 PM, Bernd Schmidt wrote:
>> On 10/07/2015 12:45 PM, Christian Bruel wrote:
>
>>> On 10/07/2015 12:18 PM, Bernd Schmidt wrote:
>>>> On 10/07/2015 09:04 AM, Christian Bruel wrote:
>>>>> +      /* Similarly, relayout function's alignment if not forced.  */
>>>>> +      if (!DECL_USER_ALIGN (fndecl)
>>>>> +          && (TREE_CODE (fntype) != METHOD_TYPE
>>>>> +          || TARGET_PTRMEMFUNC_VBIT_LOCATION !=
>>>>> ptrmemfunc_vbit_in_pfn))
>>>>> +        DECL_ALIGN (fndecl) = FUNCTION_BOUNDARY;
>>>>>         }
>
> Hmm, more questions are coming to mind - are other places that set
> DECL_ALIGN for functions redundant after this change? It looks like the
> main place where it's set is make_node_stat where it's also set to
> FUNCTION_BOUNDARY. That's small enough not to bother changing it,

Yes it is. I thought about poisoning it but make_node_stat is used for 
synthesized functions as well and we need to keep the default correct.

> but it
> raises another issue: we don't allocate a struct function for mere
> declarations, so does that mean they can have an incorrect DECL_ALIGN?
>

Probably at the time of start_decl, because DECL_ALIGN will have the 
boundary given by the global target_flags at that time. But this 
shouldn't be a problem since what matters is the DECL_ALIGN recomputed 
with the definition when there is something to layout.
Bernd Schmidt Oct. 8, 2015, 1:20 p.m. UTC | #7
On 10/08/2015 03:14 PM, Christian Bruel wrote:

> Probably at the time of start_decl, because DECL_ALIGN will have the
> boundary given by the global target_flags at that time. But this
> shouldn't be a problem since what matters is the DECL_ALIGN recomputed
> with the definition when there is something to layout.

I'm not so sure. Don't we take DECL_ALIGN into account when optimizing 
things like alignment tests?


Bernd
Christian Bruel Oct. 8, 2015, 1:50 p.m. UTC | #8
On 10/08/2015 03:20 PM, Bernd Schmidt wrote:
> On 10/08/2015 03:14 PM, Christian Bruel wrote:
>
>> Probably at the time of start_decl, because DECL_ALIGN will have the
>> boundary given by the global target_flags at that time. But this
>> shouldn't be a problem since what matters is the DECL_ALIGN recomputed
>> with the definition when there is something to layout.
>
> I'm not so sure. Don't we take DECL_ALIGN into account when optimizing
> things like alignment tests?
>
>

Humm, I don't know what kind of alignment optimization for functions we 
have based on a declaration only. greping DECL_ALIGN on functions there 
are some bits in the ipa-icf code that seems to merge code using this 
information, but I think we have a definition at that point.
but honestly, I'm very unfamiliar with this pass. Do you have something 
else in mind ?

> Bernd
>
Bernd Schmidt Oct. 8, 2015, 2:30 p.m. UTC | #9
On 10/08/2015 03:50 PM, Christian Bruel wrote:
> Humm, I don't know what kind of alignment optimization for functions we
> have based on a declaration only. greping DECL_ALIGN on functions there
> are some bits in the ipa-icf code that seems to merge code using this
> information, but I think we have a definition at that point.
> but honestly, I'm very unfamiliar with this pass. Do you have something
> else in mind ?

I had a vague memory of us optimizing that, but I can't find the code 
either and maybe it's just not there. That doesn't mean someone isn't 
going to add it in the future, and I'm uncomfortable leaving incorrect 
DECL_ALIGN values around.

It looks like rest_of_decl_compilation may be a good place to take care 
of declarations, but using FUNCTION_BOUNDARY is probably going to give 
the wrong results. So maybe a target hook, function_boundary_for_decl, 
defaulting to just returning FUNCTION_BOUNDARY? Eventually it could 
replace the macro entirely.


Bernd
diff mbox

Patch

2015-10-07  Christian Bruel  <christian.bruel@st.com>

	PR target/67745
	* function.c (allocate_struct_function): Relayout function's alignment.

Index: gcc/function.c
===================================================================
--- gcc/function.c	(revision 228515)
+++ gcc/function.c	(working copy)
@@ -4840,6 +4840,12 @@  allocate_struct_function (tree fndecl, b
 	  for (tree parm = DECL_ARGUMENTS (fndecl); parm;
 	       parm = DECL_CHAIN (parm))
 	    relayout_decl (parm);
+
+	  /* Similarly, relayout function's alignment if not forced.  */
+	  if (!DECL_USER_ALIGN (fndecl)
+	      && (TREE_CODE (fntype) != METHOD_TYPE
+		  || TARGET_PTRMEMFUNC_VBIT_LOCATION != ptrmemfunc_vbit_in_pfn))
+	    DECL_ALIGN (fndecl) = FUNCTION_BOUNDARY;
 	}
 
       if (!abstract_p && aggregate_value_p (result, fndecl))