[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