Skip to content

Commit de6d43f

Browse files
author
Whitney Tsang
committed
Revert "[LoopNest] Allow empty basic blocks without loops"
This reverts commit 9a17bff.
1 parent 1915523 commit de6d43f

File tree

5 files changed

+39
-143
lines changed

5 files changed

+39
-143
lines changed

llvm/include/llvm/Analysis/LoopNestAnalysis.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,6 @@ class LoopNest {
128128
[](const Loop *L) { return L->isLoopSimplifyForm(); });
129129
}
130130

131-
/// Return true if all loops in the loop nest are in rotated form.
132-
bool areAllLoopsRotatedForm() const {
133-
return std::all_of(Loops.begin(), Loops.end(),
134-
[](const Loop *L) { return L->isRotatedForm(); });
135-
}
136-
137131
StringRef getName() const { return Loops.front()->getName(); }
138132

139133
protected:

llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,6 @@ unsigned SplitAllCriticalEdges(Function &F,
244244
const CriticalEdgeSplittingOptions &Options =
245245
CriticalEdgeSplittingOptions());
246246

247-
/// Recursivelly traverse all empty 'single successor' basic blocks of \p From
248-
/// (if there are any). Return the last basic block found or \p End if it was
249-
/// reached during the search.
250-
const BasicBlock &skipEmptyBlockUntil(const BasicBlock *From,
251-
const BasicBlock *End);
252-
253247
/// Split the edge connecting the specified blocks, and return the newly created
254248
/// basic block between \p From and \p To.
255249
BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,

llvm/lib/Analysis/LoopNestAnalysis.cpp

Lines changed: 39 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "llvm/ADT/Statistic.h"
1717
#include "llvm/Analysis/PostDominators.h"
1818
#include "llvm/Analysis/ValueTracking.h"
19-
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
2019

2120
using namespace llvm;
2221

@@ -254,66 +253,49 @@ static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
254253
// Ensure the only branch that may exist between the loops is the inner loop
255254
// guard.
256255
if (OuterLoopHeader != InnerLoopPreHeader) {
257-
const BasicBlock &SingleSucc =
258-
skipEmptyBlockUntil(OuterLoopHeader, InnerLoopPreHeader);
259-
260-
// no conditional branch present
261-
if (&SingleSucc != InnerLoopPreHeader) {
262-
const BranchInst *BI = dyn_cast<BranchInst>(SingleSucc.getTerminator());
263-
264-
if (!BI || BI != InnerLoop.getLoopGuardBranch())
265-
return false;
266-
267-
bool InnerLoopExitContainsLCSSA = ContainsLCSSAPhi(*InnerLoopExit);
268-
269-
// The successors of the inner loop guard should be the inner loop
270-
// preheader or the outer loop latch possibly through empty blocks.
271-
for (const BasicBlock *Succ : BI->successors()) {
272-
const BasicBlock *PotentialInnerPreHeader = Succ;
273-
const BasicBlock *PotentialOuterLatch = Succ;
274-
275-
// Ensure the inner loop guard successor is empty before skipping
276-
// blocks.
277-
if (Succ->getInstList().size() == 1) {
278-
PotentialInnerPreHeader =
279-
&skipEmptyBlockUntil(Succ, InnerLoopPreHeader);
280-
PotentialOuterLatch = &skipEmptyBlockUntil(Succ, OuterLoopLatch);
281-
}
282-
283-
if (PotentialInnerPreHeader == InnerLoopPreHeader)
284-
continue;
285-
if (PotentialOuterLatch == OuterLoopLatch)
286-
continue;
287-
288-
// If `InnerLoopExit` contains LCSSA Phi instructions, additional block
289-
// may be inserted before the `OuterLoopLatch` to which `BI` jumps. The
290-
// loops are still considered perfectly nested if the extra block only
291-
// contains Phi instructions from InnerLoopExit and OuterLoopHeader.
292-
if (InnerLoopExitContainsLCSSA && IsExtraPhiBlock(*Succ) &&
293-
Succ->getSingleSuccessor() == OuterLoopLatch) {
294-
// Points to the extra block so that we can reference it later in the
295-
// final check. We can also conclude that the inner loop is
296-
// guarded and there exists LCSSA Phi node in the exit block later if
297-
// we see a non-null `ExtraPhiBlock`.
298-
ExtraPhiBlock = Succ;
299-
continue;
300-
}
301-
302-
DEBUG_WITH_TYPE(VerboseDebug, {
303-
dbgs() << "Inner loop guard successor " << Succ->getName()
304-
<< " doesn't lead to inner loop preheader or "
305-
"outer loop latch.\n";
306-
});
307-
return false;
256+
const BranchInst *BI =
257+
dyn_cast<BranchInst>(OuterLoopHeader->getTerminator());
258+
259+
if (!BI || BI != InnerLoop.getLoopGuardBranch())
260+
return false;
261+
262+
bool InnerLoopExitContainsLCSSA = ContainsLCSSAPhi(*InnerLoopExit);
263+
264+
// The successors of the inner loop guard should be the inner loop
265+
// preheader and the outer loop latch.
266+
for (const BasicBlock *Succ : BI->successors()) {
267+
if (Succ == InnerLoopPreHeader)
268+
continue;
269+
if (Succ == OuterLoopLatch)
270+
continue;
271+
272+
// If `InnerLoopExit` contains LCSSA Phi instructions, additional block
273+
// may be inserted before the `OuterLoopLatch` to which `BI` jumps. The
274+
// loops are still considered perfectly nested if the extra block only
275+
// contains Phi instructions from InnerLoopExit and OuterLoopHeader.
276+
if (InnerLoopExitContainsLCSSA && IsExtraPhiBlock(*Succ) &&
277+
Succ->getSingleSuccessor() == OuterLoopLatch) {
278+
// Points to the extra block so that we can reference it later in the
279+
// final check. We can also conclude that the inner loop is
280+
// guarded and there exists LCSSA Phi node in the exit block later if we
281+
// see a non-null `ExtraPhiBlock`.
282+
ExtraPhiBlock = Succ;
283+
continue;
308284
}
285+
286+
DEBUG_WITH_TYPE(VerboseDebug, {
287+
dbgs() << "Inner loop guard successor " << Succ->getName()
288+
<< " doesn't lead to inner loop preheader or "
289+
"outer loop latch.\n";
290+
});
291+
return false;
309292
}
310293
}
311294

312-
// Ensure the inner loop exit block lead to the outer loop latch possibly
313-
// through empty blocks.
314-
const BasicBlock &SuccInner =
315-
skipEmptyBlockUntil(InnerLoop.getExitBlock(), OuterLoopLatch);
316-
if (&SuccInner != OuterLoopLatch && &SuccInner != ExtraPhiBlock) {
295+
// Ensure the inner loop exit block leads to the outer loop latch.
296+
const BasicBlock *SuccInner = InnerLoopExit->getSingleSuccessor();
297+
if (!SuccInner ||
298+
(SuccInner != OuterLoopLatch && SuccInner != ExtraPhiBlock)) {
317299
DEBUG_WITH_TYPE(
318300
VerboseDebug,
319301
dbgs() << "Inner loop exit block " << *InnerLoopExit

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -494,31 +494,6 @@ void llvm::ReplaceInstWithInst(Instruction *From, Instruction *To) {
494494
ReplaceInstWithInst(From->getParent()->getInstList(), BI, To);
495495
}
496496

497-
const BasicBlock &llvm::skipEmptyBlockUntil(const BasicBlock *From,
498-
const BasicBlock *End) {
499-
assert(From && "Expecting valid From");
500-
assert(End && "Expecting valid End");
501-
502-
if (From == End || !From->getSingleSuccessor())
503-
return *From;
504-
505-
auto IsEmpty = [](const BasicBlock *BB) {
506-
return (BB->getInstList().size() == 1);
507-
};
508-
509-
// Visited is used to avoid running into an infinite loop.
510-
SmallPtrSet<const BasicBlock *, 4> Visited;
511-
const BasicBlock *BB = From->getSingleSuccessor();
512-
const BasicBlock *PredBB = BB;
513-
while (BB && BB != End && IsEmpty(BB) && !Visited.count(BB)) {
514-
Visited.insert(BB);
515-
PredBB = BB;
516-
BB = BB->getSingleSuccessor();
517-
}
518-
519-
return (BB == End) ? *End : *PredBB;
520-
}
521-
522497
BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, DominatorTree *DT,
523498
LoopInfo *LI, MemorySSAUpdater *MSSAU) {
524499
unsigned SuccNum = GetSuccessorNumber(BB, Succ);

llvm/test/Analysis/LoopNestAnalysis/perfectnest.ll

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -85,55 +85,6 @@ perf_nest_2D_2_loop_i_end:
8585
ret void
8686
}
8787

88-
define void @perf_nest_2D_3(i32** %y, i32** %x, i64 signext %nx, i64 signext %ny) {
89-
; CHECK-LABEL: IsPerfect=true, Depth=1, OutermostLoop: perf_nest_2D_3_loop_j, Loops: ( perf_nest_2D_3_loop_j )
90-
; CHECK-LABEL: IsPerfect=true, Depth=2, OutermostLoop: perf_nest_2D_3_loop_i, Loops: ( perf_nest_2D_3_loop_i perf_nest_2D_3_loop_j )
91-
entry:
92-
br label %perf_nest_2D_3_loop_i
93-
94-
perf_nest_2D_3_loop_i:
95-
%i = phi i64 [ 0, %entry ], [ %inc13, %inc_i ]
96-
%cmp21 = icmp slt i64 0, %ny
97-
br label %singleSucc
98-
99-
singleSucc:
100-
br i1 %cmp21, label %preheader.j, label %for.end
101-
102-
preheader.j:
103-
br label %perf_nest_2D_3_loop_j
104-
105-
perf_nest_2D_3_loop_j:
106-
%j = phi i64 [ 0, %preheader.j ], [ %inc, %inc_j ]
107-
%arrayidx = getelementptr inbounds i32*, i32** %x, i64 %j
108-
%0 = load i32*, i32** %arrayidx, align 8
109-
%arrayidx6 = getelementptr inbounds i32, i32* %0, i64 %j
110-
%1 = load i32, i32* %arrayidx6, align 4
111-
%arrayidx8 = getelementptr inbounds i32*, i32** %y, i64 %j
112-
%2 = load i32*, i32** %arrayidx8, align 8
113-
%arrayidx11 = getelementptr inbounds i32, i32* %2, i64 %i
114-
store i32 %1, i32* %arrayidx11, align 4
115-
br label %inc_j
116-
117-
inc_j:
118-
%inc = add nsw i64 %j, 1
119-
%cmp2 = icmp slt i64 %inc, %ny
120-
br i1 %cmp2, label %perf_nest_2D_3_loop_j, label %for.exit
121-
122-
for.exit:
123-
br label %for.end
124-
125-
for.end:
126-
br label %inc_i
127-
128-
inc_i:
129-
%inc13 = add nsw i64 %i, 1
130-
%cmp = icmp slt i64 %inc13, %nx
131-
br i1 %cmp, label %perf_nest_2D_3_loop_i, label %perf_nest_2D_3_loop_i_end
132-
133-
perf_nest_2D_3_loop_i_end:
134-
ret void
135-
}
136-
13788
; Test a perfect 3-dim loop nest of the form:
13889
; for (i=0; i<nx; ++i)
13990
; for (j=0; j<ny; ++j)

0 commit comments

Comments
 (0)