summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/NewGVN.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/NewGVN.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/NewGVN.cpp54
1 files changed, 38 insertions, 16 deletions
diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp
index e67cd1f2818..594f6771c8b 100644
--- a/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -213,6 +213,11 @@ class NewGVN : public FunctionPass {
ArrayRecycler<Value *> ArgRecycler;
// Congruence class info.
+
+ // This class is called INITIAL in the paper. It is the class everything
+ // startsout in, and represents any value. Being an optimistic analysis,
+ // anything in the INITIAL class has the value TOP, which is indeterminate and
+ // equivalent to everything.
CongruenceClass *InitialClass;
std::vector<CongruenceClass *> CongruenceClasses;
unsigned NextCongruenceNum;
@@ -691,8 +696,15 @@ const CallExpression *NewGVN::createCallExpression(CallInst *CI,
// return it. Otherwise, return the operand itself.
Value *NewGVN::lookupOperandLeader(Value *V) const {
CongruenceClass *CC = ValueToClass.lookup(V);
- if (CC && (CC != InitialClass))
+ if (CC) {
+ // Everything in INITIAL is represneted by undef, as it can be any value.
+ // We do have to make sure we get the type right though, so we can't set the
+ // RepLeader to undef.
+ if (CC == InitialClass)
+ return UndefValue::get(V->getType());
return CC->RepStoredValue ? CC->RepStoredValue : CC->RepLeader;
+ }
+
return V;
}
@@ -957,9 +969,8 @@ const Expression *NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) {
// expression.
assert(II->getNumArgOperands() == 2 &&
"Expect two args for recognised intrinsics.");
- return createBinaryExpression(Opcode, EI->getType(),
- II->getArgOperand(0),
- II->getArgOperand(1));
+ return createBinaryExpression(
+ Opcode, EI->getType(), II->getArgOperand(0), II->getArgOperand(1));
}
}
}
@@ -1200,7 +1211,7 @@ void NewGVN::moveValueToNewCongruenceClass(Instruction *I,
}
// We don't need to sort members if there is only 1, and we don't care about
- // sorting the initial class because everything either gets out of it or is
+ // sorting the INITIAL class because everything either gets out of it or is
// unreachable.
if (OldClass->Members.size() == 1 || OldClass == InitialClass) {
OldClass->RepLeader = *(OldClass->Members.begin());
@@ -1229,7 +1240,7 @@ void NewGVN::moveValueToNewCongruenceClass(Instruction *I,
void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) {
ValueToExpression[I] = E;
// This is guaranteed to return something, since it will at least find
- // INITIAL.
+ // TOP.
CongruenceClass *IClass = ValueToClass[I];
assert(IClass && "Should have found a IClass");
@@ -1418,8 +1429,7 @@ void NewGVN::processOutgoingEdges(TerminatorInst *TI, BasicBlock *B) {
}
// The algorithm initially places the values of the routine in the INITIAL
-// congruence
-// class. The leader of INITIAL is the undetermined value `TOP`.
+// congruence class. The leader of INITIAL is the undetermined value `TOP`.
// When the algorithm has finished, values still in INITIAL are unreachable.
void NewGVN::initializeCongruenceClasses(Function &F) {
// FIXME now i can't remember why this is 2
@@ -1433,8 +1443,11 @@ void NewGVN::initializeCongruenceClasses(Function &F) {
MemoryAccessToClass[MP] = InitialClass;
for (auto &I : B) {
- InitialValues.insert(&I);
- ValueToClass[&I] = InitialClass;
+ // Don't insert void terminators into the class
+ if (!isa<TerminatorInst>(I) || !I.getType()->isVoidTy()) {
+ InitialValues.insert(&I);
+ ValueToClass[&I] = InitialClass;
+ }
// All memory accesses are equivalent to live on entry to start. They must
// be initialized to something so that initial changes are noticed. For
// the maximal answer, we initialize them all to be the same as
@@ -1585,7 +1598,8 @@ void NewGVN::valueNumberInstruction(Instruction *I) {
performCongruenceFinding(I, Symbolized);
} else {
// Handle terminators that return values. All of them produce values we
- // don't currently understand.
+ // don't currently understand. We don't place non-value producing
+ // terminators in a class.
if (!I->getType()->isVoidTy()) {
auto *Symbolized = createUnknownExpression(I);
performCongruenceFinding(I, Symbolized);
@@ -2198,12 +2212,20 @@ bool NewGVN::eliminateInstructions(Function &F) {
// dead store elimination.
SmallVector<ValueDFS, 8> PossibleDeadStores;
- // FIXME: We should eventually be able to replace everything still
- // in the initial class with undef, as they should be unreachable.
- // Right now, initial still contains some things we skip value
- // numbering of (UNREACHABLE's, for example).
- if (CC == InitialClass || CC->Dead)
+ if (CC->Dead)
continue;
+ // Everything still in the INITIAL class is unreachable or dead.
+ if (CC == InitialClass) {
+#ifndef NDEBUG
+ for (auto M : CC->Members)
+ assert((!ReachableBlocks.count(cast<Instruction>(M)->getParent()) ||
+ InstructionsToErase.count(cast<Instruction>(M))) &&
+ "Everything in INITIAL should be unreachable or dead at this "
+ "point");
+#endif
+ continue;
+ }
+
assert(CC->RepLeader && "We should have had a leader");
// If this is a leader that is always available, and it's a
OpenPOWER on IntegriCloud