forked from OSchip/llvm-project
[SCEV] Split isSCEVExprNeverPoison reasoning explicitly into scope and mustexecute parts [NFC]
Inspired by the needs to D111001 and D109845. The seperation of concerns also amakes it easier to reason about correctness and completeness.
This commit is contained in:
parent
c1e32b3fc0
commit
26223af256
|
@ -1920,6 +1920,16 @@ private:
|
||||||
/// would trigger undefined behavior on overflow.
|
/// would trigger undefined behavior on overflow.
|
||||||
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
|
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
|
||||||
|
|
||||||
|
/// If S trivially defines a scope (without needing to recurse through
|
||||||
|
/// operands), return the first instruction in it. Else, return nullptr.
|
||||||
|
/// (See scope definition rules associated with flag discussion above)
|
||||||
|
const Instruction *getDefinedScopeRoot(const SCEV *S);
|
||||||
|
|
||||||
|
/// Given two instructions in the same function, return true if we can
|
||||||
|
/// prove B must execute given A executes.
|
||||||
|
bool isGuaranteedToTransferExecutionTo(const Instruction *A,
|
||||||
|
const Instruction *B);
|
||||||
|
|
||||||
/// Return true if the SCEV corresponding to \p I is never poison. Proving
|
/// Return true if the SCEV corresponding to \p I is never poison. Proving
|
||||||
/// this is more complex than proving that just \p I is never poison, since
|
/// this is more complex than proving that just \p I is never poison, since
|
||||||
/// SCEV commons expressions across control flow, and you can have cases
|
/// SCEV commons expressions across control flow, and you can have cases
|
||||||
|
|
|
@ -6569,6 +6569,31 @@ SCEV::NoWrapFlags ScalarEvolution::getNoWrapFlagsFromUB(const Value *V) {
|
||||||
return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
|
return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Instruction *ScalarEvolution::getDefinedScopeRoot(const SCEV *S) {
|
||||||
|
if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(S))
|
||||||
|
return &*AddRec->getLoop()->getHeader()->begin();
|
||||||
|
// TODO: add SCEVConstant and SCEVUnknown caxes here
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
isGuaranteedToTransferExecutionToSuccessor(BasicBlock::const_iterator Begin,
|
||||||
|
BasicBlock::const_iterator End) {
|
||||||
|
return llvm::all_of( make_range(Begin, End), [](const Instruction &I) {
|
||||||
|
return isGuaranteedToTransferExecutionToSuccessor(&I);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScalarEvolution::isGuaranteedToTransferExecutionTo(const Instruction *A,
|
||||||
|
const Instruction *B) {
|
||||||
|
if (A->getParent() == B->getParent() &&
|
||||||
|
::isGuaranteedToTransferExecutionToSuccessor(A->getIterator(),
|
||||||
|
B->getIterator()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
|
bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
|
||||||
// Here we check that I is in the header of the innermost loop containing I,
|
// Here we check that I is in the header of the innermost loop containing I,
|
||||||
// since we only deal with instructions in the loop header. The actual loop we
|
// since we only deal with instructions in the loop header. The actual loop we
|
||||||
|
@ -6600,11 +6625,9 @@ bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
|
||||||
// TODO: We can do better here in some cases.
|
// TODO: We can do better here in some cases.
|
||||||
if (!isSCEVable(Op->getType()))
|
if (!isSCEVable(Op->getType()))
|
||||||
return false;
|
return false;
|
||||||
const SCEV *OpS = getSCEV(Op);
|
if (auto *DefI = getDefinedScopeRoot(getSCEV(Op)))
|
||||||
if (auto *AddRecS = dyn_cast<SCEVAddRecExpr>(OpS)) {
|
if (isGuaranteedToTransferExecutionTo(DefI, I))
|
||||||
if (isGuaranteedToExecuteForEveryIteration(I, AddRecS->getLoop()))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue