Skip to content

Commit bd045a3

Browse files
momchil-velikovantoniofrighetto
authored andcommitted
[GVN] MemorySSA for GVN: embed the memory state in symbolic expressions
While migrating towards MemorySSA, account for the memory state modeled by MemorySSA by hashing it, when computing the symbolic expressions for the memory operations. Likewise, when phi-translating while walking the CFG for PRE possibilities, see if the value number of an operand may be refined with one of the value from the incoming edges of the MemoryPhi associated to the current phi.
1 parent fc7a1ed commit bd045a3

File tree

2 files changed

+95
-6
lines changed
  • llvm
    • include/llvm/Transforms/Scalar
    • lib/Transforms/Scalar

2 files changed

+95
-6
lines changed

llvm/include/llvm/Transforms/Scalar/GVN.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,18 @@ class GVNPass : public PassInfoMixin<GVNPass> {
172172
// Value number to PHINode mapping. Used for phi-translate in scalarpre.
173173
DenseMap<uint32_t, PHINode *> NumberingPhi;
174174

175+
// Value number to BasicBlock mapping. Used for phi-translate across
176+
// MemoryPhis.
177+
DenseMap<uint32_t, BasicBlock *> NumberingBB;
178+
175179
// Cache for phi-translate in scalarpre.
176180
using PhiTranslateMap =
177181
DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>;
178182
PhiTranslateMap PhiTranslateTable;
179183

180184
AAResults *AA = nullptr;
181185
MemoryDependenceResults *MD = nullptr;
186+
MemorySSA *MSSA = nullptr;
182187
DominatorTree *DT = nullptr;
183188

184189
uint32_t nextValueNumber = 1;
@@ -189,12 +194,14 @@ class GVNPass : public PassInfoMixin<GVNPass> {
189194
Expression createExtractvalueExpr(ExtractValueInst *EI);
190195
Expression createGEPExpr(GetElementPtrInst *GEP);
191196
uint32_t lookupOrAddCall(CallInst *C);
197+
uint32_t lookupOrAddLoadStore(Instruction *I);
192198
uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
193199
uint32_t Num, GVNPass &Gvn);
194200
bool areCallValsEqual(uint32_t Num, uint32_t NewNum, const BasicBlock *Pred,
195201
const BasicBlock *PhiBlock, GVNPass &Gvn);
196202
std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
197203
bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVNPass &Gvn);
204+
void addMemoryStateToExp(Instruction *I, Expression &E);
198205

199206
public:
200207
ValueTable();
@@ -217,6 +224,7 @@ class GVNPass : public PassInfoMixin<GVNPass> {
217224
void setAliasAnalysis(AAResults *A) { AA = A; }
218225
AAResults *getAliasAnalysis() const { return AA; }
219226
void setMemDep(MemoryDependenceResults *M) { MD = M; }
227+
void setMemorySSA(MemorySSA *M) { MSSA = M; }
220228
void setDomTree(DominatorTree *D) { DT = D; }
221229
uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
222230
void verifyRemoved(const Value *) const;

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,27 @@ void GVNPass::ValueTable::add(Value *V, uint32_t num) {
476476
NumberingPhi[num] = PN;
477477
}
478478

479+
// Include the incoming memory state into the hash of the expression for the
480+
// given instruction. If the incoming memory state is:
481+
// * LiveOnEntry, add the value number of the entry block,
482+
// * a MemoryPhi, add the value number of the basic block corresponding to that
483+
// MemoryPhi,
484+
// * a MemoryDef, add the value number of the memory setting instruction.
485+
void GVNPass::ValueTable::addMemoryStateToExp(Instruction *I, Expression &E) {
486+
assert(MSSA && "addMemoryStateToExp should not be called without MemorySSA");
487+
assert(MSSA->getMemoryAccess(I) && "Instruction does not access memory");
488+
MemoryAccess *MA = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(I);
489+
490+
uint32_t N = 0;
491+
if (isa<MemoryPhi>(MA))
492+
N = lookupOrAdd(MA->getBlock());
493+
else if (MSSA->isLiveOnEntryDef(MA))
494+
N = lookupOrAdd(&I->getFunction()->getEntryBlock());
495+
else
496+
N = lookupOrAdd(cast<MemoryDef>(MA)->getMemoryInst());
497+
E.varargs.push_back(N);
498+
}
499+
479500
uint32_t GVNPass::ValueTable::lookupOrAddCall(CallInst *C) {
480501
// FIXME: Currently the calls which may access the thread id may
481502
// be considered as not accessing the memory. But this is
@@ -596,10 +617,37 @@ uint32_t GVNPass::ValueTable::lookupOrAddCall(CallInst *C) {
596617
return v;
597618
}
598619

620+
if (MSSA && AA->onlyReadsMemory(C)) {
621+
Expression exp = createExpr(C);
622+
addMemoryStateToExp(C, exp);
623+
uint32_t e = assignExpNewValueNum(exp).first;
624+
valueNumbering[C] = e;
625+
return e;
626+
}
627+
599628
valueNumbering[C] = nextValueNumber;
600629
return nextValueNumber++;
601630
}
602631

632+
/// Returns the value number for the specified load or store instruction.
633+
uint32_t GVNPass::ValueTable::lookupOrAddLoadStore(Instruction *I) {
634+
if (!MSSA) {
635+
valueNumbering[I] = nextValueNumber;
636+
return nextValueNumber++;
637+
}
638+
639+
Expression E;
640+
E.type = I->getType();
641+
E.opcode = I->getOpcode();
642+
for (Use &Op : I->operands())
643+
E.varargs.push_back(lookupOrAdd(Op));
644+
addMemoryStateToExp(I, E);
645+
646+
uint32_t N = assignExpNewValueNum(E).first;
647+
valueNumbering[I] = N;
648+
return N;
649+
}
650+
603651
/// Returns true if a value number exists for the specified value.
604652
bool GVNPass::ValueTable::exists(Value *V) const {
605653
return valueNumbering.contains(V);
@@ -615,6 +663,8 @@ uint32_t GVNPass::ValueTable::lookupOrAdd(Value *V) {
615663
auto *I = dyn_cast<Instruction>(V);
616664
if (!I) {
617665
valueNumbering[V] = nextValueNumber;
666+
if (MSSA && isa<BasicBlock>(V))
667+
NumberingBB[nextValueNumber] = cast<BasicBlock>(V);
618668
return nextValueNumber++;
619669
}
620670

@@ -674,6 +724,9 @@ uint32_t GVNPass::ValueTable::lookupOrAdd(Value *V) {
674724
valueNumbering[V] = nextValueNumber;
675725
NumberingPhi[nextValueNumber] = cast<PHINode>(V);
676726
return nextValueNumber++;
727+
case Instruction::Load:
728+
case Instruction::Store:
729+
return lookupOrAddLoadStore(I);
677730
default:
678731
valueNumbering[V] = nextValueNumber;
679732
return nextValueNumber++;
@@ -711,6 +764,7 @@ void GVNPass::ValueTable::clear() {
711764
valueNumbering.clear();
712765
expressionNumbering.clear();
713766
NumberingPhi.clear();
767+
NumberingBB.clear();
714768
PhiTranslateTable.clear();
715769
nextValueNumber = 1;
716770
Expressions.clear();
@@ -725,6 +779,8 @@ void GVNPass::ValueTable::erase(Value *V) {
725779
// If V is PHINode, V <--> value number is an one-to-one mapping.
726780
if (isa<PHINode>(V))
727781
NumberingPhi.erase(Num);
782+
else if (isa<BasicBlock>(V))
783+
NumberingBB.erase(Num);
728784
}
729785

730786
/// verifyRemoved - Verify that the value is removed from all internal data
@@ -2294,15 +2350,39 @@ bool GVNPass::ValueTable::areCallValsEqual(uint32_t Num, uint32_t NewNum,
22942350
uint32_t GVNPass::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
22952351
const BasicBlock *PhiBlock,
22962352
uint32_t Num, GVNPass &Gvn) {
2353+
// See if we can refine the value number by looking at the PN incoming value
2354+
// for the given predecessor.
22972355
if (PHINode *PN = NumberingPhi[Num]) {
2298-
for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) {
2299-
if (PN->getParent() == PhiBlock && PN->getIncomingBlock(i) == Pred)
2300-
if (uint32_t TransVal = lookup(PN->getIncomingValue(i), false))
2301-
return TransVal;
2302-
}
2356+
if (PN->getParent() == PhiBlock)
2357+
for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i)
2358+
if (PN->getIncomingBlock(i) == Pred)
2359+
if (uint32_t TransVal = lookup(PN->getIncomingValue(i), false))
2360+
return TransVal;
23032361
return Num;
23042362
}
23052363

2364+
if (BasicBlock *BB = NumberingBB[Num]) {
2365+
assert(MSSA && "NumberingBB is non-empty only when using MemorySSA");
2366+
// Value numbers of basic blocks are used to represent memory state in
2367+
// load/store instructions and read-only function calls when said state is
2368+
// set by a MemoryPhi.
2369+
if (BB != PhiBlock)
2370+
return Num;
2371+
MemoryPhi *MPhi = MSSA->getMemoryAccess(BB);
2372+
for (unsigned i = 0, N = MPhi->getNumIncomingValues(); i != N; ++i) {
2373+
if (MPhi->getIncomingBlock(i) != Pred)
2374+
continue;
2375+
MemoryAccess *MA = MPhi->getIncomingValue(i);
2376+
if (auto *PredPhi = dyn_cast<MemoryPhi>(MA))
2377+
return lookupOrAdd(PredPhi->getBlock());
2378+
if (MSSA->isLiveOnEntryDef(MA))
2379+
return lookupOrAdd(&BB->getParent()->getEntryBlock());
2380+
return lookupOrAdd(cast<MemoryUseOrDef>(MA)->getMemoryInst());
2381+
}
2382+
llvm_unreachable(
2383+
"CFG/MemorySSA mismatch: predecessor not found among incoming blocks");
2384+
}
2385+
23062386
// If there is any value related with Num is defined in a BB other than
23072387
// PhiBlock, it cannot depend on a phi in PhiBlock without going through
23082388
// a backedge. We can do an early exit in that case to save compile time.
@@ -2337,7 +2417,7 @@ uint32_t GVNPass::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
23372417
}
23382418

23392419
if (uint32_t NewNum = expressionNumbering[Exp]) {
2340-
if (Exp.opcode == Instruction::Call && NewNum != Num)
2420+
if (!MSSA && Exp.opcode == Instruction::Call && NewNum != Num)
23412421
return areCallValsEqual(Num, NewNum, Pred, PhiBlock, Gvn) ? NewNum : Num;
23422422
return NewNum;
23432423
}
@@ -2738,6 +2818,7 @@ bool GVNPass::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
27382818
ICF = &ImplicitCFT;
27392819
this->LI = &LI;
27402820
VN.setMemDep(MD);
2821+
VN.setMemorySSA(MSSA);
27412822
ORE = RunORE;
27422823
InvalidBlockRPONumbers = true;
27432824
MemorySSAUpdater Updater(MSSA);

0 commit comments

Comments
 (0)