mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 14:10:41 +00:00
Make GVN's propagateEquality non-recursive. No intended functionality change.
The modifications are a lot more trivial than they appear to be in the diff! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154174 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f85cb768fe
commit
a28bd85aa9
@ -1974,112 +1974,119 @@ unsigned GVN::replaceAllDominatedUsesWith(Value *From, Value *To,
|
|||||||
/// dominated by 'Root'. Exploit this, for example by replacing 'LHS' with
|
/// dominated by 'Root'. Exploit this, for example by replacing 'LHS' with
|
||||||
/// 'RHS' everywhere in the scope. Returns whether a change was made.
|
/// 'RHS' everywhere in the scope. Returns whether a change was made.
|
||||||
bool GVN::propagateEquality(Value *LHS, Value *RHS, BasicBlock *Root) {
|
bool GVN::propagateEquality(Value *LHS, Value *RHS, BasicBlock *Root) {
|
||||||
if (LHS == RHS) return false;
|
SmallVector<std::pair<Value*, Value*>, 4> Worklist;
|
||||||
assert(LHS->getType() == RHS->getType() && "Equal but types differ!");
|
Worklist.push_back(std::make_pair(LHS, RHS));
|
||||||
|
|
||||||
// Don't try to propagate equalities between constants.
|
|
||||||
if (isa<Constant>(LHS) && isa<Constant>(RHS))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Prefer a constant on the right-hand side, or an Argument if no constants.
|
|
||||||
if (isa<Constant>(LHS) || (isa<Argument>(LHS) && !isa<Constant>(RHS)))
|
|
||||||
std::swap(LHS, RHS);
|
|
||||||
assert((isa<Argument>(LHS) || isa<Instruction>(LHS)) && "Unexpected value!");
|
|
||||||
|
|
||||||
// If there is no obvious reason to prefer the left-hand side over the right-
|
|
||||||
// hand side, ensure the longest lived term is on the right-hand side, so the
|
|
||||||
// shortest lived term will be replaced by the longest lived. This tends to
|
|
||||||
// expose more simplifications.
|
|
||||||
uint32_t LVN = VN.lookup_or_add(LHS);
|
|
||||||
if ((isa<Argument>(LHS) && isa<Argument>(RHS)) ||
|
|
||||||
(isa<Instruction>(LHS) && isa<Instruction>(RHS))) {
|
|
||||||
// Move the 'oldest' value to the right-hand side, using the value number as
|
|
||||||
// a proxy for age.
|
|
||||||
uint32_t RVN = VN.lookup_or_add(RHS);
|
|
||||||
if (LVN < RVN) {
|
|
||||||
std::swap(LHS, RHS);
|
|
||||||
LVN = RVN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert((!isa<Instruction>(RHS) ||
|
|
||||||
DT->properlyDominates(cast<Instruction>(RHS)->getParent(), Root)) &&
|
|
||||||
"Instruction doesn't dominate scope!");
|
|
||||||
|
|
||||||
// If value numbering later deduces that an instruction in the scope is equal
|
|
||||||
// to 'LHS' then ensure it will be turned into 'RHS'.
|
|
||||||
addToLeaderTable(LVN, RHS, Root);
|
|
||||||
|
|
||||||
// Replace all occurrences of 'LHS' with 'RHS' everywhere in the scope. As
|
|
||||||
// LHS always has at least one use that is not dominated by Root, this will
|
|
||||||
// never do anything if LHS has only one use.
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
if (!LHS->hasOneUse()) {
|
|
||||||
unsigned NumReplacements = replaceAllDominatedUsesWith(LHS, RHS, Root);
|
|
||||||
Changed |= NumReplacements > 0;
|
|
||||||
NumGVNEqProp += NumReplacements;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now try to deduce additional equalities from this one. For example, if the
|
while (!Worklist.empty()) {
|
||||||
// known equality was "(A != B)" == "false" then it follows that A and B are
|
std::pair<Value*, Value*> Item = Worklist.pop_back_val();
|
||||||
// equal in the scope. Only boolean equalities with an explicit true or false
|
LHS = Item.first; RHS = Item.second;
|
||||||
// RHS are currently supported.
|
|
||||||
if (!RHS->getType()->isIntegerTy(1))
|
|
||||||
// Not a boolean equality - bail out.
|
|
||||||
return Changed;
|
|
||||||
ConstantInt *CI = dyn_cast<ConstantInt>(RHS);
|
|
||||||
if (!CI)
|
|
||||||
// RHS neither 'true' nor 'false' - bail out.
|
|
||||||
return Changed;
|
|
||||||
// Whether RHS equals 'true'. Otherwise it equals 'false'.
|
|
||||||
bool isKnownTrue = CI->isAllOnesValue();
|
|
||||||
bool isKnownFalse = !isKnownTrue;
|
|
||||||
|
|
||||||
// If "A && B" is known true then both A and B are known true. If "A || B"
|
if (LHS == RHS) continue;
|
||||||
// is known false then both A and B are known false.
|
assert(LHS->getType() == RHS->getType() && "Equality but unequal types!");
|
||||||
Value *A, *B;
|
|
||||||
if ((isKnownTrue && match(LHS, m_And(m_Value(A), m_Value(B)))) ||
|
|
||||||
(isKnownFalse && match(LHS, m_Or(m_Value(A), m_Value(B))))) {
|
|
||||||
Changed |= propagateEquality(A, RHS, Root);
|
|
||||||
Changed |= propagateEquality(B, RHS, Root);
|
|
||||||
return Changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are propagating an equality like "(A == B)" == "true" then also
|
// Don't try to propagate equalities between constants.
|
||||||
// propagate the equality A == B. When propagating a comparison such as
|
if (isa<Constant>(LHS) && isa<Constant>(RHS)) continue;
|
||||||
// "(A >= B)" == "true", replace all instances of "A < B" with "false".
|
|
||||||
if (ICmpInst *Cmp = dyn_cast<ICmpInst>(LHS)) {
|
|
||||||
Value *Op0 = Cmp->getOperand(0), *Op1 = Cmp->getOperand(1);
|
|
||||||
|
|
||||||
// If "A == B" is known true, or "A != B" is known false, then replace
|
// Prefer a constant on the right-hand side, or an Argument if no constants.
|
||||||
// A with B everywhere in the scope.
|
if (isa<Constant>(LHS) || (isa<Argument>(LHS) && !isa<Constant>(RHS)))
|
||||||
if ((isKnownTrue && Cmp->getPredicate() == CmpInst::ICMP_EQ) ||
|
std::swap(LHS, RHS);
|
||||||
(isKnownFalse && Cmp->getPredicate() == CmpInst::ICMP_NE))
|
assert((isa<Argument>(LHS) || isa<Instruction>(LHS)) && "Unexpected value!");
|
||||||
Changed |= propagateEquality(Op0, Op1, Root);
|
|
||||||
|
|
||||||
// If "A >= B" is known true, replace "A < B" with false everywhere.
|
// If there is no obvious reason to prefer the left-hand side over the right-
|
||||||
CmpInst::Predicate NotPred = Cmp->getInversePredicate();
|
// hand side, ensure the longest lived term is on the right-hand side, so the
|
||||||
Constant *NotVal = ConstantInt::get(Cmp->getType(), isKnownFalse);
|
// shortest lived term will be replaced by the longest lived. This tends to
|
||||||
// Since we don't have the instruction "A < B" immediately to hand, work out
|
// expose more simplifications.
|
||||||
// the value number that it would have and use that to find an appropriate
|
uint32_t LVN = VN.lookup_or_add(LHS);
|
||||||
// instruction (if any).
|
if ((isa<Argument>(LHS) && isa<Argument>(RHS)) ||
|
||||||
uint32_t NextNum = VN.getNextUnusedValueNumber();
|
(isa<Instruction>(LHS) && isa<Instruction>(RHS))) {
|
||||||
uint32_t Num = VN.lookup_or_add_cmp(Cmp->getOpcode(), NotPred, Op0, Op1);
|
// Move the 'oldest' value to the right-hand side, using the value number as
|
||||||
// If the number we were assigned was brand new then there is no point in
|
// a proxy for age.
|
||||||
// looking for an instruction realizing it: there cannot be one!
|
uint32_t RVN = VN.lookup_or_add(RHS);
|
||||||
if (Num < NextNum) {
|
if (LVN < RVN) {
|
||||||
Value *NotCmp = findLeader(Root, Num);
|
std::swap(LHS, RHS);
|
||||||
if (NotCmp && isa<Instruction>(NotCmp)) {
|
LVN = RVN;
|
||||||
unsigned NumReplacements =
|
|
||||||
replaceAllDominatedUsesWith(NotCmp, NotVal, Root);
|
|
||||||
Changed |= NumReplacements > 0;
|
|
||||||
NumGVNEqProp += NumReplacements;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ensure that any instruction in scope that gets the "A < B" value number
|
assert((!isa<Instruction>(RHS) ||
|
||||||
// is replaced with false.
|
DT->properlyDominates(cast<Instruction>(RHS)->getParent(), Root)) &&
|
||||||
addToLeaderTable(Num, NotVal, Root);
|
"Instruction doesn't dominate scope!");
|
||||||
|
|
||||||
return Changed;
|
// If value numbering later deduces that an instruction in the scope is equal
|
||||||
|
// to 'LHS' then ensure it will be turned into 'RHS'.
|
||||||
|
addToLeaderTable(LVN, RHS, Root);
|
||||||
|
|
||||||
|
// Replace all occurrences of 'LHS' with 'RHS' everywhere in the scope. As
|
||||||
|
// LHS always has at least one use that is not dominated by Root, this will
|
||||||
|
// never do anything if LHS has only one use.
|
||||||
|
if (!LHS->hasOneUse()) {
|
||||||
|
unsigned NumReplacements = replaceAllDominatedUsesWith(LHS, RHS, Root);
|
||||||
|
Changed |= NumReplacements > 0;
|
||||||
|
NumGVNEqProp += NumReplacements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now try to deduce additional equalities from this one. For example, if the
|
||||||
|
// known equality was "(A != B)" == "false" then it follows that A and B are
|
||||||
|
// equal in the scope. Only boolean equalities with an explicit true or false
|
||||||
|
// RHS are currently supported.
|
||||||
|
if (!RHS->getType()->isIntegerTy(1))
|
||||||
|
// Not a boolean equality - bail out.
|
||||||
|
continue;
|
||||||
|
ConstantInt *CI = dyn_cast<ConstantInt>(RHS);
|
||||||
|
if (!CI)
|
||||||
|
// RHS neither 'true' nor 'false' - bail out.
|
||||||
|
continue;
|
||||||
|
// Whether RHS equals 'true'. Otherwise it equals 'false'.
|
||||||
|
bool isKnownTrue = CI->isAllOnesValue();
|
||||||
|
bool isKnownFalse = !isKnownTrue;
|
||||||
|
|
||||||
|
// If "A && B" is known true then both A and B are known true. If "A || B"
|
||||||
|
// is known false then both A and B are known false.
|
||||||
|
Value *A, *B;
|
||||||
|
if ((isKnownTrue && match(LHS, m_And(m_Value(A), m_Value(B)))) ||
|
||||||
|
(isKnownFalse && match(LHS, m_Or(m_Value(A), m_Value(B))))) {
|
||||||
|
Worklist.push_back(std::make_pair(A, RHS));
|
||||||
|
Worklist.push_back(std::make_pair(B, RHS));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are propagating an equality like "(A == B)" == "true" then also
|
||||||
|
// propagate the equality A == B. When propagating a comparison such as
|
||||||
|
// "(A >= B)" == "true", replace all instances of "A < B" with "false".
|
||||||
|
if (ICmpInst *Cmp = dyn_cast<ICmpInst>(LHS)) {
|
||||||
|
Value *Op0 = Cmp->getOperand(0), *Op1 = Cmp->getOperand(1);
|
||||||
|
|
||||||
|
// If "A == B" is known true, or "A != B" is known false, then replace
|
||||||
|
// A with B everywhere in the scope.
|
||||||
|
if ((isKnownTrue && Cmp->getPredicate() == CmpInst::ICMP_EQ) ||
|
||||||
|
(isKnownFalse && Cmp->getPredicate() == CmpInst::ICMP_NE))
|
||||||
|
Worklist.push_back(std::make_pair(Op0, Op1));
|
||||||
|
|
||||||
|
// If "A >= B" is known true, replace "A < B" with false everywhere.
|
||||||
|
CmpInst::Predicate NotPred = Cmp->getInversePredicate();
|
||||||
|
Constant *NotVal = ConstantInt::get(Cmp->getType(), isKnownFalse);
|
||||||
|
// Since we don't have the instruction "A < B" immediately to hand, work out
|
||||||
|
// the value number that it would have and use that to find an appropriate
|
||||||
|
// instruction (if any).
|
||||||
|
uint32_t NextNum = VN.getNextUnusedValueNumber();
|
||||||
|
uint32_t Num = VN.lookup_or_add_cmp(Cmp->getOpcode(), NotPred, Op0, Op1);
|
||||||
|
// If the number we were assigned was brand new then there is no point in
|
||||||
|
// looking for an instruction realizing it: there cannot be one!
|
||||||
|
if (Num < NextNum) {
|
||||||
|
Value *NotCmp = findLeader(Root, Num);
|
||||||
|
if (NotCmp && isa<Instruction>(NotCmp)) {
|
||||||
|
unsigned NumReplacements =
|
||||||
|
replaceAllDominatedUsesWith(NotCmp, NotVal, Root);
|
||||||
|
Changed |= NumReplacements > 0;
|
||||||
|
NumGVNEqProp += NumReplacements;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure that any instruction in scope that gets the "A < B" value number
|
||||||
|
// is replaced with false.
|
||||||
|
addToLeaderTable(Num, NotVal, Root);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
|
Loading…
Reference in New Issue
Block a user