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)
...