[Bug rtl-optimization/75964] New: insn combiner removes comparison after ABS

gjl at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Sat Aug 13 13:25:00 GMT 2016


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=75964

            Bug ID: 75964
           Summary: insn combiner removes comparison after ABS
           Product: gcc
           Version: 6.1.1
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gjl at gcc dot gnu.org
  Target Milestone: ---
            Target: avr

== Testcase ==

typedef __UINT8_TYPE__ uint8_t;

uint8_t abs8 (uint8_t x)
{
    if (x & 0x80)
        x = -x;

    if (x & 0x80)
        x = 0x7f;

    return x;
}

compile with

$ avr-gcc-6.1.1  code.c -S -Os -dp -fdump-rtl-combine-details -fdump-rtl-ud_dce

After pass .combine, the 2nd comparison is missing, presumably because combiner
invokes signed overflow on ABS which does not apply because all computations
are performed as unsigned.

avr backend implements absqi2 insn which is introduced by .ce1.  Just before
.combine the code reads (from .ud_dce):

(note 5 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(insn 2 5 3 2 (set (reg/v:QI 45 [ x ])
        (reg:QI 24 r24 [ x ])) foo.c:4 71 {movqi_insn}
     (expr_list:REG_DEAD (reg:QI 24 r24 [ x ])
        (nil)))
(note 3 2 27 2 NOTE_INSN_FUNCTION_BEG)
(insn 27 3 13 2 (set (reg/v:QI 45 [ x ])
        (abs:QI (reg/v:QI 45 [ x ]))) foo.c:6 364 {absqi2}
     (nil))
(insn 13 27 14 2 (set (cc0)
        (compare (reg/v:QI 45 [ x ])
            (const_int 0 [0]))) foo.c:8 404 {*cmpqi}
     (nil))
(jump_insn 14 13 15 2 (set (pc)
        (if_then_else (ge (cc0)
                (const_int 0 [0]))
            (label_ref 16)
            (pc))) foo.c:8 428 {branch}
     (int_list:REG_BR_PROB 5711 (nil))
 -> 16)
(note 15 14 4 3 [bb 3] NOTE_INSN_BASIC_BLOCK)
(insn 4 15 16 3 (set (reg/v:QI 45 [ x ])
        (const_int 127 [0x7f])) foo.c:9 71 {movqi_insn}
     (nil))
(code_label 16 4 17 4 3 "" [1 uses])
(note 17 16 22 4 [bb 4] NOTE_INSN_BASIC_BLOCK)
(insn 22 17 23 4 (set (reg/i:QI 24 r24)
        (reg/v:QI 45 [ x ])) foo.c:12 71 {movqi_insn}
     (expr_list:REG_DEAD (reg/v:QI 45 [ x ])
        (nil)))
(insn 23 22 0 4 (use (reg/i:QI 24 r24)) foo.c:12 -1
     (nil))


The .combine dump then reads:


(note 5 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 5 3 2 NOTE_INSN_DELETED)
(note 3 2 27 2 NOTE_INSN_FUNCTION_BEG)
(insn 27 3 22 2 (set (reg/v:QI 45 [ x ])
        (abs:QI (reg:QI 24 r24 [ x ]))) foo.c:6 364 {absqi2}
     (expr_list:REG_DEAD (reg:QI 24 r24 [ x ])
        (nil)))
(insn 22 27 23 2 (set (reg/i:QI 24 r24)
        (reg/v:QI 45 [ x ])) foo.c:12 71 {movqi_insn}
     (expr_list:REG_DEAD (reg/v:QI 45 [ x ])
        (nil)))
(insn 23 22 0 2 (use (reg/i:QI 24 r24)) foo.c:12 -1
     (nil))


Which is wrong because at that stage, nothing is known about the signedness of
R24.

Dunno what is needed to reproduce this on more popular targets, presumably at
least:

1) Target implements abs<mode>2 for some integer mode and

2) This expands to rtx_code abs.


More information about the Gcc-bugs mailing list