------- Comment #4 from dje at gcc dot gnu dot org 2006-04-25 04:24 -------
This optimization occurred in 4.1 between life2 and lreg:
life2:
(insn 24 23 25 2 (set (reg:SI 126)
(const_int -503316480 [0xffffffffe2000000])) 279 {*movsi_internal1}
(nil)
(nil))
(insn 30 29 31 2 (parallel [
(set (reg:SI 134)
(and:SI (reg:SI 130)
(reg:SI 126)))
(clobber (scratch:CC))
]) 98 {andsi3} (insn_list:REG_DEP_TRUE 24 (insn_list:REG_DEP_TRUE 29
(nil)))
(expr_list:REG_UNUSED (scratch:CC)
(expr_list:REG_DEAD (reg:SI 130)
(expr_list:REG_DEAD (reg:SI 126)
(expr_list:REG_UNUSED (scratch:CC)
(nil))))))
lreg:
(insn 30 29 31 2 (parallel [
(set (reg:SI 134)
(and:SI (reg:SI 130)
(const_int -503316480 [0xffffffffe2000000])))
(clobber (scratch:CC))
]) 98 {andsi3} (insn_list:REG_DEP_TRUE 24 (insn_list:REG_DEP_TRUE 29
(nil)))
(expr_list:REG_UNUSED (scratch:CC)
(expr_list:REG_DEAD (reg:SI 130)
(expr_list:REG_UNUSED (scratch:CC)
(nil)))))
and the constant remained properly sign extended through combine.
In 4.2, the value is correct in life1:
(insn 23 22 24 4 (set (reg:SI 126)
(const_int -503316480 [0xffffffffe2000000])) 310 {*movsi_internal1}
(nil)
(nil))
(insn 28 27 29 4 (parallel [
(set (reg:SI 130)
(and:SI (reg:SI 131)
(reg:SI 126)))
(clobber (scratch:CC))
]) 129 {andsi3} (insn_list:REG_DEP_TRUE 27 (nil))
(expr_list:REG_DEAD (reg:SI 131)
(expr_list:REG_DEAD (reg:SI 126)
(expr_list:REG_UNUSED (scratch:CC)
(nil)))))
but wrong in combine:
(insn 29 28 30 4 (parallel [
(set (reg:SI 134)
(and:SI (reg:SI 130)
(const_int 3791650816 [0xe2000000])))
(clobber (scratch:CC))
]) 129 {andsi3} (insn_list:REG_DEP_TRUE 28 (nil))
(expr_list:REG_UNUSED (scratch:CC)
(expr_list:REG_DEAD (reg:SI 130)
(nil))))
This optimization is occurring in an earlier pass, but the constant is being
regenerated incorrectly.
I'm not sure if this is related to simplify_and_const_int or
simplify_const_binary_operation. I do notice that simplify_and_const_int is
invoked in simplify_logical as
x = simplify_and_const_int (x, mode, op0, INTVAL (op1));
while simplify_and_const_int signature is
simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop,
unsigned HOST_WIDE_INT constop)
with an unsigned HWI argument. It then reconstructs the argument as
x = simplify_gen_binary (AND, GET_MODE (varop), varop, GEN_INT (constop));
Apparently changing the GEN_INT() to gen_int_mode() fixes the testcase. The
current logic is dropping sign bits on the floor.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27282