[PATCH] D35264: [LICM] Teach LICM to hoist conditional loads
Amara Emerson via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 11 09:15:04 PDT 2017
aemerson created this revision.
If the pointer operand of a load has been accessed by a load/store in a dominating block of the loop then it's safe to hoist.
Repository:
rL LLVM
https://reviews.llvm.org/D35264
Files:
lib/Transforms/Scalar/LICM.cpp
test/Transforms/LICM/hoisting.ll
Index: test/Transforms/LICM/hoisting.ll
===================================================================
--- test/Transforms/LICM/hoisting.ll
+++ test/Transforms/LICM/hoisting.ll
@@ -320,3 +320,37 @@
loopexit:
ret i32 %sum
}
+
+
+declare i32 @foo3(i32) nounwind readonly
+
+;; It is ok and desirable to hoist this load %B due to the load of %A.
+define i32 @test_cond_load(i1 %c, i1 %c2, i32* noalias %ptr, i32* noalias %storeptr) {
+; CHECK-LABEL: @test_cond_load(
+; CHECK: %A = load i32, i32* %ptr
+; CHECK: br label %Loop.ph
+; CHECK: %B = load i32, i32* %ptr
+; CHECK: br label %Loop
+; CHECK: Loop:
+entry:
+ %A = load i32, i32* %ptr
+ br label %Loop.ph
+
+Loop.ph:
+ br label %Loop
+
+Loop:
+ br i1 %c2, label %if.then, label %Loop.cont
+if.then:
+ %B = load i32, i32* %ptr
+ %res = call i32 @foo3(i32 %B)
+ store i32 %res, i32* %storeptr
+ br label %Loop.cont
+
+Loop.cont:
+ %res.phi = phi i32 [0, %Loop], [%res, %if.then]
+ br i1 %c, label %Loop, label %Out
+Out: ; preds = %Loop
+ %C = sub i32 %A, %res.phi
+ ret i32 %C
+}
Index: lib/Transforms/Scalar/LICM.cpp
===================================================================
--- lib/Transforms/Scalar/LICM.cpp
+++ lib/Transforms/Scalar/LICM.cpp
@@ -903,6 +903,33 @@
return true;
}
+/// Checks if the given load's pointer is dereferenceable on all paths to the
+/// loop preheader.
+static bool isLoadPtrDereferenceable(LoadInst *LI, const DominatorTree *DT,
+ const Loop *CurLoop) {
+ if (LI->isVolatile() || LI->isAtomic())
+ return false;
+
+ BasicBlock *PH = CurLoop->getLoopPreheader();
+ Value *Ptr = LI->getPointerOperand();
+
+ for (auto *PUser : Ptr->users()) {
+ if (isa<LoadInst>(PUser) || isa<StoreInst>(PUser)) {
+ Instruction *LSI = cast<Instruction>(PUser);
+ // For a common case of the pointer originating from the loop, avoid a DT
+ // query in favour of a densemap lookup.
+ if (CurLoop->contains(LSI->getParent()) ||
+ !DT->dominates(LSI->getParent(), PH))
+ continue;
+ // Since the block dominates the preheader, we know that execution must
+ // have transferred from the user's block to its successors.
+ return true;
+ }
+ }
+ return false;
+}
+
+
/// Only sink or hoist an instruction if it is not a trapping instruction,
/// or if the instruction is known not to trap when moved to the preheader.
/// or if it is a trapping instruction and is guaranteed to execute.
@@ -919,7 +946,12 @@
isGuaranteedToExecute(Inst, DT, CurLoop, SafetyInfo);
if (!GuaranteedToExecute) {
+ // Conditional loads may be hoisted if the address has already been accessed
+ // by a dominating block.
auto *LI = dyn_cast<LoadInst>(&Inst);
+ if (LI && isLoadPtrDereferenceable(LI, DT, CurLoop))
+ return true;
+
if (LI && CurLoop->isLoopInvariant(LI->getPointerOperand()))
ORE->emit(OptimizationRemarkMissed(
DEBUG_TYPE, "LoadWithLoopInvariantAddressCondExecuted", LI)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D35264.106047.patch
Type: text/x-patch
Size: 3066 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170711/32df7d07/attachment.bin>
More information about the llvm-commits
mailing list