mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
* Pull some code out into the definedInRegion/definedInCaller methods
* Add a stub for the severSplitPHINodes which will allow us to bbextract bb's with PHI nodes in them soon. * Remove unused arguments from findInputsOutputs * Dramatically simplify the code in findInputsOutputs. In particular, nothing really cares whether or not a PHI node is using something. * Move moveCodeToFunction to after emitCallAndSwitchStatement as that's the order they get called. * Fix a bug where we would code extract a region that included a call to vastart. Like 'alloca', calls to vastart must stay in the function that they are defined in. * Add some comments. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13482 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
346be7f5bc
commit
bf749367cb
@ -17,6 +17,7 @@
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
@ -55,9 +56,28 @@ namespace {
|
||||
bool isEligible(const std::vector<BasicBlock*> &code);
|
||||
|
||||
private:
|
||||
void findInputsOutputs(Values &inputs, Values &outputs,
|
||||
BasicBlock *newHeader,
|
||||
BasicBlock *newRootNode);
|
||||
/// definedInRegion - Return true if the specified value is defined in the
|
||||
/// extracted region.
|
||||
bool definedInRegion(Value *V) const {
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (BlocksToExtract.count(I->getParent()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// definedInCaller - Return true if the specified value is defined in the
|
||||
/// function being code extracted, but not in the region being extracted.
|
||||
/// These values must be passed in as live-ins to the function.
|
||||
bool definedInCaller(Value *V) const {
|
||||
if (isa<Argument>(V)) return true;
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (!BlocksToExtract.count(I->getParent()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void severSplitPHINodes(BasicBlock *&Header);
|
||||
void findInputsOutputs(Values &inputs, Values &outputs);
|
||||
|
||||
Function *constructFunction(const Values &inputs,
|
||||
const Values &outputs,
|
||||
@ -75,51 +95,40 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs,
|
||||
BasicBlock *newHeader,
|
||||
BasicBlock *newRootNode) {
|
||||
/// severSplitPHINodes - If a PHI node has multiple inputs from outside of the
|
||||
/// region, we need to split the entry block of the region so that the PHI node
|
||||
/// is easier to deal with.
|
||||
void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// findInputsOutputs - Find inputs to, outputs from the code region.
|
||||
//
|
||||
void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs) {
|
||||
std::set<BasicBlock*> ExitBlocks;
|
||||
for (std::set<BasicBlock*>::const_iterator ci = BlocksToExtract.begin(),
|
||||
ce = BlocksToExtract.end(); ci != ce; ++ci) {
|
||||
BasicBlock *BB = *ci;
|
||||
|
||||
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
|
||||
// If a used value is defined outside the region, it's an input. If an
|
||||
// instruction is used outside the region, it's an output.
|
||||
if (PHINode *PN = dyn_cast<PHINode>(I)) {
|
||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||
Value *V = PN->getIncomingValue(i);
|
||||
if (!BlocksToExtract.count(PN->getIncomingBlock(i)) &&
|
||||
(isa<Instruction>(V) || isa<Argument>(V)))
|
||||
inputs.push_back(V);
|
||||
else if (Instruction *opI = dyn_cast<Instruction>(V)) {
|
||||
if (!BlocksToExtract.count(opI->getParent()))
|
||||
inputs.push_back(opI);
|
||||
} else if (isa<Argument>(V))
|
||||
inputs.push_back(V);
|
||||
}
|
||||
} else {
|
||||
// All other instructions go through the generic input finder
|
||||
// Loop over the operands of each instruction (inputs)
|
||||
for (User::op_iterator op = I->op_begin(), opE = I->op_end();
|
||||
op != opE; ++op)
|
||||
if (Instruction *opI = dyn_cast<Instruction>(*op)) {
|
||||
// Check if definition of this operand is within the loop
|
||||
if (!BlocksToExtract.count(opI->getParent()))
|
||||
inputs.push_back(opI);
|
||||
} else if (isa<Argument>(*op)) {
|
||||
inputs.push_back(*op);
|
||||
}
|
||||
}
|
||||
for (User::op_iterator O = I->op_begin(), E = I->op_end(); O != E; ++O)
|
||||
if (definedInCaller(*O))
|
||||
inputs.push_back(*O);
|
||||
|
||||
// Consider uses of this instruction (outputs)
|
||||
// Consider uses of this instruction (outputs).
|
||||
for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
|
||||
UI != E; ++UI)
|
||||
if (!BlocksToExtract.count(cast<Instruction>(*UI)->getParent())) {
|
||||
if (!definedInRegion(*UI)) {
|
||||
outputs.push_back(I);
|
||||
break;
|
||||
}
|
||||
} // for: insts
|
||||
|
||||
// Keep track of the exit blocks from the region.
|
||||
TerminatorInst *TI = BB->getTerminator();
|
||||
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
|
||||
if (!BlocksToExtract.count(TI->getSuccessor(i)))
|
||||
@ -238,30 +247,14 @@ Function *CodeExtractor::constructFunction(const Values &inputs,
|
||||
return newFunction;
|
||||
}
|
||||
|
||||
void CodeExtractor::moveCodeToFunction(Function *newFunction) {
|
||||
Function *oldFunc = (*BlocksToExtract.begin())->getParent();
|
||||
Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList();
|
||||
Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList();
|
||||
|
||||
for (std::set<BasicBlock*>::const_iterator i = BlocksToExtract.begin(),
|
||||
e = BlocksToExtract.end(); i != e; ++i) {
|
||||
// Delete the basic block from the old function, and the list of blocks
|
||||
oldBlocks.remove(*i);
|
||||
|
||||
// Insert this basic block into the new function
|
||||
newBlocks.push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
|
||||
BasicBlock *codeReplacer,
|
||||
Values &inputs,
|
||||
Values &outputs) {
|
||||
|
||||
// Emit a call to the new function, passing in:
|
||||
// *pointer to struct (if aggregating parameters), or
|
||||
// plan inputs and allocated memory for outputs
|
||||
/// emitCallAndSwitchStatement - This method sets up the caller side by adding
|
||||
/// the call instruction, splitting any PHI nodes in the header block as
|
||||
/// necessary.
|
||||
void CodeExtractor::
|
||||
emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer,
|
||||
Values &inputs, Values &outputs) {
|
||||
// Emit a call to the new function, passing in: *pointer to struct (if
|
||||
// aggregating parameters), or plan inputs and allocated memory for outputs
|
||||
std::vector<Value*> params, StructValues, ReloadOutputs;
|
||||
|
||||
// Add inputs as params, or to be filled into the struct
|
||||
@ -462,6 +455,20 @@ CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
|
||||
}
|
||||
}
|
||||
|
||||
void CodeExtractor::moveCodeToFunction(Function *newFunction) {
|
||||
Function *oldFunc = (*BlocksToExtract.begin())->getParent();
|
||||
Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList();
|
||||
Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList();
|
||||
|
||||
for (std::set<BasicBlock*>::const_iterator i = BlocksToExtract.begin(),
|
||||
e = BlocksToExtract.end(); i != e; ++i) {
|
||||
// Delete the basic block from the old function, and the list of blocks
|
||||
oldBlocks.remove(*i);
|
||||
|
||||
// Insert this basic block into the new function
|
||||
newBlocks.push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
/// ExtractRegion - Removes a loop from a function, replaces it with a call to
|
||||
/// new function. Returns pointer to the new function.
|
||||
@ -497,6 +504,10 @@ Function *CodeExtractor::ExtractCodeRegion(const std::vector<BasicBlock*> &code)
|
||||
// Assumption: this is a single-entry code region, and the header is the first
|
||||
// block in the region.
|
||||
BasicBlock *header = code[0];
|
||||
|
||||
// If we have to split PHI nodes, do so now.
|
||||
severSplitPHINodes(header);
|
||||
|
||||
for (unsigned i = 1, e = code.size(); i != e; ++i)
|
||||
for (pred_iterator PI = pred_begin(code[i]), E = pred_end(code[i]);
|
||||
PI != E; ++PI)
|
||||
@ -510,29 +521,14 @@ Function *CodeExtractor::ExtractCodeRegion(const std::vector<BasicBlock*> &code)
|
||||
BasicBlock *codeReplacer = new BasicBlock("codeRepl", oldFunction);
|
||||
|
||||
// The new function needs a root node because other nodes can branch to the
|
||||
// head of the loop, and the root cannot have predecessors
|
||||
// head of the region, but the entry node of a function cannot have preds.
|
||||
BasicBlock *newFuncRoot = new BasicBlock("newFuncRoot");
|
||||
newFuncRoot->getInstList().push_back(new BranchInst(header));
|
||||
|
||||
// Find inputs to, outputs from the code region
|
||||
//
|
||||
// If one of the inputs is coming from a different basic block and it's in a
|
||||
// phi node, we need to rewrite the phi node:
|
||||
//
|
||||
// * All the inputs which involve basic blocks OUTSIDE of this region go into
|
||||
// a NEW phi node that takes care of finding which value really came in.
|
||||
// The result of this phi is passed to the function as an argument.
|
||||
//
|
||||
// * All the other phi values stay.
|
||||
//
|
||||
// FIXME: PHI nodes' incoming blocks aren't being rewritten to accomodate for
|
||||
// blocks moving to a new function.
|
||||
// SOLUTION: move Phi nodes out of the loop header into the codeReplacer, pass
|
||||
// the values as parameters to the function
|
||||
findInputsOutputs(inputs, outputs, codeReplacer, newFuncRoot);
|
||||
// Find inputs to, outputs from the code region.
|
||||
findInputsOutputs(inputs, outputs);
|
||||
|
||||
// Step 2: Construct new function based on inputs/outputs,
|
||||
// Add allocas for all defs
|
||||
// Construct new function based on inputs/outputs & add allocas for all defs.
|
||||
Function *newFunction = constructFunction(inputs, outputs, code[0],
|
||||
newFuncRoot,
|
||||
codeReplacer, oldFunction,
|
||||
@ -568,13 +564,17 @@ Function *CodeExtractor::ExtractCodeRegion(const std::vector<BasicBlock*> &code)
|
||||
}
|
||||
|
||||
bool CodeExtractor::isEligible(const std::vector<BasicBlock*> &code) {
|
||||
// Deny code region if it contains allocas
|
||||
// Deny code region if it contains allocas or vastarts.
|
||||
for (std::vector<BasicBlock*>::const_iterator BB = code.begin(), e=code.end();
|
||||
BB != e; ++BB)
|
||||
for (BasicBlock::const_iterator I = (*BB)->begin(), Ie = (*BB)->end();
|
||||
I != Ie; ++I)
|
||||
if (isa<AllocaInst>(*I))
|
||||
return false;
|
||||
else if (const CallInst *CI = dyn_cast<CallInst>(I))
|
||||
if (const Function *F = CI->getCalledFunction())
|
||||
if (F->getIntrinsicID() == Intrinsic::vastart)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user