-void CodeExtractor::processPhiNodeInputs(PHINode *Phi,
- Values &inputs,
- BasicBlock *codeReplacer,
- BasicBlock *newFuncRoot) {
- // Separate incoming values and BasicBlocks as internal/external. We ignore
- // the case where both the value and BasicBlock are internal, because we don't
- // need to do a thing.
- std::vector<unsigned> EValEBB;
- std::vector<unsigned> EValIBB;
- std::vector<unsigned> IValEBB;
-
- for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) {
- Value *phiVal = Phi->getIncomingValue(i);
- if (Instruction *Inst = dyn_cast<Instruction>(phiVal)) {
- if (BlocksToExtract.count(Inst->getParent())) {
- if (!BlocksToExtract.count(Phi->getIncomingBlock(i)))
- IValEBB.push_back(i);
- } else {
- if (BlocksToExtract.count(Phi->getIncomingBlock(i)))
- EValIBB.push_back(i);
- else
- EValEBB.push_back(i);
- }
- } else if (Argument *Arg = dyn_cast<Argument>(phiVal)) {
- // arguments are external
- if (BlocksToExtract.count(Phi->getIncomingBlock(i)))
- EValIBB.push_back(i);
- else
- EValEBB.push_back(i);
- } else {
- // Globals/Constants are internal, but considered `external' if they are
- // coming from an external block.
- if (!BlocksToExtract.count(Phi->getIncomingBlock(i)))
- EValEBB.push_back(i);
- }
- }
-
- // Both value and block are external. Need to group all of these, have an
- // external phi, pass the result as an argument, and have THIS phi use that
- // result.
- if (EValEBB.size() > 0) {
- if (EValEBB.size() == 1) {
- // Now if it's coming from the newFuncRoot, it's that funky input
- unsigned phiIdx = EValEBB[0];
- if (!isa<Constant>(Phi->getIncomingValue(phiIdx))) {
- PhiVal2Arg[Phi].push_back(std::make_pair(phiIdx, inputs.size()));
- // We can just pass this value in as argument
- inputs.push_back(Phi->getIncomingValue(phiIdx));
- }
- Phi->setIncomingBlock(phiIdx, newFuncRoot);
- } else {
- PHINode *externalPhi = new PHINode(Phi->getType(), "extPhi");
- codeReplacer->getInstList().insert(codeReplacer->begin(), externalPhi);
- for (std::vector<unsigned>::iterator i = EValEBB.begin(),
- e = EValEBB.end(); i != e; ++i) {
- externalPhi->addIncoming(Phi->getIncomingValue(*i),
- Phi->getIncomingBlock(*i));
-
- // We make these values invalid instead of deleting them because that
- // would shift the indices of other values... The fixPhiNodes should
- // clean these phi nodes up later.
- Phi->setIncomingValue(*i, 0);
- Phi->setIncomingBlock(*i, 0);
- }
- PhiVal2Arg[Phi].push_back(std::make_pair(Phi->getNumIncomingValues(),
- inputs.size()));
- // We can just pass this value in as argument
- inputs.push_back(externalPhi);
- }
- }
-
- // When the value is external, but block internal... just pass it in as
- // argument, no change to phi node
- for (std::vector<unsigned>::iterator i = EValIBB.begin(),
- e = EValIBB.end(); i != e; ++i) {
- // rewrite the phi input node to be an argument
- PhiVal2Arg[Phi].push_back(std::make_pair(*i, inputs.size()));
- inputs.push_back(Phi->getIncomingValue(*i));
- }
-
- // Value internal, block external this can happen if we are extracting a part
- // of a loop.
- for (std::vector<unsigned>::iterator i = IValEBB.begin(),
- e = IValEBB.end(); i != e; ++i) {
- assert(0 && "Cannot (YET) handle internal values via external blocks");
- }
-}
-
-