aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorAndrew Pinski <pinskia@gmail.com>2011-03-18 07:01:41 -0700
committerJeff Law <law@gcc.gnu.org>2011-03-18 08:01:41 -0600
commit3bf162a0c94ef343184acdff9e283859a7c24744 (patch)
treefac2cd6805c5b5c3555dd0cab957fb496436e8e5 /gcc/expr.c
parent2abbb0fe9e51ba2b1235f8cddf4953bfb8e48e93 (diff)
downloadgcc-3bf162a0c94ef343184acdff9e283859a7c24744.zip
gcc-3bf162a0c94ef343184acdff9e283859a7c24744.tar.gz
gcc-3bf162a0c94ef343184acdff9e283859a7c24744.tar.bz2
re PR middle-end/47790 (optimize_bitfield_assignment_op no longer works in 4.5.x)
PR middle-end/47790 * expr.c (optimize_bitfield_assignment_op): Revamp to work again after expansion changes. From-SVN: r171139
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 3295156..dc8366d 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -3974,6 +3974,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
tree op0, op1;
rtx value, result;
optab binop;
+ gimple srcstmt;
+ enum tree_code code;
if (mode1 != VOIDmode
|| bitsize >= BITS_PER_WORD
@@ -3983,13 +3985,37 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
return false;
STRIP_NOPS (src);
- if (!BINARY_CLASS_P (src)
- || TREE_CODE (TREE_TYPE (src)) != INTEGER_TYPE)
+ if (TREE_CODE (src) != SSA_NAME)
+ return false;
+ if (TREE_CODE (TREE_TYPE (src)) != INTEGER_TYPE)
+ return false;
+
+ srcstmt = get_gimple_for_ssa_name (src);
+ if (!srcstmt
+ || TREE_CODE_CLASS (gimple_assign_rhs_code (srcstmt)) != tcc_binary)
return false;
- op0 = TREE_OPERAND (src, 0);
- op1 = TREE_OPERAND (src, 1);
- STRIP_NOPS (op0);
+ code = gimple_assign_rhs_code (srcstmt);
+
+ op0 = gimple_assign_rhs1 (srcstmt);
+
+ /* If OP0 is an SSA_NAME, then we want to walk the use-def chain
+ to find its initialization. Hopefully the initialization will
+ be from a bitfield load. */
+ if (TREE_CODE (op0) == SSA_NAME)
+ {
+ gimple op0stmt = get_gimple_for_ssa_name (op0);
+
+ /* We want to eventually have OP0 be the same as TO, which
+ should be a bitfield. */
+ if (!op0stmt
+ || !is_gimple_assign (op0stmt)
+ || gimple_assign_rhs_code (op0stmt) != TREE_CODE (to))
+ return false;
+ op0 = gimple_assign_rhs1 (op0stmt);
+ }
+
+ op1 = gimple_assign_rhs2 (srcstmt);
if (!operand_equal_p (to, op0, 0))
return false;
@@ -4026,7 +4052,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
if (BYTES_BIG_ENDIAN)
bitpos = str_bitsize - bitpos - bitsize;
- switch (TREE_CODE (src))
+ switch (code)
{
case PLUS_EXPR:
case MINUS_EXPR:
@@ -4054,7 +4080,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
set_mem_expr (str_rtx, 0);
}
- binop = TREE_CODE (src) == PLUS_EXPR ? add_optab : sub_optab;
+ binop = code == PLUS_EXPR ? add_optab : sub_optab;
if (bitsize == 1 && bitpos + bitsize != str_bitsize)
{
value = expand_and (str_mode, value, const1_rtx, NULL);
@@ -4087,7 +4113,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
set_mem_expr (str_rtx, 0);
}
- binop = TREE_CODE (src) == BIT_IOR_EXPR ? ior_optab : xor_optab;
+ binop = code == BIT_IOR_EXPR ? ior_optab : xor_optab;
if (bitpos + bitsize != GET_MODE_BITSIZE (GET_MODE (str_rtx)))
{
rtx mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << bitsize)