http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57130



             Bug #: 57130

           Summary: Incorrect "and --> extract" conversion in combine

    Classification: Unclassified

           Product: gcc

           Version: 4.9.0

            Status: UNCONFIRMED

          Severity: normal

          Priority: P3

         Component: rtl-optimization

        AssignedTo: unassig...@gcc.gnu.org

        ReportedBy: w...@google.com





Created attachment 29986

  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=29986

Testcase



For the smallcase 1.ii attached.



~/workarea/gcc-r198433/build/install/bin/g++ 1.ii -o a1.out

./a1.out  --> correct output:

1

3



~/workarea/gcc-r198433/build/install/bin/g++ -fno-inline

-fno-omit-frame-pointer -O2 1.ii -o a2.out

./a2.out  --> incorrect output:

1

-1



In 1.ii.196r.ud_dce:



(insn 7 2 84 2 (set (reg:DI 64)

        (const_int -4294967296 [0xffffffff00000000])) 1.ii:26 84

{*movdi_internal}

     (nil))

...

(insn 40 36 44 2 (parallel [

            (set (reg:DI 88)

                (and:DI (reg:DI 80)

                    (reg:DI 64)))

            (clobber (reg:CC 17 flags))

        ]) 1.ii:32 386 {*anddi_1}

     (expr_list:REG_DEAD (reg:DI 80)

        (expr_list:REG_DEAD (reg:DI 64)

            (expr_list:REG_UNUSED (reg:CC 17 flags)

                (expr_list:REG_EQUAL (and:DI (reg:DI 80)

                        (const_int -4294967296 [0xffffffff00000000]))

                    (nil))))))

(insn 44 40 45 2 (set (reg:DI 92 [ mini_rect ])

        (zero_extend:DI (subreg:SI (reg:DI 88) 0))) 1.ii:33 127

{*zero_extendsidi2}

     (expr_list:REG_DEAD (reg:DI 88)

        (nil)))



The value of r92 here should always be 0.



After try_combine with params (i3==insn44, i2==insn40, i1==insn7), insn44 is

transformed to: 

(insn 44 40 45 2 (parallel [

            (set (reg:DI 92 [ mini_rect ])

                (ashiftrt:DI (reg:DI 88)

                    (const_int 63 [0x3f])))

            (clobber (reg:CC 17 flags))

        ]) 1.ii:33 528 {ashrdi3_cvt}

     (expr_list:REG_UNUSED (reg:CC 17 flags)

        (expr_list:REG_DEAD (reg:DI 88)

            (nil))))



The value of r92 now equals either 0 or -1 which depends on the highest bit of

r88. 



Try to understand what happen in try_combine:

In try_combine, after subst(PATTERN (i3), i2dest, i2src, ...), insn 44 is

transformed to the following form. This step is correct. 



(insn 44 40 45 2 (set (reg:DI 92 [ mini_rect ])

        (neg:DI (ne:DI (subreg:SI (and:DI (reg:DI 80)

                        (reg:DI 64)) 0)

                (const_int 0 [0])))) 1.ii:33 127 {*zero_extendsidi2}

     (expr_list:REG_DEAD (reg:DI 88)

        (nil)))



In subst(PATTERN (i3), i1dest, i1src, ...), insn 44 is firstly transformed to

the following in simplify_logical, which is correct:



(insn 44 40 45 2 (set (reg:DI 92 [ mini_rect ])

        (neg:DI (ne:DI (subreg:SI ((and:DI (reg:DI 80)

                        (const_int 34359738368 [0x800000000]))) 0)

                (const_int 0 [0])))) 1.ii:33 127 {*zero_extendsidi2}

     (expr_list:REG_DEAD (reg:DI 88)

        (nil)))



then it is transformed to the following in make_compound_operation, which is

incorrect:



(insn 44 40 45 2 (set (reg:DI 92 [ mini_rect ])

        (sign_extract:DI (reg:DI 80)

            (const_int 1 [0x1])

            (const_int 35 [0x23]))) 1.ii:33 127 {*zero_extendsidi2}

     (expr_list:REG_DEAD (reg:DI 88)

        (nil)))





make_compound_operation transforms



(and:DI (reg:DI 80)

    (const_int 34359738368 [0x800000000]))



to



(zero_extract:DI (reg:DI 80)

    (const_int 1 [0x1])

    (const_int 35 [0x23]))



because it thinks the "and expr" here is in a compare. But actually the "and

expr" is firstly the kid in a subreg: 



subreg:SI ((and:DI (reg:DI 80)

    (const_int 34359738368 [0x800000000]))  ==> always 0



is not identical with



subreg:SI ((zero_extract:DI (reg:DI 80)

    (const_int 1 [0x1])

    (const_int 35 [0x23]))      ==> 0 or 1



So it is the cause of the problem. The second actual of make_compound_operation

(combine.c:7701, r198433) should not be in_code.

Reply via email to