My student Zhengyang (@liuz) has written a superoptimizer for LLVM IR, and lately he has turned it towards codes that make heavy use of floating point. It comes up with plenty of interesting optimizations that LLVM currently misses; below is small collection of them that seem pretty easy to understand and also pretty clearly desirable. All of these were found when compiling OpenBLAS, but also they seem like they would probably be generically useful to our users who find FP performance to be important.
; Compiler Explorer
; Compiler Explorer
define float @src(float %0) {
entry:
%1 = fmul float %0, 0.000000e+00
%2 = fmul float %1, 3.000000e+00
ret float %2
}
define float @tgt(float %0) {
entry:
%1 = fmul float %0, 0.000000e+00
ret float %1
}
;==============================cut==============================
;Compiler Explorer
;Compiler Explorer
define <2 x double> @src(double %0, double %1, i1 %2, i1 %3, i1 %4) {
if.end:
%5 = fadd double %1, -1.0
%6 = insertelement <2 x double> poison, double %0, i64 0
%7 = insertelement <2 x double> %6, double %5, i64 1
%8 = fadd <2 x double> %7, <double 4.0, double poison>
ret <2 x double> %8
}
define <2 x double> @tgt(double %0, double %1, i1 %2, i1 %3, i1 %4) {
%6 = insertelement <2 x double> poison, double %0, i64 0
%7 = fadd <2 x double> %6, <double 4.0, double poison>
ret <2 x double> %7
}
;==============================cut==============================
;Compiler Explorer
;Compiler Explorer
define i1 @src(float %0, float %1) {
if.then:
%2 = fsub float %0, %1
%3 = fcmp ogt float %2, 0.000000e+00
ret i1 %3
}
define i1 @tgt(float %0, float %1) {
if.then:
%olt = fcmp olt float %1, %0
ret i1 %olt
}
;==============================cut==============================
;Compiler Explorer
;Compiler Explorer
define i1 @src(double %0, double %1, double %2, double %3, double %4, double %5, i1 %6, i1 %7, i8 %8) {
entry:
%t1 = fcmp uno double %0, 0.000000e+00
%t2 = fcmp uno double %1, 0.000000e+00
%t3 = select i1 %t1, i1 true, i1 %t2
ret i1 %t3
}
define i1 @tgt(double %0, double %1, double %2, double %3, double %4, double %5, i1 %6, i1 %7, i8 %8) {
entry:
%uno = fcmp uno double %0, %1
ret i1 %uno
}
; ==============================cut==============================
; this one is weird
; Compiler Explorer
; Compiler Explorer
declare double @llvm.floor.f64(double)
define i1 @src(double %0, i1 %1) {
%2 = fmul double %0, 7.812500e-03
%3 = call double @llvm.floor.f64(double %2)
%4 = fcmp ogt double %3, 0.000000e+00
ret i1 %4
}
define i1 @tgt(double %0, i1 %1) {
%oge = fcmp oge double %0, 1.280000e+02
ret i1 %oge
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define i1 @src(float %0) {
if.end192:
%1 = fcmp oge float %0, 0.000000e+00
%2 = fneg float %0
%3 = select i1 %1, float %0, float %2
%4 = fcmp oeq float %3, 0.000000e+00
ret i1 %4
}
define i1 @tgt(float %0) {
if.end192:
%oeq = fcmp oeq float %0, 0.000000e+00
ret i1 %oeq
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define float @src(i1 %0) {
if.else285:
%t2 = select i1 %0, float -1.000000e+00, float 1.000000e+00
%t3 = fneg float %t2
ret float %t3
}
define float @tgt(i1 %0) {
if.else285:
%sel = select i1 %0, float 1.000000e+00, float -1.000000e+00
ret float %sel
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define i1 @src(float %0, float %1, i1 %2, i1 %3, i1 %4) {
%t5 = fcmp ult float %0, 0.000000e+00
%t6 = select i1 %t5, float -1.000000e+00, float 1.000000e+00
%t7 = fcmp ult float %1, 0.000000e+00
%t8 = select i1 %t7, float -1.000000e+00, float 1.000000e+00
%t9 = fcmp une float %t6, %t8
ret i1 %t9
}
define i1 @tgt(float %0, float %1, i1 %2, i1 %3, i1 %4) {
%t5 = fcmp ult float %0, 0.000000e+00
%t6 = fcmp ult float %1, 0.000000e+00
%xor = xor i1 %t5, %t6
ret i1 %xor
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define float @src(float %0, float %1, i1 %c1, i1 %c2) {
if.else:
%4 = fneg float %1
%5 = select i1 %c1, float %1, float %4
%6 = select i1 %c1, float %4, float %1
%7 = select i1 %c2, float %6, float %5
%8 = fneg float %7
ret float %8
sink: ; No predecessors!
unreachable
}
define float @tgt(float %0, float %1, i1 %c1, i1 %c2) {
if.else:
%4 = fneg float %1
%5 = select i1 %c1, float %1, float %4
%6 = select i1 %c1, float %4, float %1
%sel = select i1 %c2, float %5, float %6
ret float %sel
sink: ; No predecessors!
unreachable
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define i1 @src(float %0) {
if.end35:
%1 = fmul float %0, 2.000000e+00
%2 = fcmp oge float %1, 0.000000e+00
ret i1 %2
}
define i1 @tgt(float %0) {
if.end35:
%oge = fcmp oge float %0, 0.000000e+00
ret i1 %oge
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define i1 @src(double %0) {
if.end155:
%1 = fptrunc double %0 to float
%2 = fcmp oge float %1, 1.000000e+02
ret i1 %2
}
define i1 @tgt(double %0) {
if.end155:
%oge = fcmp oge double %0, 0x4058FFFFF0000000
ret i1 %oge
}
; ==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define i1 @src(float %0) {
%t1 = fmul float %0, 0x3FF0CCCCC0000000
%t2 = fcmp olt float %t1, 0x3FE20418A0000000
ret i1 %t2
}
define i1 @tgt(float %0) {
%ole = fcmp ole float %0, 0x3FE12878E0000000
ret i1 %ole
}
;==============================cut==============================
https://alive2.llvm.org/ce/z/bFW9vZ
define i64 @src(float %0) {
if.end27:
%1 = fptosi float %0 to i32
%2 = sext i32 %1 to i64
ret i64 %2
sink: ; No predecessors!
unreachable
}
define i64 @tgt(float %0) {
if.end27:
%1 = fptosi float %0 to i64
ret i64 %1
sink: ; No predecessors!
unreachable
}
;==============================cut==============================
; Compiler Explorer
; Compiler Explorer
define i32 @src(float %0) {
if.then83:
%1 = tail call float @llvm.fabs.f32(float %0)
%2 = bitcast float %0 to i32
%3 = bitcast float %1 to i32
%4 = xor i32 %3, %2
ret i32 %4
}
declare float @llvm.fabs.f32(float)
define i32 @tgt(float %0) {
if.then83:
%1 = bitcast float %0 to i32
%and = and i32 %1, -2147483648
ret i32 %and
}