mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
Try to appease MSVC, NFCI.
This time by lifting the lambda's in `createNodeFromSelectLikePHI` to the file scope. Looks like there are differences in capture rules between clang and MSVC? llvm-svn: 249222
This commit is contained in:
parent
d683063aaa
commit
4572919871
@ -3742,116 +3742,116 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
|
// Checks if the SCEV S is available at BB. S is considered available at BB
|
||||||
const Loop *L = LI.getLoopFor(PN->getParent());
|
// if S can be materialized at BB without introducing a fault.
|
||||||
|
static bool IsAvailableOnEntry(const Loop *L, DominatorTree &DT, const SCEV *S,
|
||||||
|
BasicBlock *BB) {
|
||||||
|
struct CheckAvailable {
|
||||||
|
bool TraversalDone = false;
|
||||||
|
bool Available = true;
|
||||||
|
|
||||||
// Try to match a control flow sequence that branches out at BI and merges
|
const Loop *L = nullptr; // The loop BB is in (can be nullptr)
|
||||||
// back at Merge into a "C ? LHS : RHS" select pattern. Return true on a
|
BasicBlock *BB = nullptr;
|
||||||
// successful match.
|
DominatorTree &DT;
|
||||||
auto BrPHIToSelect = [&](BranchInst *BI, PHINode *Merge, Value *&C,
|
|
||||||
Value *&LHS, Value *&RHS) {
|
|
||||||
C = BI->getCondition();
|
|
||||||
|
|
||||||
BasicBlockEdge LeftEdge(BI->getParent(), BI->getSuccessor(0));
|
CheckAvailable(const Loop *L, BasicBlock *BB, DominatorTree &DT)
|
||||||
BasicBlockEdge RightEdge(BI->getParent(), BI->getSuccessor(1));
|
: L(L), BB(BB), DT(DT) {}
|
||||||
|
|
||||||
if (!LeftEdge.isSingleEdge())
|
bool setUnavailable() {
|
||||||
|
TraversalDone = true;
|
||||||
|
Available = false;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert(RightEdge.isSingleEdge() && "Follows from LeftEdge.isSingleEdge()");
|
|
||||||
|
|
||||||
Use &LeftUse = Merge->getOperandUse(0);
|
|
||||||
Use &RightUse = Merge->getOperandUse(1);
|
|
||||||
|
|
||||||
if (DT.dominates(LeftEdge, LeftUse) && DT.dominates(RightEdge, RightUse)) {
|
|
||||||
LHS = LeftUse;
|
|
||||||
RHS = RightUse;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DT.dominates(LeftEdge, RightUse) && DT.dominates(RightEdge, LeftUse)) {
|
bool follow(const SCEV *S) {
|
||||||
LHS = RightUse;
|
switch (S->getSCEVType()) {
|
||||||
RHS = LeftUse;
|
case scConstant: case scTruncate: case scZeroExtend: case scSignExtend:
|
||||||
|
case scAddExpr: case scMulExpr: case scUMaxExpr: case scSMaxExpr:
|
||||||
|
// These expressions are available if their operand(s) is/are.
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
case scAddRecExpr: {
|
||||||
};
|
// We allow add recurrences that are on the loop BB is in, or some
|
||||||
|
// outer loop. This guarantees availability because the value of the
|
||||||
// Checks if the SCEV S is available at BB. S is considered available at BB
|
// add recurrence at BB is simply the "current" value of the induction
|
||||||
// if S can be materialized at BB without introducing a fault.
|
// variable. We can relax this in the future; for instance an add
|
||||||
auto IsAvailableOnEntry = [&](const SCEV *S, BasicBlock *BB) {
|
// recurrence on a sibling dominating loop is also available at BB.
|
||||||
struct CheckAvailable {
|
const auto *ARLoop = cast<SCEVAddRecExpr>(S)->getLoop();
|
||||||
bool TraversalDone = false;
|
if (L && (ARLoop == L || ARLoop->contains(L)))
|
||||||
bool Available = true;
|
|
||||||
|
|
||||||
const Loop *L = nullptr; // The loop BB is in (can be nullptr)
|
|
||||||
BasicBlock *BB = nullptr;
|
|
||||||
DominatorTree &DT;
|
|
||||||
|
|
||||||
CheckAvailable(const Loop *L, BasicBlock *BB, DominatorTree &DT)
|
|
||||||
: L(L), BB(BB), DT(DT) {}
|
|
||||||
|
|
||||||
bool setUnavailable() {
|
|
||||||
TraversalDone = true;
|
|
||||||
Available = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool follow(const SCEV *S) {
|
|
||||||
switch (S->getSCEVType()) {
|
|
||||||
case scConstant: case scTruncate: case scZeroExtend: case scSignExtend:
|
|
||||||
case scAddExpr: case scMulExpr: case scUMaxExpr: case scSMaxExpr:
|
|
||||||
// These expressions are available if their operand(s) is/are.
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case scAddRecExpr: {
|
return setUnavailable();
|
||||||
// We allow add recurrences that are on the loop BB is in, or some
|
|
||||||
// outer loop. This guarantees availability because the value of the
|
|
||||||
// add recurrence at BB is simply the "current" value of the induction
|
|
||||||
// variable. We can relax this in the future; for instance an add
|
|
||||||
// recurrence on a sibling dominating loop is also available at BB.
|
|
||||||
const auto *ARLoop = cast<SCEVAddRecExpr>(S)->getLoop();
|
|
||||||
if (L && (ARLoop == L || ARLoop->contains(L)))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return setUnavailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
case scUnknown: {
|
|
||||||
// For SCEVUnknown, we check for simple dominance.
|
|
||||||
const auto *SU = cast<SCEVUnknown>(S);
|
|
||||||
Value *V = SU->getValue();
|
|
||||||
|
|
||||||
if (isa<Argument>(V))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (isa<Instruction>(V) &&
|
|
||||||
this->DT.dominates(cast<Instruction>(V), BB))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return setUnavailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
case scUDivExpr:
|
|
||||||
case scCouldNotCompute:
|
|
||||||
// We do not try to smart about these at all.
|
|
||||||
return setUnavailable();
|
|
||||||
}
|
|
||||||
llvm_unreachable("switch should be fully covered!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDone() { return TraversalDone; }
|
case scUnknown: {
|
||||||
};
|
// For SCEVUnknown, we check for simple dominance.
|
||||||
|
const auto *SU = cast<SCEVUnknown>(S);
|
||||||
|
Value *V = SU->getValue();
|
||||||
|
|
||||||
CheckAvailable CA(L, BB, this->DT);
|
if (isa<Argument>(V))
|
||||||
SCEVTraversal<CheckAvailable> ST(CA);
|
return false;
|
||||||
|
|
||||||
ST.visitAll(S);
|
if (isa<Instruction>(V) && DT.dominates(cast<Instruction>(V), BB))
|
||||||
return CA.Available;
|
return false;
|
||||||
|
|
||||||
|
return setUnavailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
case scUDivExpr:
|
||||||
|
case scCouldNotCompute:
|
||||||
|
// We do not try to smart about these at all.
|
||||||
|
return setUnavailable();
|
||||||
|
}
|
||||||
|
llvm_unreachable("switch should be fully covered!");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDone() { return TraversalDone; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CheckAvailable CA(L, BB, DT);
|
||||||
|
SCEVTraversal<CheckAvailable> ST(CA);
|
||||||
|
|
||||||
|
ST.visitAll(S);
|
||||||
|
return CA.Available;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to match a control flow sequence that branches out at BI and merges back
|
||||||
|
// at Merge into a "C ? LHS : RHS" select pattern. Return true on a successful
|
||||||
|
// match.
|
||||||
|
static bool BrPHIToSelect(DominatorTree &DT, BranchInst *BI, PHINode *Merge,
|
||||||
|
Value *&C, Value *&LHS, Value *&RHS) {
|
||||||
|
C = BI->getCondition();
|
||||||
|
|
||||||
|
BasicBlockEdge LeftEdge(BI->getParent(), BI->getSuccessor(0));
|
||||||
|
BasicBlockEdge RightEdge(BI->getParent(), BI->getSuccessor(1));
|
||||||
|
|
||||||
|
if (!LeftEdge.isSingleEdge())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
assert(RightEdge.isSingleEdge() && "Follows from LeftEdge.isSingleEdge()");
|
||||||
|
|
||||||
|
Use &LeftUse = Merge->getOperandUse(0);
|
||||||
|
Use &RightUse = Merge->getOperandUse(1);
|
||||||
|
|
||||||
|
if (DT.dominates(LeftEdge, LeftUse) && DT.dominates(RightEdge, RightUse)) {
|
||||||
|
LHS = LeftUse;
|
||||||
|
RHS = RightUse;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DT.dominates(LeftEdge, RightUse) && DT.dominates(RightEdge, LeftUse)) {
|
||||||
|
LHS = RightUse;
|
||||||
|
RHS = LeftUse;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
|
||||||
if (PN->getNumIncomingValues() == 2) {
|
if (PN->getNumIncomingValues() == 2) {
|
||||||
|
const Loop *L = LI.getLoopFor(PN->getParent());
|
||||||
|
|
||||||
// Try to match
|
// Try to match
|
||||||
//
|
//
|
||||||
// br %cond, label %left, label %right
|
// br %cond, label %left, label %right
|
||||||
@ -3870,9 +3870,10 @@ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
|
|||||||
auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
|
auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
|
||||||
Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
|
Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
|
||||||
|
|
||||||
if (BI && BI->isConditional() && BrPHIToSelect(BI, PN, Cond, LHS, RHS) &&
|
if (BI && BI->isConditional() &&
|
||||||
IsAvailableOnEntry(getSCEV(LHS), PN->getParent()) &&
|
BrPHIToSelect(DT, BI, PN, Cond, LHS, RHS) &&
|
||||||
IsAvailableOnEntry(getSCEV(RHS), PN->getParent()))
|
IsAvailableOnEntry(L, DT, getSCEV(LHS), PN->getParent()) &&
|
||||||
|
IsAvailableOnEntry(L, DT, getSCEV(RHS), PN->getParent()))
|
||||||
return createNodeForSelectOrPHI(PN, Cond, LHS, RHS);
|
return createNodeForSelectOrPHI(PN, Cond, LHS, RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user