[PATCH 4.8 v2, i386]: Make CCZ mode compatible with CCGOC and CCGO modes

Uros Bizjak ubizjak@gmail.com
Sat Feb 11 08:42:00 GMT 2012


On Tue, Feb 7, 2012 at 5:37 PM, Uros Bizjak <ubizjak@gmail.com> wrote:

>> Attached patch declares CCZmode compatible with CCGOC, CCGO and CCNO modes.
>
> Actually, CCZ mode is not compatible with CCNO mode, since the later
> only declares that overflow flag is not set. CCGOC and CCGO declare
> garbage in overflow (and carry in case of CCGOC) flag, so implicitly
> declare that CCZ flag is valid. Following this reasoning, CCZ mode
> should be compatible with CCGOC and CCGO modes.
>
> 2012-02-07  Uros Bizjak  <ubizjak@gmail.com>
>
>       * config/i386/i386.c (ix86_cc_modes_compatible): Declare CCZmode
>       compatible with CCGOCmode and CCGCmode.
>
> Attached patch was bootstrapped and regression tested on x86_64-pc-linux-gnu.

... where it uncovers another problem how RTL optimizer handles
compatible compares!

With attached patch, the example from pr28685

--cut here--
int test(int a, int b)
{
  int lt = a < b;
  int eq = a == b;
  if (lt)
    return 1;
  return eq;
}
--cut here--

triggers compare elimination in CSE2 pass. We enter CSE2 pass with:

(insn 8 5 9 2 (set (reg:CCGC 17 flags)
        (compare:CCGC (reg/v:SI 62 [ a ])
            (reg/v:SI 63 [ b ]))) pr28685.c:7 6 {*cmpsi_1}
     (nil))

(jump_insn 9 8 10 2 (set (pc)
        (if_then_else (lt (reg:CCGC 17 flags)
                (const_int 0 [0]))
            (label_ref:DI 15)
            (pc))) pr28685.c:7 599 {*jcc_1}
     (expr_list:REG_DEAD (reg:CCGC 17 flags)
        (expr_list:REG_BR_PROB (const_int 3900 [0xf3c])
            (nil)))
 -> 15)

[...]

(note 10 9 11 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

(insn 11 10 12 3 (set (reg:CCZ 17 flags)
        (compare:CCZ (reg/v:SI 62 [ a ])
            (reg/v:SI 63 [ b ]))) pr28685.c:6 6 {*cmpsi_1}
     (expr_list:REG_DEAD (reg/v:SI 63 [ b ])
        (expr_list:REG_DEAD (reg/v:SI 62 [ a ])
            (nil))))

(insn 12 11 13 3 (set (reg:QI 65)
        (eq:QI (reg:CCZ 17 flags)
            (const_int 0 [0]))) pr28685.c:6 595 {*setcc_qi}
     (expr_list:REG_DEAD (reg:CCZ 17 flags)
        (nil)))

After CSE2 pass, we have:

(insn 8 5 9 2 (set (reg:CCGC 17 flags)
        (compare:CCGC (reg/v:SI 62 [ a ])
            (reg/v:SI 63 [ b ]))) pr28685.c:7 6 {*cmpsi_1}
     (nil))

(jump_insn 9 8 10 2 (set (pc)
        (if_then_else (lt (reg:CCGC 17 flags)
                (const_int 0 [0]))
            (label_ref:DI 15)
            (pc))) pr28685.c:7 599 {*jcc_1}
     (expr_list:REG_DEAD (reg:CCGC 17 flags)
        (expr_list:REG_BR_PROB (const_int 3900 [0xf3c])
            (nil)))
 -> 15)

[...]

(note 10 9 12 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

(insn 12 10 13 3 (set (reg:QI 65)
        (eq:QI (reg:CCGC 17 flags)
            (const_int 0 [0]))) pr28685.c:6 595 {*setcc_qi}
     (expr_list:REG_DEAD (reg:CCGC 17 flags)
        (nil)))

CSE2 pass eliminated (insn 11), which is OK since CCZ is compatible
with CCGC, so (CCGC, CCZ)->CCGC. However, the pass also changed the
mode of flags register in (insn 12). I don't think this is correct,
the user should not be changed at all.

Uros.



More information about the Gcc-patches mailing list