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] expr.c: Fix PR middle-end/18008.


Hi,

Attached is a patch to fix a regression, PR middle-end/18008.

Consider

struct B {
  unsigned b : 2;
};

void
store (struct B *b, int v)
{
  b->b = v;
}

After the tree optimizers run, I get

  b->b = (<unnamed type>) (unsigned char) v;

where <unnamed type> is a 2-bit integer type.  The problem is that we
get ANDs from two places.  The first one is generated by the cast to
(<unnamed type>).  The second one is from the assignment, more
specifically store_bit_field.

The patch fixes the problem by stripping a narrowing conversion.

Personally, I don't like the way the patch fixes the problem because
the tree optimizers make the types very strict for us so that we won't
do a type-mismatched assignment, but now we are sort of breaking it.

Tested on i686-pc-linux-gnu.  Any comments?

p.s.
Another way to fix this is to not generate any code when we are
casting to (<unnamed type>).  Whenever we need to convert a variable
of (<unnamed type>) to a wider type, we then use an AND.

Kazu Hirata

2004-10-15  Kazu Hirata  <kazu@cs.umass.edu>

	* expr.c (store_field): Remove a narrowing conversion.

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.726
diff -u -r1.726 expr.c
--- expr.c	3 Oct 2004 22:50:18 -0000	1.726
+++ expr.c	17 Oct 2004 05:15:38 -0000
@@ -5187,7 +5187,24 @@
 	  && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
 	  && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
     {
-      rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
+      rtx temp;
+
+      /* store_bit_field is responsible for narrowing EXP.  If EXP
+	 contains a narrowing conversion, remove it.  */
+      if (TREE_CODE (exp) == NOP_EXPR
+	  || TREE_CODE (exp) == CONVERT_EXPR)
+	{
+	  tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+	  tree inner_type_size = TYPE_SIZE (inner_type);
+	  if (TREE_CODE (TYPE_SIZE (inner_type)) == INTEGER_CST
+	      && compare_tree_int (inner_type_size, bitsize) >= 0
+	      && TREE_INT_CST_HIGH (inner_type_size) == 0
+	      && TRULY_NOOP_TRUNCATION (bitsize,
+					TREE_INT_CST_LOW (inner_type_size)))
+	    exp = TREE_OPERAND (exp, 0);
+	}
+
+      temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
 
       /* If BITSIZE is narrower than the size of the type of EXP
 	 we will be narrowing TEMP.  Normally, what's wanted are the


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