DemoteRegToStack.cpp [plain text]
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
using namespace llvm;
AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,
Instruction *AllocaPoint) {
if (I.use_empty()) {
I.eraseFromParent();
return 0;
}
AllocaInst *Slot;
if (AllocaPoint) {
Slot = new AllocaInst(I.getType(), 0,
I.getName()+".reg2mem", AllocaPoint);
} else {
Function *F = I.getParent()->getParent();
Slot = new AllocaInst(I.getType(), 0, I.getName()+".reg2mem",
F->getEntryBlock().begin());
}
while (!I.use_empty()) {
Instruction *U = cast<Instruction>(I.use_back());
if (PHINode *PN = dyn_cast<PHINode>(U)) {
DenseMap<BasicBlock*, Value*> Loads;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (PN->getIncomingValue(i) == &I) {
Value *&V = Loads[PN->getIncomingBlock(i)];
if (V == 0) {
V = new LoadInst(Slot, I.getName()+".reload", VolatileLoads,
PN->getIncomingBlock(i)->getTerminator());
}
PN->setIncomingValue(i, V);
}
} else {
Value *V = new LoadInst(Slot, I.getName()+".reload", VolatileLoads, U);
U->replaceUsesOfWith(&I, V);
}
}
BasicBlock::iterator InsertPt;
if (!isa<TerminatorInst>(I)) {
InsertPt = &I;
++InsertPt;
} else {
InvokeInst &II = cast<InvokeInst>(I);
if (II.getNormalDest()->getSinglePredecessor())
InsertPt = II.getNormalDest()->getFirstInsertionPt();
else {
unsigned SuccNum = GetSuccessorNumber(I.getParent(), II.getNormalDest());
TerminatorInst *TI = &cast<TerminatorInst>(I);
assert (isCriticalEdge(TI, SuccNum) &&
"Expected a critical edge!");
BasicBlock *BB = SplitCriticalEdge(TI, SuccNum);
assert (BB && "Unable to split critical edge.");
InsertPt = BB->getFirstInsertionPt();
}
}
for (; isa<PHINode>(InsertPt) || isa<LandingPadInst>(InsertPt); ++InsertPt)
;
new StoreInst(&I, Slot, InsertPt);
return Slot;
}
AllocaInst *llvm::DemotePHIToStack(PHINode *P, Instruction *AllocaPoint) {
if (P->use_empty()) {
P->eraseFromParent();
return 0;
}
AllocaInst *Slot;
if (AllocaPoint) {
Slot = new AllocaInst(P->getType(), 0,
P->getName()+".reg2mem", AllocaPoint);
} else {
Function *F = P->getParent()->getParent();
Slot = new AllocaInst(P->getType(), 0, P->getName()+".reg2mem",
F->getEntryBlock().begin());
}
for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) {
if (InvokeInst *II = dyn_cast<InvokeInst>(P->getIncomingValue(i))) {
assert(II->getParent() != P->getIncomingBlock(i) &&
"Invoke edge not supported yet"); (void)II;
}
new StoreInst(P->getIncomingValue(i), Slot,
P->getIncomingBlock(i)->getTerminator());
}
BasicBlock::iterator InsertPt = P;
for (; isa<PHINode>(InsertPt) || isa<LandingPadInst>(InsertPt); ++InsertPt)
;
Value *V = new LoadInst(Slot, P->getName()+".reload", InsertPt);
P->replaceAllUsesWith(V);
P->eraseFromParent();
return Slot;
}