This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC] "Fix" PR50716, override type alignment knowledge


This changes alignment computation of a MEM during expansion
from MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp))
to something weaker (with possibly less alignment) when we
were able to compute an explicit misaligned value (thus,
get_object_alignment_1 (exp, &misalign) would return an
alignment of 8, but misaligned by 4, for example - in which
case get_object_alignment () would return 4).  This is to
less often fall into the trap that the frontends and the middle-end
are not careful about providing a type with properly alignment
for misaligned memory references (classical example is
struct __attribute__((packed)) { int i; } a; &a, where
&a has int * type, not int __attribute__((aligned(1))) * type).

The patch unbreaks the testcase in the PR (which is strictly
invalid) by using precise misalign information we are able to
compute at -O1 and up:

typedef int vec __attribute__((vector_size(16)));
int main ()
{
 int * arr = __builtin_malloc (1024);
 vec *p = (vec *) &arr[1];
 *p = (vec){1, 2, 3, 4};
 return *(char *)p;
}

on x86_64 without the patch we emit movaps while with the
patch we use a movups instruction (which is being nice to
our users).

I didn't bother to try thinking of a heuristic when to
use the misaligned info and when not - always using it
makes the most sense consistency-wise.  I had considered
only using TYPE_ALIGN () when get_object_alignment_1 returns
BITS_PER_UNIT for the alignment (which sort-of means
don't know).

Bootstrap and regtest scheduled on x86_64-unknown-linux-gnu.

Any comments?

Thanks,
Richard.

2011-10-17  Richard Guenther  <rguenther@suse.de>

	PR middle-end/50716
	* expr.c (get_object_or_type_alignment): New function.
	(expand_assignment): Use it.
	(expand_expr_real_1): Likewise.

Index: gcc/expr.c
===================================================================
*** gcc/expr.c	(revision 180077)
--- gcc/expr.c	(working copy)
*************** get_bit_range (unsigned HOST_WIDE_INT *b
*** 4544,4549 ****
--- 4544,4568 ----
      }
  }
  
+ /* Return the alignment of the object EXP, also considering its type
+    when we do not know of explicit misalignment.
+    ???  Note that generally the type of an expression is not kept
+    consistent with misalignment information by the frontend, for
+    example when taking the address of a member of a packed structure.
+    So taking into account type information for alignment is generally
+    wrong, but is done here as a compromise.  */
+ 
+ static unsigned int
+ get_object_or_type_alignment (tree exp)
+ {
+   unsigned HOST_WIDE_INT misalign;
+   unsigned int align = get_object_alignment_1 (exp, &misalign);
+   align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
+   if (misalign != 0)
+     align = (misalign & -misalign);
+   return align;
+ }
+ 
  /* Expand an assignment that stores the value of FROM into TO.  If NONTEMPORAL
     is true, try generating a nontemporal store.  */
  
*************** expand_assignment (tree to, tree from, b
*** 4553,4559 ****
    rtx to_rtx = 0;
    rtx result;
    enum machine_mode mode;
!   int align;
    enum insn_code icode;
  
    /* Don't crash if the lhs of the assignment was erroneous.  */
--- 4572,4578 ----
    rtx to_rtx = 0;
    rtx result;
    enum machine_mode mode;
!   unsigned int align;
    enum insn_code icode;
  
    /* Don't crash if the lhs of the assignment was erroneous.  */
*************** expand_assignment (tree to, tree from, b
*** 4571,4578 ****
    if ((TREE_CODE (to) == MEM_REF
         || TREE_CODE (to) == TARGET_MEM_REF)
        && mode != BLKmode
!       && ((align = MAX (TYPE_ALIGN (TREE_TYPE (to)), get_object_alignment (to)))
! 	  < (signed) GET_MODE_ALIGNMENT (mode))
        && ((icode = optab_handler (movmisalign_optab, mode))
  	  != CODE_FOR_nothing))
      {
--- 4590,4597 ----
    if ((TREE_CODE (to) == MEM_REF
         || TREE_CODE (to) == TARGET_MEM_REF)
        && mode != BLKmode
!       && ((align = get_object_or_type_alignment (to))
! 	  < GET_MODE_ALIGNMENT (mode))
        && ((icode = optab_handler (movmisalign_optab, mode))
  	  != CODE_FOR_nothing))
      {
*************** expand_expr_real_1 (tree exp, rtx target
*** 9241,9247 ****
  	addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
  	struct mem_address addr;
  	enum insn_code icode;
! 	int align;
  
  	get_address_description (exp, &addr);
  	op0 = addr_for_mem_ref (&addr, as, true);
--- 9260,9266 ----
  	addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
  	struct mem_address addr;
  	enum insn_code icode;
! 	unsigned int align;
  
  	get_address_description (exp, &addr);
  	op0 = addr_for_mem_ref (&addr, as, true);
*************** expand_expr_real_1 (tree exp, rtx target
*** 9249,9257 ****
  	temp = gen_rtx_MEM (mode, op0);
  	set_mem_attributes (temp, exp, 0);
  	set_mem_addr_space (temp, as);
! 	align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
  	if (mode != BLKmode
! 	    && (unsigned) align < GET_MODE_ALIGNMENT (mode)
  	    /* If the target does not have special handling for unaligned
  	       loads of mode then it can use regular moves for them.  */
  	    && ((icode = optab_handler (movmisalign_optab, mode))
--- 9268,9276 ----
  	temp = gen_rtx_MEM (mode, op0);
  	set_mem_attributes (temp, exp, 0);
  	set_mem_addr_space (temp, as);
! 	align = get_object_or_type_alignment (exp);
  	if (mode != BLKmode
! 	    && align < GET_MODE_ALIGNMENT (mode)
  	    /* If the target does not have special handling for unaligned
  	       loads of mode then it can use regular moves for them.  */
  	    && ((icode = optab_handler (movmisalign_optab, mode))
*************** expand_expr_real_1 (tree exp, rtx target
*** 9278,9284 ****
  	tree base = TREE_OPERAND (exp, 0);
  	gimple def_stmt;
  	enum insn_code icode;
! 	int align;
  	/* Handle expansion of non-aliased memory with non-BLKmode.  That
  	   might end up in a register.  */
  	if (TREE_CODE (base) == ADDR_EXPR)
--- 9297,9303 ----
  	tree base = TREE_OPERAND (exp, 0);
  	gimple def_stmt;
  	enum insn_code icode;
! 	unsigned align;
  	/* Handle expansion of non-aliased memory with non-BLKmode.  That
  	   might end up in a register.  */
  	if (TREE_CODE (base) == ADDR_EXPR)
*************** expand_expr_real_1 (tree exp, rtx target
*** 9329,9335 ****
  			   gimple_assign_rhs1 (def_stmt), mask);
  	    TREE_OPERAND (exp, 0) = base;
  	  }
! 	align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
  	op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
  	op0 = memory_address_addr_space (address_mode, op0, as);
  	if (!integer_zerop (TREE_OPERAND (exp, 1)))
--- 9348,9354 ----
  			   gimple_assign_rhs1 (def_stmt), mask);
  	    TREE_OPERAND (exp, 0) = base;
  	  }
! 	align = get_object_or_type_alignment (exp);
  	op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
  	op0 = memory_address_addr_space (address_mode, op0, as);
  	if (!integer_zerop (TREE_OPERAND (exp, 1)))
*************** expand_expr_real_1 (tree exp, rtx target
*** 9345,9351 ****
  	if (TREE_THIS_VOLATILE (exp))
  	  MEM_VOLATILE_P (temp) = 1;
  	if (mode != BLKmode
! 	    && (unsigned) align < GET_MODE_ALIGNMENT (mode)
  	    /* If the target does not have special handling for unaligned
  	       loads of mode then it can use regular moves for them.  */
  	    && ((icode = optab_handler (movmisalign_optab, mode))
--- 9364,9370 ----
  	if (TREE_THIS_VOLATILE (exp))
  	  MEM_VOLATILE_P (temp) = 1;
  	if (mode != BLKmode
! 	    && align < GET_MODE_ALIGNMENT (mode)
  	    /* If the target does not have special handling for unaligned
  	       loads of mode then it can use regular moves for them.  */
  	    && ((icode = optab_handler (movmisalign_optab, mode))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]