From e932091eb5e17511e0db975811fc5aaf038b7be3 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 31 Jan 2014 00:09:00 +0000 Subject: [PATCH] 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 --- docs/LangRef.rst | 5 +- lib/Analysis/ValueTracking.cpp | 6 ++ test/Transforms/SimplifyCFG/speculate-math.ll | 58 +++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 test/Transforms/SimplifyCFG/speculate-math.ll diff --git a/docs/LangRef.rst b/docs/LangRef.rst index d1eaee16a66..62ce112d573 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 1e423c45126..5ebb6130fbb 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 00000000000..fa7976d0689 --- /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 +} + -- 2.34.1