[llvm] r363234 - [ARM][TTI] Scan for existing loop intrinsics
Sam Parker via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 13 01:28:46 PDT 2019
Author: sam_parker
Date: Thu Jun 13 01:28:46 2019
New Revision: 363234
URL: http://llvm.org/viewvc/llvm-project?rev=363234&view=rev
Log:
[ARM][TTI] Scan for existing loop intrinsics
TTI should report that it's not profitable to generate a hardware loop
if it, or one of its child loops, has already been converted.
Differential Revision: https://reviews.llvm.org/D63212
Modified:
llvm/trunk/lib/Target/ARM/ARMTargetTransformInfo.cpp
llvm/trunk/test/Transforms/HardwareLoops/ARM/structure.ll
Modified: llvm/trunk/lib/Target/ARM/ARMTargetTransformInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMTargetTransformInfo.cpp?rev=363234&r1=363233&r2=363234&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMTargetTransformInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMTargetTransformInfo.cpp Thu Jun 13 01:28:46 2019
@@ -804,12 +804,39 @@ bool ARMTTIImpl::isHardwareLoopProfitabl
return false;
};
+ auto IsHardwareLoopIntrinsic = [](Instruction &I) {
+ if (auto *Call = dyn_cast<IntrinsicInst>(&I)) {
+ switch (Call->getCalledFunction()->getIntrinsicID()) {
+ default:
+ break;
+ case Intrinsic::set_loop_iterations:
+ case Intrinsic::loop_decrement:
+ case Intrinsic::loop_decrement_reg:
+ return true;
+ }
+ }
+ return false;
+ };
+
// Scan the instructions to see if there's any that we know will turn into a
- // call.
- for (auto *BB : L->getBlocks())
- for (auto &I : *BB)
- if (MaybeCall(I))
- return false;
+ // call or if this loop is already a low-overhead loop.
+ auto ScanLoop = [&](Loop *L) {
+ for (auto *BB : L->getBlocks()) {
+ for (auto &I : *BB) {
+ if (MaybeCall(I) || IsHardwareLoopIntrinsic(I))
+ return false;
+ }
+ }
+ return true;
+ };
+
+ // Visit inner loops.
+ for (auto Inner : *L)
+ if (!ScanLoop(Inner))
+ return false;
+
+ if (!ScanLoop(L))
+ return false;
// TODO: Check whether the trip count calculation is expensive. If L is the
// inner loop but we know it has a low trip count, calculating that trip
@@ -817,6 +844,7 @@ bool ARMTTIImpl::isHardwareLoopProfitabl
LLVMContext &C = L->getHeader()->getContext();
HWLoopInfo.CounterInReg = true;
+ HWLoopInfo.IsNestingLegal = false;
HWLoopInfo.CountType = Type::getInt32Ty(C);
HWLoopInfo.LoopDecrement = ConstantInt::get(HWLoopInfo.CountType, 1);
return true;
Modified: llvm/trunk/test/Transforms/HardwareLoops/ARM/structure.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HardwareLoops/ARM/structure.ll?rev=363234&r1=363233&r2=363234&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/HardwareLoops/ARM/structure.ll (original)
+++ llvm/trunk/test/Transforms/HardwareLoops/ARM/structure.ll Thu Jun 13 01:28:46 2019
@@ -70,3 +70,71 @@ while.cond1.while.end_crit_edge.us:
while.end7:
ret void
}
+
+; CHECK-LABEL: pre_existing
+; CHECK: llvm.set.loop.iterations
+; CHECK-NOT: llvm.set.loop.iterations
+; CHECK: call i32 @llvm.loop.decrement.reg.i32.i32.i32(i32 %0, i32 1)
+; CHECK-NOT: call i32 @llvm.loop.decrement.reg
+define i32 @pre_existing(i32 %n, i32* nocapture %p, i32* nocapture readonly %q) {
+entry:
+ call void @llvm.set.loop.iterations.i32(i32 %n)
+ br label %while.body
+
+while.body: ; preds = %while.body, %entry
+ %q.addr.05 = phi i32* [ %incdec.ptr, %while.body ], [ %q, %entry ]
+ %p.addr.04 = phi i32* [ %incdec.ptr1, %while.body ], [ %p, %entry ]
+ %0 = phi i32 [ %n, %entry ], [ %2, %while.body ]
+ %incdec.ptr = getelementptr inbounds i32, i32* %q.addr.05, i32 1
+ %1 = load i32, i32* %q.addr.05, align 4
+ %incdec.ptr1 = getelementptr inbounds i32, i32* %p.addr.04, i32 1
+ store i32 %1, i32* %p.addr.04, align 4
+ %2 = call i32 @llvm.loop.decrement.reg.i32.i32.i32(i32 %0, i32 1)
+ %3 = icmp ne i32 %2, 0
+ br i1 %3, label %while.body, label %while.end
+
+while.end: ; preds = %while.body
+ ret i32 0
+}
+
+; CHECK-LABEL: pre_existing_inner
+; CHECK-NOT: llvm.set.loop.iterations
+; CHECK: while.cond1.preheader.us:
+; CHECK: call void @llvm.set.loop.iterations.i32(i32 %N)
+; CHECK: call i32 @llvm.loop.decrement.reg.i32.i32.i32(i32 %0, i32 1)
+; CHECK: br i1
+; CHECK-NOT: call i32 @llvm.loop.decrement
+define void @pre_existing_inner(i32* nocapture %A, i32 %N) {
+entry:
+ %cmp20 = icmp eq i32 %N, 0
+ br i1 %cmp20, label %while.end7, label %while.cond1.preheader.us
+
+while.cond1.preheader.us:
+ %i.021.us = phi i32 [ %inc6.us, %while.cond1.while.end_crit_edge.us ], [ 0, %entry ]
+ %mul.us = mul i32 %i.021.us, %N
+ call void @llvm.set.loop.iterations.i32(i32 %N)
+ br label %while.body3.us
+
+while.body3.us:
+ %j.019.us = phi i32 [ 0, %while.cond1.preheader.us ], [ %inc.us, %while.body3.us ]
+ %0 = phi i32 [ %N, %while.cond1.preheader.us ], [ %1, %while.body3.us ]
+ %add.us = add i32 %j.019.us, %mul.us
+ %arrayidx.us = getelementptr inbounds i32, i32* %A, i32 %add.us
+ store i32 %add.us, i32* %arrayidx.us, align 4
+ %inc.us = add nuw i32 %j.019.us, 1
+ %1 = call i32 @llvm.loop.decrement.reg.i32.i32.i32(i32 %0, i32 1)
+ %2 = icmp ne i32 %1, 0
+ br i1 %2, label %while.body3.us, label %while.cond1.while.end_crit_edge.us
+
+while.cond1.while.end_crit_edge.us:
+ %inc6.us = add nuw i32 %i.021.us, 1
+ %exitcond23 = icmp eq i32 %inc6.us, %N
+ br i1 %exitcond23, label %while.end7, label %while.cond1.preheader.us
+
+while.end7:
+ ret void
+}
+
+declare void @llvm.set.loop.iterations.i32(i32) #0
+declare i32 @llvm.loop.decrement.reg.i32.i32.i32(i32, i32) #0
+
More information about the llvm-commits
mailing list