Pull in r276136 from upstream llvm trunk (by Wei Mi):

Use ValueOffsetPair to enhance value reuse during SCEV expansion.

  In D12090, the ExprValueMap was added to reuse existing value during
  SCEV expansion. However, const folding and sext/zext distribution can
  make the reuse still difficult.

  A simplified case is: suppose we know S1 expands to V1 in
  ExprValueMap, and
    S1 = S2 + C_a
    S3 = S2 + C_b
  where C_a and C_b are different SCEVConstants. Then we'd like to
  expand S3 as V1 - C_a + C_b instead of expanding S2 literally. It is
  helpful when S2 is a complex SCEV expr and S2 has no entry in
  ExprValueMap, which is usually caused by the fact that S3 is
  generated from S1 after const folding.

  In order to do that, we represent ExprValueMap as a mapping from SCEV
  to ValueOffsetPair. We will save both S1->{V1, 0} and S2->{V1, C_a}
  into the ExprValueMap when we create SCEV for V1. When S3 is
  expanded, it will first expand S2 to V1 - C_a because of S2->{V1,
  C_a} in the map, then expand S3 to V1 - C_a + C_b.

  Differential Revision: https://reviews.llvm.org/D21313

This should fix assertion failures when building OpenCV >= 3.1.

PR:		215649
MFC after:	3 days
This commit is contained in:
Dimitry Andric 2017-01-25 17:59:22 +00:00
parent 02dbdb1677
commit 1324fa835c
4 changed files with 103 additions and 36 deletions

View File

@ -495,10 +495,29 @@ namespace llvm {
/// The typedef for ExprValueMap. /// The typedef for ExprValueMap.
/// ///
typedef DenseMap<const SCEV *, SetVector<Value *>> ExprValueMapType; typedef std::pair<Value *, ConstantInt *> ValueOffsetPair;
typedef DenseMap<const SCEV *, SetVector<ValueOffsetPair>> ExprValueMapType;
/// ExprValueMap -- This map records the original values from which /// ExprValueMap -- This map records the original values from which
/// the SCEV expr is generated from. /// the SCEV expr is generated from.
///
/// We want to represent the mapping as SCEV -> ValueOffsetPair instead
/// of SCEV -> Value:
/// Suppose we know S1 expands to V1, and
/// S1 = S2 + C_a
/// S3 = S2 + C_b
/// where C_a and C_b are different SCEVConstants. Then we'd like to
/// expand S3 as V1 - C_a + C_b instead of expanding S2 literally.
/// It is helpful when S2 is a complex SCEV expr.
///
/// In order to do that, we represent ExprValueMap as a mapping from
/// SCEV to ValueOffsetPair. We will save both S1->{V1, 0} and
/// S2->{V1, C_a} into the map when we create SCEV for V1. When S3
/// is expanded, it will first expand S2 to V1 - C_a because of
/// S2->{V1, C_a} in the map, then expand S3 to V1 - C_a + C_b.
///
/// Note: S->{V, Offset} in the ExprValueMap means S can be expanded
/// to V - Offset.
ExprValueMapType ExprValueMap; ExprValueMapType ExprValueMap;
/// The typedef for ValueExprMap. /// The typedef for ValueExprMap.
@ -1181,7 +1200,7 @@ namespace llvm {
bool containsAddRecurrence(const SCEV *S); bool containsAddRecurrence(const SCEV *S);
/// Return the Value set from which the SCEV expr is generated. /// Return the Value set from which the SCEV expr is generated.
SetVector<Value *> *getSCEVValues(const SCEV *S); SetVector<ValueOffsetPair> *getSCEVValues(const SCEV *S);
/// Erase Value from ValueExprMap and ExprValueMap. /// Erase Value from ValueExprMap and ExprValueMap.
void eraseValueFromMap(Value *V); void eraseValueFromMap(Value *V);

View File

@ -325,7 +325,8 @@ namespace llvm {
PointerType *PTy, Type *Ty, Value *V); PointerType *PTy, Type *Ty, Value *V);
/// \brief Find a previous Value in ExprValueMap for expand. /// \brief Find a previous Value in ExprValueMap for expand.
Value *FindValueInExprValueMap(const SCEV *S, const Instruction *InsertPt); ScalarEvolution::ValueOffsetPair
FindValueInExprValueMap(const SCEV *S, const Instruction *InsertPt);
Value *expand(const SCEV *S); Value *expand(const SCEV *S);

View File

@ -3378,8 +3378,28 @@ bool ScalarEvolution::containsAddRecurrence(const SCEV *S) {
return F.FoundOne; return F.FoundOne;
} }
/// Return the Value set from S. /// Try to split a SCEVAddExpr into a pair of {SCEV, ConstantInt}.
SetVector<Value *> *ScalarEvolution::getSCEVValues(const SCEV *S) { /// If \p S is a SCEVAddExpr and is composed of a sub SCEV S' and an
/// offset I, then return {S', I}, else return {\p S, nullptr}.
static std::pair<const SCEV *, ConstantInt *> splitAddExpr(const SCEV *S) {
const auto *Add = dyn_cast<SCEVAddExpr>(S);
if (!Add)
return {S, nullptr};
if (Add->getNumOperands() != 2)
return {S, nullptr};
auto *ConstOp = dyn_cast<SCEVConstant>(Add->getOperand(0));
if (!ConstOp)
return {S, nullptr};
return {Add->getOperand(1), ConstOp->getValue()};
}
/// Return the ValueOffsetPair set for \p S. \p S can be represented
/// by the value and offset from any ValueOffsetPair in the set.
SetVector<ScalarEvolution::ValueOffsetPair> *
ScalarEvolution::getSCEVValues(const SCEV *S) {
ExprValueMapType::iterator SI = ExprValueMap.find_as(S); ExprValueMapType::iterator SI = ExprValueMap.find_as(S);
if (SI == ExprValueMap.end()) if (SI == ExprValueMap.end())
return nullptr; return nullptr;
@ -3387,24 +3407,31 @@ SetVector<Value *> *ScalarEvolution::getSCEVValues(const SCEV *S) {
if (VerifySCEVMap) { if (VerifySCEVMap) {
// Check there is no dangling Value in the set returned. // Check there is no dangling Value in the set returned.
for (const auto &VE : SI->second) for (const auto &VE : SI->second)
assert(ValueExprMap.count(VE)); assert(ValueExprMap.count(VE.first));
} }
#endif #endif
return &SI->second; return &SI->second;
} }
/// Erase Value from ValueExprMap and ExprValueMap. If ValueExprMap.erase(V) is /// Erase Value from ValueExprMap and ExprValueMap. ValueExprMap.erase(V)
/// not used together with forgetMemoizedResults(S), eraseValueFromMap should be /// cannot be used separately. eraseValueFromMap should be used to remove
/// used instead to ensure whenever V->S is removed from ValueExprMap, V is also /// V from ValueExprMap and ExprValueMap at the same time.
/// removed from the set of ExprValueMap[S].
void ScalarEvolution::eraseValueFromMap(Value *V) { void ScalarEvolution::eraseValueFromMap(Value *V) {
ValueExprMapType::iterator I = ValueExprMap.find_as(V); ValueExprMapType::iterator I = ValueExprMap.find_as(V);
if (I != ValueExprMap.end()) { if (I != ValueExprMap.end()) {
const SCEV *S = I->second; const SCEV *S = I->second;
SetVector<Value *> *SV = getSCEVValues(S); // Remove {V, 0} from the set of ExprValueMap[S]
// Remove V from the set of ExprValueMap[S] if (SetVector<ValueOffsetPair> *SV = getSCEVValues(S))
if (SV) SV->remove({V, nullptr});
SV->remove(V);
// Remove {V, Offset} from the set of ExprValueMap[Stripped]
const SCEV *Stripped;
ConstantInt *Offset;
std::tie(Stripped, Offset) = splitAddExpr(S);
if (Offset != nullptr) {
if (SetVector<ValueOffsetPair> *SV = getSCEVValues(Stripped))
SV->remove({V, Offset});
}
ValueExprMap.erase(V); ValueExprMap.erase(V);
} }
} }
@ -3419,11 +3446,26 @@ const SCEV *ScalarEvolution::getSCEV(Value *V) {
S = createSCEV(V); S = createSCEV(V);
// During PHI resolution, it is possible to create two SCEVs for the same // During PHI resolution, it is possible to create two SCEVs for the same
// V, so it is needed to double check whether V->S is inserted into // V, so it is needed to double check whether V->S is inserted into
// ValueExprMap before insert S->V into ExprValueMap. // ValueExprMap before insert S->{V, 0} into ExprValueMap.
std::pair<ValueExprMapType::iterator, bool> Pair = std::pair<ValueExprMapType::iterator, bool> Pair =
ValueExprMap.insert({SCEVCallbackVH(V, this), S}); ValueExprMap.insert({SCEVCallbackVH(V, this), S});
if (Pair.second) if (Pair.second) {
ExprValueMap[S].insert(V); ExprValueMap[S].insert({V, nullptr});
// If S == Stripped + Offset, add Stripped -> {V, Offset} into
// ExprValueMap.
const SCEV *Stripped = S;
ConstantInt *Offset = nullptr;
std::tie(Stripped, Offset) = splitAddExpr(S);
// If stripped is SCEVUnknown, don't bother to save
// Stripped -> {V, offset}. It doesn't simplify and sometimes even
// increase the complexity of the expansion code.
// If V is GetElementPtrInst, don't save Stripped -> {V, offset}
// because it may generate add/sub instead of GEP in SCEV expansion.
if (Offset != nullptr && !isa<SCEVUnknown>(Stripped) &&
!isa<GetElementPtrInst>(V))
ExprValueMap[Stripped].insert({V, Offset});
}
} }
return S; return S;
} }
@ -3436,8 +3478,8 @@ const SCEV *ScalarEvolution::getExistingSCEV(Value *V) {
const SCEV *S = I->second; const SCEV *S = I->second;
if (checkValidity(S)) if (checkValidity(S))
return S; return S;
eraseValueFromMap(V);
forgetMemoizedResults(S); forgetMemoizedResults(S);
ValueExprMap.erase(I);
} }
return nullptr; return nullptr;
} }
@ -3675,8 +3717,8 @@ void ScalarEvolution::forgetSymbolicName(Instruction *PN, const SCEV *SymName) {
if (!isa<PHINode>(I) || if (!isa<PHINode>(I) ||
!isa<SCEVUnknown>(Old) || !isa<SCEVUnknown>(Old) ||
(I != PN && Old == SymName)) { (I != PN && Old == SymName)) {
eraseValueFromMap(It->first);
forgetMemoizedResults(Old); forgetMemoizedResults(Old);
ValueExprMap.erase(It);
} }
} }
@ -4055,7 +4097,7 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
// to create an AddRecExpr for this PHI node. We can not keep this temporary // to create an AddRecExpr for this PHI node. We can not keep this temporary
// as it will prevent later (possibly simpler) SCEV expressions to be added // as it will prevent later (possibly simpler) SCEV expressions to be added
// to the ValueExprMap. // to the ValueExprMap.
ValueExprMap.erase(PN); eraseValueFromMap(PN);
} }
return nullptr; return nullptr;
@ -5435,8 +5477,8 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
// case, createNodeForPHI will perform the necessary updates on its // case, createNodeForPHI will perform the necessary updates on its
// own when it gets to that point. // own when it gets to that point.
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) { if (!isa<PHINode>(I) || !isa<SCEVUnknown>(Old)) {
eraseValueFromMap(It->first);
forgetMemoizedResults(Old); forgetMemoizedResults(Old);
ValueExprMap.erase(It);
} }
if (PHINode *PN = dyn_cast<PHINode>(I)) if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN); ConstantEvolutionLoopExitValue.erase(PN);
@ -5481,8 +5523,8 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
ValueExprMapType::iterator It = ValueExprMapType::iterator It =
ValueExprMap.find_as(static_cast<Value *>(I)); ValueExprMap.find_as(static_cast<Value *>(I));
if (It != ValueExprMap.end()) { if (It != ValueExprMap.end()) {
eraseValueFromMap(It->first);
forgetMemoizedResults(It->second); forgetMemoizedResults(It->second);
ValueExprMap.erase(It);
if (PHINode *PN = dyn_cast<PHINode>(I)) if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN); ConstantEvolutionLoopExitValue.erase(PN);
} }
@ -5515,8 +5557,8 @@ void ScalarEvolution::forgetValue(Value *V) {
ValueExprMapType::iterator It = ValueExprMapType::iterator It =
ValueExprMap.find_as(static_cast<Value *>(I)); ValueExprMap.find_as(static_cast<Value *>(I));
if (It != ValueExprMap.end()) { if (It != ValueExprMap.end()) {
eraseValueFromMap(It->first);
forgetMemoizedResults(It->second); forgetMemoizedResults(It->second);
ValueExprMap.erase(It);
if (PHINode *PN = dyn_cast<PHINode>(I)) if (PHINode *PN = dyn_cast<PHINode>(I))
ConstantEvolutionLoopExitValue.erase(PN); ConstantEvolutionLoopExitValue.erase(PN);
} }

View File

@ -1625,9 +1625,10 @@ Value *SCEVExpander::expandCodeFor(const SCEV *SH, Type *Ty) {
return V; return V;
} }
Value *SCEVExpander::FindValueInExprValueMap(const SCEV *S, ScalarEvolution::ValueOffsetPair
const Instruction *InsertPt) { SCEVExpander::FindValueInExprValueMap(const SCEV *S,
SetVector<Value *> *Set = SE.getSCEVValues(S); const Instruction *InsertPt) {
SetVector<ScalarEvolution::ValueOffsetPair> *Set = SE.getSCEVValues(S);
// If the expansion is not in CanonicalMode, and the SCEV contains any // If the expansion is not in CanonicalMode, and the SCEV contains any
// sub scAddRecExpr type SCEV, it is required to expand the SCEV literally. // sub scAddRecExpr type SCEV, it is required to expand the SCEV literally.
if (CanonicalMode || !SE.containsAddRecurrence(S)) { if (CanonicalMode || !SE.containsAddRecurrence(S)) {
@ -1636,21 +1637,21 @@ Value *SCEVExpander::FindValueInExprValueMap(const SCEV *S,
// Choose a Value from the set which dominates the insertPt. // Choose a Value from the set which dominates the insertPt.
// insertPt should be inside the Value's parent loop so as not to break // insertPt should be inside the Value's parent loop so as not to break
// the LCSSA form. // the LCSSA form.
for (auto const &Ent : *Set) { for (auto const &VOPair : *Set) {
Value *V = VOPair.first;
ConstantInt *Offset = VOPair.second;
Instruction *EntInst = nullptr; Instruction *EntInst = nullptr;
if (Ent && isa<Instruction>(Ent) && if (V && isa<Instruction>(V) && (EntInst = cast<Instruction>(V)) &&
(EntInst = cast<Instruction>(Ent)) && S->getType() == V->getType() &&
S->getType() == Ent->getType() &&
EntInst->getFunction() == InsertPt->getFunction() && EntInst->getFunction() == InsertPt->getFunction() &&
SE.DT.dominates(EntInst, InsertPt) && SE.DT.dominates(EntInst, InsertPt) &&
(SE.LI.getLoopFor(EntInst->getParent()) == nullptr || (SE.LI.getLoopFor(EntInst->getParent()) == nullptr ||
SE.LI.getLoopFor(EntInst->getParent())->contains(InsertPt))) { SE.LI.getLoopFor(EntInst->getParent())->contains(InsertPt)))
return Ent; return {V, Offset};
}
} }
} }
} }
return nullptr; return {nullptr, nullptr};
} }
// The expansion of SCEV will either reuse a previous Value in ExprValueMap, // The expansion of SCEV will either reuse a previous Value in ExprValueMap,
@ -1698,10 +1699,14 @@ Value *SCEVExpander::expand(const SCEV *S) {
Builder.SetInsertPoint(InsertPt); Builder.SetInsertPoint(InsertPt);
// Expand the expression into instructions. // Expand the expression into instructions.
Value *V = FindValueInExprValueMap(S, InsertPt); ScalarEvolution::ValueOffsetPair VO = FindValueInExprValueMap(S, InsertPt);
Value *V = VO.first;
if (!V) if (!V)
V = visit(S); V = visit(S);
else if (VO.second) {
V = Builder.CreateSub(V, VO.second);
}
// Remember the expanded value for this SCEV at this location. // Remember the expanded value for this SCEV at this location.
// //
@ -1914,7 +1919,7 @@ Value *SCEVExpander::findExistingExpansion(const SCEV *S,
// Use expand's logic which is used for reusing a previous Value in // Use expand's logic which is used for reusing a previous Value in
// ExprValueMap. // ExprValueMap.
if (Value *Val = FindValueInExprValueMap(S, At)) if (Value *Val = FindValueInExprValueMap(S, At).first)
return Val; return Val;
// There is potential to make this significantly smarter, but this simple // There is potential to make this significantly smarter, but this simple