* expr.c (is_aligning_offset): New function.
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 9 Apr 2002 13:41:58 +0000 (13:41 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 9 Apr 2002 13:41:58 +0000 (13:41 +0000)
(expand_expr, case COMPONENT_EXPR): Call it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52077 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c

index 81074d5..b38c09a 100644 (file)
@@ -1,3 +1,8 @@
+Tue Apr  9 09:35:45 2002  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * expr.c (is_aligning_offset): New function.
+       (expand_expr, case COMPONENT_EXPR): Call it.
+
 2002-04-08  David S. Miller  <davem@redhat.com>
 
        PR target/6082
index 066b454..11f1a53 100644 (file)
@@ -147,6 +147,7 @@ static rtx store_field              PARAMS ((rtx, HOST_WIDE_INT,
                                         int));
 static rtx var_rtx             PARAMS ((tree));
 static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
+static int is_aligning_offset  PARAMS ((tree, tree));
 static rtx expand_increment    PARAMS ((tree, int, int));
 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
 static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
@@ -6927,6 +6928,12 @@ expand_expr (exp, target, tmode, modifier)
                                  highest_pow2_factor (offset));
          }
 
+       /* If OFFSET is making OP0 more aligned than BIGGEST_ALIGNMENT,
+          record its alignment as BIGGEST_ALIGNMENT.  */
+       if (GET_CODE (op0) == MEM && bitpos == 0 && offset != 0
+           && is_aligning_offset (offset, tem))
+         set_mem_align (op0, BIGGEST_ALIGNMENT);
+
        /* Don't forget about volatility even if this is a bitfield.  */
        if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
          {
@@ -8823,6 +8830,56 @@ expand_expr (exp, target, tmode, modifier)
   return temp;
 }
 \f
+/* Subroutine of above: returns 1 if OFFSET corresponds to an offset that
+   when applied to the address of EXP produces an address known to be
+   aligned more than BIGGEST_ALIGNMENT.  */
+
+static int
+is_aligning_offset (offset, exp)
+     tree offset;
+     tree exp;
+{
+  /* Strip off any conversions and WITH_RECORD_EXPR nodes.  */
+  while (TREE_CODE (offset) == NON_LVALUE_EXPR
+        || TREE_CODE (offset) == NOP_EXPR
+        || TREE_CODE (offset) == CONVERT_EXPR
+        || TREE_CODE (offset) == WITH_RECORD_EXPR)
+    offset = TREE_OPERAND (offset, 0);
+
+  /* We must now have a BIT_AND_EXPR with a constant that is one less than
+     power of 2 and which is larger than BIGGEST_ALIGNMENT.  */
+  if (TREE_CODE (offset) != BIT_AND_EXPR
+      || !host_integerp (TREE_OPERAND (offset, 1), 1)
+      || compare_tree_int (TREE_OPERAND (offset, 1), BIGGEST_ALIGNMENT) <= 0
+      || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
+    return 0;
+
+  /* Look at the first operand of BIT_AND_EXPR and strip any conversion.
+     It must be NEGATE_EXPR.  Then strip any more conversions.  */
+  offset = TREE_OPERAND (offset, 0);
+  while (TREE_CODE (offset) == NON_LVALUE_EXPR
+        || TREE_CODE (offset) == NOP_EXPR
+        || TREE_CODE (offset) == CONVERT_EXPR)
+    offset = TREE_OPERAND (offset, 0);
+
+  if (TREE_CODE (offset) != NEGATE_EXPR)
+    return 0;
+
+  offset = TREE_OPERAND (offset, 0);
+  while (TREE_CODE (offset) == NON_LVALUE_EXPR
+        || TREE_CODE (offset) == NOP_EXPR
+        || TREE_CODE (offset) == CONVERT_EXPR)
+    offset = TREE_OPERAND (offset, 0);
+
+  /* This must now be the address either of EXP or of a PLACEHOLDER_EXPR
+     whose type is the same as EXP.  */
+  return (TREE_CODE (offset) == ADDR_EXPR
+         && (TREE_OPERAND (offset, 0) == exp
+             || (TREE_CODE (TREE_OPERAND (offset, 0)) == PLACEHOLDER_EXPR
+                 && (TREE_TYPE (TREE_OPERAND (offset, 0))
+                     == TREE_TYPE (exp)))));
+}
+\f
 /* Return the tree node if a ARG corresponds to a string constant or zero
    if it doesn't.  If we return non-zero, set *PTR_OFFSET to the offset
    in bytes within the string that ARG is accessing.  The type of the