Hi,
  When I modified GCC to change the majority of bitfield accesses
which were done via component ref to BIT_FIELD_REF, SRA messes up
because when it does the replacement it still tries to use the
BIT_FIELD_REF except it never places the old value in the struct for
the BIT_FIELD_REF to work correctly.

This patch fixes the problem by expanding what BIT_FIELD_REF does
internally for both writing and reading.  Note we can't use
BIT_FIELD_REF directly on the left hand since we don't support partial
writes yet (except for vector and complex types).

This is only a RFC since I don't know a way to reproduce this bug on
the trunk. I tested it on x86_64-linux-gnu with no regressions.

Thanks,
Andrew Pinski

ChangeLog:
* tree-sra.c (sra_modify_expr): Handle BIT_FIELD_REF specially if we
are doing a replacement of the struct with one variable.
Index: tree-sra.c
===================================================================
--- tree-sra.c  (revision 73809)
+++ tree-sra.c  (working copy)
@@ -2648,6 +2648,7 @@ sra_modify_expr (tree *expr, gimple_stmt
   location_t loc;
   struct access *access;
   tree type, bfr;
+  tree *orig_expr = expr;
 
   if (TREE_CODE (*expr) == BIT_FIELD_REF)
     {
@@ -2668,6 +2669,56 @@ sra_modify_expr (tree *expr, gimple_stmt
   if (access->grp_to_be_replaced)
     {
       tree repl = get_access_replacement (access);
+      /* BIT_FIELD_REFs with writes have to be handled specially. */
+      if (bfr)
+       {
+         tree mask;
+         HOST_WIDE_INT nbitsize;
+         HOST_WIDE_INT lbitsize;
+         HOST_WIDE_INT lbitpos;
+         tree unsignedtype;
+         gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (repl)));
+
+         unsignedtype = signed_or_unsigned_type_for (1, TREE_TYPE (repl));
+         nbitsize = TYPE_PRECISION (TREE_TYPE (repl));
+         lbitsize = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
+         lbitpos = tree_low_cst (TREE_OPERAND (bfr, 2), 1);
+         mask = build_int_cst_type (unsignedtype, -1);
+         mask = int_const_binop (LSHIFT_EXPR, mask, size_int (nbitsize - 
lbitsize));
+         mask = int_const_binop (RSHIFT_EXPR, mask,
+                                 size_int (nbitsize - lbitsize - lbitpos));
+         if (write)
+           {
+             tree lhs, rhs;
+             tree notmask;
+             gimple stmt = gsi_stmt (*gsi);
+             double_int val = double_int_not (tree_to_double_int (mask));
+             notmask = force_fit_type_double (TREE_TYPE (mask), val, 0, 0);
+             /* (REPL & (~mask)) | ((RHS<<offset)&mask) */
+             lhs = fold_convert (unsignedtype, repl);
+             lhs = fold_build2_loc (loc, BIT_AND_EXPR, unsignedtype, lhs, 
notmask);
+             rhs = gimple_assign_rhs1 (stmt); 
+             rhs = fold_convert_loc (loc, unsignedtype, rhs);
+             rhs = fold_build2_loc (loc, LSHIFT_EXPR, unsignedtype, rhs, 
size_int (lbitpos));
+             rhs = fold_build2_loc (loc, BIT_AND_EXPR, unsignedtype, rhs, 
mask);
+             rhs = fold_build2_loc (loc, BIT_IOR_EXPR, unsignedtype, lhs, rhs);
+             rhs = fold_convert_loc (loc, TREE_TYPE (repl), rhs);
+             rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
+                                             true, GSI_SAME_STMT);
+             stmt = gimple_build_assign (repl, rhs);
+             gimple_set_location (stmt, loc);
+             gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+           }
+         else
+           {
+             tree access;
+             access = fold_convert_loc (loc, unsignedtype, repl);
+             access = fold_build2_loc (loc, RSHIFT_EXPR, unsignedtype, access, 
size_int (lbitpos));
+             access = fold_convert_loc (loc, TREE_TYPE (bfr), access);
+             *orig_expr = force_gimple_operand_gsi (gsi, access, true, 
NULL_TREE,
+                                                    true, GSI_SAME_STMT);
+           }
+       }
       /* If we replace a non-register typed access simply use the original
          access expression to extract the scalar component afterwards.
         This happens if scalarizing a function return value or parameter
@@ -2678,7 +2729,7 @@ sra_modify_expr (tree *expr, gimple_stmt
          be accessed as a different type too, potentially creating a need for
          type conversion (see PR42196) and when scalarized unions are involved
          in assembler statements (see PR42398).  */
-      if (!useless_type_conversion_p (type, access->type))
+      else if (!useless_type_conversion_p (type, access->type))
        {
          tree ref;
 

Reply via email to