Index: include/llvm/Transforms/Utils/Local.h =================================================================== --- include/llvm/Transforms/Utils/Local.h +++ include/llvm/Transforms/Utils/Local.h @@ -51,6 +51,9 @@ typedef SmallVector DbgValueList; +typedef DenseMap> + LoopHeaderList; + //===----------------------------------------------------------------------===// // Local constant propagation. // @@ -138,7 +141,7 @@ /// eliminate. bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, unsigned BonusInstThreshold, AssumptionCache *AC = nullptr, - SmallPtrSetImpl *LoopHeaders = nullptr); + LoopHeaderList *LoopHeaders = nullptr); /// This function is used to flatten a CFG. For example, it uses parallel-and /// and parallel-or mode to collapse if-conditions and merge if-regions with Index: lib/Transforms/Scalar/SimplifyCFGPass.cpp =================================================================== --- lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -136,9 +136,10 @@ SmallVector, 32> Edges; FindFunctionBackedges(F, Edges); - SmallPtrSet LoopHeaders; + LoopHeaderList LoopHeaders; + for (unsigned i = 0, e = Edges.size(); i != e; ++i) - LoopHeaders.insert(const_cast(Edges[i].second)); + LoopHeaders[Edges[i].second].insert(Edges[i].first); while (LocalChange) { LocalChange = false; Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -169,7 +169,7 @@ const DataLayout &DL; unsigned BonusInstThreshold; AssumptionCache *AC; - SmallPtrSetImpl *LoopHeaders; + LoopHeaderList *LoopHeaders; Value *isValueEqualityComparison(TerminatorInst *TI); BasicBlock *GetValueEqualityComparisonCases( TerminatorInst *TI, std::vector &Cases); @@ -193,7 +193,7 @@ public: SimplifyCFGOpt(const TargetTransformInfo &TTI, const DataLayout &DL, unsigned BonusInstThreshold, AssumptionCache *AC, - SmallPtrSetImpl *LoopHeaders) + LoopHeaderList *LoopHeaders) : TTI(TTI), DL(DL), BonusInstThreshold(BonusInstThreshold), AC(AC), LoopHeaders(LoopHeaders) {} @@ -1680,7 +1680,8 @@ /// check whether BBEnd has only two predecessors and the other predecessor /// ends with an unconditional branch. If it is true, sink any common code /// in the two predecessors to BBEnd. -static bool SinkThenElseCodeToEnd(BranchInst *BI1) { +static bool SinkThenElseCodeToEnd(BranchInst *BI1, + LoopHeaderList *LoopHeaders) { assert(BI1->isUnconditional()); BasicBlock *BBEnd = BI1->getSuccessor(0); @@ -1795,6 +1796,26 @@ DEBUG(dbgs() << "SINK: Splitting edge\n"); // We have a conditional edge and we're going to sink some instructions. // Insert a new block postdominating all blocks we're going to sink from. + + if (LoopHeaders && LoopHeaders->count(BI1->getSuccessor(0))) { + // If we are handling a loop header and both backedges and non-backedges + // are hooked to the new block, this will make the loop irreduciable + // because the new block is not dominated by the loop header. In such + // case, we should not split it to keep it as a valid loop. + bool HasBackedge = false; + bool HasNonBackedge = false; + SmallPtrSet &BackEdges = + (*LoopHeaders)[BI1->getSuccessor(0)]; + for (auto PredBB : UnconditionalPreds) { + if (BackEdges.count(PredBB)) + HasBackedge = true; + else + HasNonBackedge = true; + if (HasNonBackedge && HasBackedge) + return false; + } + } + if (!SplitBlockPredecessors(BI1->getSuccessor(0), UnconditionalPreds, ".sink.split")) // Edges couldn't be split. @@ -5691,7 +5712,7 @@ IRBuilder<> &Builder) { BasicBlock *BB = BI->getParent(); - if (SinkCommon && SinkThenElseCodeToEnd(BI)) + if (SinkCommon && SinkThenElseCodeToEnd(BI, LoopHeaders)) return true; // If the Terminator is the only non-phi instruction, simplify the block. @@ -6022,7 +6043,7 @@ /// bool llvm::SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, unsigned BonusInstThreshold, AssumptionCache *AC, - SmallPtrSetImpl *LoopHeaders) { + LoopHeaderList *LoopHeaders) { return SimplifyCFGOpt(TTI, BB->getModule()->getDataLayout(), BonusInstThreshold, AC, LoopHeaders) .run(BB); Index: test/Transforms/SimplifyCFG/sink-common-code.ll =================================================================== --- test/Transforms/SimplifyCFG/sink-common-code.ll +++ test/Transforms/SimplifyCFG/sink-common-code.ll @@ -792,6 +792,40 @@ ; CHECK: call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8) ; CHECK: call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6) +; Check that simplifycfg doesn't transform the loop (%loop.header) into an irreduciable loop. + +define zeroext i1 @test_keeploop(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks, i8* %p) { +entry: + br i1 %flag, label %if.then, label %loop.header + +if.then: + %cmp = icmp uge i32 %blksA, %nblks + %frombool1 = zext i1 %cmp to i8 + store i8 %frombool1, i8* %p + br label %loop.header + +loop.header: + %c = call i1 @f2() + br i1 %c, label %loop.inc, label %loop.exit + +loop.inc: + %add = add i32 %nblks, %blksB + %cmp2 = icmp ule i32 %add, %blksA + %frombool3 = zext i1 %cmp2 to i8 + store i8 %frombool3, i8* %p + br label %loop.header + +loop.exit: + ret i1 true +} +declare i1 @f2() + +; CHECK-LABEL: @test_keeploop +; CHECK-LABE: if.then: +; CHECK: br label %loop.header +; CHECK-LABE: loop.inc: +; CHECK: br label %loop.header + declare i32 @call_target() define void @test_operand_bundles(i1 %cond, i32* %ptr) {