mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-21 19:48:46 +00:00
split rewriting of single-store allocas into its own
method. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40806 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bbe104002f
commit
5dd75b4ca7
@ -78,6 +78,7 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
struct AllocaInfo;
|
||||||
|
|
||||||
// Data package used by RenamePass()
|
// Data package used by RenamePass()
|
||||||
class VISIBILITY_HIDDEN RenamePassData {
|
class VISIBILITY_HIDDEN RenamePassData {
|
||||||
@ -165,6 +166,8 @@ namespace {
|
|||||||
--AllocaIdx;
|
--AllocaIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info);
|
||||||
|
|
||||||
void MarkDominatingPHILive(BasicBlock *BB, unsigned AllocaNum,
|
void MarkDominatingPHILive(BasicBlock *BB, unsigned AllocaNum,
|
||||||
SmallPtrSet<PHINode*, 16> &DeadPHINodes);
|
SmallPtrSet<PHINode*, 16> &DeadPHINodes);
|
||||||
bool PromoteLocallyUsedAlloca(BasicBlock *BB, AllocaInst *AI);
|
bool PromoteLocallyUsedAlloca(BasicBlock *BB, AllocaInst *AI);
|
||||||
@ -232,6 +235,7 @@ namespace {
|
|||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
void PromoteMem2Reg::run() {
|
void PromoteMem2Reg::run() {
|
||||||
Function &F = *DF.getRoot()->getParent();
|
Function &F = *DF.getRoot()->getParent();
|
||||||
|
|
||||||
@ -282,45 +286,7 @@ void PromoteMem2Reg::run() {
|
|||||||
// If there is only a single store to this value, replace any loads of
|
// If there is only a single store to this value, replace any loads of
|
||||||
// it that are directly dominated by the definition with the value stored.
|
// it that are directly dominated by the definition with the value stored.
|
||||||
if (Info.DefiningBlocks.size() == 1) {
|
if (Info.DefiningBlocks.size() == 1) {
|
||||||
// Be aware of loads before the store.
|
RewriteSingleStoreAlloca(AI, Info);
|
||||||
std::set<BasicBlock*> ProcessedBlocks;
|
|
||||||
for (unsigned i = 0, e = Info.UsingBlocks.size(); i != e; ++i)
|
|
||||||
// If the store dominates the block and if we haven't processed it yet,
|
|
||||||
// do so now.
|
|
||||||
if (dominates(Info.OnlyStore->getParent(), Info.UsingBlocks[i]))
|
|
||||||
if (ProcessedBlocks.insert(Info.UsingBlocks[i]).second) {
|
|
||||||
BasicBlock *UseBlock = Info.UsingBlocks[i];
|
|
||||||
|
|
||||||
// If the use and store are in the same block, do a quick scan to
|
|
||||||
// verify that there are no uses before the store.
|
|
||||||
if (UseBlock == Info.OnlyStore->getParent()) {
|
|
||||||
BasicBlock::iterator I = UseBlock->begin();
|
|
||||||
for (; &*I != Info.OnlyStore; ++I) { // scan block for store.
|
|
||||||
if (isa<LoadInst>(I) && I->getOperand(0) == AI)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (&*I != Info.OnlyStore) break; // Do not handle this case.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, if this is a different block or if all uses happen
|
|
||||||
// after the store, do a simple linear scan to replace loads with
|
|
||||||
// the stored value.
|
|
||||||
for (BasicBlock::iterator I = UseBlock->begin(),E = UseBlock->end();
|
|
||||||
I != E; ) {
|
|
||||||
if (LoadInst *LI = dyn_cast<LoadInst>(I++)) {
|
|
||||||
if (LI->getOperand(0) == AI) {
|
|
||||||
LI->replaceAllUsesWith(Info.OnlyStore->getOperand(0));
|
|
||||||
if (AST && isa<PointerType>(LI->getType()))
|
|
||||||
AST->deleteValue(LI);
|
|
||||||
LI->eraseFromParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, remove this block from the UsingBlock set.
|
|
||||||
Info.UsingBlocks[i] = Info.UsingBlocks.back();
|
|
||||||
--i; --e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, after the scan, check to see if the store is all that is left.
|
// Finally, after the scan, check to see if the store is all that is left.
|
||||||
if (Info.UsingBlocks.empty()) {
|
if (Info.UsingBlocks.empty()) {
|
||||||
@ -559,6 +525,58 @@ void PromoteMem2Reg::run() {
|
|||||||
NewPhiNodes.clear();
|
NewPhiNodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// RewriteSingleStoreAlloca - If there is only a single store to this value,
|
||||||
|
/// replace any loads of it that are directly dominated by the definition with
|
||||||
|
/// the value stored.
|
||||||
|
void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI,
|
||||||
|
AllocaInfo &Info) {
|
||||||
|
// Be aware of loads before the store.
|
||||||
|
std::set<BasicBlock*> ProcessedBlocks;
|
||||||
|
for (unsigned i = 0, e = Info.UsingBlocks.size(); i != e; ++i) {
|
||||||
|
// If the store dominates the block and if we haven't processed it yet,
|
||||||
|
// do so now.
|
||||||
|
if (!dominates(Info.OnlyStore->getParent(), Info.UsingBlocks[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!ProcessedBlocks.insert(Info.UsingBlocks[i]).second)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BasicBlock *UseBlock = Info.UsingBlocks[i];
|
||||||
|
|
||||||
|
// If the use and store are in the same block, do a quick scan to
|
||||||
|
// verify that there are no uses before the store.
|
||||||
|
if (UseBlock == Info.OnlyStore->getParent()) {
|
||||||
|
BasicBlock::iterator I = UseBlock->begin();
|
||||||
|
for (; &*I != Info.OnlyStore; ++I) { // scan block for store.
|
||||||
|
if (isa<LoadInst>(I) && I->getOperand(0) == AI)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (&*I != Info.OnlyStore) break; // Do not handle this case.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if this is a different block or if all uses happen
|
||||||
|
// after the store, do a simple linear scan to replace loads with
|
||||||
|
// the stored value.
|
||||||
|
for (BasicBlock::iterator I = UseBlock->begin(),E = UseBlock->end();
|
||||||
|
I != E; ) {
|
||||||
|
if (LoadInst *LI = dyn_cast<LoadInst>(I++)) {
|
||||||
|
if (LI->getOperand(0) == AI) {
|
||||||
|
LI->replaceAllUsesWith(Info.OnlyStore->getOperand(0));
|
||||||
|
if (AST && isa<PointerType>(LI->getType()))
|
||||||
|
AST->deleteValue(LI);
|
||||||
|
LI->eraseFromParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, remove this block from the UsingBlock set.
|
||||||
|
Info.UsingBlocks[i] = Info.UsingBlocks.back();
|
||||||
|
--i; --e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MarkDominatingPHILive - Mem2Reg wants to construct "pruned" SSA form, not
|
// MarkDominatingPHILive - Mem2Reg wants to construct "pruned" SSA form, not
|
||||||
// "minimal" SSA form. To do this, it inserts all of the PHI nodes on the IDF
|
// "minimal" SSA form. To do this, it inserts all of the PHI nodes on the IDF
|
||||||
// as usual (inserting the PHI nodes in the DeadPHINodes set), then processes
|
// as usual (inserting the PHI nodes in the DeadPHINodes set), then processes
|
||||||
|
Loading…
Reference in New Issue
Block a user