------- 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