re PR middle-end/37774 (Alignment information is lost for ARRAY_REFs)
authorJakub Jelinek <jakub@redhat.com>
Thu, 9 Oct 2008 08:17:08 +0000 (10:17 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 9 Oct 2008 08:17:08 +0000 (10:17 +0200)
PR middle-end/37774
* tree.h (get_object_alignment): Declare.
* emit-rtl.c (set_mem_attributes_minus_bitpos): Call
get_object_alignment if needed.
* builtins.c (get_pointer_alignment): Move ADDR_EXPR operand handling
to ...
(get_object_alignment): ... here.  New function.  Try harder to
determine alignment from get_inner_reference returned offset.

From-SVN: r141003

gcc/ChangeLog
gcc/builtins.c
gcc/emit-rtl.c
gcc/tree.h

index c6053c4cc4e64defc96479788a180e03257ef79a..8e9648ae0616621614c0a23424e8d14e9d6db6b1 100644 (file)
@@ -7,6 +7,15 @@
        * tree-cfg.c (make_cond_expr_edges, make_goto_expr_edges): Only set
        goto_block on edges if goto_locus is known.
 
+       PR middle-end/37774
+       * tree.h (get_object_alignment): Declare.
+       * emit-rtl.c (set_mem_attributes_minus_bitpos): Call
+       get_object_alignment if needed.
+       * builtins.c (get_pointer_alignment): Move ADDR_EXPR operand handling
+       to ...
+       (get_object_alignment): ... here.  New function.  Try harder to
+       determine alignment from get_inner_reference returned offset.
+
 2008-10-08  Jakub Jelinek  <jakub@redhat.com>
 
        * graphite.c (gloog): Don't call find_unreachable_blocks
index ea1a16d9bddb77d9b0a3a90244696761df34fda5..5ed60bb0531f75e07dc157cb298875e9c01e8c06 100644 (file)
@@ -253,6 +253,82 @@ static bool called_as_built_in (tree node)
   return false;
 }
 
+/* Return the alignment in bits of EXP, an object.
+   Don't return more than MAX_ALIGN no matter what, ALIGN is the inital
+   guessed alignment e.g. from type alignment.  */
+
+int
+get_object_alignment (tree exp, unsigned int align, unsigned int max_align)
+{
+  unsigned int inner;
+
+  inner = max_align;
+  if (handled_component_p (exp))
+   {
+      HOST_WIDE_INT bitsize, bitpos;
+      tree offset;
+      enum machine_mode mode; 
+      int unsignedp, volatilep;
+
+      exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
+                                &mode, &unsignedp, &volatilep, true);
+      if (bitpos)
+       inner = MIN (inner, (unsigned) (bitpos & -bitpos));
+      while (offset)
+       {
+         tree next_offset;
+
+         if (TREE_CODE (offset) == PLUS_EXPR)
+           {
+             next_offset = TREE_OPERAND (offset, 0);
+             offset = TREE_OPERAND (offset, 1);
+           }
+         else
+           next_offset = NULL;
+         if (host_integerp (offset, 1))
+           {
+             /* Any overflow in calculating offset_bits won't change
+                the alignment.  */
+             unsigned offset_bits
+               = ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
+
+             if (offset_bits)
+               inner = MIN (inner, (offset_bits & -offset_bits));
+           }
+         else if (TREE_CODE (offset) == MULT_EXPR
+                  && host_integerp (TREE_OPERAND (offset, 1), 1))
+           {
+             /* Any overflow in calculating offset_factor won't change
+                the alignment.  */
+             unsigned offset_factor
+               = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
+                  * BITS_PER_UNIT);
+
+             if (offset_factor)
+               inner = MIN (inner, (offset_factor & -offset_factor));
+           }
+         else
+           {
+             inner = MIN (inner, BITS_PER_UNIT);
+             break;
+           }
+         offset = next_offset;
+       }
+    }
+  if (DECL_P (exp))
+    align = MIN (inner, DECL_ALIGN (exp));
+#ifdef CONSTANT_ALIGNMENT
+  else if (CONSTANT_CLASS_P (exp))
+    align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
+#endif
+  else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
+          || TREE_CODE (exp) == INDIRECT_REF)
+    align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
+  else
+    align = MIN (align, inner);
+  return MIN (align, max_align);
+}
+
 /* Return the alignment in bits of EXP, a pointer valued expression.
    But don't return more than MAX_ALIGN no matter what.
    The alignment returned is, by default, the alignment of the thing that
@@ -306,59 +382,7 @@ get_pointer_alignment (tree exp, unsigned int max_align)
 
        case ADDR_EXPR:
          /* See what we are pointing at and look at its alignment.  */
-         exp = TREE_OPERAND (exp, 0);
-         inner = max_align;
-         if (handled_component_p (exp))
-           {
-             HOST_WIDE_INT bitsize, bitpos;
-             tree offset;
-             enum machine_mode mode; 
-             int unsignedp, volatilep;
-
-             exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-                                        &mode, &unsignedp, &volatilep, true);
-             if (bitpos)
-               inner = MIN (inner, (unsigned) (bitpos & -bitpos));
-             if (offset && TREE_CODE (offset) == PLUS_EXPR
-                 && host_integerp (TREE_OPERAND (offset, 1), 1))
-               {
-                 /* Any overflow in calculating offset_bits won't change
-                    the alignment.  */
-                 unsigned offset_bits
-                   = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
-                      * BITS_PER_UNIT);
-
-                 if (offset_bits)
-                   inner = MIN (inner, (offset_bits & -offset_bits));
-                 offset = TREE_OPERAND (offset, 0);
-               }
-             if (offset && TREE_CODE (offset) == MULT_EXPR
-                 && host_integerp (TREE_OPERAND (offset, 1), 1))
-               {
-                 /* Any overflow in calculating offset_factor won't change
-                    the alignment.  */
-                 unsigned offset_factor
-                   = ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
-                      * BITS_PER_UNIT);
-
-                 if (offset_factor)
-                   inner = MIN (inner, (offset_factor & -offset_factor));
-               }
-             else if (offset)
-               inner = MIN (inner, BITS_PER_UNIT);
-           }
-         if (DECL_P (exp))
-           align = MIN (inner, DECL_ALIGN (exp));
-#ifdef CONSTANT_ALIGNMENT
-         else if (CONSTANT_CLASS_P (exp))
-           align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
-#endif
-         else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
-                  || TREE_CODE (exp) == INDIRECT_REF)
-           align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
-         else
-           align = MIN (align, inner);
-         return MIN (align, max_align);
+         return get_object_alignment (TREE_OPERAND (exp, 0), align, max_align);
 
        default:
          return align;
index 318ae77533006ae409651fdfa43a1f27bd53a51b..4564a0b7485d6e40d355dbbff42c1c6ca0df6bcf 100644 (file)
@@ -1564,6 +1564,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
   if (! TYPE_P (t))
     {
       tree base;
+      bool align_computed = false;
 
       if (TREE_THIS_VOLATILE (t))
        MEM_VOLATILE_P (ref) = 1;
@@ -1620,6 +1621,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
                  && host_integerp (DECL_SIZE_UNIT (t), 1)
                  ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
          align = DECL_ALIGN (t);
+         align_computed = true;
        }
 
       /* If this is a constant, we know the alignment.  */
@@ -1629,6 +1631,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
 #ifdef CONSTANT_ALIGNMENT
          align = CONSTANT_ALIGNMENT (t, align);
 #endif
+         align_computed = true;
        }
 
       /* If this is a field reference and not a bit-field, record it.  */
@@ -1688,6 +1691,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
                  align = DECL_ALIGN (t2);
                  if (aoff && (unsigned HOST_WIDE_INT) aoff < align)
                    align = aoff;
+                 align_computed = true;
                  offset = GEN_INT (ioff);
                  apply_bitpos = bitpos;
                }
@@ -1721,6 +1725,13 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
          expr = t;
          offset = NULL;
        }
+
+      if (!align_computed && !INDIRECT_REF_P (t))
+       {
+         unsigned int obj_align
+           = get_object_alignment (t, align, BIGGEST_ALIGNMENT);
+         align = MAX (align, obj_align);
+       }
     }
 
   /* If we modified OFFSET based on T, then subtract the outstanding
index 44bc3f0f2828725afd10e6024f44be0f0e999620..034be6a35cbebbd3bdd02797093d78ae2df5544d 100644 (file)
@@ -4864,6 +4864,7 @@ extern tree build_string_literal (int, const char *);
 extern bool validate_arglist (const_tree, ...);
 extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
 extern int get_pointer_alignment (tree, unsigned int);
+extern int get_object_alignment (tree, unsigned int, unsigned int);
 extern tree fold_call_stmt (gimple, bool);
 extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);