/// Comparison functor to sort two Control Flow Equivalent fusion candidates
/// into dominance order.
/// If LHS dominates RHS and RHS post-dominates LHS, return true;
- /// IF RHS dominates LHS and LHS post-dominates RHS, return false;
+ /// If RHS dominates LHS and LHS post-dominates RHS, return false;
+ /// If both LHS and RHS are not dominating each other then, non-strictly
+ /// post dominate check will decide the order of candidates. If RHS
+ /// non-strictly post dominates LHS then, return true. If LHS non-strictly
+ /// post dominates RHS then, return false. If both are non-strictly post
+ /// dominate each other then, level in the post dominator tree will decide
+ /// the order of candidates.
bool operator()(const FusionCandidate &LHS,
const FusionCandidate &RHS) const {
const DominatorTree *DT = &(LHS.DT);
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!");
}
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=loop-fusion -S | FileCheck %s
+define void @test_long_1() {
+; CHECK-LABEL: @test_long_1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 true, label [[FOR_BODY6_PREHEADER:%.*]], label [[ENTRY_VECTOR_BODY_CRIT_EDGE:%.*]]
+; CHECK: entry.vector.body_crit_edge:
+; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
+; CHECK: vector.body:
+; CHECK-NEXT: br i1 true, label [[VECTOR_BODY_FOR_COND_CLEANUP5_CRIT_EDGE:%.*]], label [[VECTOR_BODY]]
+; CHECK: vector.body.for.cond.cleanup5_crit_edge:
+; CHECK-NEXT: br label [[FOR_COND_CLEANUP5:%.*]]
+; CHECK: for.body6.preheader:
+; CHECK-NEXT: br label [[FOR_COND_CLEANUP5]]
+; CHECK: for.cond.cleanup5:
+; CHECK-NEXT: br i1 true, label [[FOR_BODY17_PREHEADER:%.*]], label [[FOR_COND_CLEANUP5_VECTOR_BODY23_CRIT_EDGE:%.*]]
+; CHECK: for.cond.cleanup5.vector.body23_crit_edge:
+; CHECK-NEXT: br label [[VECTOR_BODY23:%.*]]
+; CHECK: vector.body23:
+; CHECK-NEXT: br i1 true, label [[MIDDLE_BLOCK15:%.*]], label [[VECTOR_BODY23]]
+; CHECK: middle.block15:
+; CHECK-NEXT: br label [[ENTRY_VECTOR_BODY_CRIT_EDGE]]
+; CHECK: for.body17.preheader:
+; CHECK-NEXT: unreachable
+;
+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
+ br label %entry.vector.body_crit_edge
+
+for.body17.preheader: ; preds = %for.cond.cleanup5
+ unreachable
+}