Reland "[DomTree] Assert non-null block for pre-dom tree" (#187005)
Reland #186790 with fix for SCEV. A loop can have more than one latch, in which case getLoopLatch returns null.
This commit is contained in:
parent
0f1ec17f29
commit
43ec60eee5
@ -384,11 +384,15 @@ protected:
|
||||
private:
|
||||
std::optional<unsigned> getNodeIndex(const NodeT *BB) const {
|
||||
if constexpr (GraphHasNodeNumbers<NodeT *>) {
|
||||
// BB can be nullptr, map nullptr to index 0.
|
||||
assert(BlockNumberEpoch ==
|
||||
GraphTraits<ParentPtr>::getNumberEpoch(Parent) &&
|
||||
"dominator tree used with outdated block numbers");
|
||||
return BB ? GraphTraits<const NodeT *>::getNumber(BB) + 1 : 0;
|
||||
if constexpr (IsPostDom) {
|
||||
if (!BB)
|
||||
return 0; // BB may be nullptr for post-dominator tree, map to 0.
|
||||
} else
|
||||
assert(BB && "dominator tree block must be non-null");
|
||||
return GraphTraits<const NodeT *>::getNumber(BB) + 1;
|
||||
} else {
|
||||
if (auto It = NodeNumberMap.find(BB); It != NodeNumberMap.end())
|
||||
return It->second;
|
||||
|
||||
@ -12463,9 +12463,10 @@ bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart(
|
||||
// Make sure AR varies in the context block.
|
||||
if (auto *AR = dyn_cast<SCEVAddRecExpr>(FoundLHS)) {
|
||||
const Loop *L = AR->getLoop();
|
||||
const auto *Latch = L->getLoopLatch();
|
||||
// Make sure that context belongs to the loop and executes on 1st iteration
|
||||
// (if it ever executes at all).
|
||||
if (!L->contains(ContextBB) || !DT.dominates(ContextBB, L->getLoopLatch()))
|
||||
if (!L->contains(ContextBB) || !Latch || !DT.dominates(ContextBB, Latch))
|
||||
return false;
|
||||
if (!isAvailableAtLoopEntry(FoundRHS, AR->getLoop()))
|
||||
return false;
|
||||
@ -12474,9 +12475,10 @@ bool ScalarEvolution::isImpliedCondOperandsViaAddRecStart(
|
||||
|
||||
if (auto *AR = dyn_cast<SCEVAddRecExpr>(FoundRHS)) {
|
||||
const Loop *L = AR->getLoop();
|
||||
const auto *Latch = L->getLoopLatch();
|
||||
// Make sure that context belongs to the loop and executes on 1st iteration
|
||||
// (if it ever executes at all).
|
||||
if (!L->contains(ContextBB) || !DT.dominates(ContextBB, L->getLoopLatch()))
|
||||
if (!L->contains(ContextBB) || !Latch || !DT.dominates(ContextBB, Latch))
|
||||
return false;
|
||||
if (!isAvailableAtLoopEntry(FoundLHS, AR->getLoop()))
|
||||
return false;
|
||||
|
||||
@ -28343,6 +28343,8 @@ bool SLPVectorizerPass::vectorizeGEPIndices(BasicBlock *BB, BoUpSLP &R) {
|
||||
const SCEV *SCEVI = SE->getSCEV(GEPList[I]);
|
||||
for (int J = I + 1; J < E && Candidates.size() > 1; ++J) {
|
||||
auto *GEPJ = GEPList[J];
|
||||
if (!Candidates.count(GEPJ))
|
||||
continue;
|
||||
const SCEV *SCEVJ = SE->getSCEV(GEPList[J]);
|
||||
if (isa<SCEVConstant>(SE->getMinusSCEV(SCEVI, SCEVJ))) {
|
||||
Candidates.remove(GEPI);
|
||||
|
||||
58
llvm/test/Analysis/ScalarEvolution/two-loop-latches.ll
Normal file
58
llvm/test/Analysis/ScalarEvolution/two-loop-latches.ll
Normal file
@ -0,0 +1,58 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
|
||||
; RUN: opt -disable-output -passes='print<scalar-evolution>' < %s 2>&1 | FileCheck %s
|
||||
|
||||
; Test where the outermost loop doesn't contain exactly one latch;
|
||||
; ScalarEvolution shouldn't crash in this case.
|
||||
|
||||
define void @f(ptr %a0) {
|
||||
; CHECK-LABEL: 'f'
|
||||
; CHECK-NEXT: Classifying expressions for: @f
|
||||
; CHECK-NEXT: %phi1 = phi ptr [ null, %entry ], [ %inc, %b3 ], [ %inc, %b4 ]
|
||||
; CHECK-NEXT: --> {null,+,-32}<%b1> U: [0,-31) S: [-9223372036854775808,9223372036854775777) Exits: <<Unknown>> LoopDispositions: { %b1: Computable, %b3: Invariant }
|
||||
; CHECK-NEXT: %inc = getelementptr i8, ptr %phi1, i64 -32
|
||||
; CHECK-NEXT: --> {(-32 + null)<nuw><nsw>,+,-32}<%b1> U: [0,-31) S: [-9223372036854775808,9223372036854775777) Exits: <<Unknown>> LoopDispositions: { %b1: Computable, %b3: Invariant }
|
||||
; CHECK-NEXT: %phi2 = phi ptr [ %a0, %b2 ], [ %inc2, %b5 ]
|
||||
; CHECK-NEXT: --> {%a0,+,1}<%b3> U: full-set S: full-set Exits: ((-1 * (ptrtoint ptr %a0 to i64)) + %a0) LoopDispositions: { %b3: Computable, %b1: Variant }
|
||||
; CHECK-NEXT: %ld1 = load i8, ptr %phi2, align 1
|
||||
; CHECK-NEXT: --> %ld1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %b3: Variant, %b1: Variant }
|
||||
; CHECK-NEXT: %ld2 = load i8, ptr null, align 1
|
||||
; CHECK-NEXT: --> %ld2 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %b3: Variant, %b1: Variant }
|
||||
; CHECK-NEXT: %inc2 = getelementptr i8, ptr %phi2, i64 1
|
||||
; CHECK-NEXT: --> {(1 + %a0),+,1}<%b3> U: full-set S: full-set Exits: (1 + (-1 * (ptrtoint ptr %a0 to i64)) + %a0) LoopDispositions: { %b3: Computable, %b1: Variant }
|
||||
; CHECK-NEXT: Determining loop execution counts for: @f
|
||||
; CHECK-NEXT: Loop %b3: <multiple exits> backedge-taken count is (-1 * (ptrtoint ptr %a0 to i64))
|
||||
; CHECK-NEXT: exit count for b3: (-1 * (ptrtoint ptr %a0 to i64))
|
||||
; CHECK-NEXT: exit count for b4: ***COULDNOTCOMPUTE***
|
||||
; CHECK-NEXT: Loop %b3: constant max backedge-taken count is i64 -1
|
||||
; CHECK-NEXT: Loop %b3: symbolic max backedge-taken count is (-1 * (ptrtoint ptr %a0 to i64))
|
||||
; CHECK-NEXT: symbolic max exit count for b3: (-1 * (ptrtoint ptr %a0 to i64))
|
||||
; CHECK-NEXT: symbolic max exit count for b4: ***COULDNOTCOMPUTE***
|
||||
; CHECK-NEXT: Loop %b3: Trip multiple is 1
|
||||
; CHECK-NEXT: Loop %b1: Unpredictable backedge-taken count.
|
||||
; CHECK-NEXT: Loop %b1: Unpredictable constant max backedge-taken count.
|
||||
; CHECK-NEXT: Loop %b1: Unpredictable symbolic max backedge-taken count.
|
||||
;
|
||||
entry:
|
||||
br label %b1
|
||||
b1:
|
||||
%phi1 = phi ptr [ null, %entry ], [ %inc, %b3 ], [ %inc, %b4 ]
|
||||
%cmp1 = icmp eq ptr %phi1, null
|
||||
br i1 %cmp1, label %ret, label %b2
|
||||
b2:
|
||||
%inc = getelementptr i8, ptr %phi1, i64 -32
|
||||
br label %b3
|
||||
b3:
|
||||
%phi2 = phi ptr [ %a0, %b2 ], [ %inc2, %b5 ]
|
||||
%cmp2 = icmp eq ptr %phi2, null
|
||||
br i1 %cmp2, label %b1, label %b4
|
||||
b4:
|
||||
%ld1 = load i8, ptr %phi2, align 1
|
||||
%ld2 = load i8, ptr null, align 1
|
||||
%cmp3 = icmp slt i8 %ld1, %ld2
|
||||
br i1 false, label %b1, label %b5
|
||||
b5:
|
||||
%inc2 = getelementptr i8, ptr %phi2, i64 1
|
||||
br label %b3
|
||||
ret:
|
||||
ret void
|
||||
}
|
||||
@ -637,7 +637,7 @@ void ScopBuilder::propagateDomainConstraintsToRegionExit(
|
||||
auto *RI = scop->getRegion().getRegionInfo();
|
||||
auto *BBReg = RI ? RI->getRegionFor(BB) : nullptr;
|
||||
auto *ExitBB = BBReg ? BBReg->getExit() : nullptr;
|
||||
if (!BBReg || BBReg->getEntry() != BB || !scop->contains(ExitBB))
|
||||
if (!BBReg || BBReg->getEntry() != BB || !ExitBB || !scop->contains(ExitBB))
|
||||
return;
|
||||
|
||||
// Do not propagate the domain if there is a loop backedge inside the region
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user