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

            Bug ID: 86511
           Summary: Unordered comparisons are expanded with branchless
                    code
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ubizjak at gmail dot com
  Target Milestone: ---

Following testcase:

--cut here--
#include <fenv.h>

extern void abort (void);
extern void exit (int);

volatile double x = __builtin_nan ("");
volatile int i;

int
main (void)
{
  i = !__builtin_isless (x, 1.0);
  if (fetestexcept (FE_INVALID))
    abort ();
}
--cut here--

compiles for alphaev68-linux-gnu (-O2 -mieee) to brachless code:

        cvtsts $f12,$f11
        cmptun/su $f10,$f11,$f12
        ftoit $f12,$2
>>      cmptle/su $f11,$f10,$f12
        cmpult $31,$2,$2
        ftoit $f12,$1
        cmovne $1,1,$2
        bis $31,$2,$1
        ldq $2,i($29)           !literal

where cmptle generates unwanted exception and the testcase aborts.

gcc-7.3.0 generates:

        cvtsts $f12,$f11
        trapb
        cmptun/su $f10,$f11,$f12
        trapb
        fbne $f12,$L2
        cmptle/su $f11,$f10,$f12
        trapb
        fbeq $f12,$L5
$L2:
        ldq $2,i($29)           !literal

which avoids cmptle for unordered arguments.

Both compilers generate following _.optimized tree dump:

  x.0_1 ={v} x;
  _2 = x.0_1 u>= 1.0e+0;
  _3 = (int) _2;
  i ={v} _3;

gcc-9 expands to branchless code:

...

(insn 14 13 15 2 (set (reg:SF 87)
        (mem/u/c:SF (lo_sum:DI (reg:DI 86)
                (symbol_ref/u:DI ("*$LC1") [flags 0x2])) [0  S4 A32]))
"inf-compare-7.c":16 211 {*movsf}
     (nil))
(insn 15 14 16 2 (set (reg:DF 85)
        (float_extend:DF (reg:SF 87))) "inf-compare-7.c":16 144
{*extendsfdf2_ieee}
     (expr_list:REG_EQUAL (const_double:DF 1.0e+0 [0x0.8p+1])
        (nil)))
(insn 16 15 17 2 (set (reg:DF 90)
        (unordered:DF (reg:DF 70 [ x.0_1 ])
            (reg:DF 85))) "inf-compare-7.c":16 176 {*cmpdf_internal}
     (nil))
(insn 17 16 18 2 (set (reg:DI 89)
        (ne:DI (subreg:DI (reg:DF 90) 0)
            (const_int 0 [0]))) "inf-compare-7.c":16 149 {*setne_internal}
     (nil))
(insn 18 17 19 2 (set (reg:SI 88)
        (subreg:SI (reg:DI 89) 0)) "inf-compare-7.c":16 214 {*movsi}
     (nil))
(insn 19 18 20 2 (set (reg:DI 92)
        (high:DI (symbol_ref/u:DI ("*$LC1") [flags 0x2]))) "inf-compare-7.c":16
221 {*movdi}
     (nil))
(insn 20 19 21 2 (set (reg:SF 93)
        (mem/u/c:SF (lo_sum:DI (reg:DI 92)
                (symbol_ref/u:DI ("*$LC1") [flags 0x2])) [0  S4 A32]))
"inf-compare-7.c":16 211 {*movsf}
     (nil))
(insn 21 20 22 2 (set (reg:DF 91)
        (float_extend:DF (reg:SF 93))) "inf-compare-7.c":16 144
{*extendsfdf2_ieee}
     (expr_list:REG_EQUAL (const_double:DF 1.0e+0 [0x0.8p+1])
        (nil)))
(insn 22 21 23 2 (set (reg:DF 94)
        (le:DF (reg:DF 91)
            (reg:DF 70 [ x.0_1 ]))) "inf-compare-7.c":16 176 {*cmpdf_internal}
     (nil))
(insn 23 22 24 2 (set (reg:SI 76)
        (if_then_else:SI (ne (subreg:DI (reg:DF 94) 0)
                (const_int 0 [0]))
            (const_int 1 [0x1])
            (reg:SI 88))) "inf-compare-7.c":16 152 {*movsicc_internal}
     (nil))

...

where gcc-7 expands to:

...

(insn 21 20 22 2 (set (reg:SF 97)
        (mem/u/c:SF (lo_sum:DI (reg:DI 96)
                (symbol_ref/u:DI ("*$LC1") [flags 0x2])) [2  S4 A32]))
"inf-compare-7.c":16 230 {*movsf}
     (nil))
(insn 22 21 23 2 (set (reg:DF 95)
        (float_extend:DF (reg:SF 97))) "inf-compare-7.c":16 161
{*extendsfdf2_ieee}
     (expr_list:REG_EQUAL (const_double:DF 1.0e+0 [0x0.8p+1])
        (nil)))
(insn 23 22 24 2 (set (reg:DF 98)
        (unordered:DF (reg:DF 70 [ x.0_1 ])
            (reg:DF 95))) "inf-compare-7.c":16 194 {*cmpdf_ieee}
     (nil))
(jump_insn 24 23 53 2 (set (pc)
        (if_then_else (ne:CC (reg:DF 98)
                (const_double:DF 0.0 [0x0.0p+0]))
            (label_ref 31)
            (pc))) "inf-compare-7.c":16 205 {*fbcc_normal}
     (int_list:REG_BR_PROB 100 (nil))
 -> 31)
;;  succ:       6 [1.0%] 
;;              4 [99.0%]  (FALLTHRU)

;; basic block 4, loop depth 0, count 0, freq 9900, maybe hot
;;  prev block 2, next block 5, flags: (NEW, REACHABLE, RTL, MODIFIED)
;;  pred:       2 [99.0%]  (FALLTHRU)
(note 53 24 25 4 [bb 4] NOTE_INSN_BASIC_BLOCK)
(insn 25 53 26 4 (set (reg:DI 100)
        (high:DI (symbol_ref/u:DI ("*$LC1") [flags 0x2]))) "inf-compare-7.c":16
240 {*movdi}
     (nil))
(insn 26 25 27 4 (set (reg:SF 101)
        (mem/u/c:SF (lo_sum:DI (reg:DI 100)
                (symbol_ref/u:DI ("*$LC1") [flags 0x2])) [2  S4 A32]))
"inf-compare-7.c":16 230 {*movsf}
     (nil))
(insn 27 26 28 4 (set (reg:DF 99)
        (float_extend:DF (reg:SF 101))) "inf-compare-7.c":16 161
{*extendsfdf2_ieee}
     (expr_list:REG_EQUAL (const_double:DF 1.0e+0 [0x0.8p+1])
        (nil)))
(insn 28 27 29 4 (set (reg:DF 102)
        (le:DF (reg:DF 99)
            (reg:DF 70 [ x.0_1 ]))) "inf-compare-7.c":16 194 {*cmpdf_ieee}
     (nil))
(jump_insn 29 28 54 4 (set (pc)
        (if_then_else (ne:CC (reg:DF 102)
                (const_double:DF 0.0 [0x0.0p+0]))
            (label_ref 31)
            (pc))) "inf-compare-7.c":16 205 {*fbcc_normal}
     (int_list:REG_BR_PROB 5000 (nil))
 -> 31)

...

Reply via email to