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

Reply via email to