void PatmosSPMark::removeUncalledSPFunctions(const Module &M) { for(Module::const_iterator F(M.begin()), FE(M.end()); F != FE; ++F) { if (F->hasFnAttribute("sp-maybe")) { // get the machine-level function MachineFunction *MF = MMI->getMachineFunction(F); assert( MF ); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); if (!PMFI->isSinglePath()) { DEBUG(dbgs() << " Remove function: " << F->getName() << "\n"); // delete all MBBs while (MF->begin() != MF->end()) { MF->begin()->eraseFromParent(); } // insert a new single MBB with a single return instruction MachineBasicBlock *EmptyMBB = MF->CreateMachineBasicBlock(); MF->push_back(EmptyMBB); DebugLoc DL; AddDefaultPred(BuildMI(*EmptyMBB, EmptyMBB->end(), DL, TM.getInstrInfo()->get(Patmos::RET))); NumSPCleared++; // bump STATISTIC }; } } }
bool PatmosSPMark::runOnMachineModule(const Module &M) { DEBUG( dbgs() << "[Single-Path] Mark functions reachable from single-path roots\n"); MMI = &getAnalysis<MachineModuleInfo>(); assert(MMI); Worklist W; // initialize the worklist with machine functions that have either // sp-root or sp-reachable function attribute for(Module::const_iterator F(M.begin()), FE(M.end()); F != FE; ++F) { if (F->hasFnAttribute("sp-root") || F->hasFnAttribute("sp-reachable")) { // get the machine-level function MachineFunction *MF = MMI->getMachineFunction(F); assert( MF ); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); PMFI->setSinglePath(); NumSPTotal++; // bump STATISTIC W.push_back(MF); } } // process worklist while (!W.empty()) { MachineFunction *MF = W.front(); W.pop_front(); scanAndRewriteCalls(MF, W); } removeUncalledSPFunctions(M); // We either have rewritten calls or removed superfluous functions. return true; }
void PatmosSPMark::scanAndRewriteCalls(MachineFunction *MF, Worklist &W) { for (MachineFunction::iterator MBB = MF->begin(), MBBE = MF->end(); MBB != MBBE; ++MBB) { for( MachineBasicBlock::iterator MI = MBB->begin(), ME = MBB->getFirstTerminator(); MI != ME; ++MI) { if (MI->isCall()) { MachineFunction *MF = getCallTargetMF(MI); if (!MF) { dbgs() << "[Single-Path] WARNING: Cannot rewrite call in " << MBB->getParent()->getFunction()->getName() << " (indirect call?)\n"; continue; }; const Function *Target = getCallTarget(MI); if (Target->getName() == "__udivsi3") { //DEBUG(dbgs() << "[Single-Path] skipping call to " // << Target->getName() << "\n"); //continue; } PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); if (!PMFI->isSinglePath()) { // rewrite call to _sp variant rewriteCall(MI); // set _sp MF to single path in PMFI (MF has changed!) MachineFunction *MF = getCallTargetMF(MI); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); // we possibly have already marked the _sp variant as single-path // in an earlier call if (!PMFI->isSinglePath()) { PMFI->setSinglePath(); // add the new single-path function to the worklist W.push_back(MF); NumSPTotal++; // bump STATISTIC NumSPMaybe++; // bump STATISTIC } } } } } }
void PatmosSPMark::scanAndRewriteCalls(MachineFunction *MF, Worklist &W) { DEBUG(dbgs() << "In function '" << MF->getName() << "':\n"); for (MachineFunction::iterator MBB = MF->begin(), MBBE = MF->end(); MBB != MBBE; ++MBB) { for( MachineBasicBlock::iterator MI = MBB->begin(), ME = MBB->getFirstTerminator(); MI != ME; ++MI) { if (MI->isCall()) { MachineFunction *MF = getCallTargetMF(MI); if (!MF) { dbgs() << "[Single-Path] WARNING: Cannot rewrite call in " << MBB->getParent()->getFunction()->getName() << " (indirect call?)\n"; continue; }; const Function *Target = getCallTarget(MI); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); if (!PMFI->isSinglePath()) { // sp-reachable functions were already marked as single-path. // Hence, we have _potential_ sp-maybe functions left; the call // needs to be rewritten to point to the sp-maybe clone. rewriteCall(MI); // set _sp MF to single path in PMFI (MF has changed!) MachineFunction *MF = getCallTargetMF(MI); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); // we possibly have already marked the _sp variant as single-path // in an earlier call, if not, then set this final decision. if (!PMFI->isSinglePath()) { PMFI->setSinglePath(); // add the new single-path function to the worklist W.push_back(MF); NumSPTotal++; // bump STATISTIC NumSPMaybe++; // bump STATISTIC } } } } } }
bool PatmosSPMark::runOnMachineModule(const Module &M) { DEBUG( dbgs() << "[Single-Path] Mark functions reachable from single-path roots\n"); MMI = &getAnalysis<MachineModuleInfo>(); assert(MMI); Worklist W; // initialize the worklist with machine functions that have either // sp-root or sp-reachable function attribute for(Module::const_iterator F(M.begin()), FE(M.end()); F != FE; ++F) { if (F->hasFnAttribute("sp-root") || F->hasFnAttribute("sp-reachable")) { // get the machine-level function MachineFunction *MF = MMI->getMachineFunction(F); assert( MF ); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); PMFI->setSinglePath(); NumSPTotal++; // bump STATISTIC W.push_back(MF); } } // process worklist while (!W.empty()) { MachineFunction *MF = W.front(); W.pop_front(); scanAndRewriteCalls(MF, W); } // clear all cloned machine functions that are not marked as single-path // by now for(Module::const_iterator F(M.begin()), FE(M.end()); F != FE; ++F) { if (F->hasFnAttribute("sp-maybe")) { // get the machine-level function MachineFunction *MF = MMI->getMachineFunction(F); assert( MF ); PatmosMachineFunctionInfo *PMFI = MF->getInfo<PatmosMachineFunctionInfo>(); if (!PMFI->isSinglePath()) { // delete all MBBs while (MF->begin() != MF->end()) { MF->begin()->eraseFromParent(); } // insert a new single MBB with a single return instruction MachineBasicBlock *EmptyMBB = MF->CreateMachineBasicBlock(); MF->push_back(EmptyMBB); DebugLoc DL; AddDefaultPred(BuildMI(*EmptyMBB, EmptyMBB->end(), DL, TM.getInstrInfo()->get(Patmos::RET))); NumSPCleared++; // bump STATISTIC }; } } return true; }