Fold fcmp in cases where value is provably non-negative. By Arch Robison.
This patch folds fcmp in some cases of interest in Julia. The patch adds a function CannotBeOrderedLessThanZero that returns true if a value is provably not less than zero. I.e. the function returns true if the value is provably -0, +0, positive, or a NaN. The patch extends InstructionSimplify.cpp to fold instances of fcmp where:
- the predicate is olt or uge
- the first operand is provably not less than zero
- the second operand is zero
The motivation for handling these cases optimizing away domain checks for sqrt in Julia for common idioms such as sqrt(x*x+y*y)..
http://reviews.llvm.org/D6972
llvm-svn: 227298
diff --git a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
new file mode 100644
index 0000000..af48d06
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll
@@ -0,0 +1,60 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; These tests choose arbitrarily between float and double,
+; and between uge and olt, to give reasonble coverage
+; without combinatorial explosion.
+
+declare float @llvm.fabs.f32(float)
+declare float @llvm.sqrt.f32(float)
+declare double @llvm.powi.f64(double,i32)
+declare float @llvm.exp.f32(float)
+declare double @llvm.exp2.f64(double)
+declare float @llvm.fma.f32(float,float,float)
+
+declare void @expect_equal(i1,i1)
+
+; CHECK-LABEL: @orderedLessZeroTree(
+define i1 @orderedLessZeroTree(float,float,float,float) {
+ %square = fmul float %0, %0
+ %abs = call float @llvm.fabs.f32(float %1)
+ %sqrt = call float @llvm.sqrt.f32(float %2)
+ %fma = call float @llvm.fma.f32(float %3, float %3, float %sqrt)
+ %div = fdiv float %square, %abs
+ %rem = frem float %sqrt, %fma
+ %add = fadd float %div, %rem
+ %uge = fcmp uge float %add, 0.000000e+00
+; CHECK: ret i1 true
+ ret i1 %uge
+}
+
+; CHECK-LABEL: @orderedLessZeroExpExt(
+define i1 @orderedLessZeroExpExt(float) {
+ %a = call float @llvm.exp.f32(float %0)
+ %b = fpext float %a to double
+ %uge = fcmp uge double %b, 0.000000e+00
+; CHECK: ret i1 true
+ ret i1 %uge
+}
+
+; CHECK-LABEL: @orderedLessZeroExp2Trunc(
+define i1 @orderedLessZeroExp2Trunc(double) {
+ %a = call double @llvm.exp2.f64(double %0)
+ %b = fptrunc double %a to float
+ %olt = fcmp olt float %b, 0.000000e+00
+; CHECK: ret i1 false
+ ret i1 %olt
+}
+
+; CHECK-LABEL: @orderedLessZeroPowi(
+define i1 @orderedLessZeroPowi(double,double) {
+ ; Even constant exponent
+ %a = call double @llvm.powi.f64(double %0, i32 2)
+ %square = fmul double %1, %1
+ ; Odd constant exponent with provably non-negative base
+ %b = call double @llvm.powi.f64(double %square, i32 3)
+ %c = fadd double %a, %b
+ %olt = fcmp olt double %b, 0.000000e+00
+; CHECK: ret i1 false
+ ret i1 %olt
+}
+