diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 176a13a5399..cb69c8f5f20 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-03-16 Andrew Pinski + + PR middle-end/47790 + * expr.c (optimize_bitfield_assignment_op): Revamp to work + again after expansion changes. + 2011-03-18 Chung-Lin Tang * combine.c (try_combine): Do simplification only call of diff --git a/gcc/expr.c b/gcc/expr.c index 3295156e139..dc8366d0ae1 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; - op0 = TREE_OPERAND (src, 0); - op1 = TREE_OPERAND (src, 1); - STRIP_NOPS (op0); + srcstmt = get_gimple_for_ssa_name (src); + if (!srcstmt + || TREE_CODE_CLASS (gimple_assign_rhs_code (srcstmt)) != tcc_binary) + return false; + + 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)