[PATCH][mem-ref2] Fix expansion of MEM_REF of registers

Richard Guenther rguenther@suse.de
Fri Jun 11 14:09:00 GMT 2010


While we do not (yet) create too many of those the current code
does not deal with all cases correctly.  The following patch
aims to fix that (and it was also tested together with a patch
that exposes way more MEM_REFs of this kind).

The expander is one part that I would like to get reviews on before
merging the branch - I will at some point post a separate merge
patch for these parts.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.

Richard.

2010-06-11  Richard Guenther  <rguenther@suse.de>

	* expr.c (store_field): If expanding a MEM_REF of a non-addressable
	decl use bitfield operations.
	(expand_expr_real_1): More properly deal with the register base
	case.

	* gcc.dg/torture/20100610-1.c: New testcase.

Index: gcc/expr.c
===================================================================
*** gcc/expr.c	(revision 160604)
--- gcc/expr.c	(working copy)
*************** store_field (rtx target, HOST_WIDE_INT b
*** 5847,5853 ****
  	 operations.  */
        || (bitsize >= 0
  	  && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
! 	  && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
      {
        rtx temp;
        gimple nop_def;
--- 5847,5861 ----
  	 operations.  */
        || (bitsize >= 0
  	  && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
! 	  && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0)
!       /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
!          decl we must use bitfield operations.  */
!       || (bitsize >= 0
! 	  && TREE_CODE (exp) == MEM_REF
! 	  && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
! 	  && DECL_P (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
! 	  && !TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (exp, 0),0 ))
! 	  && DECL_MODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != BLKmode))
      {
        rtx temp;
        gimple nop_def;
*************** expand_expr_real_1 (tree exp, rtx target
*** 8806,8829 ****
  		gcc_assert (base);
  		offset = size_binop (PLUS_EXPR, offset, bitsize_int (off));
  	      }
  	    if (DECL_P (base)
  		&& !TREE_ADDRESSABLE (base)
! 		&& integer_zerop (offset)
! 		&& DECL_MODE (base) != BLKmode
! 		&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
! 		&& (GET_MODE_BITSIZE (DECL_MODE (base))
! 		    == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
! 	      return expand_expr (build1 (VIEW_CONVERT_EXPR,
! 					  TREE_TYPE (exp), base),
! 				  target, tmode, modifier);
! 	    if (DECL_P (base)
! 		&& !TREE_ADDRESSABLE (base)
! 		&& TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
! 	      return expand_expr (build3 (BIT_FIELD_REF, TREE_TYPE (exp),
! 					  base,
! 					  bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)))),
! 					  offset),
! 				  target, tmode, modifier);
  	  }
  	address_mode = targetm.addr_space.address_mode (as);
  	op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, address_mode,
--- 8814,8843 ----
  		gcc_assert (base);
  		offset = size_binop (PLUS_EXPR, offset, bitsize_int (off));
  	      }
+ 	    /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
+ 	       decl we must use bitfield operations.  */
  	    if (DECL_P (base)
  		&& !TREE_ADDRESSABLE (base)
! 		&& DECL_MODE (base) != BLKmode)
! 	      {
! 		tree bftype;
! 		if (integer_zerop (offset)
! 		    && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
! 		    && (GET_MODE_BITSIZE (DECL_MODE (base))
! 			== TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
! 		  return expand_expr (build1 (VIEW_CONVERT_EXPR,
! 					      TREE_TYPE (exp), base),
! 				      target, tmode, modifier);
! 		gcc_assert (!DECL_RTL_SET_P (base) || REG_P (DECL_RTL (base)));
! 		bftype = TREE_TYPE (base);
! 		if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
! 		  bftype = TREE_TYPE (exp);
! 		return expand_expr (build3 (BIT_FIELD_REF, bftype,
! 					    base,
! 					    TYPE_SIZE (TREE_TYPE (exp)),
! 					    offset),
! 				    target, tmode, modifier);
! 	      }
  	  }
  	address_mode = targetm.addr_space.address_mode (as);
  	op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, address_mode,
Index: gcc/testsuite/gcc.dg/torture/20100610-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/20100610-1.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/20100610-1.c	(revision 0)
***************
*** 0 ****
--- 1,36 ----
+ /* { dg-do run } */
+ /* { dg-require-effective-target lp64 } */
+ 
+ struct X { long x };
+ static inline long __attribute__((always_inline))
+ test (int o1, int o2, int sz)
+ {
+   struct X i, j;
+   i.x = 0xdeadbeefdeadbeef;
+   j.x = 0x1122334455667788;
+   memcpy ((char *)&i + o1, (char *)&j + o2, sz);
+   return i.x;
+ }
+ extern void abort (void);
+ int main()
+ {
+   if (test (0, 0, 8) != 0x1122334455667788)
+     abort ();
+   if (test (0, 0, 5) == 0xdeadbe4455667788)
+     {
+       if (test (0, 1, 5) != 0xdeadbe3344556677)
+ 	abort ();
+       if (test (3, 1, 3) != 0xdead556677adbeef)
+ 	abort ();
+     } 
+   else if (test (0, 0, 5) == 0x1122334455adbeef)
+     {
+       if (test (0, 1, 5) != 0x2233445566adbeef)
+ 	abort ();
+       if (test (3, 1, 3) != 0xdeadbe223344beef)
+ 	abort ();
+     }
+   else
+     abort ();
+   return 0;
+ }



More information about the Gcc-patches mailing list