This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/57130] New: Incorrect "and --> extract" conversion in combine
- From: "wmi at google dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 30 Apr 2013 23:43:18 +0000
- Subject: [Bug rtl-optimization/57130] New: Incorrect "and --> extract" conversion in combine
- Auto-submitted: auto-generated
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: unassigned@gcc.gnu.org
ReportedBy: wmi@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.