bool LLPE::runOnModule(Module &M) { vector<int> argv = readInputFile(); for (Module::iterator F = M.begin(), F_end = M.end(); F != F_end; ++F) { for (Function::arg_iterator A = F->arg_begin(), A_end = F->arg_end(); A != A_end; ++A) { //Search for variables referencing argv if (A->getName() == "argv") { //Iterate through uses of argv for (Value::use_iterator U = A->use_begin(), U_end = A->use_end(); U != U_end; ++U) { Instruction *User = dyn_cast<Instruction>(*U); StoreInst *SI = dyn_cast<StoreInst>(User); AllocaInst *OrigAlloca = dyn_cast<AllocaInst>(SI->getOperand(1)); for (Value::use_iterator U2 = OrigAlloca->use_begin(), U2_end = OrigAlloca->use_end(); U2 != U2_end; ++U2) { Instruction *User2 = dyn_cast<Instruction>(*U2); for (Value::use_iterator U3 = User2->use_begin(), U3_end = OrigAlloca->use_end(); U3 != U3_end; ++U3) { searchForStoreInstruction(dyn_cast<Instruction>(*U3)->getParent(), argv); } } } } } } return true; }
void ExecutionState::dumpStack(llvm::raw_ostream &out) const { unsigned idx = 0; const KInstruction *target = prevPC; for (ExecutionState::stack_ty::const_reverse_iterator it = stack.rbegin(), ie = stack.rend(); it != ie; ++it) { const StackFrame &sf = *it; Function *f = sf.kf->function; const InstructionInfo &ii = *target->info; out << "\t#" << idx++; std::stringstream AssStream; AssStream << std::setw(8) << std::setfill('0') << ii.assemblyLine; out << AssStream.str(); out << " in " << f->getName().str() << " ("; // Yawn, we could go up and print varargs if we wanted to. unsigned index = 0; for (Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end(); ai != ae; ++ai) { if (ai!=f->arg_begin()) out << ", "; out << ai->getName().str(); // XXX should go through function ref<Expr> value = sf.locals[sf.kf->getArgRegister(index++)].value; if (value.get() && isa<ConstantExpr>(value)) out << "=" << value; } out << ")"; if (ii.file != "") out << " at " << ii.file << ":" << ii.line; out << "\n"; target = sf.caller; } }
void StackTrace::dump(std::ostream &out) const { unsigned idx = 0; for (stack_t::const_iterator it = contents.begin(); it != contents.end(); it++) { Function *f = it->first.first->function; const InstructionInfo &ii = *it->first.second->info; out << "\t#" << idx++ << " " << std::setw(8) << std::setfill('0') << ii.assemblyLine << " in " << f->getName().str() << " ("; unsigned index = 0; for (Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end(); ai != ae; ++ai) { if (ai!=f->arg_begin()) out << ", "; out << ai->getName().str(); // XXX should go through function ref<Expr> value = it->second[index++]; if (isa<ConstantExpr>(value)) out << "=" << value; } out << ")"; if (ii.file != "") out << " at " << ii.file << ":" << ii.line; out << "\n"; } }
int get_arg_count(const char *name, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } for (i = 1; i <= MAX_ARGS; i++) { char *funcName = (char *) malloc(20); sprintf(funcName, "__op_gen_label%d", i); Function *f = ops->getFunction(std::string(funcName)); if (f != NULL) { for (Function::use_iterator j = f->use_begin(), e = f->use_end(); j != e; ++j) { if (Instruction *inst = dyn_cast<Instruction>(*j)) { if (inst->getParent()->getParent() == op) { args_present[i - 1] = 1; } } } } else { std::cout << "symbol not found\n"; } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } return nb_args; }
/// lowerIncomingArguments - To avoid having to handle incoming arguments /// specially, we lower each arg to a copy instruction in the entry block. This /// ensures that the argument value itself cannot be live out of the entry /// block. void SjLjEHPrepare::lowerIncomingArguments(Function &F) { BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); while (isa<AllocaInst>(AfterAllocaInsPt) && isa<ConstantInt>(cast<AllocaInst>(AfterAllocaInsPt)->getArraySize())) ++AfterAllocaInsPt; for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++AI) { Type *Ty = AI->getType(); if (isa<StructType>(Ty) || isa<ArrayType>(Ty)) { // Aggregate types can't be cast, but are legal argument types, // so we have to handle them differently. We use // select i8 true, %arg, undef to achieve the same goal Value *TrueValue = ConstantInt::getTrue(F.getContext()); Value *UndefValue = UndefValue::get(Ty); Instruction *SI = SelectInst::Create(TrueValue, AI, UndefValue, AI->getName() + ".tmp", AfterAllocaInsPt); AI->replaceAllUsesWith(SI); SI->setOperand(1, AI); } else { // This is always a no-op cast because we're casting AI to AI->getType() // so src and destination types are identical. BitCast is the only // possibility. CastInst *NC = new BitCastInst(AI, AI->getType(), AI->getName() + ".tmp", AfterAllocaInsPt); AI->replaceAllUsesWith(NC); // Set the operand of the cast instruction back to the AllocaInst. // Normally it's forbidden to replace a CastInst's operand because it // could cause the opcode to reflect an illegal conversion. However, we're // replacing it here with the same value it was constructed with. We do // this because the above replaceAllUsesWith() clobbered the operand, but // we want this one to remain. NC->setOperand(0, AI); } } }
/* for the vi and lsup, find their corresponding argument*/ Value *FindFunctionArgumentOfInstr(Instruction *I, Function *F) { int notFound = 1; Value *via = 0; Function::arg_iterator FI = F->arg_begin(), FE = F->arg_end(); while (FI != FE && notFound) { if (FI->getName() == I->getName()) { via = &*FI; notFound = 0; } ++FI; } return via; }
// Maybe make a clone, if a clone is made, return a pointer to it, if a clone // was not made return nullptr. Function *CSDataRando::makeFunctionClone(Function *F) { // Now we know how many arguments need to be passed, so we make the clones FuncInfo &FI = FunctionInfo[F]; if (FI.ArgNodes.size() == 0) { // No additional args to pass, no need to clone. return nullptr; } // Determine the type of the new function, we insert the new parameters for // the masks after the normal arguments, but before any va_args Type *MaskTy = TypeBuilder<mask_t, false>::get(F->getContext()); FunctionType *OldFuncTy = F->getFunctionType(); std::vector<Type*> ArgTys; ArgTys.insert(ArgTys.end(), OldFuncTy->param_begin(), OldFuncTy->param_end()); ArgTys.insert(ArgTys.end(), FI.ArgNodes.size(), MaskTy); FunctionType *CloneFuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys, OldFuncTy->isVarArg()); Function *Clone = Function::Create(CloneFuncTy, Function::InternalLinkage, F->getName() + "_CONTEXT_SENSITIVE"); F->getParent()->getFunctionList().insert(F->getIterator(), Clone); Function::arg_iterator CI = Clone->arg_begin(), CE = Clone->arg_end(); // Map the old arguments to the clone arguments and set the name of the // clone arguments the same as the original. for (Function::arg_iterator i = F->arg_begin(), e = F->arg_end(); i != e && CI != CE; i++, CI++) { FI.OldToNewMap[&*i] = &*CI; CI->setName(i->getName()); } // Set the name of the arg masks and associate them with the nodes they are // the masks for. for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++CI) { CI->setName("arg_mask"); FI.ArgMaskMap[FI.ArgNodes[i]] = &*CI; } SmallVector<ReturnInst*, 8> Returns; CloneFunctionInto(Clone, F, FI.OldToNewMap, false, Returns); Clone->setCallingConv(F->getCallingConv()); // Invert OldToNewMap for (auto I : FI.OldToNewMap) { FI.NewToOldMap[I.second] = I.first; } NumClones++; return Clone; }
void HeterotbbTransform::copy_function (Function* NF, Function* F) { DenseMap<const Value*, Value *> ValueMap; // Get the names of the parameters for old function for(Function::arg_iterator FI = F->arg_begin(), FE=F->arg_end(), DI=NF->arg_begin(); FE!=FI; ++FI,++DI) { DI->setName(FI->getName()); ValueMap[FI]=DI; } for (Function::const_iterator BI=F->begin(),BE = F->end(); BI != BE; ++BI) { const BasicBlock &FBB = *BI; BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF); ValueMap[&FBB] = NFBB; if (FBB.hasName()) { NFBB->setName(FBB.getName()); //DEBUG(dbgs()<<NFBB->getName()<<"\n"); } for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } } // Remap the instructions again to take care of forward jumps for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) { for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) { int opIdx = 0; //DEBUG(dbgs()<<*II<<"\n"); for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) { Value *V = *i; if (ValueMap[V] != NULL) { II->setOperand(opIdx, ValueMap[V]); } } } } //NF->dump(); }
/// lowerIncomingArguments - To avoid having to handle incoming arguments /// specially, we lower each arg to a copy instruction in the entry block. This /// ensures that the argument value itself cannot be live out of the entry /// block. void SjLjEHPass::lowerIncomingArguments(Function &F) { BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); while (isa<AllocaInst>(AfterAllocaInsPt) && isa<ConstantInt>(cast<AllocaInst>(AfterAllocaInsPt)->getArraySize())) ++AfterAllocaInsPt; for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++AI) { Type *Ty = AI->getType(); // Aggregate types can't be cast, but are legal argument types, so we have // to handle them differently. We use an extract/insert pair as a // lightweight method to achieve the same goal. if (isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) { Instruction *EI = ExtractValueInst::Create(AI, 0, "", AfterAllocaInsPt); Instruction *NI = InsertValueInst::Create(AI, EI, 0); NI->insertAfter(EI); AI->replaceAllUsesWith(NI); // Set the operand of the instructions back to the AllocaInst. EI->setOperand(0, AI); NI->setOperand(0, AI); } else { // This is always a no-op cast because we're casting AI to AI->getType() // so src and destination types are identical. BitCast is the only // possibility. CastInst *NC = new BitCastInst(AI, AI->getType(), AI->getName() + ".tmp", AfterAllocaInsPt); AI->replaceAllUsesWith(NC); // Set the operand of the cast instruction back to the AllocaInst. // Normally it's forbidden to replace a CastInst's operand because it // could cause the opcode to reflect an illegal conversion. However, we're // replacing it here with the same value it was constructed with. We do // this because the above replaceAllUsesWith() clobbered the operand, but // we want this one to remain. NC->setOperand(0, AI); } } }
///////////////////////// //dupFuncArgu() // ///////////////////////// void InsDuplica::dupFuncArgu(Function &F) { BasicBlock *firstBB = F.begin(); Instruction *firstI = firstBB->begin(); for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); AI != E; ++AI) { arguSet.insert(AI); //if argument is used only once or all on the same block, //do not dup it. if (AI->hasOneUse()) { valueMap[AI] = AI; } else { //make copy of cast Type *arguType = AI->getType(); //FIXME unknow signed or not CastInst* newCast = CastInst::CreateIntegerCast(AI, arguType, 1, AI->getName()+"_dup", firstI); //CastInst *newCast = new CastInst(AI, arguType, AI->getName()+"_dup", firstI); valueMap[AI] = newCast; } } }
/// lowerIncomingArguments - To avoid having to handle incoming arguments /// specially, we lower each arg to a copy instruction in the entry block. This /// ensures that the argument value itself cannot be live out of the entry /// block. void SjLjEHPrepare::lowerIncomingArguments(Function &F) { BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); while (isa<AllocaInst>(AfterAllocaInsPt) && isa<ConstantInt>(cast<AllocaInst>(AfterAllocaInsPt)->getArraySize())) ++AfterAllocaInsPt; for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++AI) { Type *Ty = AI->getType(); // Use 'select i8 true, %arg, undef' to simulate a 'no-op' instruction. Value *TrueValue = ConstantInt::getTrue(F.getContext()); Value *UndefValue = UndefValue::get(Ty); Instruction *SI = SelectInst::Create(TrueValue, AI, UndefValue, AI->getName() + ".tmp", AfterAllocaInsPt); AI->replaceAllUsesWith(SI); // Reset the operand, because it was clobbered by the RAUW above. SI->setOperand(1, AI); } }
// linkFunctionBody - Copy the source function over into the dest function and // fix up references to values. At this point we know that Dest is an external // function, and that Src is not. void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) { assert(Src && Dst && Dst->isDeclaration() && !Src->isDeclaration()); // Go through and convert function arguments over, remembering the mapping. Function::arg_iterator DI = Dst->arg_begin(); for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); I != E; ++I, ++DI) { DI->setName(I->getName()); // Copy the name over. // Add a mapping to our mapping. ValueMap[I] = DI; } if (Mode == Linker::DestroySource) { // Splice the body of the source function into the dest function. Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList()); // At this point, all of the instructions and values of the function are now // copied over. The only problem is that they are still referencing values in // the Source function as operands. Loop through all of the operands of the // functions and patch them up to point to the local versions. for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap); } else { // Clone the body of the function into the dest function. SmallVector<ReturnInst*, 8> Returns; // Ignore returns. CloneFunctionInto(Dst, Src, ValueMap, false, Returns, "", NULL, &TypeMap); } // There is no need to map the arguments anymore. for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); I != E; ++I) ValueMap.erase(I); }
// First thing we need to do is scan the whole function for values that are // live across unwind edges. Each value that is live across an unwind edge // we spill into a stack location, guaranteeing that there is nothing live // across the unwind edge. This process also splits all critical edges // coming out of invoke's. void LowerInvoke:: splitLiveRangesLiveAcrossInvokes(std::vector<InvokeInst*> &Invokes) { // First step, split all critical edges from invoke instructions. for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { InvokeInst *II = Invokes[i]; SplitCriticalEdge(II, 0, this); SplitCriticalEdge(II, 1, this); assert(!isa<PHINode>(II->getNormalDest()) && !isa<PHINode>(II->getUnwindDest()) && "critical edge splitting left single entry phi nodes?"); } Function *F = Invokes.back()->getParent()->getParent(); // To avoid having to handle incoming arguments specially, we lower each arg // to a copy instruction in the entry block. This ensures that the argument // value itself cannot be live across the entry block. BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin(); while (isa<AllocaInst>(AfterAllocaInsertPt) && isa<ConstantInt>(cast<AllocaInst>(AfterAllocaInsertPt)->getArraySize())) ++AfterAllocaInsertPt; for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI) { // This is always a no-op cast because we're casting AI to AI->getType() so // src and destination types are identical. BitCast is the only possibility. CastInst *NC = new BitCastInst( AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); AI->replaceAllUsesWith(NC); // Normally its is forbidden to replace a CastInst's operand because it // could cause the opcode to reflect an illegal conversion. However, we're // replacing it here with the same value it was constructed with to simply // make NC its user. NC->setOperand(0, AI); } // Finally, scan the code looking for instructions with bad live ranges. for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { // Ignore obvious cases we don't have to handle. In particular, most // instructions either have no uses or only have a single use inside the // current block. Ignore them quickly. Instruction *Inst = II; if (Inst->use_empty()) continue; if (Inst->hasOneUse() && cast<Instruction>(Inst->use_back())->getParent() == BB && !isa<PHINode>(Inst->use_back())) continue; // If this is an alloca in the entry block, it's not a real register // value. if (AllocaInst *AI = dyn_cast<AllocaInst>(Inst)) if (isa<ConstantInt>(AI->getArraySize()) && BB == F->begin()) continue; // Avoid iterator invalidation by copying users to a temporary vector. std::vector<Instruction*> Users; for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { Instruction *User = cast<Instruction>(*UI); if (User->getParent() != BB || isa<PHINode>(User)) Users.push_back(User); } // Scan all of the uses and see if the live range is live across an unwind // edge. If we find a use live across an invoke edge, create an alloca // and spill the value. std::set<InvokeInst*> InvokesWithStoreInserted; // Find all of the blocks that this value is live in. std::set<BasicBlock*> LiveBBs; LiveBBs.insert(Inst->getParent()); while (!Users.empty()) { Instruction *U = Users.back(); Users.pop_back(); if (!isa<PHINode>(U)) { MarkBlocksLiveIn(U->getParent(), LiveBBs); } else { // Uses for a PHI node occur in their predecessor block. PHINode *PN = cast<PHINode>(U); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (PN->getIncomingValue(i) == Inst) MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); } } // Now that we know all of the blocks that this thing is live in, see if // it includes any of the unwind locations. bool NeedsSpill = false; for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { NeedsSpill = true; } } // If we decided we need a spill, do it. if (NeedsSpill) { ++NumSpilled; DemoteRegToStack(*Inst, true); } } }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Clone functions that take GEPs as arguments // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool GEPExprArgs::runOnModule(Module& M) { bool changed; do { changed = false; for (Module::iterator F = M.begin(); F != M.end(); ++F){ for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { CallInst *CI = dyn_cast<CallInst>(I++); if(!CI) continue; if(CI->hasByValArgument()) continue; // if the GEP calls a function, that is externally defined, // or might be changed, ignore this call site. Function *F = CI->getCalledFunction(); if (!F || (F->isDeclaration() || F->mayBeOverridden())) continue; if(F->hasStructRetAttr()) continue; if(F->isVarArg()) continue; // find the argument we must replace Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); unsigned argNum = 1; for(; argNum < CI->getNumOperands();argNum++, ++ai) { if(ai->use_empty()) continue; if (isa<GEPOperator>(CI->getOperand(argNum))) break; } // if no argument was a GEP operator to be changed if(ai == ae) continue; GEPOperator *GEP = dyn_cast<GEPOperator>(CI->getOperand(argNum)); if(!GEP->hasAllConstantIndices()) continue; // Construct the new Type // Appends the struct Type at the beginning std::vector<Type*>TP; TP.push_back(GEP->getPointerOperand()->getType()); for(unsigned c = 1; c < CI->getNumOperands();c++) { TP.push_back(CI->getOperand(c)->getType()); } //return type is same as that of original instruction FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); Function *NewF; numSimplified++; if(numSimplified > 800) return true; NewF = Function::Create(NewFTy, GlobalValue::InternalLinkage, F->getName().str() + ".TEST", &M); Function::arg_iterator NI = NewF->arg_begin(); NI->setName("GEParg"); ++NI; ValueToValueMapTy ValueMap; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++II, ++NI) { ValueMap[II] = NI; NI->setName(II->getName()); NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1)); } NewF->setAttributes(NewF->getAttributes().addAttr( 0, F->getAttributes().getRetAttributes())); // Perform the cloning. SmallVector<ReturnInst*,100> Returns; CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector<Value*> fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { fargs.push_back(ai); } NewF->setAttributes(NewF->getAttributes().addAttr( ~0, F->getAttributes().getFnAttributes())); //Get the point to insert the GEP instr. SmallVector<Value*, 8> Ops(CI->op_begin()+1, CI->op_end()); Instruction *InsertPoint; for (BasicBlock::iterator insrt = NewF->front().begin(); isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;} NI = NewF->arg_begin(); SmallVector<Value*, 8> Indices; Indices.append(GEP->op_begin()+1, GEP->op_end()); GetElementPtrInst *GEP_new = GetElementPtrInst::Create(cast<Value>(NI), Indices, "", InsertPoint); fargs.at(argNum)->replaceAllUsesWith(GEP_new); unsigned j = argNum + 1; for(; j < CI->getNumOperands();j++) { if(CI->getOperand(j) == GEP) fargs.at(j)->replaceAllUsesWith(GEP_new); } SmallVector<AttributeWithIndex, 8> AttributesVec; // Get the initial attributes of the call AttrListPtr CallPAL = CI->getAttributes(); Attributes RAttrs = CallPAL.getRetAttributes(); Attributes FnAttrs = CallPAL.getFnAttributes(); if (RAttrs) AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs)); SmallVector<Value*, 8> Args; Args.push_back(GEP->getPointerOperand()); for(unsigned j =1;j<CI->getNumOperands();j++) { Args.push_back(CI->getOperand(j)); // position in the AttributesVec if (Attributes Attrs = CallPAL.getParamAttributes(j)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } // Create the new attributes vec. if (FnAttrs != Attribute::None) AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); CI->eraseFromParent(); changed = true; } } } } while(changed); return true; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // If a function returns a struct, make it return // a pointer to the struct. // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool StructRet::runOnModule(Module& M) { const llvm::DataLayout targetData(&M); std::vector<Function*> worklist; for (Module::iterator I = M.begin(); I != M.end(); ++I) if (!I->mayBeOverridden()) { if(I->hasAddressTaken()) continue; if(I->getReturnType()->isStructTy()) { worklist.push_back(I); } } while(!worklist.empty()) { Function *F = worklist.back(); worklist.pop_back(); Type *NewArgType = F->getReturnType()->getPointerTo(); // Construct the new Type std::vector<Type*>TP; TP.push_back(NewArgType); for (Function::arg_iterator ii = F->arg_begin(), ee = F->arg_end(); ii != ee; ++ii) { TP.push_back(ii->getType()); } FunctionType *NFTy = FunctionType::get(F->getReturnType(), TP, F->isVarArg()); // Create the new function body and insert it into the module. Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName(), &M); ValueToValueMapTy ValueMap; Function::arg_iterator NI = NF->arg_begin(); NI->setName("ret"); ++NI; for (Function::arg_iterator II = F->arg_begin(); II != F->arg_end(); ++II, ++NI) { ValueMap[II] = NI; NI->setName(II->getName()); AttributeSet attrs = F->getAttributes().getParamAttributes(II->getArgNo() + 1); if (!attrs.isEmpty()) NI->addAttr(attrs); } // Perform the cloning. SmallVector<ReturnInst*,100> Returns; if (!F->isDeclaration()) CloneFunctionInto(NF, F, ValueMap, false, Returns); std::vector<Value*> fargs; for(Function::arg_iterator ai = NF->arg_begin(), ae= NF->arg_end(); ai != ae; ++ai) { fargs.push_back(ai); } NF->setAttributes(NF->getAttributes().addAttributes( M.getContext(), 0, F->getAttributes().getRetAttributes())); NF->setAttributes(NF->getAttributes().addAttributes( M.getContext(), ~0, F->getAttributes().getFnAttributes())); for (Function::iterator B = NF->begin(), FE = NF->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { ReturnInst * RI = dyn_cast<ReturnInst>(I++); if(!RI) continue; LoadInst *LI = dyn_cast<LoadInst>(RI->getOperand(0)); assert(LI && "Return should be preceded by a load instruction"); IRBuilder<> Builder(RI); Builder.CreateMemCpy(fargs.at(0), LI->getPointerOperand(), targetData.getTypeStoreSize(LI->getType()), targetData.getPrefTypeAlignment(LI->getType())); } } for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); ui != ue; ) { CallInst *CI = dyn_cast<CallInst>(*ui++); if(!CI) continue; if(CI->getCalledFunction() != F) continue; if(CI->hasByValArgument()) continue; AllocaInst *AllocaNew = new AllocaInst(F->getReturnType(), 0, "", CI); SmallVector<Value*, 8> Args; //this should probably be done in a different manner AttributeSet NewCallPAL=AttributeSet(); // Get the initial attributes of the call AttributeSet CallPAL = CI->getAttributes(); AttributeSet RAttrs = CallPAL.getRetAttributes(); AttributeSet FnAttrs = CallPAL.getFnAttributes(); if (!RAttrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),0, RAttrs); Args.push_back(AllocaNew); for(unsigned j = 0; j < CI->getNumOperands()-1; j++) { Args.push_back(CI->getOperand(j)); // position in the NewCallPAL AttributeSet Attrs = CallPAL.getParamAttributes(j); if (!Attrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),Args.size(), Attrs); } // Create the new attributes vec. if (!FnAttrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),~0, FnAttrs); CallInst *CallI = CallInst::Create(NF, Args, "", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); LoadInst *LI = new LoadInst(AllocaNew, "", CI); CI->replaceAllUsesWith(LI); CI->eraseFromParent(); } if(F->use_empty()) F->eraseFromParent(); } return true; }
// generate code for ops which return a void value void gen_code_void_op(const char *name, FILE *outfile, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } // add local variables for op parameters if (nb_args > 0) { fprintf(outfile, " long "); for(i = 0; i < nb_args; i++) { if (i != 0) fprintf(outfile, ", "); fprintf(outfile, "param%d", i + 1); } fprintf(outfile, ";\n"); } // load parameters in variables for(i = 0; i < nb_args; i++) { fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); } // load op parameters into the arguments of the call // fprintf(outfile, "Value * args[MAX_ARGS];\n"); // for (i = 0; i < nb_args; i++) { // fprintf(outfile, "args[%d] = ConstantInt::get(Type::Int32Ty, param%d);\n", i, i + 1); // } // for (i = nb_args; i < MAX_ARGS; i++) { // fprintf(outfile, "args[%d] = zero;\n", i); // } // add call to micro op //fprintf(outfile, " currCall = new CallInst(M->getFunction(\"%s\"), (Value **)&args, %d, \"\", currInst);\n", name, MAX_ARGS); // load op parameters into the arguments of the call fprintf(outfile, "std::vector<Value *> args;\n"); for (i = 0; i < nb_args; i++) { fprintf(outfile, "args.push_back(ConstantInt::get(Type::Int32Ty, param%d));\n", i + 1); } for (i = nb_args; i < MAX_ARGS; i++) { fprintf(outfile, "args.push_back(zero);\n"); } // add call to micro op fprintf(outfile, " currCall = new CallInst(M->getFunction(\"%s\"), args.begin(), args.end(), \"\", currInst);\n", name); if (strcmp(name, "op_exit_tb") == 0) { fprintf(outfile, " currBB = new BasicBlock(\"\", tb);\n" " currInst = new ReturnInst(fallThrough, currBB);\n" ); } else if (strcmp(name, "op_goto_tb0")) { // fprintf(outfile, // " currBB = new BasicBlock(\"\", tb);\n" // " currInst = new ReturnInst(tb0, currBB);\n" // ); } else if (strcmp(name, "op_goto_tb1")) { // fprintf(outfile, // " currBB = new BasicBlock(\"\", tb);\n" // " currInst = new ReturnInst(tb1, currBB);\n" // ); } fprintf(outfile, " InlineFunction(currCall);"); // inlining can change the basic block the return instruction belongs to fprintf(outfile, " currBB = currInst->getParent();"); }
/// splitLiveRangesAcrossInvokes - Each value that is live across an unwind edge /// we spill into a stack location, guaranteeing that there is nothing live /// across the unwind edge. This process also splits all critical edges /// coming out of invoke's. /// FIXME: Move this function to a common utility file (Local.cpp?) so /// both SjLj and LowerInvoke can use it. void SjLjEHPass:: splitLiveRangesAcrossInvokes(SmallVector<InvokeInst*,16> &Invokes) { // First step, split all critical edges from invoke instructions. for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { InvokeInst *II = Invokes[i]; SplitCriticalEdge(II, 0, this); // FIXME: New EH - This if-condition will be always true in the new scheme. if (II->getUnwindDest()->isLandingPad()) { SmallVector<BasicBlock*, 2> NewBBs; SplitLandingPadPredecessors(II->getUnwindDest(), II->getParent(), ".1", ".2", this, NewBBs); LPadSuccMap[II] = *succ_begin(NewBBs[0]); } else { SplitCriticalEdge(II, 1, this); } assert(!isa<PHINode>(II->getNormalDest()) && !isa<PHINode>(II->getUnwindDest()) && "Critical edge splitting left single entry phi nodes?"); } Function *F = Invokes.back()->getParent()->getParent(); // To avoid having to handle incoming arguments specially, we lower each arg // to a copy instruction in the entry block. This ensures that the argument // value itself cannot be live across the entry block. BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin(); while (isa<AllocaInst>(AfterAllocaInsertPt) && isa<ConstantInt>(cast<AllocaInst>(AfterAllocaInsertPt)->getArraySize())) ++AfterAllocaInsertPt; for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI) { Type *Ty = AI->getType(); // Aggregate types can't be cast, but are legal argument types, so we have // to handle them differently. We use an extract/insert pair as a // lightweight method to achieve the same goal. if (isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) { Instruction *EI = ExtractValueInst::Create(AI, 0, "",AfterAllocaInsertPt); Instruction *NI = InsertValueInst::Create(AI, EI, 0); NI->insertAfter(EI); AI->replaceAllUsesWith(NI); // Set the operand of the instructions back to the AllocaInst. EI->setOperand(0, AI); NI->setOperand(0, AI); } else { // This is always a no-op cast because we're casting AI to AI->getType() // so src and destination types are identical. BitCast is the only // possibility. CastInst *NC = new BitCastInst( AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); AI->replaceAllUsesWith(NC); // Set the operand of the cast instruction back to the AllocaInst. // Normally it's forbidden to replace a CastInst's operand because it // could cause the opcode to reflect an illegal conversion. However, // we're replacing it here with the same value it was constructed with. // We do this because the above replaceAllUsesWith() clobbered the // operand, but we want this one to remain. NC->setOperand(0, AI); } } // Finally, scan the code looking for instructions with bad live ranges. for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { // Ignore obvious cases we don't have to handle. In particular, most // instructions either have no uses or only have a single use inside the // current block. Ignore them quickly. Instruction *Inst = II; if (Inst->use_empty()) continue; if (Inst->hasOneUse() && cast<Instruction>(Inst->use_back())->getParent() == BB && !isa<PHINode>(Inst->use_back())) continue; // If this is an alloca in the entry block, it's not a real register // value. if (AllocaInst *AI = dyn_cast<AllocaInst>(Inst)) if (isa<ConstantInt>(AI->getArraySize()) && BB == F->begin()) continue; // Avoid iterator invalidation by copying users to a temporary vector. SmallVector<Instruction*,16> Users; for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { Instruction *User = cast<Instruction>(*UI); if (User->getParent() != BB || isa<PHINode>(User)) Users.push_back(User); } // Find all of the blocks that this value is live in. std::set<BasicBlock*> LiveBBs; LiveBBs.insert(Inst->getParent()); while (!Users.empty()) { Instruction *U = Users.back(); Users.pop_back(); if (!isa<PHINode>(U)) { MarkBlocksLiveIn(U->getParent(), LiveBBs); } else { // Uses for a PHI node occur in their predecessor block. PHINode *PN = cast<PHINode>(U); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (PN->getIncomingValue(i) == Inst) MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); } } // Now that we know all of the blocks that this thing is live in, see if // it includes any of the unwind locations. bool NeedsSpill = false; for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { NeedsSpill = true; } } // If we decided we need a spill, do it. // FIXME: Spilling this way is overkill, as it forces all uses of // the value to be reloaded from the stack slot, even those that aren't // in the unwind blocks. We should be more selective. if (NeedsSpill) { ++NumSpilled; DemoteRegToStack(*Inst, true); } } }
Function* HeterotbbTransform::create_new_join(Module &M,Function *join) { //reduce->dump(); if(!templat) { DEBUG(dbgs()<<"NO Template Found\n"); return NULL; } //join_main->dump(); DEBUG(dbgs()<<"Objext size array"<<object_size_hetero<<"\n"); //create a global with 64*object/4 size GlobalVariable *gb = M.getGlobalVariable("opencl_kernel_join_name_local_arr",true); //gb->dump(); Value *val=gb->getOperand(0); //if(isa<ArrayType>(val->getType()))DEBUG(dbgs()<<"YES\n"); //since we are creating an integer array, the size gets divided by 4 // Do not make it a global variable -- make it a local variable with annotation for local int local_size = 64*object_size_hetero; /*const*/ ArrayType *arr= ArrayType::get(Type::getInt32Ty(M.getContext()),(64*object_size_hetero)/4); /*vector<Constant *> Initializer; APInt zero(32,0); for(int i=0;i<(16*object_size_hetero);i++){ Initializer.push_back(ConstantInt::get(M.getContext(),zero)); } Constant *init = ConstantArray::get(arr, Initializer); GlobalVariable *new_gb = new GlobalVariable(M, arr, false, GlobalVariable::InternalLinkage,init, "__hetero_local_"+join->getName()+"__local__arr",gb,false,3); new_gb->setAlignment(gb->getAlignment()); DEBUG(dbgs()<<"Global Created\n"); new_gb->dump(); */ vector</*const*/ Type *> params; int temp_size=0; object_size_hetero=0; // void join(class.name *,class.name *) //re-write join const FunctionType *FTy = join->getFunctionType(); Function::arg_iterator ArgI = join->arg_begin(); // class.name * params.push_back(PointerType::get((dyn_cast<PointerType>(ArgI->getType())->getElementType()),3)); params.push_back(PointerType::get((dyn_cast<PointerType>(ArgI->getType())->getElementType()),3)); /*const*/ Type *RetTy = FTy->getReturnType(); FunctionType *NFty = FunctionType::get(RetTy,params, false); Function *NF=Function::Create(NFty, join->getLinkage(), join->getName()+"_inline"); NF->copyAttributesFrom(join); #if EXPLICIT_REWRITE copy_function(NF,join); #else ValueToValueMapTy VMap; for(Function::arg_iterator FI = join->arg_begin(), FE=join->arg_end(), DI=NF->arg_begin(); FE!=FI; ++FI,++DI) { DI->setName(FI->getName()); VMap[FI]=DI; } CloneFunctionWithExistingBBInto(NF, NULL, join, VMap); #endif //NF->removeFnAttr(Attributes::get(NF->getContext(), Attribute::NoInline)); NF->addFnAttr(Attribute::AlwaysInline); join->getParent()->getFunctionList().insert(join, NF); params.clear(); const FunctionType *FTemp = templat->getFunctionType(); //create a new template for(Function::arg_iterator FI = templat->arg_begin(), FE=templat->arg_end(); FE!=FI; ++FI) { params.push_back(FI->getType()); } // templat->replaceUsesOfWith(reduce,NF); RetTy = FTy->getReturnType(); NFty = FunctionType::get(RetTy,params, false); Function *templat_copy =Function::Create(NFty, join->getLinkage(), join->getName()+"_hetero"); templat_copy->copyAttributesFrom(templat); #if EXPLICIT_REWRITE copy_function(templat_copy,templat); #else ValueToValueMapTy VMapp; for(Function::arg_iterator FI = templat->arg_begin(), FE=templat->arg_end(), DI=templat_copy->arg_begin(); FE!=FI; ++FI,++DI) { DI->setName(FI->getName()); VMapp[FI]=DI; } CloneFunctionWithExistingBBInto(templat_copy, NULL, templat, VMapp); #endif /* create a local variable with the following type */ Function::iterator BI = templat_copy->begin(); BasicBlock::iterator II = BI->begin(); Instruction *insn = &(*II); Constant *l_size = ConstantInt::get(Type::getInt32Ty(M.getContext()), local_size); Instruction *new_gb_ = new AllocaInst(arr, l_size, gb->getAlignment(), "hetero_local", insn); //new_gb_->dump(); Value *Elts[] = {MDString::get(M.getContext(), new_gb_->getName())}; MDNode *Node = MDNode::get(M.getContext(), Elts); new_gb_->setMetadata("local",Node); Instruction *new_gb= CastInst::Create(Instruction::BitCast, new_gb_, PointerType::get(arr,3), "hetero_local_cast", insn); //new_gb->dump(); Value *Elts1[] = {MDString::get(M.getContext(), new_gb->getName())}; MDNode *Node1 = MDNode::get(M.getContext(), Elts1); new_gb->setMetadata("local_cast",Node1); edit_template_function(M,templat_copy,NF,gb,new_gb); templat->getParent()->getFunctionList().insert(templat, templat_copy); return templat_copy; }
/// DoPromotion - This method actually performs the promotion of the specified /// arguments, and returns the new function. At this point, we know that it's /// safe to do so. static Function * doPromotion(Function *F, SmallPtrSetImpl<Argument *> &ArgsToPromote, SmallPtrSetImpl<Argument *> &ByValArgsToTransform, Optional<function_ref<void(CallSite OldCS, CallSite NewCS)>> ReplaceCallSite) { // Start by computing a new prototype for the function, which is the same as // the old function, but has modified arguments. FunctionType *FTy = F->getFunctionType(); std::vector<Type *> Params; using ScalarizeTable = std::set<std::pair<Type *, IndicesVector>>; // ScalarizedElements - If we are promoting a pointer that has elements // accessed out of it, keep track of which elements are accessed so that we // can add one argument for each. // // Arguments that are directly loaded will have a zero element value here, to // handle cases where there are both a direct load and GEP accesses. std::map<Argument *, ScalarizeTable> ScalarizedElements; // OriginalLoads - Keep track of a representative load instruction from the // original function so that we can tell the alias analysis implementation // what the new GEP/Load instructions we are inserting look like. // We need to keep the original loads for each argument and the elements // of the argument that are accessed. std::map<std::pair<Argument *, IndicesVector>, LoadInst *> OriginalLoads; // Attribute - Keep track of the parameter attributes for the arguments // that we are *not* promoting. For the ones that we do promote, the parameter // attributes are lost SmallVector<AttributeSet, 8> ArgAttrVec; AttributeList PAL = F->getAttributes(); // First, determine the new argument list unsigned ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgNo) { if (ByValArgsToTransform.count(&*I)) { // Simple byval argument? Just add all the struct element types. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); StructType *STy = cast<StructType>(AgTy); Params.insert(Params.end(), STy->element_begin(), STy->element_end()); ArgAttrVec.insert(ArgAttrVec.end(), STy->getNumElements(), AttributeSet()); ++NumByValArgsPromoted; } else if (!ArgsToPromote.count(&*I)) { // Unchanged argument Params.push_back(I->getType()); ArgAttrVec.push_back(PAL.getParamAttributes(ArgNo)); } else if (I->use_empty()) { // Dead argument (which are always marked as promotable) ++NumArgumentsDead; // There may be remaining metadata uses of the argument for things like // llvm.dbg.value. Replace them with undef. I->replaceAllUsesWith(UndefValue::get(I->getType())); } else { // Okay, this is being promoted. This means that the only uses are loads // or GEPs which are only used by loads // In this table, we will track which indices are loaded from the argument // (where direct loads are tracked as no indices). ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; for (User *U : I->users()) { Instruction *UI = cast<Instruction>(U); Type *SrcTy; if (LoadInst *L = dyn_cast<LoadInst>(UI)) SrcTy = L->getType(); else SrcTy = cast<GetElementPtrInst>(UI)->getSourceElementType(); IndicesVector Indices; Indices.reserve(UI->getNumOperands() - 1); // Since loads will only have a single operand, and GEPs only a single // non-index operand, this will record direct loads without any indices, // and gep+loads with the GEP indices. for (User::op_iterator II = UI->op_begin() + 1, IE = UI->op_end(); II != IE; ++II) Indices.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Indices.size() == 1 && Indices.front() == 0) Indices.clear(); ArgIndices.insert(std::make_pair(SrcTy, Indices)); LoadInst *OrigLoad; if (LoadInst *L = dyn_cast<LoadInst>(UI)) OrigLoad = L; else // Take any load, we will use it only to update Alias Analysis OrigLoad = cast<LoadInst>(UI->user_back()); OriginalLoads[std::make_pair(&*I, Indices)] = OrigLoad; } // Add a parameter to the function for each element passed in. for (const auto &ArgIndex : ArgIndices) { // not allowed to dereference ->begin() if size() is 0 Params.push_back(GetElementPtrInst::getIndexedType( cast<PointerType>(I->getType()->getScalarType())->getElementType(), ArgIndex.second)); ArgAttrVec.push_back(AttributeSet()); assert(Params.back()); } if (ArgIndices.size() == 1 && ArgIndices.begin()->second.empty()) ++NumArgumentsPromoted; else ++NumAggregatesPromoted; } } Type *RetTy = FTy->getReturnType(); // Construct the new function type using the new arguments. FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module. Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName()); NF->copyAttributesFrom(F); // Patch the pointer to LLVM function in debug info descriptor. NF->setSubprogram(F->getSubprogram()); F->setSubprogram(nullptr); DEBUG(dbgs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" << "From: " << *F); // Recompute the parameter attributes list based on the new arguments for // the function. NF->setAttributes(AttributeList::get(F->getContext(), PAL.getFnAttributes(), PAL.getRetAttributes(), ArgAttrVec)); ArgAttrVec.clear(); F->getParent()->getFunctionList().insert(F->getIterator(), NF); NF->takeName(F); // Loop over all of the callers of the function, transforming the call sites // to pass in the loaded pointers. // SmallVector<Value *, 16> Args; while (!F->use_empty()) { CallSite CS(F->user_back()); assert(CS.getCalledFunction() == F); Instruction *Call = CS.getInstruction(); const AttributeList &CallPAL = CS.getAttributes(); // Loop over the operands, inserting GEP and loads in the caller as // appropriate. CallSite::arg_iterator AI = CS.arg_begin(); ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++AI, ++ArgNo) if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*I)) { Args.push_back(*AI); // Unmodified argument ArgAttrVec.push_back(CallPAL.getParamAttributes(ArgNo)); } else if (ByValArgsToTransform.count(&*I)) { // Emit a GEP and load for each element of the struct. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr}; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create( STy, *AI, Idxs, (*AI)->getName() + "." + Twine(i), Call); // TODO: Tell AA about the new values? Args.push_back(new LoadInst(Idx, Idx->getName() + ".val", Call)); ArgAttrVec.push_back(AttributeSet()); } } else if (!I->use_empty()) { // Non-dead argument: insert GEPs and loads as appropriate. ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; // Store the Value* version of the indices in here, but declare it now // for reuse. std::vector<Value *> Ops; for (const auto &ArgIndex : ArgIndices) { Value *V = *AI; LoadInst *OrigLoad = OriginalLoads[std::make_pair(&*I, ArgIndex.second)]; if (!ArgIndex.second.empty()) { Ops.reserve(ArgIndex.second.size()); Type *ElTy = V->getType(); for (auto II : ArgIndex.second) { // Use i32 to index structs, and i64 for others (pointers/arrays). // This satisfies GEP constraints. Type *IdxTy = (ElTy->isStructTy() ? Type::getInt32Ty(F->getContext()) : Type::getInt64Ty(F->getContext())); Ops.push_back(ConstantInt::get(IdxTy, II)); // Keep track of the type we're currently indexing. if (auto *ElPTy = dyn_cast<PointerType>(ElTy)) ElTy = ElPTy->getElementType(); else ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(II); } // And create a GEP to extract those indices. V = GetElementPtrInst::Create(ArgIndex.first, V, Ops, V->getName() + ".idx", Call); Ops.clear(); } // Since we're replacing a load make sure we take the alignment // of the previous load. LoadInst *newLoad = new LoadInst(V, V->getName() + ".val", Call); newLoad->setAlignment(OrigLoad->getAlignment()); // Transfer the AA info too. AAMDNodes AAInfo; OrigLoad->getAAMetadata(AAInfo); newLoad->setAAMetadata(AAInfo); Args.push_back(newLoad); ArgAttrVec.push_back(AttributeSet()); } } // Push any varargs arguments on the list. for (; AI != CS.arg_end(); ++AI, ++ArgNo) { Args.push_back(*AI); ArgAttrVec.push_back(CallPAL.getParamAttributes(ArgNo)); } SmallVector<OperandBundleDef, 1> OpBundles; CS.getOperandBundlesAsDefs(OpBundles); CallSite NewCS; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { NewCS = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, OpBundles, "", Call); } else { auto *NewCall = CallInst::Create(NF, Args, OpBundles, "", Call); NewCall->setTailCallKind(cast<CallInst>(Call)->getTailCallKind()); NewCS = NewCall; } NewCS.setCallingConv(CS.getCallingConv()); NewCS.setAttributes( AttributeList::get(F->getContext(), CallPAL.getFnAttributes(), CallPAL.getRetAttributes(), ArgAttrVec)); NewCS->setDebugLoc(Call->getDebugLoc()); uint64_t W; if (Call->extractProfTotalWeight(W)) NewCS->setProfWeight(W); Args.clear(); ArgAttrVec.clear(); // Update the callgraph to know that the callsite has been transformed. if (ReplaceCallSite) (*ReplaceCallSite)(CS, NewCS); if (!Call->use_empty()) { Call->replaceAllUsesWith(NewCS.getInstruction()); NewCS->takeName(Call); } // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } const DataLayout &DL = F->getParent()->getDataLayout(); // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I) { if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*I)) { // If this is an unmodified argument, move the name and users over to the // new version. I->replaceAllUsesWith(&*I2); I2->takeName(&*I); ++I2; continue; } if (ByValArgsToTransform.count(&*I)) { // In the callee, we create an alloca, and store each of the new incoming // arguments into the alloca. Instruction *InsertPt = &NF->begin()->front(); // Just add all the struct element types. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, DL.getAllocaAddrSpace(), nullptr, I->getParamAlignment(), "", InsertPt); StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = {ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr}; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create( AgTy, TheAlloca, Idxs, TheAlloca->getName() + "." + Twine(i), InsertPt); I2->setName(I->getName() + "." + Twine(i)); new StoreInst(&*I2++, Idx, InsertPt); } // Anything that used the arg should now use the alloca. I->replaceAllUsesWith(TheAlloca); TheAlloca->takeName(&*I); // If the alloca is used in a call, we must clear the tail flag since // the callee now uses an alloca from the caller. for (User *U : TheAlloca->users()) { CallInst *Call = dyn_cast<CallInst>(U); if (!Call) continue; Call->setTailCall(false); } continue; } if (I->use_empty()) continue; // Otherwise, if we promoted this argument, then all users are load // instructions (or GEPs with only load users), and all loads should be // using the new argument that we added. ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; while (!I->use_empty()) { if (LoadInst *LI = dyn_cast<LoadInst>(I->user_back())) { assert(ArgIndices.begin()->second.empty() && "Load element should sort to front!"); I2->setName(I->getName() + ".val"); LI->replaceAllUsesWith(&*I2); LI->eraseFromParent(); DEBUG(dbgs() << "*** Promoted load of argument '" << I->getName() << "' in function '" << F->getName() << "'\n"); } else { GetElementPtrInst *GEP = cast<GetElementPtrInst>(I->user_back()); IndicesVector Operands; Operands.reserve(GEP->getNumIndices()); for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); II != IE; ++II) Operands.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Operands.size() == 1 && Operands.front() == 0) Operands.clear(); Function::arg_iterator TheArg = I2; for (ScalarizeTable::iterator It = ArgIndices.begin(); It->second != Operands; ++It, ++TheArg) { assert(It != ArgIndices.end() && "GEP not handled??"); } std::string NewName = I->getName(); for (unsigned i = 0, e = Operands.size(); i != e; ++i) { NewName += "." + utostr(Operands[i]); } NewName += ".val"; TheArg->setName(NewName); DEBUG(dbgs() << "*** Promoted agg argument '" << TheArg->getName() << "' of function '" << NF->getName() << "'\n"); // All of the uses must be load instructions. Replace them all with // the argument specified by ArgNo. while (!GEP->use_empty()) { LoadInst *L = cast<LoadInst>(GEP->user_back()); L->replaceAllUsesWith(&*TheArg); L->eraseFromParent(); } GEP->eraseFromParent(); } } // Increment I2 past all of the arguments added for this promoted pointer. std::advance(I2, ArgIndices.size()); } return NF; }
void RocketShip::processFunction(Function &F) { // Everything is reset per function. Ideally we would just make // this a per-function pass, but extended feature plans make // applying this at the module level a better idea. _nodeId = 0; _blockId = 0; _blocks.clear(); _pnodes.clear(); std::vector<BasicBlock*> blockList; std::string functionLabel = F.getName(); std::string demangledLabel = getDemangledName(functionLabel); if (demangledLabel == functionLabel || demangledLabel.length() == 0) { functionLabel = F.getReturnType()->getDescription() + " " + functionLabel; functionLabel = functionLabel + "("; for (Function::arg_iterator arg = F.arg_begin(); arg != F.arg_end(); arg++) { if (arg != F.arg_begin()) { functionLabel = functionLabel + ", "; } functionLabel = functionLabel + arg->getType()->getDescription() + " " + std::string(arg->getName()); } functionLabel = functionLabel + ")"; } else { functionLabel = demangledLabel; } // Each block in the function needs to be processed and added to // the mapping. for (Function::iterator bblock = F.begin(); bblock != F.end(); bblock++) { pBlock block(new Block(_nodeId++, bblock->getName())); _blocks.insert(std::pair<BasicBlock*, pBlock>(bblock, block)); blockList.push_back(bblock); if (bblock == F.begin()) { pNode node(new Node(_nodeId++)); block->appendNode(node); node->setNodeLabel(functionLabel); node->setNodeType(Node::START); } processBlock(bblock, block); } // Each block needs to process its contained nodes and we need to // keep a local copy of each node for later processing. for (std::map<BasicBlock*, pBlock>::iterator it = _blocks.begin(); it != _blocks.end(); it++) { it->second->processNodes(_blocks); Nodes nodes = it->second->getNodes(); for (Nodes::iterator node = nodes.begin(); node != nodes.end(); node++) { _pnodes.push_back(*node); } } // Generates the function name and filename/output stream. std::string functionIdentifier = F.getName(); char* result = cplus_demangle(functionIdentifier.c_str(), DMGL_ANSI|DMGL_PARAMS); std::replace(functionIdentifier.begin(), functionIdentifier.end(), '.', '_'); _outputFile.open(std::string(functionIdentifier + ".dot").c_str()); _outputFile << "digraph " << functionIdentifier << " {\n"; // Emit each node to the output stream. This should be modified // to have the node print itself out by passing in the output // stream rather than calling a separate function for (Nodes::iterator it = _pnodes.begin(); it != _pnodes.end(); it++) { if ((*it) == NULL) { continue; } // We only care about nodes with labels since they are what is // actually presented. if ((*it)->getNodeLabel().length() > 0) { emitNode(&(*(*it))); } } _outputFile << "}"; _outputFile.close(); }
// generate code for ops which return a void value void gen_code_void_op(const char *name, FILE *outfile, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } // add local variables for op parameters if (nb_args > 0) { fprintf(outfile, " long "); for(i = 0; i < nb_args; i++) { if (i != 0) fprintf(outfile, ", "); fprintf(outfile, "param%d", i + 1); } fprintf(outfile, ";\n"); } // load parameres in variables for(i = 0; i < nb_args; i++) { fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); } // load op parameters into the arguments of the call fprintf(outfile, "Value * args[MAX_ARGS];\n"); for (i = 0; i < nb_args; i++) { fprintf(outfile, "args[%d] = ConstantInt::get(Type::Int32Ty, param%d);\n", i, i + 1); } for (i = nb_args; i < MAX_ARGS; i++) { fprintf(outfile, "args[%d] = zero;\n", i); } // add call to micro op fprintf(outfile, " currCall = new CallInst(M->getFunction(\"%s\"), (Value **)&args, %d, \"\", currBB);\n", name, MAX_ARGS); fprintf(outfile, " InlineFunction(currCall);"); }
/* * Clone a given function removing dead stores */ Function* DeadStoreEliminationPass::cloneFunctionWithoutDeadStore(Function *Fn, Instruction* caller, std::string suffix) { Function *NF = Function::Create(Fn->getFunctionType(), Fn->getLinkage()); NF->copyAttributesFrom(Fn); // Copy the parameter names, to ease function inspection afterwards. Function::arg_iterator NFArg = NF->arg_begin(); for (Function::arg_iterator Arg = Fn->arg_begin(), ArgEnd = Fn->arg_end(); Arg != ArgEnd; ++Arg, ++NFArg) { NFArg->setName(Arg->getName()); } // To avoid name collision, we should select another name. NF->setName(Fn->getName() + suffix); // Fill clone content ValueToValueMapTy VMap; SmallVector<ReturnInst*, 8> Returns; Function::arg_iterator NI = NF->arg_begin(); for (Function::arg_iterator I = Fn->arg_begin(); NI != NF->arg_end(); ++I, ++NI) { VMap[I] = NI; } CloneAndPruneFunctionInto(NF, Fn, VMap, false, Returns); // Remove dead stores std::set<Value*> deadArgs = deadArguments[caller]; std::set<Value*> removeStoresTo; Function::arg_iterator NFArgIter = NF->arg_begin(); for (Function::arg_iterator FnArgIter = Fn->arg_begin(); FnArgIter != Fn->arg_end(); ++FnArgIter, ++NFArgIter) { Value *FnArg = FnArgIter; if (deadArgs.count(FnArg)) { removeStoresTo.insert(NFArgIter); } } std::vector<Instruction*> toRemove; for (Function::iterator BB = NF->begin(); BB != NF->end(); ++BB) { for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { Instruction *inst = I; if (!isa<StoreInst>(inst)) continue; StoreInst *SI = dyn_cast<StoreInst>(inst); Value *ptrOp = SI->getPointerOperand(); if (removeStoresTo.count(ptrOp)) { DEBUG(errs() << "will remove this store: " << *inst << "\n"); toRemove.push_back(inst); } } } for (std::vector<Instruction*>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) { Instruction* inst = *it; inst->eraseFromParent(); RemovedStores++; } // Insert the clone function before the original Fn->getParent()->getFunctionList().insert(Fn, NF); return NF; }
static bool eliminateRecursiveTailCall(CallInst *CI, ReturnInst *Ret, BasicBlock *&OldEntry, bool &TailCallsAreMarkedTail, SmallVectorImpl<PHINode *> &ArgumentPHIs, bool CannotTailCallElimCallsMarkedTail) { // If we are introducing accumulator recursion to eliminate operations after // the call instruction that are both associative and commutative, the initial // value for the accumulator is placed in this variable. If this value is set // then we actually perform accumulator recursion elimination instead of // simple tail recursion elimination. If the operation is an LLVM instruction // (eg: "add") then it is recorded in AccumulatorRecursionInstr. If not, then // we are handling the case when the return instruction returns a constant C // which is different to the constant returned by other return instructions // (which is recorded in AccumulatorRecursionEliminationInitVal). This is a // special case of accumulator recursion, the operation being "return C". Value *AccumulatorRecursionEliminationInitVal = nullptr; Instruction *AccumulatorRecursionInstr = nullptr; // Ok, we found a potential tail call. We can currently only transform the // tail call if all of the instructions between the call and the return are // movable to above the call itself, leaving the call next to the return. // Check that this is the case now. BasicBlock::iterator BBI(CI); for (++BBI; &*BBI != Ret; ++BBI) { if (canMoveAboveCall(&*BBI, CI)) continue; // If we can't move the instruction above the call, it might be because it // is an associative and commutative operation that could be transformed // using accumulator recursion elimination. Check to see if this is the // case, and if so, remember the initial accumulator value for later. if ((AccumulatorRecursionEliminationInitVal = canTransformAccumulatorRecursion(&*BBI, CI))) { // Yes, this is accumulator recursion. Remember which instruction // accumulates. AccumulatorRecursionInstr = &*BBI; } else { return false; // Otherwise, we cannot eliminate the tail recursion! } } // We can only transform call/return pairs that either ignore the return value // of the call and return void, ignore the value of the call and return a // constant, return the value returned by the tail call, or that are being // accumulator recursion variable eliminated. if (Ret->getNumOperands() == 1 && Ret->getReturnValue() != CI && !isa<UndefValue>(Ret->getReturnValue()) && AccumulatorRecursionEliminationInitVal == nullptr && !getCommonReturnValue(nullptr, CI)) { // One case remains that we are able to handle: the current return // instruction returns a constant, and all other return instructions // return a different constant. if (!isDynamicConstant(Ret->getReturnValue(), CI, Ret)) return false; // Current return instruction does not return a constant. // Check that all other return instructions return a common constant. If // so, record it in AccumulatorRecursionEliminationInitVal. AccumulatorRecursionEliminationInitVal = getCommonReturnValue(Ret, CI); if (!AccumulatorRecursionEliminationInitVal) return false; } BasicBlock *BB = Ret->getParent(); Function *F = BB->getParent(); emitOptimizationRemark(F->getContext(), "tailcallelim", *F, CI->getDebugLoc(), "transforming tail recursion to loop"); // OK! We can transform this tail call. If this is the first one found, // create the new entry block, allowing us to branch back to the old entry. if (!OldEntry) { OldEntry = &F->getEntryBlock(); BasicBlock *NewEntry = BasicBlock::Create(F->getContext(), "", F, OldEntry); NewEntry->takeName(OldEntry); OldEntry->setName("tailrecurse"); BranchInst::Create(OldEntry, NewEntry); // If this tail call is marked 'tail' and if there are any allocas in the // entry block, move them up to the new entry block. TailCallsAreMarkedTail = CI->isTailCall(); if (TailCallsAreMarkedTail) // Move all fixed sized allocas from OldEntry to NewEntry. for (BasicBlock::iterator OEBI = OldEntry->begin(), E = OldEntry->end(), NEBI = NewEntry->begin(); OEBI != E; ) if (AllocaInst *AI = dyn_cast<AllocaInst>(OEBI++)) if (isa<ConstantInt>(AI->getArraySize())) AI->moveBefore(&*NEBI); // Now that we have created a new block, which jumps to the entry // block, insert a PHI node for each argument of the function. // For now, we initialize each PHI to only have the real arguments // which are passed in. Instruction *InsertPos = &OldEntry->front(); for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { PHINode *PN = PHINode::Create(I->getType(), 2, I->getName() + ".tr", InsertPos); I->replaceAllUsesWith(PN); // Everyone use the PHI node now! PN->addIncoming(&*I, NewEntry); ArgumentPHIs.push_back(PN); } } // If this function has self recursive calls in the tail position where some // are marked tail and some are not, only transform one flavor or another. We // have to choose whether we move allocas in the entry block to the new entry // block or not, so we can't make a good choice for both. NOTE: We could do // slightly better here in the case that the function has no entry block // allocas. if (TailCallsAreMarkedTail && !CI->isTailCall()) return false; // Ok, now that we know we have a pseudo-entry block WITH all of the // required PHI nodes, add entries into the PHI node for the actual // parameters passed into the tail-recursive call. for (unsigned i = 0, e = CI->getNumArgOperands(); i != e; ++i) ArgumentPHIs[i]->addIncoming(CI->getArgOperand(i), BB); // If we are introducing an accumulator variable to eliminate the recursion, // do so now. Note that we _know_ that no subsequent tail recursion // eliminations will happen on this function because of the way the // accumulator recursion predicate is set up. // if (AccumulatorRecursionEliminationInitVal) { Instruction *AccRecInstr = AccumulatorRecursionInstr; // Start by inserting a new PHI node for the accumulator. pred_iterator PB = pred_begin(OldEntry), PE = pred_end(OldEntry); PHINode *AccPN = PHINode::Create( AccumulatorRecursionEliminationInitVal->getType(), std::distance(PB, PE) + 1, "accumulator.tr", &OldEntry->front()); // Loop over all of the predecessors of the tail recursion block. For the // real entry into the function we seed the PHI with the initial value, // computed earlier. For any other existing branches to this block (due to // other tail recursions eliminated) the accumulator is not modified. // Because we haven't added the branch in the current block to OldEntry yet, // it will not show up as a predecessor. for (pred_iterator PI = PB; PI != PE; ++PI) { BasicBlock *P = *PI; if (P == &F->getEntryBlock()) AccPN->addIncoming(AccumulatorRecursionEliminationInitVal, P); else AccPN->addIncoming(AccPN, P); } if (AccRecInstr) { // Add an incoming argument for the current block, which is computed by // our associative and commutative accumulator instruction. AccPN->addIncoming(AccRecInstr, BB); // Next, rewrite the accumulator recursion instruction so that it does not // use the result of the call anymore, instead, use the PHI node we just // inserted. AccRecInstr->setOperand(AccRecInstr->getOperand(0) != CI, AccPN); } else { // Add an incoming argument for the current block, which is just the // constant returned by the current return instruction. AccPN->addIncoming(Ret->getReturnValue(), BB); } // Finally, rewrite any return instructions in the program to return the PHI // node instead of the "initval" that they do currently. This loop will // actually rewrite the return value we are destroying, but that's ok. for (BasicBlock &BBI : *F) if (ReturnInst *RI = dyn_cast<ReturnInst>(BBI.getTerminator())) RI->setOperand(0, AccPN); ++NumAccumAdded; } // Now that all of the PHI nodes are in place, remove the call and // ret instructions, replacing them with an unconditional branch. BranchInst *NewBI = BranchInst::Create(OldEntry, Ret); NewBI->setDebugLoc(CI->getDebugLoc()); BB->getInstList().erase(Ret); // Remove return. BB->getInstList().erase(CI); // Remove call. ++NumEliminated; return true; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Clone functions that take LoadInsts as arguments // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool LoadArgs::runOnModule(Module& M) { std::map<std::pair<Function*, const Type * > , Function* > fnCache; bool changed; do { changed = false; for (Module::iterator Func = M.begin(); Func != M.end(); ++Func) { for (Function::iterator B = Func->begin(), FE = Func->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { CallInst *CI = dyn_cast<CallInst>(I++); if(!CI) continue; if(CI->hasByValArgument()) continue; // if the CallInst calls a function, that is externally defined, // or might be changed, ignore this call site. Function *F = CI->getCalledFunction(); if (!F || (F->isDeclaration() || F->mayBeOverridden())) continue; if(F->hasStructRetAttr()) continue; if(F->isVarArg()) continue; // find the argument we must replace Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); unsigned argNum = 0; for(; argNum < CI->getNumArgOperands();argNum++, ++ai) { // do not care about dead arguments if(ai->use_empty()) continue; if(F->getAttributes().getParamAttributes(argNum).hasAttrSomewhere(Attribute::SExt) || F->getAttributes().getParamAttributes(argNum).hasAttrSomewhere(Attribute::ZExt)) continue; if (isa<LoadInst>(CI->getArgOperand(argNum))) break; } // if no argument was a GEP operator to be changed if(ai == ae) continue; LoadInst *LI = dyn_cast<LoadInst>(CI->getArgOperand(argNum)); Instruction * InsertPt = &(Func->getEntryBlock().front()); AllocaInst *NewVal = new AllocaInst(LI->getType(), "",InsertPt); StoreInst *Copy = new StoreInst(LI, NewVal); Copy->insertAfter(LI); /*if(LI->getParent() != CI->getParent()) continue; // Also check that there is no store after the load. // TODO: Check if the load/store do not alias. BasicBlock::iterator bii = LI->getParent()->begin(); Instruction *BII = bii; while(BII != LI) { ++bii; BII = bii; } while(BII != CI) { if(isa<StoreInst>(BII)) break; ++bii; BII = bii; } if(isa<StoreInst>(bii)){ continue; }*/ // Construct the new Type // Appends the struct Type at the beginning std::vector<Type*>TP; for(unsigned c = 0; c < CI->getNumArgOperands();c++) { if(c == argNum) TP.push_back(LI->getPointerOperand()->getType()); TP.push_back(CI->getArgOperand(c)->getType()); } //return type is same as that of original instruction FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); numSimplified++; //if(numSimplified > 1000) //return true; Function *NewF; std::map<std::pair<Function*, const Type* > , Function* >::iterator Test; Test = fnCache.find(std::make_pair(F, NewFTy)); if(Test != fnCache.end()) { NewF = Test->second; } else { NewF = Function::Create(NewFTy, GlobalValue::InternalLinkage, F->getName().str() + ".TEST", &M); fnCache[std::make_pair(F, NewFTy)] = NewF; Function::arg_iterator NI = NewF->arg_begin(); ValueToValueMapTy ValueMap; unsigned count = 0; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++count, ++NI) { if(count == argNum) { NI->setName("LDarg"); continue; } ValueMap[II] = NI; NI->setName(II->getName()); NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1)); ++II; } // Perform the cloning. SmallVector<ReturnInst*,100> Returns; CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector<Value*> fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { fargs.push_back(ai); } NewF->setAttributes(NewF->getAttributes().addAttributes( F->getContext(), 0, F->getAttributes().getRetAttributes())); NewF->setAttributes(NewF->getAttributes().addAttributes( F->getContext(), ~0, F->getAttributes().getFnAttributes())); //Get the point to insert the GEP instr. Instruction *InsertPoint; for (BasicBlock::iterator insrt = NewF->front().begin(); isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;} LoadInst *LI_new = new LoadInst(fargs.at(argNum), "", InsertPoint); fargs.at(argNum+1)->replaceAllUsesWith(LI_new); } //this does not seem to be a good idea AttributeSet NewCallPAL=AttributeSet(); // Get the initial attributes of the call AttributeSet CallPAL = CI->getAttributes(); AttributeSet RAttrs = CallPAL.getRetAttributes(); AttributeSet FnAttrs = CallPAL.getFnAttributes(); if (!RAttrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),0, RAttrs); SmallVector<Value*, 8> Args; for(unsigned j =0;j<CI->getNumArgOperands();j++) { if(j == argNum) { Args.push_back(NewVal); } Args.push_back(CI->getArgOperand(j)); // position in the NewCallPAL AttributeSet Attrs = CallPAL.getParamAttributes(j+1); if (!Attrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),Args.size(), Attrs); } // Create the new attributes vec. if (!FnAttrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),~0, FnAttrs); CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); CI->eraseFromParent(); changed = true; } } } } while(changed); return true; }
/// DoPromotion - This method actually performs the promotion of the specified /// arguments, and returns the new function. At this point, we know that it's /// safe to do so. CallGraphNode *ArgPromotion::DoPromotion(Function *F, SmallPtrSet<Argument*, 8> &ArgsToPromote, SmallPtrSet<Argument*, 8> &ByValArgsToTransform) { // Start by computing a new prototype for the function, which is the same as // the old function, but has modified arguments. const FunctionType *FTy = F->getFunctionType(); std::vector<const Type*> Params; typedef std::set<IndicesVector> ScalarizeTable; // ScalarizedElements - If we are promoting a pointer that has elements // accessed out of it, keep track of which elements are accessed so that we // can add one argument for each. // // Arguments that are directly loaded will have a zero element value here, to // handle cases where there are both a direct load and GEP accesses. // std::map<Argument*, ScalarizeTable> ScalarizedElements; // OriginalLoads - Keep track of a representative load instruction from the // original function so that we can tell the alias analysis implementation // what the new GEP/Load instructions we are inserting look like. std::map<IndicesVector, LoadInst*> OriginalLoads; // Attributes - Keep track of the parameter attributes for the arguments // that we are *not* promoting. For the ones that we do promote, the parameter // attributes are lost SmallVector<AttributeWithIndex, 8> AttributesVec; const AttrListPtr &PAL = F->getAttributes(); // Add any return attributes. if (Attributes attrs = PAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // First, determine the new argument list unsigned ArgIndex = 1; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgIndex) { if (ByValArgsToTransform.count(I)) { // Simple byval argument? Just add all the struct element types. const Type *AgTy = cast<PointerType>(I->getType())->getElementType(); const StructType *STy = cast<StructType>(AgTy); for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) Params.push_back(STy->getElementType(i)); ++NumByValArgsPromoted; } else if (!ArgsToPromote.count(I)) { // Unchanged argument Params.push_back(I->getType()); if (Attributes attrs = PAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Params.size(), attrs)); } else if (I->use_empty()) { // Dead argument (which are always marked as promotable) ++NumArgumentsDead; } else { // Okay, this is being promoted. This means that the only uses are loads // or GEPs which are only used by loads // In this table, we will track which indices are loaded from the argument // (where direct loads are tracked as no indices). ScalarizeTable &ArgIndices = ScalarizedElements[I]; for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) { Instruction *User = cast<Instruction>(*UI); assert(isa<LoadInst>(User) || isa<GetElementPtrInst>(User)); IndicesVector Indices; Indices.reserve(User->getNumOperands() - 1); // Since loads will only have a single operand, and GEPs only a single // non-index operand, this will record direct loads without any indices, // and gep+loads with the GEP indices. for (User::op_iterator II = User->op_begin() + 1, IE = User->op_end(); II != IE; ++II) Indices.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Indices.size() == 1 && Indices.front() == 0) Indices.clear(); ArgIndices.insert(Indices); LoadInst *OrigLoad; if (LoadInst *L = dyn_cast<LoadInst>(User)) OrigLoad = L; else // Take any load, we will use it only to update Alias Analysis OrigLoad = cast<LoadInst>(User->use_back()); OriginalLoads[Indices] = OrigLoad; } // Add a parameter to the function for each element passed in. for (ScalarizeTable::iterator SI = ArgIndices.begin(), E = ArgIndices.end(); SI != E; ++SI) { // not allowed to dereference ->begin() if size() is 0 Params.push_back(GetElementPtrInst::getIndexedType(I->getType(), SI->begin(), SI->end())); assert(Params.back()); } if (ArgIndices.size() == 1 && ArgIndices.begin()->empty()) ++NumArgumentsPromoted; else ++NumAggregatesPromoted; } } // Add any function attributes. if (Attributes attrs = PAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); const Type *RetTy = FTy->getReturnType(); // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which // have zero fixed arguments. bool ExtraArgHack = false; if (Params.empty() && FTy->isVarArg()) { ExtraArgHack = true; Params.push_back(Type::getInt32Ty(F->getContext())); } // Construct the new function type using the new arguments. FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module. Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName()); NF->copyAttributesFrom(F); DEBUG(dbgs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" << "From: " << *F); // Recompute the parameter attributes list based on the new arguments for // the function. NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); AttributesVec.clear(); F->getParent()->getFunctionList().insert(F, NF); NF->takeName(F); // Get the alias analysis information that we need to update to reflect our // changes. AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); // Get the callgraph information that we need to update to reflect our // changes. CallGraph &CG = getAnalysis<CallGraph>(); // Get a new callgraph node for NF. CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); // Loop over all of the callers of the function, transforming the call sites // to pass in the loaded pointers. // SmallVector<Value*, 16> Args; while (!F->use_empty()) { CallSite CS = CallSite::get(F->use_back()); assert(CS.getCalledFunction() == F); Instruction *Call = CS.getInstruction(); const AttrListPtr &CallPAL = CS.getAttributes(); // Add any return attributes. if (Attributes attrs = CallPAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // Loop over the operands, inserting GEP and loads in the caller as // appropriate. CallSite::arg_iterator AI = CS.arg_begin(); ArgIndex = 1; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++AI, ++ArgIndex) if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { Args.push_back(*AI); // Unmodified argument if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } else if (ByValArgsToTransform.count(I)) { // Emit a GEP and load for each element of the struct. const Type *AgTy = cast<PointerType>(I->getType())->getElementType(); const StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 }; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create(*AI, Idxs, Idxs+2, (*AI)->getName()+"."+utostr(i), Call); // TODO: Tell AA about the new values? Args.push_back(new LoadInst(Idx, Idx->getName()+".val", Call)); } } else if (!I->use_empty()) { // Non-dead argument: insert GEPs and loads as appropriate. ScalarizeTable &ArgIndices = ScalarizedElements[I]; // Store the Value* version of the indices in here, but declare it now // for reuse. std::vector<Value*> Ops; for (ScalarizeTable::iterator SI = ArgIndices.begin(), E = ArgIndices.end(); SI != E; ++SI) { Value *V = *AI; LoadInst *OrigLoad = OriginalLoads[*SI]; if (!SI->empty()) { Ops.reserve(SI->size()); const Type *ElTy = V->getType(); for (IndicesVector::const_iterator II = SI->begin(), IE = SI->end(); II != IE; ++II) { // Use i32 to index structs, and i64 for others (pointers/arrays). // This satisfies GEP constraints. const Type *IdxTy = (ElTy->isStructTy() ? Type::getInt32Ty(F->getContext()) : Type::getInt64Ty(F->getContext())); Ops.push_back(ConstantInt::get(IdxTy, *II)); // Keep track of the type we're currently indexing. ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(*II); } // And create a GEP to extract those indices. V = GetElementPtrInst::Create(V, Ops.begin(), Ops.end(), V->getName()+".idx", Call); Ops.clear(); AA.copyValue(OrigLoad->getOperand(0), V); } // Since we're replacing a load make sure we take the alignment // of the previous load. LoadInst *newLoad = new LoadInst(V, V->getName()+".val", Call); newLoad->setAlignment(OrigLoad->getAlignment()); Args.push_back(newLoad); AA.copyValue(OrigLoad, Args.back()); } } if (ExtraArgHack) Args.push_back(Constant::getNullValue(Type::getInt32Ty(F->getContext()))); // Push any varargs arguments on the list. for (; AI != CS.arg_end(); ++AI, ++ArgIndex) { Args.push_back(*AI); if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } // Add any function attributes. if (Attributes attrs = CallPAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args.begin(), Args.end(), "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); } else { New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } Args.clear(); AttributesVec.clear(); // Update the alias analysis implementation to know that we are replacing // the old call with a new one. AA.replaceWithNewValue(Call, New); // Update the callgraph to know that the callsite has been transformed. CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; CalleeNode->replaceCallEdge(Call, New, NF_CGN); if (!Call->use_empty()) { Call->replaceAllUsesWith(New); New->takeName(Call); } // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transfering uses of the old arguments over to // the new arguments, also transfering over the names as well. // for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I) { if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { // If this is an unmodified argument, move the name and users over to the // new version. I->replaceAllUsesWith(I2); I2->takeName(I); AA.replaceWithNewValue(I, I2); ++I2; continue; } if (ByValArgsToTransform.count(I)) { // In the callee, we create an alloca, and store each of the new incoming // arguments into the alloca. Instruction *InsertPt = NF->begin()->begin(); // Just add all the struct element types. const Type *AgTy = cast<PointerType>(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, 0, "", InsertPt); const StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 }; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create(TheAlloca, Idxs, Idxs+2, TheAlloca->getName()+"."+Twine(i), InsertPt); I2->setName(I->getName()+"."+Twine(i)); new StoreInst(I2++, Idx, InsertPt); } // Anything that used the arg should now use the alloca. I->replaceAllUsesWith(TheAlloca); TheAlloca->takeName(I); AA.replaceWithNewValue(I, TheAlloca); continue; } if (I->use_empty()) { AA.deleteValue(I); continue; } // Otherwise, if we promoted this argument, then all users are load // instructions (or GEPs with only load users), and all loads should be // using the new argument that we added. ScalarizeTable &ArgIndices = ScalarizedElements[I]; while (!I->use_empty()) { if (LoadInst *LI = dyn_cast<LoadInst>(I->use_back())) { assert(ArgIndices.begin()->empty() && "Load element should sort to front!"); I2->setName(I->getName()+".val"); LI->replaceAllUsesWith(I2); AA.replaceWithNewValue(LI, I2); LI->eraseFromParent(); DEBUG(dbgs() << "*** Promoted load of argument '" << I->getName() << "' in function '" << F->getName() << "'\n"); } else { GetElementPtrInst *GEP = cast<GetElementPtrInst>(I->use_back()); IndicesVector Operands; Operands.reserve(GEP->getNumIndices()); for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); II != IE; ++II) Operands.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Operands.size() == 1 && Operands.front() == 0) Operands.clear(); Function::arg_iterator TheArg = I2; for (ScalarizeTable::iterator It = ArgIndices.begin(); *It != Operands; ++It, ++TheArg) { assert(It != ArgIndices.end() && "GEP not handled??"); } std::string NewName = I->getName(); for (unsigned i = 0, e = Operands.size(); i != e; ++i) { NewName += "." + utostr(Operands[i]); } NewName += ".val"; TheArg->setName(NewName); DEBUG(dbgs() << "*** Promoted agg argument '" << TheArg->getName() << "' of function '" << NF->getName() << "'\n"); // All of the uses must be load instructions. Replace them all with // the argument specified by ArgNo. while (!GEP->use_empty()) { LoadInst *L = cast<LoadInst>(GEP->use_back()); L->replaceAllUsesWith(TheArg); AA.replaceWithNewValue(L, TheArg); L->eraseFromParent(); } AA.deleteValue(GEP); GEP->eraseFromParent(); } } // Increment I2 past all of the arguments added for this promoted pointer. for (unsigned i = 0, e = ArgIndices.size(); i != e; ++i) ++I2; } // Notify the alias analysis implementation that we inserted a new argument. if (ExtraArgHack) AA.copyValue(Constant::getNullValue(Type::getInt32Ty(F->getContext())), NF->arg_begin()); // Tell the alias analysis that the old function is about to disappear. AA.replaceWithNewValue(F, NF); NF_CGN->stealCalledFunctionsFrom(CG[F]); // Now that the old function is dead, delete it. If there is a dangling // reference to the CallgraphNode, just leave the dead function around for // someone else to nuke. CallGraphNode *CGN = CG[F]; if (CGN->getNumReferences() == 0) delete CG.removeFunctionFromModule(CGN); else F->setLinkage(Function::ExternalLinkage); return NF_CGN; }
// ============================================================================= // createProcess // // Create a new function that contains a call to the old function. // We inline the call in order to clone the old function's implementation. // ============================================================================= Function *TLMBasicPassImpl::createProcess(Function *oldProc, sc_core::sc_module *initiatorMod) { LLVMContext &context = getGlobalContext(); IntegerType *intType; if (this->is64Bit) { intType = Type::getInt64Ty(context); } else { intType = Type::getInt32Ty(context); } // Retrieve a pointer to the initiator module ConstantInt *initiatorModVal = ConstantInt::getSigned(intType,reinterpret_cast<intptr_t>(initiatorMod)); FunctionType *funType = oldProc->getFunctionType(); Type *type = funType->getParamType(0); IntToPtrInst *thisAddr = new IntToPtrInst(initiatorModVal, type, ""); // Compute the type of the new function FunctionType *oldProcType = oldProc->getFunctionType(); Value **argsBegin = new Value*[1]; Value **argsEnd = argsBegin; *argsEnd++ = thisAddr; const unsigned argsSize = argsEnd-argsBegin; Value **args = argsBegin; assert(oldProcType->getNumParams()==argsSize); assert(!oldProc->isDeclaration()); std::vector<Type*> argTypes; for (unsigned i = 0; i!=argsSize; ++i) argTypes.push_back(oldProcType->getParamType(i)); FunctionType *newProcType = FunctionType::get(oldProc->getReturnType(), ArrayRef<Type*>(argTypes), false); // Create the new function std::ostringstream id; id << proc_counter++; std::string name = oldProc->getName().str()+std::string("_clone_")+id.str(); Function *newProc = Function::Create(newProcType, Function::ExternalLinkage, name, this->llvmMod); assert(newProc->empty()); newProc->addFnAttr(Attributes::InlineHint); { // Set name of newfunc arguments and complete args Function::arg_iterator nai = newProc->arg_begin(); Function::arg_iterator oai = oldProc->arg_begin(); for (unsigned i = 0; i!=argsSize; ++i, ++oai) { nai->setName(oai->getName()); args[i] = nai; ++nai; } assert(nai==newProc->arg_end()); assert(oai==oldProc->arg_end()); } // Create call to old function BasicBlock *bb = BasicBlock::Create(context, "entry", newProc); IRBuilder<> *irb = new IRBuilder<>(context); irb->SetInsertPoint(bb); CallInst *ci = irb->CreateCall(oldProc, ArrayRef<Value*>(argsBegin, argsEnd)); bb->getInstList().insert(ci, thisAddr); if (ci->getType()->isVoidTy()) irb->CreateRetVoid(); else irb->CreateRet(ci); // The function should be valid now verifyFunction(*newProc); { // Inline the call DataLayout *td = new DataLayout(this->llvmMod); InlineFunctionInfo i(NULL, td); bool success = InlineFunction(ci, i); assert(success); verifyFunction(*newProc); } //newProc->dump(); return newProc; }
// RemoveDeadStuffFromFunction - Remove any arguments and return values from F // that are not in LiveValues. Transform the function and all of the callees of // the function to not have these arguments and return values. // bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Don't modify fully live functions if (LiveFunctions.count(F)) return false; // Start by computing a new prototype for the function, which is the same as // the old function, but has fewer arguments and a different return type. FunctionType *FTy = F->getFunctionType(); std::vector<Type*> Params; // Set up to build a new list of parameter attributes. SmallVector<AttributeWithIndex, 8> AttributesVec; const AttributeSet &PAL = F->getAttributes(); // Find out the new return value. Type *RetTy = FTy->getReturnType(); Type *NRetTy = NULL; unsigned RetCount = NumRetVals(F); // -1 means unused, other numbers are the new index SmallVector<int, 5> NewRetIdxs(RetCount, -1); std::vector<Type*> RetTypes; if (RetTy->isVoidTy()) { NRetTy = RetTy; } else { StructType *STy = dyn_cast<StructType>(RetTy); if (STy) // Look at each of the original return values individually. for (unsigned i = 0; i != RetCount; ++i) { RetOrArg Ret = CreateRet(F, i); if (LiveValues.erase(Ret)) { RetTypes.push_back(STy->getElementType(i)); NewRetIdxs[i] = RetTypes.size() - 1; } else { ++NumRetValsEliminated; DEBUG(dbgs() << "DAE - Removing return value " << i << " from " << F->getName() << "\n"); } } else // We used to return a single value. if (LiveValues.erase(CreateRet(F, 0))) { RetTypes.push_back(RetTy); NewRetIdxs[0] = 0; } else { DEBUG(dbgs() << "DAE - Removing return value from " << F->getName() << "\n"); ++NumRetValsEliminated; } if (RetTypes.size() > 1) // More than one return type? Return a struct with them. Also, if we used // to return a struct and didn't change the number of return values, // return a struct again. This prevents changing {something} into // something and {} into void. // Make the new struct packed if we used to return a packed struct // already. NRetTy = StructType::get(STy->getContext(), RetTypes, STy->isPacked()); else if (RetTypes.size() == 1) // One return type? Just a simple value then, but only if we didn't use to // return a struct with that simple value before. NRetTy = RetTypes.front(); else if (RetTypes.size() == 0) // No return types? Make it void, but only if we didn't use to return {}. NRetTy = Type::getVoidTy(F->getContext()); } assert(NRetTy && "No new return type found?"); // The existing function return attributes. AttributeSet RAttrs = PAL.getRetAttributes(); // Remove any incompatible attributes, but only if we removed all return // values. Otherwise, ensure that we don't have any conflicting attributes // here. Currently, this should not be possible, but special handling might be // required when new return value attributes are added. if (NRetTy->isVoidTy()) RAttrs = AttributeSet::get(NRetTy->getContext(), AttributeSet::ReturnIndex, AttrBuilder(RAttrs, AttributeSet::ReturnIndex). removeAttributes(AttributeFuncs::typeIncompatible(NRetTy))); else assert(!AttrBuilder(RAttrs, AttributeSet::ReturnIndex). hasAttributes(AttributeFuncs::typeIncompatible(NRetTy)) && "Return attributes no longer compatible?"); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeWithIndex::get(NRetTy->getContext(), AttributeSet::ReturnIndex, RAttrs)); // Remember which arguments are still alive. SmallVector<bool, 10> ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct // a new set of parameter attributes to correspond. Skip the first parameter // attribute, since that belongs to the return value. unsigned i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++i) { RetOrArg Arg = CreateArg(F, i); if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); ArgAlive[i] = true; // Get the original parameter attributes (skipping the first one, that is // for the return value. if (PAL.hasAttributes(i + 1)) { AttributesVec. push_back(AttributeWithIndex::get(F->getContext(), i + 1, PAL.getParamAttributes(i + 1))); AttributesVec.back().Index = Params.size(); } } else { ++NumArgumentsEliminated; DEBUG(dbgs() << "DAE - Removing argument " << i << " (" << I->getName() << ") from " << F->getName() << "\n"); } } if (PAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeWithIndex::get(F->getContext(), AttributeSet::FunctionIndex, PAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewPAL = AttributeSet::get(F->getContext(), AttributesVec); // Create the new function type based on the recomputed parameters. FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); // No change? if (NFTy == FTy) return false; // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); NF->copyAttributesFrom(F); NF->setAttributes(NewPAL); // Insert the new function before the old function, so we won't be processing // it again. F->getParent()->getFunctionList().insert(F, NF); NF->takeName(F); // Loop over all of the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. // std::vector<Value*> Args; while (!F->use_empty()) { CallSite CS(F->use_back()); Instruction *Call = CS.getInstruction(); AttributesVec.clear(); const AttributeSet &CallPAL = CS.getAttributes(); // The call return attributes. AttributeSet RAttrs = CallPAL.getRetAttributes(); // Adjust in case the function was changed to return void. RAttrs = AttributeSet::get(NF->getContext(), AttributeSet::ReturnIndex, AttrBuilder(RAttrs, AttributeSet::ReturnIndex). removeAttributes(AttributeFuncs::typeIncompatible(NF->getReturnType()))); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeWithIndex::get(NF->getContext(), AttributeSet::ReturnIndex, RAttrs)); // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs. CallSite::arg_iterator I = CS.arg_begin(); unsigned i = 0; // Loop over those operands, corresponding to the normal arguments to the // original function, and add those that are still alive. for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) if (ArgAlive[i]) { Args.push_back(*I); // Get original parameter attributes, but skip return attributes. if (CallPAL.hasAttributes(i + 1)) { AttributesVec. push_back(AttributeWithIndex::get(F->getContext(), i + 1, CallPAL.getParamAttributes(i + 1))); AttributesVec.back().Index = Args.size(); } } // Push any varargs arguments on the list. Don't forget their attributes. for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { Args.push_back(*I); if (CallPAL.hasAttributes(i + 1)) { AttributesVec. push_back(AttributeWithIndex::get(F->getContext(), i + 1, CallPAL.getParamAttributes(i + 1))); AttributesVec.back().Index = Args.size(); } } if (CallPAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeWithIndex::get(Call->getContext(), AttributeSet::FunctionIndex, CallPAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewCallPAL = AttributeSet::get(F->getContext(), AttributesVec); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(NewCallPAL); } else { New = CallInst::Create(NF, Args, "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(NewCallPAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } New->setDebugLoc(Call->getDebugLoc()); Args.clear(); if (!Call->use_empty()) { if (New->getType() == Call->getType()) { // Return type not changed? Just replace users then. Call->replaceAllUsesWith(New); New->takeName(Call); } else if (New->getType()->isVoidTy()) { // Our return value has uses, but they will get removed later on. // Replace by null for now. if (!Call->getType()->isX86_MMXTy()) Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); } else { assert(RetTy->isStructTy() && "Return type changed, but not into a void. The old return type" " must have been a struct!"); Instruction *InsertPt = Call; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { BasicBlock::iterator IP = II->getNormalDest()->begin(); while (isa<PHINode>(IP)) ++IP; InsertPt = IP; } // We used to return a struct. Instead of doing smart stuff with all the // uses of this struct, we will just rebuild it using // extract/insertvalue chaining and let instcombine clean that up. // // Start out building up our return value from undef Value *RetVal = UndefValue::get(RetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { Value *V; if (RetTypes.size() > 1) // We are still returning a struct, so extract the value from our // return value V = ExtractValueInst::Create(New, NewRetIdxs[i], "newret", InsertPt); else // We are now returning a single element, so just insert that V = New; // Insert the value at the old position RetVal = InsertValueInst::Create(RetVal, V, i, "oldret", InsertPt); } // Now, replace all uses of the old call instruction with the return // struct we built Call->replaceAllUsesWith(RetVal); New->takeName(Call); } } // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++i) if (ArgAlive[i]) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(I2); I2->takeName(I); ++I2; } else { // If this argument is dead, replace any uses of it with null constants // (these are guaranteed to become unused later on). if (!I->getType()->isX86_MMXTy()) I->replaceAllUsesWith(Constant::getNullValue(I->getType())); } // If we change the return value of the function we must rewrite any return // instructions. Check this now. if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { Value *RetVal; if (NFTy->getReturnType()->isVoidTy()) { RetVal = 0; } else { assert (RetTy->isStructTy()); // The original return value was a struct, insert // extractvalue/insertvalue chains to extract only the values we need // to return and insert them into our new result. // This does generate messy code, but we'll let it to instcombine to // clean that up. Value *OldRet = RI->getOperand(0); // Start out building up our return value from undef RetVal = UndefValue::get(NRetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "oldret", RI); if (RetTypes.size() > 1) { // We're still returning a struct, so reinsert the value into // our new return value at the new index RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "newret", RI); } else { // We are now only returning a simple value, so just return the // extracted value. RetVal = EV; } } } // Replace the return instruction with one returning the new return // value (possibly 0 if we became void). ReturnInst::Create(F->getContext(), RetVal, RI); BB->getInstList().erase(RI); } // Patch the pointer to LLVM function in debug info descriptor. FunctionDIMap::iterator DI = FunctionDIs.find(F); if (DI != FunctionDIs.end()) DI->second.replaceFunction(NF); // Now that the old function is dead, delete it. F->eraseFromParent(); return true; }
// MakeFunctionClone - If the specified function needs to be modified for pool // allocation support, make a clone of it, adding additional arguments as // necessary, and return it. If not, just return null. // Function* RTAssociate::MakeFunctionClone(Function &F, FuncInfo& FI, DSGraph* G) { if (G->node_begin() == G->node_end()) return 0; if (FI.ArgNodes.empty()) return 0; // No need to clone if no pools need to be passed in! // Update statistics.. NumArgsAdded += FI.ArgNodes.size(); if (MaxArgsAdded < FI.ArgNodes.size()) MaxArgsAdded = FI.ArgNodes.size(); ++NumCloned; // Figure out what the arguments are to be for the new version of the // function FunctionType *OldFuncTy = F.getFunctionType(); std::vector<Type*> ArgTys(FI.ArgNodes.size(), PoolDescPtrTy); ArgTys.reserve(OldFuncTy->getNumParams() + FI.ArgNodes.size()); ArgTys.insert(ArgTys.end(), OldFuncTy->param_begin(), OldFuncTy->param_end()); // Create the new function prototype FunctionType *FuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys, OldFuncTy->isVarArg()); // Create the new function... Function *New = Function::Create(FuncTy, Function::InternalLinkage, F.getName()); New->copyAttributesFrom(&F); F.getParent()->getFunctionList().insert(&F, New); // Set the rest of the new arguments names to be PDa<n> and add entries to the // pool descriptors map Function::arg_iterator NI = New->arg_begin(); for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) { FI.PoolDescriptors[FI.ArgNodes[i]] = CreateArgPool(FI.ArgNodes[i], NI); NI->setName("PDa"); } // Map the existing arguments of the old function to the corresponding // arguments of the new function, and copy over the names. ValueToValueMapTy ValueMap; for (Function::arg_iterator I = F.arg_begin(); NI != New->arg_end(); ++I, ++NI) { ValueMap[I] = NI; NI->setName(I->getName()); } // Perform the cloning. SmallVector<ReturnInst*,100> Returns; // TODO: review the boolean flag here CloneFunctionInto(New, &F, ValueMap, true, Returns); // // The CloneFunctionInto() function will copy the parameter attributes // verbatim. This is incorrect; each attribute should be shifted one so // that the pool descriptor has no attributes. // const AttributeSet OldAttrs = New->getAttributes(); if (!OldAttrs.isEmpty()) { AttributeSet NewAttrs; for (unsigned index = 0; index < OldAttrs.getNumSlots(); ++index) { const AttributeSet & PAWI = OldAttrs.getSlotAttributes(index); unsigned argIndex = OldAttrs.getSlotIndex(index); // If it's not the return value, move the attribute to the next // parameter. if (argIndex) ++argIndex; // Add the parameter to the new list. NewAttrs = NewAttrs.addAttributes(F.getContext(), argIndex, PAWI); } // Assign the new attributes to the function clone New->setAttributes(NewAttrs); } for (ValueToValueMapTy::iterator I = ValueMap.begin(), E = ValueMap.end(); I != E; ++I) FI.NewToOldValueMap.insert(std::make_pair(I->second, const_cast<Value*>(I->first))); return FI.Clone = New; }
// RemoveDeadStuffFromFunction - Remove any arguments and return values from F // that are not in LiveValues. Transform the function and all of the callees of // the function to not have these arguments and return values. // bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Don't modify fully live functions if (LiveFunctions.count(F)) return false; // Start by computing a new prototype for the function, which is the same as // the old function, but has fewer arguments and a different return type. FunctionType *FTy = F->getFunctionType(); std::vector<Type*> Params; // Keep track of if we have a live 'returned' argument bool HasLiveReturnedArg = false; // Set up to build a new list of parameter attributes. SmallVector<AttributeSet, 8> AttributesVec; const AttributeSet &PAL = F->getAttributes(); // Remember which arguments are still alive. SmallVector<bool, 10> ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct // a new set of parameter attributes to correspond. Skip the first parameter // attribute, since that belongs to the return value. unsigned i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++i) { RetOrArg Arg = CreateArg(F, i); if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); ArgAlive[i] = true; // Get the original parameter attributes (skipping the first one, that is // for the return value. if (PAL.hasAttributes(i + 1)) { AttrBuilder B(PAL, i + 1); if (B.contains(Attribute::Returned)) HasLiveReturnedArg = true; AttributesVec. push_back(AttributeSet::get(F->getContext(), Params.size(), B)); } } else { ++NumArgumentsEliminated; DEBUG(dbgs() << "DAE - Removing argument " << i << " (" << I->getName() << ") from " << F->getName() << "\n"); } } // Find out the new return value. Type *RetTy = FTy->getReturnType(); Type *NRetTy = nullptr; unsigned RetCount = NumRetVals(F); // -1 means unused, other numbers are the new index SmallVector<int, 5> NewRetIdxs(RetCount, -1); std::vector<Type*> RetTypes; // If there is a function with a live 'returned' argument but a dead return // value, then there are two possible actions: // 1) Eliminate the return value and take off the 'returned' attribute on the // argument. // 2) Retain the 'returned' attribute and treat the return value (but not the // entire function) as live so that it is not eliminated. // // It's not clear in the general case which option is more profitable because, // even in the absence of explicit uses of the return value, code generation // is free to use the 'returned' attribute to do things like eliding // save/restores of registers across calls. Whether or not this happens is // target and ABI-specific as well as depending on the amount of register // pressure, so there's no good way for an IR-level pass to figure this out. // // Fortunately, the only places where 'returned' is currently generated by // the FE are places where 'returned' is basically free and almost always a // performance win, so the second option can just be used always for now. // // This should be revisited if 'returned' is ever applied more liberally. if (RetTy->isVoidTy() || HasLiveReturnedArg) { NRetTy = RetTy; } else { // Look at each of the original return values individually. for (unsigned i = 0; i != RetCount; ++i) { RetOrArg Ret = CreateRet(F, i); if (LiveValues.erase(Ret)) { RetTypes.push_back(getRetComponentType(F, i)); NewRetIdxs[i] = RetTypes.size() - 1; } else { ++NumRetValsEliminated; DEBUG(dbgs() << "DAE - Removing return value " << i << " from " << F->getName() << "\n"); } } if (RetTypes.size() > 1) { // More than one return type? Reduce it down to size. if (StructType *STy = dyn_cast<StructType>(RetTy)) { // Make the new struct packed if we used to return a packed struct // already. NRetTy = StructType::get(STy->getContext(), RetTypes, STy->isPacked()); } else { assert(isa<ArrayType>(RetTy) && "unexpected multi-value return"); NRetTy = ArrayType::get(RetTypes[0], RetTypes.size()); } } else if (RetTypes.size() == 1) // One return type? Just a simple value then, but only if we didn't use to // return a struct with that simple value before. NRetTy = RetTypes.front(); else if (RetTypes.size() == 0) // No return types? Make it void, but only if we didn't use to return {}. NRetTy = Type::getVoidTy(F->getContext()); } assert(NRetTy && "No new return type found?"); // The existing function return attributes. AttributeSet RAttrs = PAL.getRetAttributes(); // Remove any incompatible attributes, but only if we removed all return // values. Otherwise, ensure that we don't have any conflicting attributes // here. Currently, this should not be possible, but special handling might be // required when new return value attributes are added. if (NRetTy->isVoidTy()) RAttrs = RAttrs.removeAttributes(NRetTy->getContext(), AttributeSet::ReturnIndex, AttributeFuncs::typeIncompatible(NRetTy)); else assert(!AttrBuilder(RAttrs, AttributeSet::ReturnIndex). overlaps(AttributeFuncs::typeIncompatible(NRetTy)) && "Return attributes no longer compatible?"); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeSet::get(NRetTy->getContext(), RAttrs)); if (PAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(F->getContext(), PAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewPAL = AttributeSet::get(F->getContext(), AttributesVec); // Create the new function type based on the recomputed parameters. FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); // No change? if (NFTy == FTy) return false; // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); NF->copyAttributesFrom(F); NF->setAttributes(NewPAL); // Insert the new function before the old function, so we won't be processing // it again. F->getParent()->getFunctionList().insert(F->getIterator(), NF); NF->takeName(F); // Loop over all of the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. // std::vector<Value*> Args; while (!F->use_empty()) { CallSite CS(F->user_back()); Instruction *Call = CS.getInstruction(); AttributesVec.clear(); const AttributeSet &CallPAL = CS.getAttributes(); // The call return attributes. AttributeSet RAttrs = CallPAL.getRetAttributes(); // Adjust in case the function was changed to return void. RAttrs = RAttrs.removeAttributes(NRetTy->getContext(), AttributeSet::ReturnIndex, AttributeFuncs::typeIncompatible(NF->getReturnType())); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeSet::get(NF->getContext(), RAttrs)); // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs. CallSite::arg_iterator I = CS.arg_begin(); unsigned i = 0; // Loop over those operands, corresponding to the normal arguments to the // original function, and add those that are still alive. for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) if (ArgAlive[i]) { Args.push_back(*I); // Get original parameter attributes, but skip return attributes. if (CallPAL.hasAttributes(i + 1)) { AttrBuilder B(CallPAL, i + 1); // If the return type has changed, then get rid of 'returned' on the // call site. The alternative is to make all 'returned' attributes on // call sites keep the return value alive just like 'returned' // attributes on function declaration but it's less clearly a win // and this is not an expected case anyway if (NRetTy != RetTy && B.contains(Attribute::Returned)) B.removeAttribute(Attribute::Returned); AttributesVec. push_back(AttributeSet::get(F->getContext(), Args.size(), B)); } } // Push any varargs arguments on the list. Don't forget their attributes. for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { Args.push_back(*I); if (CallPAL.hasAttributes(i + 1)) { AttrBuilder B(CallPAL, i + 1); AttributesVec. push_back(AttributeSet::get(F->getContext(), Args.size(), B)); } } if (CallPAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(Call->getContext(), CallPAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewCallPAL = AttributeSet::get(F->getContext(), AttributesVec); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Call->getParent()); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(NewCallPAL); } else { New = CallInst::Create(NF, Args, "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(NewCallPAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } New->setDebugLoc(Call->getDebugLoc()); Args.clear(); if (!Call->use_empty()) { if (New->getType() == Call->getType()) { // Return type not changed? Just replace users then. Call->replaceAllUsesWith(New); New->takeName(Call); } else if (New->getType()->isVoidTy()) { // Our return value has uses, but they will get removed later on. // Replace by null for now. if (!Call->getType()->isX86_MMXTy()) Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); } else { assert((RetTy->isStructTy() || RetTy->isArrayTy()) && "Return type changed, but not into a void. The old return type" " must have been a struct or an array!"); Instruction *InsertPt = Call; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { BasicBlock *NewEdge = SplitEdge(New->getParent(), II->getNormalDest()); InsertPt = &*NewEdge->getFirstInsertionPt(); } // We used to return a struct or array. Instead of doing smart stuff // with all the uses, we will just rebuild it using extract/insertvalue // chaining and let instcombine clean that up. // // Start out building up our return value from undef Value *RetVal = UndefValue::get(RetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { Value *V; if (RetTypes.size() > 1) // We are still returning a struct, so extract the value from our // return value V = ExtractValueInst::Create(New, NewRetIdxs[i], "newret", InsertPt); else // We are now returning a single element, so just insert that V = New; // Insert the value at the old position RetVal = InsertValueInst::Create(RetVal, V, i, "oldret", InsertPt); } // Now, replace all uses of the old call instruction with the return // struct we built Call->replaceAllUsesWith(RetVal); New->takeName(Call); } } // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++i) if (ArgAlive[i]) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(&*I2); I2->takeName(&*I); ++I2; } else { // If this argument is dead, replace any uses of it with null constants // (these are guaranteed to become unused later on). if (!I->getType()->isX86_MMXTy()) I->replaceAllUsesWith(Constant::getNullValue(I->getType())); } // If we change the return value of the function we must rewrite any return // instructions. Check this now. if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { Value *RetVal; if (NFTy->getReturnType()->isVoidTy()) { RetVal = nullptr; } else { assert(RetTy->isStructTy() || RetTy->isArrayTy()); // The original return value was a struct or array, insert // extractvalue/insertvalue chains to extract only the values we need // to return and insert them into our new result. // This does generate messy code, but we'll let it to instcombine to // clean that up. Value *OldRet = RI->getOperand(0); // Start out building up our return value from undef RetVal = UndefValue::get(NRetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "oldret", RI); if (RetTypes.size() > 1) { // We're still returning a struct, so reinsert the value into // our new return value at the new index RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "newret", RI); } else { // We are now only returning a simple value, so just return the // extracted value. RetVal = EV; } } } // Replace the return instruction with one returning the new return // value (possibly 0 if we became void). ReturnInst::Create(F->getContext(), RetVal, RI); BB->getInstList().erase(RI); } // Patch the pointer to LLVM function in debug info descriptor. NF->setSubprogram(F->getSubprogram()); // Now that the old function is dead, delete it. F->eraseFromParent(); return true; }
bool TailCallElim::ProcessReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry, bool &TailCallsAreMarkedTail, SmallVector<PHINode*, 8> &ArgumentPHIs, bool CannotTailCallElimCallsMarkedTail) { BasicBlock *BB = Ret->getParent(); Function *F = BB->getParent(); if (&BB->front() == Ret) // Make sure there is something before the ret... return false; // If the return is in the entry block, then making this transformation would // turn infinite recursion into an infinite loop. This transformation is ok // in theory, but breaks some code like: // double fabs(double f) { return __builtin_fabs(f); } // a 'fabs' call // disable this xform in this case, because the code generator will lower the // call to fabs into inline code. if (BB == &F->getEntryBlock()) return false; // Scan backwards from the return, checking to see if there is a tail call in // this block. If so, set CI to it. CallInst *CI; BasicBlock::iterator BBI = Ret; while (1) { CI = dyn_cast<CallInst>(BBI); if (CI && CI->getCalledFunction() == F) break; if (BBI == BB->begin()) return false; // Didn't find a potential tail call. --BBI; } // If this call is marked as a tail call, and if there are dynamic allocas in // the function, we cannot perform this optimization. if (CI->isTailCall() && CannotTailCallElimCallsMarkedTail) return false; // If we are introducing accumulator recursion to eliminate associative // operations after the call instruction, this variable contains the initial // value for the accumulator. If this value is set, we actually perform // accumulator recursion elimination instead of simple tail recursion // elimination. Value *AccumulatorRecursionEliminationInitVal = 0; Instruction *AccumulatorRecursionInstr = 0; // Ok, we found a potential tail call. We can currently only transform the // tail call if all of the instructions between the call and the return are // movable to above the call itself, leaving the call next to the return. // Check that this is the case now. for (BBI = CI, ++BBI; &*BBI != Ret; ++BBI) if (!CanMoveAboveCall(BBI, CI)) { // If we can't move the instruction above the call, it might be because it // is an associative operation that could be tranformed using accumulator // recursion elimination. Check to see if this is the case, and if so, // remember the initial accumulator value for later. if ((AccumulatorRecursionEliminationInitVal = CanTransformAccumulatorRecursion(BBI, CI))) { // Yes, this is accumulator recursion. Remember which instruction // accumulates. AccumulatorRecursionInstr = BBI; } else { return false; // Otherwise, we cannot eliminate the tail recursion! } } // We can only transform call/return pairs that either ignore the return value // of the call and return void, ignore the value of the call and return a // constant, return the value returned by the tail call, or that are being // accumulator recursion variable eliminated. if (Ret->getNumOperands() == 1 && Ret->getReturnValue() != CI && !isa<UndefValue>(Ret->getReturnValue()) && AccumulatorRecursionEliminationInitVal == 0 && !getCommonReturnValue(Ret, CI)) return false; // OK! We can transform this tail call. If this is the first one found, // create the new entry block, allowing us to branch back to the old entry. if (OldEntry == 0) { OldEntry = &F->getEntryBlock(); BasicBlock *NewEntry = BasicBlock::Create(F->getContext(), "", F, OldEntry); NewEntry->takeName(OldEntry); OldEntry->setName("tailrecurse"); BranchInst::Create(OldEntry, NewEntry); // If this tail call is marked 'tail' and if there are any allocas in the // entry block, move them up to the new entry block. TailCallsAreMarkedTail = CI->isTailCall(); if (TailCallsAreMarkedTail) // Move all fixed sized allocas from OldEntry to NewEntry. for (BasicBlock::iterator OEBI = OldEntry->begin(), E = OldEntry->end(), NEBI = NewEntry->begin(); OEBI != E; ) if (AllocaInst *AI = dyn_cast<AllocaInst>(OEBI++)) if (isa<ConstantInt>(AI->getArraySize())) AI->moveBefore(NEBI); // Now that we have created a new block, which jumps to the entry // block, insert a PHI node for each argument of the function. // For now, we initialize each PHI to only have the real arguments // which are passed in. Instruction *InsertPos = OldEntry->begin(); for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { PHINode *PN = PHINode::Create(I->getType(), I->getName() + ".tr", InsertPos); I->replaceAllUsesWith(PN); // Everyone use the PHI node now! PN->addIncoming(I, NewEntry); ArgumentPHIs.push_back(PN); } } // If this function has self recursive calls in the tail position where some // are marked tail and some are not, only transform one flavor or another. We // have to choose whether we move allocas in the entry block to the new entry // block or not, so we can't make a good choice for both. NOTE: We could do // slightly better here in the case that the function has no entry block // allocas. if (TailCallsAreMarkedTail && !CI->isTailCall()) return false; // Ok, now that we know we have a pseudo-entry block WITH all of the // required PHI nodes, add entries into the PHI node for the actual // parameters passed into the tail-recursive call. for (unsigned i = 0, e = CI->getNumOperands()-1; i != e; ++i) ArgumentPHIs[i]->addIncoming(CI->getOperand(i+1), BB); // If we are introducing an accumulator variable to eliminate the recursion, // do so now. Note that we _know_ that no subsequent tail recursion // eliminations will happen on this function because of the way the // accumulator recursion predicate is set up. // if (AccumulatorRecursionEliminationInitVal) { Instruction *AccRecInstr = AccumulatorRecursionInstr; // Start by inserting a new PHI node for the accumulator. PHINode *AccPN = PHINode::Create(AccRecInstr->getType(), "accumulator.tr", OldEntry->begin()); // Loop over all of the predecessors of the tail recursion block. For the // real entry into the function we seed the PHI with the initial value, // computed earlier. For any other existing branches to this block (due to // other tail recursions eliminated) the accumulator is not modified. // Because we haven't added the branch in the current block to OldEntry yet, // it will not show up as a predecessor. for (pred_iterator PI = pred_begin(OldEntry), PE = pred_end(OldEntry); PI != PE; ++PI) { if (*PI == &F->getEntryBlock()) AccPN->addIncoming(AccumulatorRecursionEliminationInitVal, *PI); else AccPN->addIncoming(AccPN, *PI); } // Add an incoming argument for the current block, which is computed by our // associative accumulator instruction. AccPN->addIncoming(AccRecInstr, BB); // Next, rewrite the accumulator recursion instruction so that it does not // use the result of the call anymore, instead, use the PHI node we just // inserted. AccRecInstr->setOperand(AccRecInstr->getOperand(0) != CI, AccPN); // Finally, rewrite any return instructions in the program to return the PHI // node instead of the "initval" that they do currently. This loop will // actually rewrite the return value we are destroying, but that's ok. for (Function::iterator BBI = F->begin(), E = F->end(); BBI != E; ++BBI) if (ReturnInst *RI = dyn_cast<ReturnInst>(BBI->getTerminator())) RI->setOperand(0, AccPN); ++NumAccumAdded; } // Now that all of the PHI nodes are in place, remove the call and // ret instructions, replacing them with an unconditional branch. BranchInst::Create(OldEntry, Ret); BB->getInstList().erase(Ret); // Remove return. BB->getInstList().erase(CI); // Remove call. ++NumEliminated; return true; }