From 7a18a238c6368449f94eeace3f4813b9b8566cc6 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Sun, 14 Aug 2016 01:04:36 +0000 Subject: [PATCH] [IRCE] Don't iterate on loops that were cloned out IRCE has the ability to further version pre-loops and post-loops that it created, but this isn't useful at all. This change teaches IRCE to leave behind some metadata in the loops it creates (by cloning the main loop) so that these new loops are not re-processed by IRCE. Today this bug is hidden by another bug -- IRCE does not update LoopInfo properly so the loop pass manager does not re-invoke IRCE on the loops it split out. However, once the latter is fixed the bug addressed in this change causes IRCE to infinite-loop in some cases (e.g. it splits out a pre-loop, a pre-pre-loop from that, a pre-pre-pre-loop from that and so on). llvm-svn: 278617 --- .../Scalar/InductiveRangeCheckElimination.cpp | 12 +++++++++++ llvm/test/Transforms/IRCE/unhandled.ll | 25 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp index b3d8aa6..cf67c00 100644 --- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp +++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp @@ -79,6 +79,8 @@ static cl::opt MaxExitProbReciprocal("irce-max-exit-prob-reciprocal", static cl::opt SkipProfitabilityChecks("irce-skip-profitability-checks", cl::Hidden, cl::init(false)); +static const char *ClonedLoopTag = "irce.loop.clone"; + #define DEBUG_TYPE "irce" namespace { @@ -630,6 +632,11 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE, BranchProbabilityInfo &BP BasicBlock *Latch = L.getLoopLatch(); assert(Latch && "Simplified loops only have one latch!"); + if (Latch->getTerminator()->getMetadata(ClonedLoopTag)) { + FailureReason = "loop has already been cloned"; + return None; + } + if (!L.isLoopExiting(Latch)) { FailureReason = "no loop latch"; return None; @@ -913,6 +920,11 @@ void LoopConstrainer::cloneLoop(LoopConstrainer::ClonedLoop &Result, return static_cast(It->second); }; + auto *ClonedLatch = + cast(GetClonedValue(OriginalLoop.getLoopLatch())); + ClonedLatch->getTerminator()->setMetadata(ClonedLoopTag, + MDNode::get(Ctx, {})); + Result.Structure = MainLoopStructure.map(GetClonedValue); Result.Structure.Tag = Tag; diff --git a/llvm/test/Transforms/IRCE/unhandled.ll b/llvm/test/Transforms/IRCE/unhandled.ll index 4c5c7c0..9889b75 100644 --- a/llvm/test/Transforms/IRCE/unhandled.ll +++ b/llvm/test/Transforms/IRCE/unhandled.ll @@ -70,5 +70,30 @@ define void @multiple_latches(i32 *%arr, i32 *%a_len_ptr, i32 %n) { ret void } +define void @already_cloned(i32 *%arr, i32 *%a_len_ptr, i32 %n) { + entry: + %len = load i32, i32* %a_len_ptr, !range !0 + %first.itr.check = icmp sgt i32 %n, 0 + br i1 %first.itr.check, label %loop, label %exit + + loop: + %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] + %idx.next = add i32 %idx, 1 + %abc = icmp slt i32 %idx, %len + br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 + + in.bounds: + %addr = getelementptr i32, i32* %arr, i32 %idx + store i32 0, i32* %addr + %next = icmp slt i32 %idx.next, %n + br i1 %next, label %loop, label %exit, !irce.loop.clone !{} + + out.of.bounds: + ret void + + exit: + ret void +} + !0 = !{i32 0, i32 2147483647} !1 = !{!"branch_weights", i32 64, i32 4} -- 2.7.4