summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2014-01-31 00:09:00 +0000
committerMatt Arsenault <Matthew.Arsenault@amd.com>2014-01-31 00:09:00 +0000
commite932091eb5e17511e0db975811fc5aaf038b7be3 (patch)
treee48df00a4fb226454a4136aba8109f9cd13b8eef
parent4b4b8088609c501da779a3de6ab3d98670dc20c4 (diff)
downloadllvm-e932091eb5e17511e0db975811fc5aaf038b7be3.tar.gz
llvm-e932091eb5e17511e0db975811fc5aaf038b7be3.tar.bz2
llvm-e932091eb5e17511e0db975811fc5aaf038b7be3.tar.xz
Allow speculating llvm.sqrt, fma and fmuladd
This doesn't set errno, so this should be OK. Also update the documentation to explicitly state that errno are not set. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200501 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/LangRef.rst5
-rw-r--r--lib/Analysis/ValueTracking.cpp6
-rw-r--r--test/Transforms/SimplifyCFG/speculate-math.ll58
3 files changed, 67 insertions, 2 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index d1eaee16a6..62ce112d57 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -7490,7 +7490,7 @@ Semantics:
""""""""""
This function returns the same values as the libm ``fma`` functions
-would.
+would, and does not set errno.
'``llvm.fabs.*``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8298,7 +8298,8 @@ is equivalent to the expression a \* b + c, except that rounding will
not be performed between the multiplication and addition steps if the
code generator fuses the operations. Fusion is not guaranteed, even if
the target platform supports it. If a fused multiply-add is required the
-corresponding llvm.fma.\* intrinsic function should be used instead.
+corresponding llvm.fma.\* intrinsic function should be used
+instead. This never sets errno, just as '``llvm.fma.*``'.
Examples:
"""""""""
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 1e423c4512..5ebb6130fb 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -2036,6 +2036,12 @@ bool llvm::isSafeToSpeculativelyExecute(const Value *V,
case Intrinsic::umul_with_overflow:
case Intrinsic::usub_with_overflow:
return true;
+ // Sqrt should be OK, since the llvm sqrt intrinsic isn't defined to set
+ // errno like libm sqrt would.
+ case Intrinsic::sqrt:
+ case Intrinsic::fma:
+ case Intrinsic::fmuladd:
+ return true;
// TODO: some fp intrinsics are marked as having the same error handling
// as libm. They're safe to speculate when they won't error.
// TODO: are convert_{from,to}_fp16 safe?
diff --git a/test/Transforms/SimplifyCFG/speculate-math.ll b/test/Transforms/SimplifyCFG/speculate-math.ll
new file mode 100644
index 0000000000..fa7976d068
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/speculate-math.ll
@@ -0,0 +1,58 @@
+; RUN: opt -S -simplifycfg -phi-node-folding-threshold=2 < %s | FileCheck %s
+
+declare float @llvm.sqrt.f32(float) nounwind readonly
+declare float @llvm.fma.f32(float, float, float) nounwind readonly
+declare float @llvm.fmuladd.f32(float, float, float) nounwind readonly
+
+; CHECK-LABEL: @sqrt_test(
+; CHECK: select
+define void @sqrt_test(float addrspace(1)* noalias nocapture %out, float %a) nounwind {
+entry:
+ %cmp.i = fcmp olt float %a, 0.000000e+00
+ br i1 %cmp.i, label %test_sqrt.exit, label %cond.else.i
+
+cond.else.i: ; preds = %entry
+ %0 = tail call float @llvm.sqrt.f32(float %a) nounwind readnone
+ br label %test_sqrt.exit
+
+test_sqrt.exit: ; preds = %cond.else.i, %entry
+ %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+ store float %cond.i, float addrspace(1)* %out, align 4
+ ret void
+}
+
+
+; CHECK-LABEL: @fma_test(
+; CHECK: select
+define void @fma_test(float addrspace(1)* noalias nocapture %out, float %a, float %b, float %c) nounwind {
+entry:
+ %cmp.i = fcmp olt float %a, 0.000000e+00
+ br i1 %cmp.i, label %test_fma.exit, label %cond.else.i
+
+cond.else.i: ; preds = %entry
+ %0 = tail call float @llvm.fma.f32(float %a, float %b, float %c) nounwind readnone
+ br label %test_fma.exit
+
+test_fma.exit: ; preds = %cond.else.i, %entry
+ %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+ store float %cond.i, float addrspace(1)* %out, align 4
+ ret void
+}
+
+; CHECK-LABEL: @fmuladd_test(
+; CHECK: select
+define void @fmuladd_test(float addrspace(1)* noalias nocapture %out, float %a, float %b, float %c) nounwind {
+entry:
+ %cmp.i = fcmp olt float %a, 0.000000e+00
+ br i1 %cmp.i, label %test_fmuladd.exit, label %cond.else.i
+
+cond.else.i: ; preds = %entry
+ %0 = tail call float @llvm.fmuladd.f32(float %a, float %b, float %c) nounwind readnone
+ br label %test_fmuladd.exit
+
+test_fmuladd.exit: ; preds = %cond.else.i, %entry
+ %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+ store float %cond.i, float addrspace(1)* %out, align 4
+ ret void
+}
+