Index: llvm/lib/Transforms/Scalar/LoopFuse.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopFuse.cpp +++ llvm/lib/Transforms/Scalar/LoopFuse.cpp @@ -415,9 +415,29 @@ return true; } - // If LHS does not dominate RHS and RHS does not dominate LHS then there is - // no dominance relationship between the two FusionCandidates. Thus, they - // should not be in the same set together. + // If two FusionCandidates are in the same level of dominator tree, + // they will not dominate each other, but may still be control flow + // equivalent. To sort those FusionCandidates, nonStrictlyPostDominate() + // function is needed. + bool wrongOrder = + nonStrictlyPostDominate(LHSEntryBlock, RHSEntryBlock, DT, LHS.PDT); + bool rightOrder = + nonStrictlyPostDominate(RHSEntryBlock, LHSEntryBlock, DT, LHS.PDT); + if (wrongOrder && rightOrder) { + // If common predecessor of LHS and RHS post dominates both + // FusionCandidates then, Order of FusionCandidate can be + // identified by its level in post dominator tree. + DomTreeNode *LNode = LHS.PDT->getNode(LHSEntryBlock); + DomTreeNode *RNode = LHS.PDT->getNode(RHSEntryBlock); + return (LNode->getLevel() > RNode->getLevel()); + } else if (wrongOrder) + return false; + else if (rightOrder) + return true; + + // If LHS does not non-strict Postdominate RHS and RHS does not non-strict + // Postdominate LHS then, there is no dominance relationship between the + // two FusionCandidates. Thus, they should not be in the same set together. llvm_unreachable( "No dominance relationship between these fusion candidates!"); } Index: llvm/test/Transforms/LoopFusion/undominated_loops.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/LoopFusion/undominated_loops.ll @@ -0,0 +1,45 @@ +; RUN: opt -S -passes=loop-fusion -debug-only=loop-fusion -disable-output < %s 2>&1 | FileCheck %s + +define void @test_long_1() { +; CHECK: Performing Loop Fusion on function test_long_1 +; CHECK: Fusion Candidates: +; CHECK: *** Fusion Candidate Set *** +; CHECK: entry.vector.body_crit_edge +; CHECK: for.cond.cleanup5.vector.body23_crit_edge +; CHECK: **************************** +; CHECK: Loop Fusion complete +entry: + br i1 true, label %for.body6.preheader, label %entry.vector.body_crit_edge + +entry.vector.body_crit_edge: ; preds = %entry + br label %vector.body + +vector.body: ; preds = %entry.vector.body_crit_edge, %vector.body + br i1 true, label %vector.body.for.cond.cleanup5_crit_edge, label %vector.body + +vector.body.for.cond.cleanup5_crit_edge: ; preds = %vector.body + br label %for.cond.cleanup5 + +for.body6.preheader: ; preds = %entry + br label %for.cond.cleanup5 + +for.cond.cleanup5: ; preds = %vector.body.for.cond.cleanup5_crit_edge, %for.body6.preheader + br i1 true, label %for.body17.preheader, label %for.cond.cleanup5.vector.body23_crit_edge + +for.cond.cleanup5.vector.body23_crit_edge: ; preds = %for.cond.cleanup5 + br label %vector.body23 + +vector.body23: ; preds = %for.cond.cleanup5.vector.body23_crit_edge, %vector.body23 + br i1 true, label %middle.block15, label %vector.body23 + +middle.block15: ; preds = %vector.body23 + unreachable + +for.body17.preheader: ; preds = %for.cond.cleanup5 + unreachable + +; uselistorder directives + uselistorder label %vector.body, { 1, 0 } + uselistorder label %for.cond.cleanup5, { 1, 0 } + uselistorder label %vector.body23, { 1, 0 } +}