diff --git a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp --- a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp +++ b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp @@ -13,6 +13,7 @@ #include "AMDGPU.h" #include "GCNSubtarget.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -157,7 +158,9 @@ /// Pop the last saved value from the control flow stack Value *SIAnnotateControlFlow::popSaved() { - return Stack.pop_back_val().second; + auto [x, y] = Stack.pop_back_val(); + // dbgs() << "popping off <" << x->getName() << ", " << *y << ">\n"; + return y; } /// Push a BB and saved value to the control flow stack @@ -209,6 +212,7 @@ Value *Ret = CallInst::Create(If, Term->getCondition(), "", Term); Term->setCondition(ExtractValueInst::Create(Ret, 0, "", Term)); push(Term->getSuccessor(1), ExtractValueInst::Create(Ret, 1, "", Term)); + // dbgs() << "Stack size " << Stack.size() << '\n'; return true; } @@ -287,7 +291,6 @@ } Term->setCondition(CallInst::Create(Loop, Arg, "", Term)); - push(Term->getSuccessor(0), Arg); return true; @@ -296,7 +299,6 @@ /// Close the last opened control flow bool SIAnnotateControlFlow::closeControlFlow(BasicBlock *BB) { llvm::Loop *L = LI->getLoopFor(BB); - assert(Stack.back().first == BB); if (L && L->getHeader() == BB) { @@ -327,13 +329,13 @@ } CallInst::Create(EndCf, Exec, "", FirstInsertionPt); } - return true; } /// Annotate the control flow with intrinsics so the backend can /// recognize if/then/else and loops. bool SIAnnotateControlFlow::runOnFunction(Function &F) { + DT = &getAnalysis().getDomTree(); LI = &getAnalysis().getLoopInfo(); DA = &getAnalysis(); @@ -348,18 +350,23 @@ BranchInst *Term = dyn_cast(BB->getTerminator()); if (!Term || Term->isUnconditional()) { - if (isTopOfStack(BB)) + if (isTopOfStack(BB)) { Changed |= closeControlFlow(BB); - + } continue; } if (I.nodeVisited(Term->getSuccessor(1))) { - if (isTopOfStack(BB)) + if (isTopOfStack(BB)) { Changed |= closeControlFlow(BB); + } - if (DT->dominates(Term->getSuccessor(1), BB)) - Changed |= handleLoop(Term); + if (DT->dominates(Term->getSuccessor(1), BB)) { + if (handleLoop(Term) && I.nodeVisited(Stack.back().first)) { + Changed = true; + closeControlFlow(Stack.back().first); + } + } continue; } @@ -373,10 +380,15 @@ Changed |= closeControlFlow(BB); } - Changed |= openIf(Term); } + // A basic block may be pushed as a result of loop handling + // and could never be processed if it was already visited before. + // Close control flow at this basic block. + // if (Stack.size() == 1) + // closeControlFlow(Stack.back().first); + if (!Stack.empty()) { // CFG was probably not structured. report_fatal_error("failed to annotate CFG"); diff --git a/llvm/test/CodeGen/AMDGPU/si-annotate-nested-control-flows.ll b/llvm/test/CodeGen/AMDGPU/si-annotate-nested-control-flows.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/si-annotate-nested-control-flows.ll @@ -0,0 +1,40 @@ +; RUN: opt -mtriple=amdgcn-- -S -structurizecfg -si-annotate-control-flow %s | FileCheck %s + +define void @nested_inf_loop(i1 %0, i1 %1) { +; CHECK-LABEL: define void @nested_inf_loop( +; CHECK-NEXT: BB: +; CHECK-NEXT: br label %BB1 +; CHECK: BB1: ; preds = %BB3, %BB +; CHECK-NEXT: %2 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %0) +; CHECK-NEXT: %3 = extractvalue { i1, i64 } %2, 0 +; CHECK-NEXT: %4 = extractvalue { i1, i64 } %2, 1 +; CHECK-NEXT: br i1 %3, label %BB3, label %BB2 +; CHECK: BB2: ; preds = %BB1 +; CHECK-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 %4) +; CHECK-NEXT: br label %BB4 +; CHECK: BB4: ; preds = %BB4, %BB2 +; CHECK-NEXT: %phi.broken = phi i64 [ %5, %BB4 ], [ 0, %BB2 ] +; CHECK-NEXT: %5 = call i64 @llvm.amdgcn.if.break.i64(i1 %1, i64 %phi.broken) +; CHECK-NEXT: %6 = call i1 @llvm.amdgcn.loop.i64(i64 %5) +; CHECK-NEXT: br i1 %6, label %BB4.BB3_crit_edge, label %BB4 +; CHECK: BB4.BB3_crit_edge: ; preds = %BB4 +; CHECK-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 %5) +; CHECK-NEXT: br label %BB3 +; CHECK: BB3: ; preds = %BB4.BB3_crit_edge, %BB1 +; CHECK-NEXT: br label %BB1 +; +BB: + br label %BB1 + +BB1: + br i1 %0, label %BB3, label %BB2 + +BB2: + br label %BB4 + +BB4: + br i1 %1, label %BB3, label %BB4 + +BB3: + br label %BB1 +}