bool JITOptimizations::runOnFunction(Function& F) { this->LI = &getAnalysis<LoopInfo>(); bool changed = false; FPM = new FunctionPassManager(F.getParent()); // if the user input something we use those passes std::vector<const PassInfo *> &customPasses = JPD->getPassList(); if (customPasses.size() > 0) { for (int i=0; i<customPasses.size();i++) { const PassInfo *pass = customPasses[i]; FPM->add(pass->createPass()); } } else { // Optimization ordering: // - ADCE // - inline // - DSE <---- THIS causes seg faults when running on sqlite3 // test in llvm test-suite // - Instruction Combining // ---- IF LOOPS ---- // - LICM // - Loop Simplify // - Loop Strength Reduction // ------------------ // - SCCP // - Simplify CFG // - SROA FPM->add(createAggressiveDCEPass()); if (JPD->getThresholdT2() != 0) FPM->add(createDynamicInlinerPass(JPD)); FPM->add(createInstructionCombiningPass()); // --- Loop optimizations --- // if (LI->begin() != LI->end()) { FPM->add(createLICMPass()); FPM->add(createLoopSimplifyPass()); FPM->add(createLoopStrengthReducePass()); } // -------------------------- // FPM->add(createSCCPPass()); FPM->add(createCFGSimplificationPass()); FPM->add(createSROAPass(false)); } changed = changed | FPM->doInitialization(); changed = changed | FPM->run(F); changed = changed | FPM->doFinalization(); delete FPM; return changed; }
void JSEdgeRemovalPass::padExitBlocks(LoopInfo& li) { for(LoopInfo::iterator b = li.begin(), e = li.end(); b != e; ++b) { Loop* l = *b; padExitBlocks(li, l); } }
// Create shadow information for function F, including top-sorting its blocks to give them indices and thus // a sensible order for specialisation. ShadowFunctionInvar* LLPEAnalysisPass::getFunctionInvarInfo(Function& F) { // Already described? DenseMap<Function*, ShadowFunctionInvar*>::iterator findit = functionInfo.find(&F); if(findit != functionInfo.end()) return findit->second; // Beware! This LoopInfo instance and whatever Loop objects come from it are only alive until // the next call to getAnalysis. Therefore the ShadowLoopInvar objects we make here // must mirror all information we're interested in from the Loops. LoopInfo* LI = &getAnalysis<LoopInfo>(F); ShadowFunctionInvar* RetInfoP = new ShadowFunctionInvar(); functionInfo[&F] = RetInfoP; ShadowFunctionInvar& RetInfo = *RetInfoP; // Top-sort all blocks, including child loop. Thanks to trickery in createTopOrderingFrom, // instead of giving all loop blocks an equal topsort value due to the latch edge cycle, // we order the header first, then the loop body in topological order ignoring the latch, then its exit blocks. std::vector<BasicBlock*> TopOrderedBlocks; SmallSet<BasicBlock*, 8> VisitedBlocks; createTopOrderingFrom(&F.getEntryBlock(), TopOrderedBlocks, VisitedBlocks, LI, /* loop = */ 0); // Since topsort gives a bottom-up ordering. std::reverse(TopOrderedBlocks.begin(), TopOrderedBlocks.end()); // Assign indices to each BB and instruction (IIndices is useful since otherwise we have to walk // the instruction list to get from an instruction to its index) DenseMap<BasicBlock*, uint32_t> BBIndices; DenseMap<Instruction*, uint32_t> IIndices; for(uint32_t i = 0; i < TopOrderedBlocks.size(); ++i) { BasicBlock* BB = TopOrderedBlocks[i]; BBIndices[BB] = i; uint32_t j; BasicBlock::iterator it, endit; for(j = 0, it = BB->begin(), endit = BB->end(); it != endit; ++it, ++j) { IIndices[it] = j; } } // Create shadow block objects: ShadowBBInvar* FShadowBlocks = new ShadowBBInvar[TopOrderedBlocks.size()]; for(uint32_t i = 0; i < TopOrderedBlocks.size(); ++i) { BasicBlock* BB = TopOrderedBlocks[i]; ShadowBBInvar& SBB = FShadowBlocks[i]; SBB.F = &RetInfo; SBB.idx = i; SBB.BB = BB; // True loop scope will be computed later, but by default... SBB.outerScope = 0; SBB.naturalScope = 0; const Loop* BBScope = LI->getLoopFor(BB); // Find successor block indices: succ_iterator SI = succ_begin(BB), SE = succ_end(BB); uint32_t succSize = std::distance(SI, SE); SBB.succIdxs = ImmutableArray<uint32_t>(new uint32_t[succSize], succSize); for(uint32_t j = 0; SI != SE; ++SI, ++j) { SBB.succIdxs[j] = BBIndices[*SI]; } // Find predecessor block indices: pred_iterator PI = pred_begin(BB), PE = pred_end(BB); uint32_t predSize = std::distance(PI, PE); SBB.predIdxs = ImmutableArray<uint32_t>(new uint32_t[predSize], predSize); for(uint32_t j = 0; PI != PE; ++PI, ++j) { SBB.predIdxs[j] = BBIndices[*PI]; if(SBB.predIdxs[j] > i) { if((!BBScope) || SBB.BB != BBScope->getHeader()) { errs() << "Warning: block " << SBB.BB->getName() << " in " << F.getName() << " has predecessor " << (*PI)->getName() << " that comes after it topologically, but this is not a loop header. The program is not in well-nested natural loop form.\n"; } } } // Find instruction def/use indices: ShadowInstructionInvar* insts = new ShadowInstructionInvar[BB->size()]; BasicBlock::iterator BI = BB->begin(), BE = BB->end(); for(uint32_t j = 0; BI != BE; ++BI, ++j) { Instruction* I = BI; ShadowInstructionInvar& SI = insts[j]; SI.idx = j; SI.parent = &SBB; SI.I = I; // Get operands indices: uint32_t NumOperands; ShadowInstIdx* operandIdxs; if(PHINode* PN = dyn_cast<PHINode>(I)) { NumOperands = PN->getNumIncomingValues(); operandIdxs = new ShadowInstIdx[NumOperands]; uint32_t* incomingBBs = new uint32_t[NumOperands]; for(unsigned k = 0, kend = PN->getNumIncomingValues(); k != kend; ++k) { if(Instruction* OpI = dyn_cast<Instruction>(PN->getIncomingValue(k))) operandIdxs[k] = ShadowInstIdx(BBIndices[OpI->getParent()], IIndices[OpI]); else if(GlobalVariable* OpGV = const_cast<GlobalVariable*>(getGlobalVar(PN->getIncomingValue(k)))) operandIdxs[k] = ShadowInstIdx(INVALID_BLOCK_IDX, getShadowGlobalIndex(OpGV)); else operandIdxs[k] = ShadowInstIdx(); incomingBBs[k] = BBIndices[PN->getIncomingBlock(k)]; } SI.operandBBs = ImmutableArray<uint32_t>(incomingBBs, NumOperands); } else { NumOperands = I->getNumOperands(); operandIdxs = new ShadowInstIdx[NumOperands]; for(unsigned k = 0, kend = I->getNumOperands(); k != kend; ++k) { if(Instruction* OpI = dyn_cast<Instruction>(I->getOperand(k))) operandIdxs[k] = ShadowInstIdx(BBIndices[OpI->getParent()], IIndices[OpI]); else if(GlobalVariable* OpGV = const_cast<GlobalVariable*>(getGlobalVar(I->getOperand(k)))) operandIdxs[k] = ShadowInstIdx(INVALID_BLOCK_IDX, getShadowGlobalIndex(OpGV)); else if(BasicBlock* OpBB = dyn_cast<BasicBlock>(I->getOperand(k))) operandIdxs[k] = ShadowInstIdx(BBIndices[OpBB], INVALID_INSTRUCTION_IDX); else operandIdxs[k] = ShadowInstIdx(); } } SI.operandIdxs = ImmutableArray<ShadowInstIdx>(operandIdxs, NumOperands); // Get user indices: unsigned nUsers = std::distance(I->use_begin(), I->use_end()); ShadowInstIdx* userIdxs = new ShadowInstIdx[nUsers]; Instruction::use_iterator UI; unsigned k; for(k = 0, UI = I->use_begin(); k != nUsers; ++k, ++UI) { if(Instruction* UserI = dyn_cast<Instruction>(UI->getUser())) { userIdxs[k] = ShadowInstIdx(BBIndices[UserI->getParent()], IIndices[UserI]); } else { userIdxs[k] = ShadowInstIdx(); } } SI.userIdxs = ImmutableArray<ShadowInstIdx>(userIdxs, nUsers); } SBB.insts = ImmutableArray<ShadowInstructionInvar>(insts, BB->size()); } RetInfo.BBs = ImmutableArray<ShadowBBInvar>(FShadowBlocks, TopOrderedBlocks.size()); // Get user info for arguments: ShadowArgInvar* Args = new ShadowArgInvar[F.arg_size()]; Function::arg_iterator AI = F.arg_begin(); uint32_t i = 0; for(; i != F.arg_size(); ++i, ++AI) { Argument* A = AI; ShadowArgInvar& SArg = Args[i]; SArg.A = A; unsigned j = 0; Argument::use_iterator UI = A->use_begin(), UE = A->use_end(); uint32_t nUsers = std::distance(UI, UE); ShadowInstIdx* Users = new ShadowInstIdx[nUsers]; for(; UI != UE; ++UI, ++j) { Value* UsedV = UI->getUser(); if(Instruction* UsedI = dyn_cast<Instruction>(UsedV)) { Users[j] = ShadowInstIdx(BBIndices[UsedI->getParent()], IIndices[UsedI]); } else { Users[j] = ShadowInstIdx(); } } SArg.userIdxs = ImmutableArray<ShadowInstIdx>(Users, nUsers); } RetInfo.Args = ImmutableArray<ShadowArgInvar>(Args, F.arg_size()); // Populate map from loop headers to header index. Due to the topological sort, // all loops consist of that block + L->getBlocks().size() further, contiguous blocks, // making is-in-loop easy to compute. DominatorTree* thisDT = DTs[&F]; for(LoopInfo::iterator it = LI->begin(), it2 = LI->end(); it != it2; ++it) { ShadowLoopInvar* newL = getLoopInfo(&RetInfo, BBIndices, *it, thisDT, 0); RetInfo.TopLevelLoops.push_back(newL); } // Count alloca instructions at the start of the function; this will control how // large the std::vector that represents the frame will be initialised. RetInfo.frameSize = 0; for(BasicBlock::iterator it = F.getEntryBlock().begin(), itend = F.getEntryBlock().end(); it != itend && isa<AllocaInst>(it); ++it) ++RetInfo.frameSize; // "&& RootIA" checks whether we're inside the initial context creation, in which case we should // allocate a frame whether or not main can ever allocate to avoid the frame index underflowing // in some circumstances. if((!RetInfo.frameSize) && RootIA) { // Magic value indicating the function will never alloca anything and we can skip all frame processing. RetInfo.frameSize = -1; for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E && RetInfo.frameSize == -1; ++I) { if(isa<AllocaInst>(*I)) RetInfo.frameSize = 0; } } return RetInfoP; }