[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