]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - opencl/llvm.git/commitdiff
Allow speculating llvm.sqrt, fma and fmuladd
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Fri, 31 Jan 2014 00:09:00 +0000 (00:09 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Fri, 31 Jan 2014 00:09:00 +0000 (00:09 +0000)
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

docs/LangRef.rst
lib/Analysis/ValueTracking.cpp
test/Transforms/SimplifyCFG/speculate-math.ll [new file with mode: 0644]

index d1eaee16a66a4e7c3cc00e6571992ffac2b47278..62ce112d5731eed53cabe636b856a6bde7ec3cb8 100644 (file)
@@ -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:
 """""""""
index 1e423c451261157e5e95421ba70fef373d469cdc..5ebb6130fbbfee71b061d42c9a7590380351d8bd 100644 (file)
@@ -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 (file)
index 0000000..fa7976d
--- /dev/null
@@ -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
+}
+