summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2017-04-11 02:22:54 +0000
committerHal Finkel <hfinkel@anl.gov>2017-04-11 02:22:54 +0000
commitb63ed9154961eb17e2eb92f3184fbd26acefb2e1 (patch)
tree28182558e59d5debb15dc16cd2d6ec7ba3d1f596
parentcef9e52736f9dd886a22696d26a86121d31e6cf2 (diff)
downloadbcm5719-llvm-b63ed9154961eb17e2eb92f3184fbd26acefb2e1.tar.gz
bcm5719-llvm-b63ed9154961eb17e2eb92f3184fbd26acefb2e1.zip
[LICM] Hoist fp division from the loops and replace by a reciprocal
When allowed, we can hoist a division out of a loop in favor of a multiplication by the reciprocal. Fixes PR32157. Patch by vit9696! Differential Revision: https://reviews.llvm.org/D30819 llvm-svn: 299911
-rw-r--r--llvm/lib/Transforms/Scalar/LICM.cpp23
-rw-r--r--llvm/test/Transforms/LICM/hoist-fast-fdiv.ll34
2 files changed, 57 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 5b1ce6f9e10..340c81fed0f 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -431,6 +431,29 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
continue;
}
+ // Attempt to remove floating point division out of the loop by converting
+ // it to a reciprocal multiplication.
+ if (I.getOpcode() == Instruction::FDiv &&
+ CurLoop->isLoopInvariant(I.getOperand(1)) &&
+ I.hasAllowReciprocal()) {
+ auto Divisor = I.getOperand(1);
+ auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0);
+ auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor);
+ ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags());
+ ReciprocalDivisor->insertBefore(&I);
+
+ auto Product = BinaryOperator::CreateFMul(I.getOperand(0),
+ ReciprocalDivisor);
+ Product->setFastMathFlags(I.getFastMathFlags());
+ Product->insertAfter(&I);
+ I.replaceAllUsesWith(Product);
+ I.eraseFromParent();
+
+ hoist(*ReciprocalDivisor, DT, CurLoop, SafetyInfo, ORE);
+ Changed = true;
+ continue;
+ }
+
// Try hoisting the instruction out to the preheader. We can only do this
// if all of the operands of the instruction are loop invariant and if it
// is safe to hoist the instruction.
diff --git a/llvm/test/Transforms/LICM/hoist-fast-fdiv.ll b/llvm/test/Transforms/LICM/hoist-fast-fdiv.ll
new file mode 100644
index 00000000000..f61564fd726
--- /dev/null
+++ b/llvm/test/Transforms/LICM/hoist-fast-fdiv.ll
@@ -0,0 +1,34 @@
+; RUN: opt -licm -S < %s | FileCheck %s
+
+; Function Attrs: noinline norecurse nounwind readnone ssp uwtable
+define zeroext i1 @f(double %v) #0 {
+entry:
+; CHECK-LABEL: @f(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: fdiv fast double 1.000000e+00, %v
+ br label %loop
+
+loop: ; preds = %entry, %loop
+ %v3 = phi i32 [ 0, %entry ], [ %v11, %loop ]
+ %v4 = phi i32 [ 0, %entry ], [ %v12, %loop ]
+ %v5 = uitofp i32 %v4 to double
+
+; CHECK-LABEL: loop:
+; CHECK: fmul fast double
+; CHECK-NOT: fdiv
+ %v6 = fdiv fast double %v5, %v
+ %v7 = fptoui double %v6 to i64
+ %v8 = and i64 %v7, 1
+ %v9 = xor i64 %v8, 1
+ %v10 = trunc i64 %v9 to i32
+ %v11 = add i32 %v10, %v3
+ %v12 = add nuw i32 %v4, 1
+ %v13 = icmp eq i32 %v12, -1
+ br i1 %v13, label %end, label %loop
+
+end: ; preds = %loop
+ %v15 = phi i32 [ %v11, %loop ]
+ %v16 = icmp ne i32 %v15, 0
+ ret i1 %v16
+}
+
OpenPOWER on IntegriCloud