mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-21 03:32:21 +00:00
* Update file header comment
*** Revamp the code which handled unreachable code in the function. Now the code is much more efficient for high-degree basic blocks, such as those that occur in the 252.eon SPEC benchmark. For the interested, the time to promote a SINGLE alloca in _ZN7mrScene4ReadERSi function used to be > 3.5s. Now it is < .075s. The function has a LOT of allocas in it, so it appeared to be infinite looping, this should make it much nicer. :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8863 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
521c16aadd
commit
afa060ea3f
@ -1,18 +1,10 @@
|
|||||||
//===- PromoteMemoryToRegister.cpp - Convert memory refs to regs ----------===//
|
//===- PromoteMemoryToRegister.cpp - Convert allocas to registers ---------===//
|
||||||
//
|
//
|
||||||
// This file is used to promote memory references to be register references. A
|
// This file promote memory references to be register references. It promotes
|
||||||
// simple example of the transformation performed by this function is:
|
// alloca instructions which only have loads and stores as uses. An alloca is
|
||||||
//
|
// transformed by using dominator frontiers to place PHI nodes, then traversing
|
||||||
// FROM CODE TO CODE
|
// the function in depth-first order to rewrite loads and stores as appropriate.
|
||||||
// %X = alloca int, uint 1 ret int 42
|
// This is just the standard SSA construction algorithm.
|
||||||
// store int 42, int *%X
|
|
||||||
// %Y = load int* %X
|
|
||||||
// ret int %Y
|
|
||||||
//
|
|
||||||
// The code is transformed by looping over all of the alloca instruction,
|
|
||||||
// calculating dominator frontiers, then inserting phi-nodes following the usual
|
|
||||||
// SSA construction algorithm. This code does not modify the CFG of the
|
|
||||||
// function.
|
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
@ -20,10 +12,8 @@
|
|||||||
#include "llvm/Analysis/Dominators.h"
|
#include "llvm/Analysis/Dominators.h"
|
||||||
#include "llvm/iMemory.h"
|
#include "llvm/iMemory.h"
|
||||||
#include "llvm/iPHINode.h"
|
#include "llvm/iPHINode.h"
|
||||||
#include "llvm/iTerminators.h"
|
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Constant.h"
|
#include "llvm/Constant.h"
|
||||||
#include "llvm/Type.h"
|
|
||||||
#include "llvm/Support/CFG.h"
|
#include "llvm/Support/CFG.h"
|
||||||
#include "Support/StringExtras.h"
|
#include "Support/StringExtras.h"
|
||||||
|
|
||||||
@ -139,6 +129,8 @@ void PromoteMem2Reg::run() {
|
|||||||
// and inserting the phi nodes we marked as necessary
|
// and inserting the phi nodes we marked as necessary
|
||||||
//
|
//
|
||||||
RenamePass(F.begin(), 0, Values);
|
RenamePass(F.begin(), 0, Values);
|
||||||
|
|
||||||
|
// The renamer uses the Visited set to avoid infinite loops. Clear it now.
|
||||||
Visited.clear();
|
Visited.clear();
|
||||||
|
|
||||||
// Remove the allocas themselves from the function...
|
// Remove the allocas themselves from the function...
|
||||||
@ -153,6 +145,54 @@ void PromoteMem2Reg::run() {
|
|||||||
A->replaceAllUsesWith(Constant::getNullValue(A->getType()));
|
A->replaceAllUsesWith(Constant::getNullValue(A->getType()));
|
||||||
A->getParent()->getInstList().erase(A);
|
A->getParent()->getInstList().erase(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// At this point, the renamer has added entries to PHI nodes for all reachable
|
||||||
|
// code. Unfortunately, there may be blocks which are not reachable, which
|
||||||
|
// the renamer hasn't traversed. If this is the case, the PHI nodes may not
|
||||||
|
// have incoming values for all predecessors. Loop over all PHI nodes we have
|
||||||
|
// created, inserting null constants if they are missing any incoming values.
|
||||||
|
//
|
||||||
|
for (std::map<BasicBlock*, std::vector<PHINode *> >::iterator I =
|
||||||
|
NewPhiNodes.begin(), E = NewPhiNodes.end(); I != E; ++I) {
|
||||||
|
|
||||||
|
std::vector<BasicBlock*> Preds(pred_begin(I->first), pred_end(I->first));
|
||||||
|
std::vector<PHINode*> &PNs = I->second;
|
||||||
|
assert(!PNs.empty() && "Empty PHI node list??");
|
||||||
|
|
||||||
|
// Only do work here if there the PHI nodes are missing incoming values. We
|
||||||
|
// know that all PHI nodes that were inserted in a block will have the same
|
||||||
|
// number of incoming values, so we can just check any PHI node.
|
||||||
|
PHINode *FirstPHI = PNs[0];
|
||||||
|
if (Preds.size() != FirstPHI->getNumIncomingValues()) {
|
||||||
|
// Ok, now we know that all of the PHI nodes are missing entries for some
|
||||||
|
// basic blocks. Start by sorting the incoming predecessors for efficient
|
||||||
|
// access.
|
||||||
|
std::sort(Preds.begin(), Preds.end());
|
||||||
|
|
||||||
|
// Now we loop through all BB's which have entries in FirstPHI and remove
|
||||||
|
// them from the Preds list.
|
||||||
|
for (unsigned i = 0, e = FirstPHI->getNumIncomingValues(); i != e; ++i) {
|
||||||
|
// Do a log(n) search of teh Preds list for the entry we want.
|
||||||
|
std::vector<BasicBlock*>::iterator EntIt =
|
||||||
|
std::lower_bound(Preds.begin(), Preds.end(),
|
||||||
|
FirstPHI->getIncomingBlock(i));
|
||||||
|
assert(EntIt != Preds.end() && *EntIt == FirstPHI->getIncomingBlock(i)&&
|
||||||
|
"PHI node has entry for a block which is not a predecessor!");
|
||||||
|
|
||||||
|
// Remove the entry
|
||||||
|
Preds.erase(EntIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, the blocks left in the preds list must have dummy
|
||||||
|
// entries inserted into every PHI nodes for the block.
|
||||||
|
for (unsigned i = 0, e = PNs.size(); i != e; ++i) {
|
||||||
|
PHINode *PN = PNs[i];
|
||||||
|
Value *NullVal = Constant::getNullValue(PN->getType());
|
||||||
|
for (unsigned pred = 0, e = Preds.size(); pred != e; ++pred)
|
||||||
|
PN->addIncoming(NullVal, Preds[pred]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,25 +209,10 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo) {
|
|||||||
|
|
||||||
// Create a PhiNode using the dereferenced type... and add the phi-node to the
|
// Create a PhiNode using the dereferenced type... and add the phi-node to the
|
||||||
// BasicBlock.
|
// BasicBlock.
|
||||||
PHINode *PN = new PHINode(Allocas[AllocaNo]->getAllocatedType(),
|
BBPNs[AllocaNo] = new PHINode(Allocas[AllocaNo]->getAllocatedType(),
|
||||||
Allocas[AllocaNo]->getName() + "." +
|
Allocas[AllocaNo]->getName() + "." +
|
||||||
utostr(VersionNumbers[AllocaNo]++),
|
utostr(VersionNumbers[AllocaNo]++),
|
||||||
BB->begin());
|
BB->begin());
|
||||||
|
|
||||||
// Add null incoming values for all predecessors. This ensures that if one of
|
|
||||||
// the predecessors is not found in the depth-first traversal of the CFG (ie,
|
|
||||||
// because it is an unreachable predecessor), that all PHI nodes will have the
|
|
||||||
// correct number of entries for their predecessors.
|
|
||||||
Value *NullVal = Constant::getNullValue(PN->getType());
|
|
||||||
|
|
||||||
// This is necessary because adding incoming values to the PHI node adds uses
|
|
||||||
// to the basic blocks being used, which can invalidate the predecessor
|
|
||||||
// iterator!
|
|
||||||
std::vector<BasicBlock*> Preds(pred_begin(BB), pred_end(BB));
|
|
||||||
for (unsigned i = 0, e = Preds.size(); i != e; ++i)
|
|
||||||
PN->addIncoming(NullVal, Preds[i]);
|
|
||||||
|
|
||||||
BBPNs[AllocaNo] = PN;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,15 +227,10 @@ void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred,
|
|||||||
std::vector<PHINode *> &BBPNs = BBPNI->second;
|
std::vector<PHINode *> &BBPNs = BBPNI->second;
|
||||||
for (unsigned k = 0; k != BBPNs.size(); ++k)
|
for (unsigned k = 0; k != BBPNs.size(); ++k)
|
||||||
if (PHINode *PN = BBPNs[k]) {
|
if (PHINode *PN = BBPNs[k]) {
|
||||||
// The PHI node may have multiple entries for this predecessor. We must
|
// Add this incoming value to the PHI node.
|
||||||
// make sure we update all of them.
|
PN->addIncoming(IncomingVals[k], Pred);
|
||||||
for (unsigned i = 0, e = PN->getNumOperands(); i != e; i += 2) {
|
|
||||||
if (PN->getOperand(i+1) == Pred)
|
// The currently active variable for this block is now the PHI.
|
||||||
// At this point we can assume that the array has phi nodes.. let's
|
|
||||||
// update the incoming data.
|
|
||||||
PN->setOperand(i, IncomingVals[k]);
|
|
||||||
}
|
|
||||||
// also note that the active variable IS designated by the phi node
|
|
||||||
IncomingVals[k] = PN;
|
IncomingVals[k] = PN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user