aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2002-04-09 13:41:58 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2002-04-09 09:41:58 -0400
commit1ce7f3c2ab0b622ec93be5bc39c3d4efa7fbef5f (patch)
tree14d76b2c26294fb26b13f27cfd4812966dd80bf0 /gcc/expr.c
parentdcf5a5dec81e8afe74a41dea213c0fccceb80cd7 (diff)
downloadgcc-1ce7f3c2ab0b622ec93be5bc39c3d4efa7fbef5f.zip
gcc-1ce7f3c2ab0b622ec93be5bc39c3d4efa7fbef5f.tar.gz
gcc-1ce7f3c2ab0b622ec93be5bc39c3d4efa7fbef5f.tar.bz2
expr.c (is_aligning_offset): New function.
* expr.c (is_aligning_offset): New function. (expand_expr, case COMPONENT_EXPR): Call it. From-SVN: r52077
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 066b454..11f1a53 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;
}
+/* 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)))));
+}
+
/* 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