This fixes an oversight in my GIMPLE store-merging patch, whereby masking out 
the bits of a signed type obviously fails to turn it into an unsigned type...
And since output_merged_store will now convert to the unsigned bitfield type, 
an existing conversion from a smaller type can be bypassed in process_store.

Tested on x86-64/Linux, applied on the mainline as obvious.


2018-06-03  Eric Botcazou  <ebotca...@adacore.com>

        PR tree-optimization/86034
        * gimple-ssa-store-merging.c (output_merged_store): Convert the RHS to
        the unsigned bitfield type in a bit insertion sequence if it does not
        have a larger precision than the bitfield size.
        (process_store): Also bypass widening conversions for BIT_INSERT_EXPR.


2018-06-03  Eric Botcazou  <ebotca...@adacore.com>

        * gcc.dg/torture/pr86034.c: New test.

-- 
Eric Botcazou
Index: gimple-ssa-store-merging.c
===================================================================
--- gimple-ssa-store-merging.c	(revision 261101)
+++ gimple-ssa-store-merging.c	(working copy)
@@ -3778,7 +3778,14 @@ imm_store_chain_info::output_merged_stor
 		  const HOST_WIDE_INT end_gap
 		    = (try_bitpos + try_size) - (info->bitpos + info->bitsize);
 		  tree tem = info->ops[0].val;
-		  if ((BYTES_BIG_ENDIAN ? start_gap : end_gap) > 0)
+		  if (TYPE_PRECISION (TREE_TYPE (tem)) <= info->bitsize)
+		    {
+		      tree bitfield_type
+			= build_nonstandard_integer_type (info->bitsize,
+							  UNSIGNED);
+		      tem = gimple_convert (&seq, loc, bitfield_type, tem);
+		    }
+		  else if ((BYTES_BIG_ENDIAN ? start_gap : end_gap) > 0)
 		    {
 		      const unsigned HOST_WIDE_INT imask
 			= (HOST_WIDE_INT_1U << info->bitsize) - 1;
@@ -4270,13 +4277,12 @@ pass_store_merging::process_store (gimpl
 	      || !multiple_p (bitpos, BITS_PER_UNIT))
 	  && const_bitsize <= 64)
 	{
-	  /* Bypass a truncating conversion to the bit-field type.  */
+	  /* Bypass a conversion to the bit-field type.  */
 	  if (is_gimple_assign (def_stmt) && CONVERT_EXPR_CODE_P (rhs_code))
 	    {
 	      tree rhs1 = gimple_assign_rhs1 (def_stmt);
 	      if (TREE_CODE (rhs1) == SSA_NAME
-		  && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
-		  && const_bitsize <= TYPE_PRECISION (TREE_TYPE (rhs1)))
+		  && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
 		rhs = rhs1;
 	    }
 	  rhs_code = BIT_INSERT_EXPR;
/* PR tree-optimization/86034 */
/* Testcase by  Zhendong Su  <s...@cs.ucdavis.edu> */

/* { dg-do run } */

struct A
{
  int b;
  int c:24;
  int d:10;
  int e;
} f;

int g; 

void h ()
{
  struct A i = { 0, 0, -1, 0 };
L:
  f = i;
  i.d = 0;
  if (g < 0)
    goto L;
}

int main (void)
{
  h ();
  if (f.e != 0) 
    __builtin_abort ();
  return 0; 
}

Reply via email to