[Bug rtl-optimization/57459] New: LRA inheritance bug
wmi at google dot com
gcc-bugzilla@gcc.gnu.org
Wed May 29 21:26:00 GMT 2013
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57459
Bug ID: 57459
Summary: LRA inheritance bug
Product: gcc
Version: 4.9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: wmi at google dot com
Created attachment 30218
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=30218&action=edit
small testcase
To reproduce the bug on using 1.c attached:
Target: x86_64-unknown-linux-gnu
gcc version 4.9.0 20130529 (experimental) (GCC)
$~/workarea/gcc-r199418/build/install/bin/gcc -fno-inline -O2
-minline-all-stringops -fno-omit-frame-pointer -m32 1.c
$./a.out
len = 9
$~/workarea/gcc-r199418/build/install/bin/gcc -O2 -m32 1.c
$./a.out
len = 8
The expanded __builtin_strlen is wrong:
80484c3: 8b 07 mov (%edi),%eax
80484c5: 83 c7 04 add $0x4,%edi
80484c8: 8d 90 ff fe fe fe lea -0x1010101(%eax),%edx
80484ce: f7 d0 not %eax
80484d0: 21 c2 and %eax,%edx
80484d2: 81 e2 80 80 80 80 and $0x80808080,%edx
80484d8: 74 e9 je 80484c3 <foo+0x63>
80484da: 89 d0 mov %edx,%eax
80484dc: 8b 55 ec mov -0x14(%ebp),%edx
80484df: 89 55 e8 mov %edx,-0x18(%ebp)
80484e2: 89 c2 mov %eax,%edx
80484e4: c1 e8 10 shr $0x10,%eax
80484e7: f7 c2 80 80 00 00 test $0x8080,%edx
80484ed: 89 45 ec mov %eax,-0x14(%ebp)
80484f0: 89 d0 mov %edx,%eax
80484f2: 8d 57 02 lea 0x2(%edi),%edx
80484f5: 0f 44 fa cmove %edx,%edi
80484f8: 8b 55 e8 mov -0x18(%ebp),%edx
80484fb: 0f 44 45 ec cmove -0x14(%ebp),%eax
80484ff: 00 45 e4 add %al,-0x1c(%ebp) ====> Wrong
here, the correct insn is: add %al, %al. %al is either 0x80 or 0x0 here. The
insn "add %al, %al" is used to check whether %al is 0x80, and it will produce
carry bit for the following sbb. (The lowest 0x80 in %eax shows where the first
'\0' is in the input string)
8048502: 83 df 03 sbb $0x3,%edi
8048505: 8b 45 08 mov 0x8(%ebp),%eax
8048508: 2b 7d 08 sub 0x8(%ebp),%edi
The IR after IRA and before LRA:
(insn 51 50 52 12 (parallel [
(set (reg:CC 17 flags)
(unspec:CC [
(subreg:QI (reg:SI 79) 0)
(subreg:QI (re(insn 292 50 51 12 (set (reg:QI 118)
(subreg:QI (reg:SI 79) 0)) 1.c:16 87 {*movqi_internal}
(nil))
(insn 51 292 52 12 (parallel [
(set (reg:CC 17 flags)
(unspec:CC [
(subreg:QI (reg:SI 79) 0)
(reg:QI 118)
] UNSPEC_ADD_CARRY))
(set (subreg:QI (reg:SI 79) 0)
(plus:QI (subreg:QI (reg:SI 79) 0)
(reg:QI 118)))
]) 1.c:16 259 {addqi3_cc}
(expr_list:REG_UNUSED (reg:SI 79)
(nil)))g:SI 79) 0)
] UNSPEC_ADD_CARRY))
(set (subreg:QI (reg:SI 79) 0)
(plus:QI (subreg:QI (reg:SI 79) 0)
(subreg:QI (reg:SI 79) 0)))
]) 1.c:16 259 {addqi3_cc}
(expr_list:REG_UNUSED (reg:SI 79)
(nil)))
The IR is correct till now. insn 51 will produce the problematic "add
%al,-0x1c(%ebp)" finally. All the input and output operands of insn 51 are
reg79. The reg79 gets no hardreg in IRA phase.
The IR after lra_constraints:
(insn 292 50 51 12 (set (reg:QI 118)
(subreg:QI (reg:SI 79) 0)) 1.c:16 87 {*movqi_internal}
(nil))
(insn 51 292 52 12 (parallel [
(set (reg:CC 17 flags)
(unspec:CC [
(subreg:QI (reg:SI 79) 0)
(reg:QI 118)
] UNSPEC_ADD_CARRY))
(set (subreg:QI (reg:SI 79) 0)
(plus:QI (subreg:QI (reg:SI 79) 0)
(reg:QI 118)))
]) 1.c:16 259 {addqi3_cc}
(expr_list:REG_UNUSED (reg:SI 79)
(nil)))
The IR is still correct.
The choosen constraints of insn 51 are "rm" "0" "rn". reg79 get no hardreg in
IRA, so the output operand and the first input operand satisfy the constraint
(staying in mem), but the second input operand should stay in register. That is
why reg118 is introduced and insn 292 is inserted.
The IR after lra_inheritance:
(insn 289 47 48 12 (set (reg:SI 116 [79])
(reg:SI 121 [79])) 1.c:16 85 {*movsi_internal}
(nil))
(insn 48 289 290 12 (set (reg:SI 116 [79])
(if_then_else:SI (eq (reg:CCNO 17 flags)
(const_int 0 [0]))
(reg:SI 122 [83])
(reg:SI 116 [79]))) 1.c:16 923 {*movsicc_noc}
(expr_list:REG_DEAD (reg:SI 122 [83])
(nil)))
(insn 290 48 294 12 (set (reg:SI 120 [79])
(reg:SI 116 [79])) 1.c:16 85 {*movsi_internal}
(nil))
......
(insn 292 50 51 12 (set (reg:QI 118)
(subreg:QI (reg:SI 120 [79]) 0)) 1.c:16 87 {*movqi_internal}
(nil))
(insn 51 292 52 12 (parallel [
(set (reg:CC 17 flags)
(unspec:CC [
(subreg:QI (reg:SI 79) 0)
(reg:QI 118)
] UNSPEC_ADD_CARRY))
(set (subreg:QI (reg:SI 79) 0)
(plus:QI (subreg:QI (reg:SI 79) 0)
(reg:QI 118)))
]) 1.c:16 259 {addqi3_cc}
(expr_list:REG_UNUSED (reg:SI 79)
(nil)))
The IR is incorrect here.
The reg79 in insn 292 get a reload reg to reuse, so it is changed to reg120.
But the reg79 in insn 51 doesn't change accordingly. It is the cause of the
problem. If all the reg79 do the reload reg reuse, then the problem will not
happen.
In inherit_in_ebb called by lra_inheritance, those pesudo reg which doesn't get
hardreg and those with reg_type == OP_IN are considered as candidates to reuse
previous reload regs (lra-constraints.c:4892, r199418). For reg79 in insn 292,
it has no hardreg and its type is OP_IN, so it is choosen and replaced by
reg120, but for reg79 in insn 51, its type is OP_INOUT, so it is not choosen. I
guess OP_INOUT should also be included into the candidate choosing conditions,
but I am not sure.
More information about the Gcc-bugs
mailing list