diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2014-01-31 00:09:00 +0000 |
---|---|---|
committer | Matt Arsenault <Matthew.Arsenault@amd.com> | 2014-01-31 00:09:00 +0000 |
commit | e932091eb5e17511e0db975811fc5aaf038b7be3 (patch) | |
tree | e48df00a4fb226454a4136aba8109f9cd13b8eef | |
parent | 4b4b8088609c501da779a3de6ab3d98670dc20c4 (diff) | |
download | llvm-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.rst | 5 | ||||
-rw-r--r-- | lib/Analysis/ValueTracking.cpp | 6 | ||||
-rw-r--r-- | test/Transforms/SimplifyCFG/speculate-math.ll | 58 |
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 +} + |