void visitCallInst(CallInst &I) { string intrinsic = I.getCalledFunction()->getName().str(); if(intrinsic.find("modmul") != -1) { CallInst *enterMontpro1 = enterMontgomery(I.getOperand(0), I.getOperand(2), &I); CallInst *enterMontpro2 = enterMontgomery(I.getOperand(1), I.getOperand(2), &I); CallInst *mulMontpro = mulMontgomery(I.getName().str(), enterMontpro1, enterMontpro2, I.getOperand(2), &I); CallInst *exitMontpro = leaveMontgomery(mulMontpro, I.getOperand(2), &I); I.replaceAllUsesWith(exitMontpro); I.removeFromParent(); } else if(intrinsic.find("modexp") != -1) { CallInst *enterMontpro1 = enterMontgomery(I.getOperand(0), I.getOperand(2), &I); CallInst *expMontpro = expMontgomery(I.getName().str(), enterMontpro1, I.getOperand(1), I.getOperand(2), &I); CallInst *exitMontpro = leaveMontgomery(expMontpro, I.getOperand(2), &I); I.replaceAllUsesWith(exitMontpro); I.eraseFromParent(); } }
bool LowerExpectIntrinsic::HandleSwitchExpect(SwitchInst *SI) { CallInst *CI = dyn_cast<CallInst>(SI->getCondition()); if (!CI) return false; Function *Fn = CI->getCalledFunction(); if (!Fn || Fn->getIntrinsicID() != Intrinsic::expect) return false; Value *ArgValue = CI->getArgOperand(0); ConstantInt *ExpectedValue = dyn_cast<ConstantInt>(CI->getArgOperand(1)); if (!ExpectedValue) return false; LLVMContext &Context = CI->getContext(); Type *Int32Ty = Type::getInt32Ty(Context); SwitchInst::CaseIt Case = SI->findCaseValue(ExpectedValue); std::vector<Value *> Vec; unsigned n = SI->getNumCases(); Vec.resize(n + 1 + 1); // +1 for MDString and +1 for default case Vec[0] = MDString::get(Context, "branch_weights"); Vec[1] = ConstantInt::get(Int32Ty, Case == SI->case_default() ? LikelyBranchWeight : UnlikelyBranchWeight); for (unsigned i = 0; i < n; ++i) { Vec[i + 1 + 1] = ConstantInt::get(Int32Ty, i == Case.getCaseIndex() ? LikelyBranchWeight : UnlikelyBranchWeight); } MDNode *WeightsNode = llvm::MDNode::get(Context, Vec); SI->setMetadata(LLVMContext::MD_prof, WeightsNode); SI->setCondition(ArgValue); return true; }
/// HandleInlinedInvoke - If we inlined an invoke site, we need to convert calls /// in the body of the inlined function into invokes and turn unwind /// instructions into branches to the invoke unwind dest. /// /// II is the invoke instruction begin inlined. FirstNewBlock is the first /// block of the inlined code (the last block is the end of the function), /// and InlineCodeInfo is information about the code that got inlined. static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock, ClonedCodeInfo &InlinedCodeInfo) { BasicBlock *InvokeDest = II->getUnwindDest(); std::vector<Value*> InvokeDestPHIValues; // If there are PHI nodes in the unwind destination block, we need to // keep track of which values came into them from this invoke, then remove // the entry for this block. BasicBlock *InvokeBlock = II->getParent(); for (BasicBlock::iterator I = InvokeDest->begin(); isa<PHINode>(I); ++I) { PHINode *PN = cast<PHINode>(I); // Save the value to use for this edge. InvokeDestPHIValues.push_back(PN->getIncomingValueForBlock(InvokeBlock)); } Function *Caller = FirstNewBlock->getParent(); // The inlined code is currently at the end of the function, scan from the // start of the inlined code to its end, checking for stuff we need to // rewrite. if (InlinedCodeInfo.ContainsCalls || InlinedCodeInfo.ContainsUnwinds) { for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB) { if (InlinedCodeInfo.ContainsCalls) { for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ){ Instruction *I = BBI++; // We only need to check for function calls: inlined invoke // instructions require no special handling. if (!isa<CallInst>(I)) continue; CallInst *CI = cast<CallInst>(I); // If this is an intrinsic function call or an inline asm, don't // convert it to an invoke. if ((CI->getCalledFunction() && CI->getCalledFunction()->getIntrinsicID()) || isa<InlineAsm>(CI->getCalledValue())) continue; // Convert this function call into an invoke instruction. // First, split the basic block. BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc"); // Next, create the new invoke instruction, inserting it at the end // of the old basic block. SmallVector<Value*, 8> InvokeArgs(CI->op_begin()+1, CI->op_end()); InvokeInst *II = new InvokeInst(CI->getCalledValue(), Split, InvokeDest, &InvokeArgs[0], InvokeArgs.size(), CI->getName(), BB->getTerminator()); II->setCallingConv(CI->getCallingConv()); // Make sure that anything using the call now uses the invoke! CI->replaceAllUsesWith(II); // Delete the unconditional branch inserted by splitBasicBlock BB->getInstList().pop_back(); Split->getInstList().pop_front(); // Delete the original call // Update any PHI nodes in the exceptional block to indicate that // there is now a new entry in them. unsigned i = 0; for (BasicBlock::iterator I = InvokeDest->begin(); isa<PHINode>(I); ++I, ++i) { PHINode *PN = cast<PHINode>(I); PN->addIncoming(InvokeDestPHIValues[i], BB); } // This basic block is now complete, start scanning the next one. break; } } if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) { // An UnwindInst requires special handling when it gets inlined into an // invoke site. Once this happens, we know that the unwind would cause // a control transfer to the invoke exception destination, so we can // transform it into a direct branch to the exception destination. new BranchInst(InvokeDest, UI); // Delete the unwind instruction! UI->getParent()->getInstList().pop_back(); // Update any PHI nodes in the exceptional block to indicate that // there is now a new entry in them. unsigned i = 0; for (BasicBlock::iterator I = InvokeDest->begin(); isa<PHINode>(I); ++I, ++i) { PHINode *PN = cast<PHINode>(I); PN->addIncoming(InvokeDestPHIValues[i], BB); } } } } // Now that everything is happy, we have one final detail. The PHI nodes in // the exception destination block still have entries due to the original // invoke instruction. Eliminate these entries (which might even delete the // PHI node) now. InvokeDest->removePredecessor(II->getParent()); }
void AMDGPUPromoteAlloca::handleAlloca(AllocaInst &I) { // Array allocations are probably not worth handling, since an allocation of // the array type is the canonical form. if (!I.isStaticAlloca() || I.isArrayAllocation()) return; IRBuilder<> Builder(&I); // First try to replace the alloca with a vector Type *AllocaTy = I.getAllocatedType(); DEBUG(dbgs() << "Trying to promote " << I << '\n'); if (tryPromoteAllocaToVector(&I)) return; DEBUG(dbgs() << " alloca is not a candidate for vectorization.\n"); const Function &ContainingFunction = *I.getParent()->getParent(); // FIXME: We should also try to get this value from the reqd_work_group_size // function attribute if it is available. unsigned WorkGroupSize = AMDGPU::getMaximumWorkGroupSize(ContainingFunction); int AllocaSize = WorkGroupSize * Mod->getDataLayout().getTypeAllocSize(AllocaTy); if (AllocaSize > LocalMemAvailable) { DEBUG(dbgs() << " Not enough local memory to promote alloca.\n"); return; } std::vector<Value*> WorkList; if (!collectUsesWithPtrTypes(&I, WorkList)) { DEBUG(dbgs() << " Do not know how to convert all uses\n"); return; } DEBUG(dbgs() << "Promoting alloca to local memory\n"); LocalMemAvailable -= AllocaSize; Function *F = I.getParent()->getParent(); Type *GVTy = ArrayType::get(I.getAllocatedType(), WorkGroupSize); GlobalVariable *GV = new GlobalVariable( *Mod, GVTy, false, GlobalValue::InternalLinkage, UndefValue::get(GVTy), Twine(F->getName()) + Twine('.') + I.getName(), nullptr, GlobalVariable::NotThreadLocal, AMDGPUAS::LOCAL_ADDRESS); GV->setUnnamedAddr(true); GV->setAlignment(I.getAlignment()); Value *TCntY, *TCntZ; std::tie(TCntY, TCntZ) = getLocalSizeYZ(Builder); Value *TIdX = getWorkitemID(Builder, 0); Value *TIdY = getWorkitemID(Builder, 1); Value *TIdZ = getWorkitemID(Builder, 2); Value *Tmp0 = Builder.CreateMul(TCntY, TCntZ, "", true, true); Tmp0 = Builder.CreateMul(Tmp0, TIdX); Value *Tmp1 = Builder.CreateMul(TIdY, TCntZ, "", true, true); Value *TID = Builder.CreateAdd(Tmp0, Tmp1); TID = Builder.CreateAdd(TID, TIdZ); Value *Indices[] = { Constant::getNullValue(Type::getInt32Ty(Mod->getContext())), TID }; Value *Offset = Builder.CreateInBoundsGEP(GVTy, GV, Indices); I.mutateType(Offset->getType()); I.replaceAllUsesWith(Offset); I.eraseFromParent(); for (Value *V : WorkList) { CallInst *Call = dyn_cast<CallInst>(V); if (!Call) { Type *EltTy = V->getType()->getPointerElementType(); PointerType *NewTy = PointerType::get(EltTy, AMDGPUAS::LOCAL_ADDRESS); // The operand's value should be corrected on its own. if (isa<AddrSpaceCastInst>(V)) continue; // FIXME: It doesn't really make sense to try to do this for all // instructions. V->mutateType(NewTy); continue; } IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(Call); if (!Intr) { // FIXME: What is this for? It doesn't make sense to promote arbitrary // function calls. If the call is to a defined function that can also be // promoted, we should be able to do this once that function is also // rewritten. std::vector<Type*> ArgTypes; for (unsigned ArgIdx = 0, ArgEnd = Call->getNumArgOperands(); ArgIdx != ArgEnd; ++ArgIdx) { ArgTypes.push_back(Call->getArgOperand(ArgIdx)->getType()); } Function *F = Call->getCalledFunction(); FunctionType *NewType = FunctionType::get(Call->getType(), ArgTypes, F->isVarArg()); Constant *C = Mod->getOrInsertFunction((F->getName() + ".local").str(), NewType, F->getAttributes()); Function *NewF = cast<Function>(C); Call->setCalledFunction(NewF); continue; } Builder.SetInsertPoint(Intr); switch (Intr->getIntrinsicID()) { case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: // These intrinsics are for address space 0 only Intr->eraseFromParent(); continue; case Intrinsic::memcpy: { MemCpyInst *MemCpy = cast<MemCpyInst>(Intr); Builder.CreateMemCpy(MemCpy->getRawDest(), MemCpy->getRawSource(), MemCpy->getLength(), MemCpy->getAlignment(), MemCpy->isVolatile()); Intr->eraseFromParent(); continue; } case Intrinsic::memmove: { MemMoveInst *MemMove = cast<MemMoveInst>(Intr); Builder.CreateMemMove(MemMove->getRawDest(), MemMove->getRawSource(), MemMove->getLength(), MemMove->getAlignment(), MemMove->isVolatile()); Intr->eraseFromParent(); continue; } case Intrinsic::memset: { MemSetInst *MemSet = cast<MemSetInst>(Intr); Builder.CreateMemSet(MemSet->getRawDest(), MemSet->getValue(), MemSet->getLength(), MemSet->getAlignment(), MemSet->isVolatile()); Intr->eraseFromParent(); continue; } case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::invariant_group_barrier: Intr->eraseFromParent(); // FIXME: I think the invariant marker should still theoretically apply, // but the intrinsics need to be changed to accept pointers with any // address space. continue; case Intrinsic::objectsize: { Value *Src = Intr->getOperand(0); Type *SrcTy = Src->getType()->getPointerElementType(); Function *ObjectSize = Intrinsic::getDeclaration(Mod, Intrinsic::objectsize, { Intr->getType(), PointerType::get(SrcTy, AMDGPUAS::LOCAL_ADDRESS) } ); CallInst *NewCall = Builder.CreateCall(ObjectSize, { Src, Intr->getOperand(1) }); Intr->replaceAllUsesWith(NewCall); Intr->eraseFromParent(); continue; } default: Intr->dump(); llvm_unreachable("Don't know how to promote alloca intrinsic use."); } } }
bool GambasPass::runOnFunction(Function &F){ IRBuilder<> Builder(F.getContext()); bool changed = false; for(Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ){ ICmpInst* ICI = dyn_cast<ICmpInst>(I); CallInst* CI = dyn_cast<CallInst>(I++); if (ICI && ICI->hasMetadata() && ICI->getMetadata("unref_slt") && dyn_cast<LoadInst>(ICI->getOperand(0))){ ICI->replaceAllUsesWith(ConstantInt::get(ICI->getType(), false)); ICI->eraseFromParent(); changed = true; continue; } if (!CI) continue; Function* callee = CI->getCalledFunction(); if (callee == NULL || !callee->isDeclaration()) continue; StringRef name = callee->getName(); if (name == "JR_release_variant" || name == "JR_borrow_variant"){ ConstantInt* vtype_int = dyn_cast<ConstantInt>(CI->getArgOperand(0)); if (!vtype_int) continue; uint64_t vtype = vtype_int->getZExtValue(); if (TYPE_is_string(vtype) || TYPE_is_object(vtype)) continue; CI->eraseFromParent(); changed = true; } else if (name == FUNCTION_NAME(__finite)){ ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0)); if (!op) continue; int val = __finite(op->getValueAPF().convertToDouble()); Constant* res = ConstantInt::get(CI->getType(), val); CI->replaceAllUsesWith(res); CI->eraseFromParent(); changed = true; } else if (name == FUNCTION_NAME(__isnan)){ ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0)); if (!op) continue; int val = __isnan(op->getValueAPF().convertToDouble()); Constant* res = ConstantInt::get(CI->getType(), val); CI->replaceAllUsesWith(res); CI->eraseFromParent(); changed = true; } else if (name == FUNCTION_NAME(__isinf)){ ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0)); if (!op) continue; int val = __isinf(op->getValueAPF().convertToDouble()); Constant* res = ConstantInt::get(CI->getType(), val); CI->replaceAllUsesWith(res); CI->eraseFromParent(); changed = true; } } } return changed; }
void TaskDebugBranchCheck::addFunctionSummaries(BasicBlock* from_bb, BasicBlock* to_bb, Instruction* first_inst) { //errs() << "++++++++++++++++++++DETECTED BRANCHES++++++++++++++++++++++\n"; //errs() << "BB 1 First inst: " << *(from_bb->getFirstNonPHI()) << "\n"; //TerminatorInst *TInst = from_bb->getTerminator(); //errs() << "BB 1 Last inst: " << *TInst << "\n\n"; //errs() << "BB 2 First inst: " << *(to_bb->getFirstNonPHI()) << "\n"; //TInst = to_bb->getTerminator(); //errs() << "BB 2 Last inst: " << *TInst << "\n\n"; //errs() << "++++++++++++++++++++DETECTED BRANCHES++++++++++++++++++++++\n"; std::vector<Value*> locks_acq; std::vector<Value*> locks_rel; bool startInst = false; for (BasicBlock::iterator i = from_bb->begin(); i != from_bb->end(); ++i) { if (startInst == false) { if (first_inst == dyn_cast<Instruction>(i)) { startInst = true; } else { continue; } } switch (i->getOpcode()) { case Instruction::Call: { CallInst* callInst = dyn_cast<CallInst>(i); if(callInst->getCalledFunction() != NULL) { if(callInst->getCalledFunction() == lockAcquire) { locks_acq.push_back(callInst->getArgOperand(1)); } else if (callInst->getCalledFunction() == lockRelease) { locks_rel.push_back(callInst->getArgOperand(1)); } } break; } case Instruction::Load: { //errs() << "LOAD INST " << *i << "\n"; Value* op_l = i->getOperand(0); if (hasAnnotation(i, op_l, "check_av", 1)) { Constant* read = ConstantInt::get(Type::getInt32Ty(to_bb->getContext()), 0); instrument_access(to_bb->getFirstNonPHI(), op_l, read, locks_acq, locks_rel); } break; } case Instruction::Store: { //errs() << "STR INST " << *i << "\n"; Value* op_s = i->getOperand(1); if (hasAnnotation(i, op_s, "check_av", 1)) { Constant* write = ConstantInt::get(Type::getInt32Ty(to_bb->getContext()), 1); instrument_access(to_bb->getFirstNonPHI(), op_s, write, locks_acq, locks_rel); } break; } } } }
void MutationGen::genMutationFile(Function & F){ int index = 0; for(Function::iterator FI = F.begin(); FI != F.end(); ++FI){ BasicBlock *BB = FI; #if NEED_LOOP_INFO bool isLoop = LI->getLoopFor(BB); #endif for(BasicBlock::iterator BI = BB->begin(); BI != BB->end(); ++BI, index++){ unsigned opc = BI->getOpcode(); if( !((opc >= 14 && opc <= 31) || opc == 34 || opc == 52 || opc == 55) ){// omit alloca and getelementptr continue; } int idxtmp = index; #if NEED_LOOP_INFO if(isLoop){ assert(idxtmp != 0); idxtmp = 0 - idxtmp; } #endif switch(opc){ case Instruction::Add: case Instruction::Sub: case Instruction::Mul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::URem: case Instruction::SRem:{ // TODO: add for i1, i8. Support i32 and i64 first if(! (BI->getType()->isIntegerTy(32) || BI->getType()->isIntegerTy(64))){ continue; } genLVR(BI, F.getName(), idxtmp); genUOI(BI, F.getName(), idxtmp); genROV(BI, F.getName(), idxtmp); genABV(BI, F.getName(), idxtmp); genAOR(BI, F.getName(), idxtmp); break; } case Instruction::ICmp:{ if(! (BI->getOperand(0)->getType()->isIntegerTy(32) || BI->getOperand(0)->getType()->isIntegerTy(64)) ){ continue; } genLVR(BI, F.getName(), idxtmp); genUOI(BI, F.getName(), idxtmp); genROV(BI, F.getName(), idxtmp); genABV(BI, F.getName(), idxtmp); genROR(BI, F.getName(), idxtmp); break; } case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: case Instruction::And: case Instruction::Or: case Instruction::Xor:{ // TODO: add for i1, i8. Support i32 and i64 first if(! (BI->getType()->isIntegerTy(32) || BI->getType()->isIntegerTy(64))){ continue; } genLVR(BI, F.getName(), idxtmp); genUOI(BI, F.getName(), idxtmp); genROV(BI, F.getName(), idxtmp); genABV(BI, F.getName(), idxtmp); genLOR(BI, F.getName(), idxtmp); break; } case Instruction::Call: { CallInst* call = cast<CallInst>(BI); // TODO: omit function-pointer if(call->getCalledFunction() == NULL){ continue; } /*Value* callee = dyn_cast<Value>(&*(call->op_end() - 1)); if(callee->getType()->isPointerTy()){ continue; }*/ StringRef name = call->getCalledFunction()->getName(); if(name.startswith("llvm")){//omit llvm inside functions continue; } // TODO: add for ommiting i8. Support i32 and i64 first if(! ( isSupportedType(BI->getType())|| BI->getType()->isVoidTy() ) ){ continue; } genLVR(BI, F.getName(), idxtmp); genUOI(BI, F.getName(), idxtmp); genROV(BI, F.getName(), idxtmp); genABV(BI, F.getName(), idxtmp); genSTDCall(BI, F.getName(), idxtmp); break; } case Instruction::Store:{ auto addr = BI->op_begin() + 1;// the pointer of the storeinst if( ! (dyn_cast<LoadInst>(&*addr) || dyn_cast<AllocaInst>(&*addr) || dyn_cast<Constant>(&*addr) || dyn_cast<GetElementPtrInst>(&*addr) ) ){ continue; } // TODO:: add for i8 Value* tobestore = dyn_cast<Value>(BI->op_begin()); if(! isSupportedType(tobestore->getType())){ continue; } genLVR(BI, F.getName(), idxtmp); genUOI(BI, F.getName(), idxtmp); genABV(BI, F.getName(), idxtmp); genSTDStore(BI, F.getName(), idxtmp); break; } case Instruction::GetElementPtr:{ // TODO: break; } default:{ } } } } ofresult.flush(); }
/// \brief Recursively handle the condition leading to a loop Value *SIAnnotateControlFlow::handleLoopCondition( Value *Cond, PHINode *Broken, llvm::Loop *L, BranchInst *Term, SmallVectorImpl<WeakTrackingVH> &LoopPhiConditions) { // Only search through PHI nodes which are inside the loop. If we try this // with PHI nodes that are outside of the loop, we end up inserting new PHI // nodes outside of the loop which depend on values defined inside the loop. // This will break the module with // 'Instruction does not dominate all users!' errors. PHINode *Phi = nullptr; if ((Phi = dyn_cast<PHINode>(Cond)) && L->contains(Phi)) { BasicBlock *Parent = Phi->getParent(); PHINode *NewPhi = PHINode::Create(Int64, 0, "loop.phi", &Parent->front()); Value *Ret = NewPhi; // Handle all non-constant incoming values first for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { Value *Incoming = Phi->getIncomingValue(i); BasicBlock *From = Phi->getIncomingBlock(i); if (isa<ConstantInt>(Incoming)) { NewPhi->addIncoming(Broken, From); continue; } Phi->setIncomingValue(i, BoolFalse); Value *PhiArg = handleLoopCondition(Incoming, Broken, L, Term, LoopPhiConditions); NewPhi->addIncoming(PhiArg, From); } BasicBlock *IDom = DT->getNode(Parent)->getIDom()->getBlock(); for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { Value *Incoming = Phi->getIncomingValue(i); if (Incoming != BoolTrue) continue; BasicBlock *From = Phi->getIncomingBlock(i); if (From == IDom) { // We're in the following situation: // IDom/From // | \ // | If-block // | / // Parent // where we want to break out of the loop if the If-block is not taken. // Due to the depth-first traversal, there should be an end.cf // intrinsic in Parent, and we insert an else.break before it. // // Note that the end.cf need not be the first non-phi instruction // of parent, particularly when we're dealing with a multi-level // break, but it should occur within a group of intrinsic calls // at the beginning of the block. CallInst *OldEnd = dyn_cast<CallInst>(Parent->getFirstInsertionPt()); while (OldEnd && OldEnd->getCalledFunction() != EndCf) OldEnd = dyn_cast<CallInst>(OldEnd->getNextNode()); if (OldEnd && OldEnd->getCalledFunction() == EndCf) { Value *Args[] = { OldEnd->getArgOperand(0), NewPhi }; Ret = CallInst::Create(ElseBreak, Args, "", OldEnd); continue; } } TerminatorInst *Insert = From->getTerminator(); Value *PhiArg = CallInst::Create(Break, Broken, "", Insert); NewPhi->setIncomingValue(i, PhiArg); } LoopPhiConditions.push_back(WeakTrackingVH(Phi)); return Ret; } if (Instruction *Inst = dyn_cast<Instruction>(Cond)) { BasicBlock *Parent = Inst->getParent(); Instruction *Insert; if (L->contains(Inst)) { Insert = Parent->getTerminator(); } else { Insert = L->getHeader()->getFirstNonPHIOrDbgOrLifetime(); } Value *Args[] = { Cond, Broken }; return CallInst::Create(IfBreak, Args, "", Insert); } // Insert IfBreak in the loop header TERM for constant COND other than true. if (isa<Constant>(Cond)) { Instruction *Insert = Cond == BoolTrue ? Term : L->getHeader()->getTerminator(); Value *Args[] = { Cond, Broken }; return CallInst::Create(IfBreak, Args, "", Insert); } llvm_unreachable("Unhandled loop condition!"); }
// addEdgesFor // Creates a node for I and inserts edges from the created node to the // appropriate node of other values. void IneqGraph::addEdgesFor(Instruction *I) { if (I->getType()->isPointerTy()) return; Range RI = RA->getRange(I); if (!RI.getLower().isMinSignedValue()) addMayEdge(AlfaConst, I, -RI.getLower().getSExtValue()); if (!RI.getUpper().isMaxSignedValue()) addMayEdge(I, AlfaConst, RI.getUpper().getSExtValue()); // TODO: Handle multiplication, remainder and division instructions. switch (I->getOpcode()) { case Instruction::SExt: case Instruction::ZExt: case Instruction::Trunc: case Instruction::BitCast: addMayEdge(I, I->getOperand(0), 0); addMayEdge(I->getOperand(0), I, 0); break; case Instruction::Add: // a = b + c // ==> a <= b + sup(c) // ==> a <= c + sup(b) // ==> b <= a - inf(c) // ==> c <= a - inf(b) { Value *A = I->getOperand(0); Value *B = I->getOperand(1); Range AR = RA->getRange(A); Range BR = RA->getRange(B); if (!isa<ConstantInt>(B) && !AR.getUpper().isMaxSignedValue()) addMayEdge(I, B, AR.getUpper()); if (!isa<ConstantInt>(A) && !BR.getUpper().isMaxSignedValue()) addMayEdge(I, A, BR.getUpper()); if (!isa<ConstantInt>(A) && !BR.getLower().isMinSignedValue()) addMayEdge(A, I, -BR.getUpper()); if (!isa<ConstantInt>(B) && !AR.getLower().isMinSignedValue()) addMayEdge(B, I, -AR.getUpper()); break; } case Instruction::Sub: // a = b - c // ==> a <= b - inf(c) { Value *A = I->getOperand(0); Value *B = I->getOperand(1); Range AR = RA->getRange(A); Range BR = RA->getRange(B); if (!isa<ConstantInt>(A) && !BR.getLower().isMinSignedValue()) addMayEdge(I, A, -BR.getLower()); break; } case Instruction::Br: // if (a > b) { // a1 = sigma(a) // b1 = sigma(b) { BranchInst *BI = cast<BranchInst>(I); ICmpInst *Cmp = dyn_cast<ICmpInst>(I->getOperand(0)); if (!Cmp) break; Value *L = Cmp->getOperand(0); DEBUG(dbgs() << "IneqGraph: L: " << *L << "\n"); Value *R = Cmp->getOperand(1); DEBUG(dbgs() << "IneqGraph: R: " << *R << "\n"); Value *LSigma = VS->findSigma(L, BI->getSuccessor(0), BI->getParent()); DEBUG(dbgs() << "IneqGraph: LSigma: " << *LSigma << "\n"); Value *RSigma = VS->findSigma(R, BI->getSuccessor(0), BI->getParent()); DEBUG(dbgs() << "IneqGraph: RSigma: " << *RSigma << "\n"); Value *LSExtSigma = VS->findSExtSigma(L, BI->getSuccessor(0), BI->getParent()); DEBUG(dbgs() << "IneqGraph: LSExtSigma: " << *LSExtSigma << "\n"); Value *RSExtSigma = VS->findSExtSigma(R, BI->getSuccessor(0), BI->getParent()); DEBUG(dbgs() << "IneqGraph: RSExtSigma: " << *RSExtSigma << "\n"); switch (Cmp->getPredicate()) { case ICmpInst::ICMP_SLT: DEBUG(dbgs() << "IneqGraph: SLT:\n"); if (!isa<ConstantInt>(R) && LSigma) { if (RSigma) addMayEdge(LSigma, RSigma, -1); if (RSExtSigma) addMayEdge(LSigma, RSExtSigma, -1); } if (!isa<ConstantInt>(R) && LSExtSigma && LSExtSigma != LSigma) { if (RSigma) addMayEdge(LSExtSigma, RSigma, -1); if (RSExtSigma) addMayEdge(LSExtSigma, RSExtSigma, -1); } break; case ICmpInst::ICMP_SLE: DEBUG(dbgs() << "IneqGraph: SLE:\n"); if (!isa<ConstantInt>(R) && LSigma && RSigma) addMayEdge(LSigma, RSigma, 0); if (!isa<ConstantInt>(R) && (LSExtSigma != LSigma || RSExtSigma != RSigma)) addMayEdge(LSExtSigma, RSExtSigma, 0); break; default: break; } break; } case Instruction::PHI: { PHINode *Phi = cast<PHINode>(I); for (unsigned Idx = 0; Idx < Phi->getNumIncomingValues(); ++Idx) { addMustEdge(Phi, Phi->getIncomingValue(Idx), 0); } break; } case Instruction::Call: { CallInst *CI = cast<CallInst>(I); if (Function *F = CI->getCalledFunction()) { unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI, ++Idx) { addMustEdge(&(*AI), CI->getArgOperand(Idx), 0); } } break; } } }
// // 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; }
// // 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; }
bool PathList::runOnModule(Module &M) { module = &M; llvm::dbgs() << "[runOnModule]: Moduel M has " << M.getFunctionList().size() << " Functions in all.\n"; // for test Function *f1 = M.getFunction("fprintf"); if (!f1) dbgs() << "[Test]: can not find function fprintf.\n"; else dbgs() << "[Test]: find function fprintf.\n"; CallGraph &CG = getAnalysis<CallGraph>(); // CG.dump(); CallGraphNode *cgNode = CG.getRoot(); cgNode->dump(); // errs()<<node->getFunction()->getName()<<'\n'; Function *startFunc; Function *endFunc; startFunc = M.getFunction("__user_main"); //std::string fileName("/home/xqx/data/xqx/projects/benckmarks-klee/texinfo-4.8/build-shit/makeinfo/../../makeinfo/insertion.c"); //int lineNo = 407; BB = getBB(fileName, lineNo); *targetBbpp = getBB(fileName, lineNo); if (BB) { endFunc = BB->getParent(); if (!endFunc) { errs()<<"Error: get endFunc failed.\n"; return false; } if (!startFunc) { errs()<<"Error: get startFunc failed.\n"; return false; } errs()<<startFunc->getName()<<'\n'; } else { errs()<<"Error: get BB failed.\n"; return false; } //read start and end from xml files // defectList enStart, enEnd; // getEntryList("/tmp/entrys.xml", &enStart, "start"); // getEntryList("/tmp/entrys.xml", &enEnd, "end"); // getEntryList("/tmp/entrys.xml", &dl, "end"); // dumpEntryList(&enStart); // dumpEntryList(&enEnd); // dumpEntryList(&dl); //read bug information from xml file /* for (defectList::iterator dit = dl.begin(); dit != dl.end(); dit++) { StringRef file(dit->first.c_str()); std::vector<int> lines = dit->second; BasicBlock *BB = getBB(file, *(lines.begin())); if (BB) { endFunc = BB->getParent(); } } */ //to store temporary path std::vector<BasicBlock*> p; // a counter int map_count = 0; for (Module::iterator i = M.begin(), e = M.end(); i != e; ++i) { Function *F = i; if (!F) { llvm::errs() << "***NULL Function***\n"; continue; } cgNode = CG.getOrInsertFunction(F); F = cgNode->getFunction(); // for (CallGraphNode::iterator I = cgNode->begin(), E = cgNode->end(); I != E; ++I){ CallGraphNode::CallRecord *cr = &*I; // llvm::errs() << "\tCS<" << cr->first << "> calls"; // check if the CallInst is existed if(cr->first){ Instruction *TmpIns = dyn_cast<Instruction>(cr->first); if(TmpIns) { // errs() << "\t" << *TmpIns << "\n"; //unsigned int l, c; //std::string cfi_path = getInstPath(TmpIns, l, c); //if (!cfi_path.empty()) { // if (cfi_path.find("uclibc") != std::string::npos) { // dbgs() << "[Filter Uclib]: find an instruction from uclibc.\n"; // continue; // } else if (cfi_path.find("POSIX") != std::string::npos) { // dbgs() << "[Filter Uclib]: find an instruction from POSIX.\n"; // continue; // } //} } else continue; } // get the funciton pointer which is called by current CallRecord cr Function *FI = cr->second->getFunction(); if (!FI) continue; // create a new CalledFunctions element and push it into calledFunctionMap. calledFunctionMap[FI].push_back(std::make_pair(F, dyn_cast<Instruction>(cr->first))); // for debuging map_count++; } } dbgs() << "[Count Number of calledFunctionMap]: "<< calledFunctionMap.size() <<'\n'; // analyze the global function pointer table if(function_pointer_analysis()) { errs() << "[Analyze global function pointer table success]\n"; } else { errs() << "[Analyze global function pointer table failed]\n"; } dbgs() << "[Count Number of calledFunctionMap]: "<< calledFunctionMap.size() <<'\n'; // filter the instructions from uclibc //filter_uclibc(); llvm::errs() << "=================================hh\n"; llvm::errs() << "get Function Path: " << endFunc->getName() << " to " << startFunc->getName() << " \n"; // printCalledFuncAndCFGPath(endFunc, startFunc, BB, p); // modification by wh evo_paths = new entire_path; //filter_paths = new func_bbs_type; //BB_paths_map = new std::map<std::pair<Function*, BasicBlock*>, std::vector<BasicBlock*> >; std::vector<std::pair< Function*, Instruction*> > tmp_func_path; // std::vector<BasicBlock*> tmp_bb_path; // explore_function_paths(endFunc, startFunc, bug_Inst, &tmp_func_path); collect_funcitons(endFunc, startFunc, bug_Inst, &tmp_func_path); // dbgs() << "++++++Found " << evo_paths->size() << " function paths.\n"; // for (entire_path::iterator ep_it = evo_paths->begin(); ep_it != evo_paths->end(); ep_it++) { // for (std::vector<std::pair< Function*, Instruction*> >::iterator pair_it = ep_it->begin(); pair_it != ep_it->end(); pair_it++) { // if (filter_paths->size() != 0) { // std::vector<Instruction*>::iterator inst_it = std::find((*filter_paths)[pair_it->first].begin(), (*filter_paths)[pair_it->first].end(), pair_it->second); // if (inst_it != (*filter_paths)[pair_it->first].end()) { // continue; // } // } // (*filter_paths)[pair_it->first].push_back(pair_it->second); // } // } dbgs() << "[filter_paths]: contain " << filter_paths->size() << " functions in all.\n"; for (func_bbs_type::iterator fbs_it = filter_paths->begin(); fbs_it != filter_paths->end(); fbs_it++) { for (std::vector<Instruction*>::iterator bb_it2 = fbs_it->second.begin(); bb_it2 != fbs_it->second.end(); bb_it2++) { dbgs() << "^^^^^^ " << fbs_it->first->getName() << ": " << (*bb_it2)->getParent()->getName() << '\n'; // to expand functions call_insts.push_back((*bb_it2)); explore_basicblock_paths(fbs_it->first, (*bb_it2)->getParent(), &(*BB_paths_map)[std::make_pair(fbs_it->first, *bb_it2)]); dbgs() << "^^^^^^ found " << (*BB_paths_map)[std::make_pair(fbs_it->first, *bb_it2)].size() << " basicblocks.\n"; } } llvm::dbgs() << "!!!!!!!! Found " << call_insts.size() << " call instructions.\n"; llvm::dbgs() << "!!!!!!!! Found " << path_basicblocks.size() << " path basicblocks.\n"; // expand functions for (std::vector<Instruction*>::iterator ci_it = call_insts.begin(); ci_it != call_insts.end(); ci_it++) { BasicBlock *call_bb = (*ci_it)->getParent(); if (!call_bb) { continue; } for (BasicBlock::iterator inst = call_bb->begin(); inst != call_bb->end(); inst++) { if (&*inst == *ci_it) { break; } if (isa<CallInst>(&*inst)) { std::vector<Instruction*>::iterator ci = std::find(path_call_insts.begin(), path_call_insts.end(), &*inst); if (ci != path_call_insts.end()) continue; path_call_insts.push_back(&*inst); } } } llvm::dbgs() << "@@@@@@@@ After search call_insts, found " << path_call_insts.size() << " call instructions.\n"; for (std::vector<BasicBlock*>::iterator p_bb_it = path_basicblocks.begin(); p_bb_it != path_basicblocks.end(); p_bb_it++) { for (BasicBlock::iterator inst = (*p_bb_it)->begin(); inst != (*p_bb_it)->end(); inst++) { if (isa<CallInst>(&*inst)) { std::vector<Instruction*>::iterator ci = std::find(path_call_insts.begin(), path_call_insts.end(), &*inst); if (ci != path_call_insts.end()) continue; path_call_insts.push_back(&*inst); } } } llvm::dbgs() << "@@@@@@@@ After search path_basicblocks, found " << path_call_insts.size() << " call instructions.\n"; for (std::vector<Instruction*>::iterator iit = path_call_insts.begin(); iit != path_call_insts.end(); iit++) { CallInst *ci = dyn_cast<CallInst>(*iit); if (!ci) continue; Function *ff = ci->getCalledFunction(); if (!ff) { //ci->dump(); //dbgs() << "\t[called value] " << ci->getOperand(0)->getName() << '\n'; continue; } std::vector<Function*>::iterator fit = std::find(otherCalledFuncs->begin(), otherCalledFuncs->end(), ff); if (fit == otherCalledFuncs->end()) otherCalledFuncs->push_back(ff); } llvm::dbgs() << "((((((((( Found " << otherCalledFuncs->size() << " functions.\n"; for (int index = 0; index < otherCalledFuncs->size(); index++) { Function *f = otherCalledFuncs->at(index); /* if (!f) { //f->dump(); llvm::dbgs() << "?????? index = " << index << " size = " << otherCalledFuncs->size()<< '\n'; continue; } */ for (inst_iterator f_it = inst_begin(f); f_it != inst_end(f); f_it++) { CallInst *ci = dyn_cast<CallInst>(&*f_it); if (!ci) continue; if (!ci->getCalledFunction()) { //ci->dump(); continue; } std::vector<Function*>::iterator fit = std::find(otherCalledFuncs->begin(), otherCalledFuncs->end(), ci->getCalledFunction()); if (fit == otherCalledFuncs->end()) otherCalledFuncs->push_back(ci->getCalledFunction()); } } llvm::dbgs() << "((((((((( Found " << otherCalledFuncs->size() << " functions.\n"; //This should be just for statistic. int tmp_funcNum_in_filter_notIn_other = 0; for (func_bbs_type::iterator fbs_it = filter_paths->begin(); fbs_it != filter_paths->end(); fbs_it++) { if (!fbs_it->first) { llvm::dbgs() << "[Warning]: Found a null Function pointer in filter_paths.\n"; continue; } std::vector<Function*>::iterator fit = std::find(otherCalledFuncs->begin(), otherCalledFuncs->end(), fbs_it->first); if (fit == otherCalledFuncs->end()) //otherCalledFuncs->push_back(fbs_it->first); tmp_funcNum_in_filter_notIn_other ++; } llvm::dbgs() << "<><><><> After searching filter_paths, found " << otherCalledFuncs->size() + tmp_funcNum_in_filter_notIn_other << " functions.\n"; /* for (entire_path::iterator ep_it = evo_paths->begin(); ep_it != evo_paths->end(); ep_it++) { dbgs() << "Path length is: " << ep_it->size() << '\n'; for (std::vector<std::pair< Function*, BasicBlock*> >::iterator pair_it = ep_it->begin(); pair_it != ep_it->end(); pair_it++) { dbgs() << "^^^^^^ " << pair_it->first->getName() << ": " << pair_it->second->getName() << '\n'; explore_basicblock_paths(pair_it->first, pair_it->second, &(*BB_paths_map)[*pair_it]); dbgs() << "^^^^^^ found " << (*BB_paths_map)[*pair_it].size() << " basicblocks.\n"; } } */ llvm::errs() << "on-end\n"; llvm::errs() << "=================================\n"; // output all of the paths /* errs()<<"Find "<<paths_found->size()<<" paths in all.\n"; for(paths::iterator ips = paths_found->begin();ips != paths_found->end();ips++) { // std::vector<BasicBlock*> *tmpP = dyn_cast<std::vector<BasicBlock*>*>(&*ips); dbgs() << "=========A Path Start============\n"; for(std::vector<BasicBlock*>::iterator ps = ips->begin(), pe = ips->end(); ps != pe; ps++) { BasicBlock *tmpStr = *ps; errs()<<"\t"<<tmpStr->getParent()->getName()<<": "<<tmpStr->getName()<<" -> \n"; } errs()<<"=================================\n"; } */ return false; }
void OptimizeFastMemoryChecks::visitCallInst(CallInst &CI) { CheckInfoType *Info = MSCI->getCheckInfo(CI.getCalledFunction()); if (Info && Info->isFastMemoryCheck()) FastCheckCalls.push_back(&CI); }
bool TracingNoGiri::visitSpecialCall(CallInst &CI) { Function *CalledFunc = CI.getCalledFunction(); // We do not support indirect calls to special functions. if (CalledFunc == nullptr) return false; // Do not consider a function special if it has a function body; in this // case, the programmer has supplied his or her version of the function, and // we will instrument it. if (!CalledFunc->isDeclaration()) return false; // Check the name of the function against a list of known special functions. std::string name = CalledFunc->getName().str(); if (name.substr(0,12) == "llvm.memset.") { instrumentLock(&CI); // Get the destination pointer and cast it to a void pointer. Value *dstPointer = CI.getOperand(0); dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI); // Get the number of bytes that will be written into the buffer. Value *NumElts = CI.getOperand(2); // Get the ID of the external funtion call instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // Create the call to the run-time to record the external call instruction. std::vector<Value *> args = make_vector(CallID, dstPointer, NumElts, 0); CallInst::Create(RecordStore, args, "", &CI); instrumentUnlock(&CI); ++NumExtFuns; // Update statistics return true; } else if (name.substr(0,12) == "llvm.memcpy." || name.substr(0,13) == "llvm.memmove." || name == "strcpy") { instrumentLock(&CI); /* Record Load src, [CI] Load dst [CI] */ // Get the destination and source pointers and cast them to void pointers. Value *dstPointer = CI.getOperand(0); Value *srcPointer = CI.getOperand(1); dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI); srcPointer = castTo(srcPointer, VoidPtrType, srcPointer->getName(), &CI); // Get the ID of the ext fun call instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // Create the call to the run-time to record the loads and stores of // external call instruction. if(name == "strcpy") { // FIXME: If the tracer function should be inserted before or after???? std::vector<Value *> args = make_vector(CallID, srcPointer, 0); CallInst::Create(RecordStrLoad, args, "", &CI); args = make_vector(CallID, dstPointer, 0); CallInst *recStore = CallInst::Create(RecordStrStore, args, "", &CI); CI.moveBefore(recStore); } else { // get the num elements to be transfered Value *NumElts = CI.getOperand(2); std::vector<Value *> args = make_vector(CallID, srcPointer, NumElts, 0); CallInst::Create(RecordLoad, args, "", &CI); args = make_vector(CallID, dstPointer, NumElts, 0); CallInst::Create(RecordStore, args, "", &CI); } instrumentUnlock(&CI); ++NumExtFuns; // Update statistics return true; } else if (name == "strcat") { /* Record Load dst, Load Src, Store dst-end before call inst */ instrumentLock(&CI); // Get the destination and source pointers and cast them to void pointers. Value *dstPointer = CI.getOperand(0); Value *srcPointer = CI.getOperand(1); dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI); srcPointer = castTo(srcPointer, VoidPtrType, srcPointer->getName(), &CI); // Get the ID of the ext fun call instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // Create the call to the run-time to record the loads and stores of // external call instruction. // CHECK: If the tracer function should be inserted before or after???? std::vector<Value *> args = make_vector(CallID, dstPointer, 0); CallInst::Create(RecordStrLoad, args, "", &CI); args = make_vector(CallID, srcPointer, 0); CallInst::Create(RecordStrLoad, args, "", &CI); // Record the addresses before concat as they will be lost after concat args = make_vector(CallID, dstPointer, srcPointer, 0); CallInst::Create(RecordStrcatStore, args, "", &CI); instrumentUnlock(&CI); ++NumExtFuns; // Update statistics return true; } else if (name == "strlen") { /* Record Load */ instrumentLock(&CI); // Get the destination and source pointers and cast them to void pointers. Value *srcPointer = CI.getOperand(0); srcPointer = castTo(srcPointer, VoidPtrType, srcPointer->getName(), &CI); // Get the ID of the ext fun call instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); std::vector<Value *> args = make_vector(CallID, srcPointer, 0); CallInst::Create(RecordStrLoad, args, "", &CI); instrumentUnlock(&CI); ++NumExtFuns; // Update statistics return true; } else if (name == "calloc") { instrumentLock(&CI); // Get the number of bytes that will be written into the buffer. Value *NumElts = BinaryOperator::Create(BinaryOperator::Mul, CI.getOperand(0), CI.getOperand(1), "calloc par1 * par2", &CI); // Get the destination pointer and cast it to a void pointer. // Instruction * dstPointerInst; Value *dstPointer = castTo(&CI, VoidPtrType, CI.getName(), &CI); /* // To move after call inst, we need to know if cast is a constant expr or inst if ((dstPointerInst = dyn_cast<Instruction>(dstPointer))) { CI.moveBefore(dstPointerInst); // dstPointerInst->insertAfter(&CI); // ((Instruction *)NumElts)->insertAfter(dstPointerInst); } else { CI.moveBefore((Instruction *)NumElts); // ((Instruction *)NumElts)->insertAfter(&CI); } dstPointer = dstPointerInst; // Assign to dstPointer for instrn or non-instrn values */ // Get the ID of the external funtion call instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // // Create the call to the run-time to record the external call instruction. // std::vector<Value *> args = make_vector(CallID, dstPointer, NumElts, 0); CallInst *recStore = CallInst::Create(RecordStore, args, "", &CI); CI.moveBefore(recStore); //recStore->insertAfter((Instruction *)NumElts); // Moove cast, #byte computation and store to after call inst CI.moveBefore(cast<Instruction>(NumElts)); instrumentUnlock(&CI); ++NumExtFuns; // Update statistics return true; } else if (name == "tolower" || name == "toupper") { // Not needed as there are no loads and stores /* } else if (name == "strncpy/itoa/stdarg/scanf/fscanf/sscanf/fread/complex/strftime/strptime/asctime/ctime") { */ } else if (name == "fscanf") { // TODO // In stead of parsing format string, can we use the type of the arguments?? } else if (name == "sscanf") { // TODO } else if (name == "sprintf") { instrumentLock(&CI); // Get the pointer to the destination buffer. Value *dstPointer = CI.getOperand(0); dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI); // Get the ID of the call instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // Scan through the arguments looking for what appears to be a character // string. Generate load records for each of these strings. for (unsigned index = 2; index < CI.getNumOperands(); ++index) { if (CI.getOperand(index)->getType() == VoidPtrType) { // Create the call to the run-time to record the load from the string. // What about other loads?? Value *Ptr = CI.getOperand(index); std::vector<Value *> args = make_vector(CallID, Ptr, 0); CallInst::Create(RecordStrLoad, args, "", &CI); ++NumLoadStrings; // Update statistics } } // Create the call to the run-time to record the external call instruction. std::vector<Value *> args = make_vector(CallID, dstPointer, 0); CallInst *recStore = CallInst::Create(RecordStrStore, args, "", &CI); CI.moveBefore(recStore); instrumentUnlock(&CI); ++NumStoreStrings; // Update statistics return true; } else if (name == "fgets") { instrumentLock(&CI); // Get the pointer to the destination buffer. Value * dstPointer = CI.getOperand(0); dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI); // Get the ID of the ext fun call instruction. Value * CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // Create the call to the run-time to record the external call instruction. std::vector<Value *> args = make_vector(CallID, dstPointer, 0); CallInst *recStore = CallInst::Create(RecordStrStore, args, "", &CI); CI.moveBefore(recStore); instrumentUnlock(&CI); // Update statistics ++NumStoreStrings; return true; } return false; }
bool InlineModule::runOnModule( Module & M ) { std::vector<std::string> leafNames; //File *file = fopen("inline_info.txt", "r"); //if (!file) { // errs() << "Error: Could not open inline_info file.\n"; // retrun true; //} std::string line; std::ifstream file ("inline_info.txt"); if(file.is_open()) { while(std::getline(file, line)) leafNames.push_back(line); file.close(); } else errs() << "Error: Could not open inline_info file.\n"; //makeLeaf.push_back(M.getFunction("ORACLE_0")); //makeLeaf.push_back(M.getFunction("ORACLE_1")); //makeLeaf.push_back(M.getFunction("ORACLE_2")); //makeLeaf.push_back(M.getFunction("ORACLE_3")); for (std::vector<std::string>::iterator i = leafNames.begin(), e = leafNames.end(); i!=e; ++i) { if (debugInlining) errs() << "inline_info: " << *i << "\n"; makeLeaf.push_back(M.getFunction(*i)); } // First, get a pointer to previous analysis results CallGraph & CG = getAnalysis<CallGraph>(); CallGraphNode * entry = CG.getRoot(); if( entry && entry->getFunction() && debugInlining) errs() << "Entry is function: " << entry->getFunction()->getName() << "\n"; // Iterate over all SCCs in the module in bottom-up order for( scc_iterator<CallGraph*> si=scc_begin( &CG ), se=scc_end( &CG ); si != se; ++si ) { runOnSCC( *si ); } //reverse the vector for preorder std::reverse(vectPostOrder.begin(),vectPostOrder.end()); for(std::vector<Function*>::iterator vit = vectPostOrder.begin(), vitE = vectPostOrder.end(); vit!=vitE; ++vit) { Function *f = *vit; runOnFunction(*f); } // now we have all the call sites which need to be inlined // inline from the leaves all the way up const TargetData *TD = getAnalysisIfAvailable<TargetData>(); InlineFunctionInfo InlineInfo(&CG, TD); std::reverse(inlineCallInsts.begin(),inlineCallInsts.end()); for (std::vector<CallInst*>::iterator i = inlineCallInsts.begin(), e = inlineCallInsts.end(); i!=e; ++i) { CallInst* CI = *i; bool success = InlineFunction(CI, InlineInfo, false); if(!success) { if (debugInlining) errs() << "Error: Could not inline callee function " << CI->getCalledFunction()->getName() << " into caller function " << "\n"; continue; } if (debugInlining) errs() << "Successfully inlined callee function " << CI->getCalledFunction()->getName() << "into caller function " << "\n"; } return false; }
void TracingNoGiri::visitCallInst(CallInst &CI) { // Attempt to get the called function. Function *CalledFunc = CI.getCalledFunction(); if (!CalledFunc) return; // Do not instrument calls to tracing run-time functions or debug functions. if (isTracerFunction(CalledFunc)) return; if (!CalledFunc->getName().str().compare(0,9,"llvm.dbg.")) return; // Instrument external calls which can have invariants on its return value if (CalledFunc->isDeclaration() && CalledFunc->isIntrinsic()) { // Instrument special external calls which loads/stores // e.g. strlen(), strcpy(), memcpy() etc. visitSpecialCall(CI); return; } // If the called value is inline assembly code, then don't instrument it. if (isa<InlineAsm>(CI.getCalledValue()->stripPointerCasts())) return; instrumentLock(&CI); // Get the ID of the store instruction. Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI)); // Get the called function value and cast it to a void pointer. Value *FP = castTo(CI.getCalledValue(), VoidPtrType, "", &CI); // Create the call to the run-time to record the call instruction. std::vector<Value *> args = make_vector<Value *>(CallID, FP, 0); // Do not add calls to function call stack for external functions // as return records won't be used/needed for them, so call a special record function // FIXME!!!! Do we still need it after adding separate return records???? Instruction *RC; if (CalledFunc->isDeclaration()) RC = CallInst::Create(RecordExtCall, args, "", &CI); else RC = CallInst::Create(RecordCall, args, "", &CI); instrumentUnlock(RC); // Create the call to the run-time to record the return of call instruction. CallInst *CallInst = CallInst::Create(RecordReturn, args, "", &CI); CI.moveBefore(CallInst); instrumentLock(CallInst); instrumentUnlock(CallInst); ++NumCalls; // Update statistics // The best way to handle external call is to set a flag before calling ext fn and // use that to determine if an internal function is called from ext fn. It flag can be // reset afterwards and restored to its original value before returning to ext code. // FIXME!!!! LATER #if 0 if (CalledFunc->isDeclaration() && CalledFunc->getName().str() == "pthread_create") { // If pthread_create is called then handle it specially as it calls // functions externally and add an extra call for the externally // called functions with the same id so that returns can match with it. // In addition to a function call to pthread_create. // Get the external function pointer operand and cast it to a void pointer Value *FP = castTo(CI.getOperand(2), VoidPtrType, "", &CI); // Create the call to the run-time to record the call instruction. std::vector<Value *> argsExt = make_vector<Value *>(CallID, FP, 0); CallInst = CallInst::Create(RecordCall, argsExt, "", &CI); CI.moveBefore(CallInst); // Update statistics ++Calls; // For, both external functions and internal/ext functions called from // external functions, return records are not useful as they won't be used. // Since, we won't create return records for them, simply update the call // stack to mark the end of function call. //args = make_vector<Value *>(CallID, FP, 0); //CallInst::Create(RecordExtCallRet, args.begin(), args.end(), "", &CI); // Create the call to the run-time to record the return of call instruction. CallInst::Create(RecordReturn, argsExt, "", &CI); } #endif // Instrument special external calls which loads/stores // like strlen, strcpy, memcpy etc. visitSpecialCall(CI); }
int compile(list<string> args, list<string> kgen_args, string merge, list<string> merge_args, string input, string output, int arch, string host_compiler, string fileprefix) { // // The LLVM compiler to emit IR. // const char* llvm_compiler = "kernelgen-gfortran"; // // Interpret kernelgen compile options. // for (list<string>::iterator iarg = kgen_args.begin(), iearg = kgen_args.end(); iarg != iearg; iarg++) { const char* arg = (*iarg).c_str(); if (!strncmp(arg, "-Wk,--llvm-compiler=", 20)) llvm_compiler = arg + 20; } // // Generate temporary output file. // Check if output file is specified in the command line. // Replace or add output to the temporary file. // cfiledesc tmp_output = cfiledesc::mktemp(fileprefix); bool output_specified = false; for (list<string>::iterator iarg = args.begin(), iearg = args.end(); iarg != iearg; iarg++) { const char* arg = (*iarg).c_str(); if (!strcmp(arg, "-o")) { iarg++; *iarg = tmp_output.getFilename(); output_specified = true; break; } } if (!output_specified) { args.push_back("-o"); args.push_back(tmp_output.getFilename()); } // // 1) Compile source code using regular host compiler. // { if (verbose) { cout << host_compiler; for (list<string>::iterator iarg = args.begin(), iearg = args.end(); iarg != iearg; iarg++) cout << " " << *iarg; cout << endl; } int status = execute(host_compiler, args, "", NULL, NULL); if (status) return status; } // // 2) Emit LLVM IR. // string out = ""; { list<string> emit_ir_args; for (list<string>::iterator iarg = args.begin(), iearg = args.end(); iarg != iearg; iarg++) { const char* arg = (*iarg).c_str(); if (!strcmp(arg, "-c") || !strcmp(arg, "-o")) { iarg++; continue; } if (!strcmp(arg, "-g")) { continue; } emit_ir_args.push_back(*iarg); } emit_ir_args.push_back("-fplugin=/opt/kernelgen/lib/dragonegg.so"); emit_ir_args.push_back("-fplugin-arg-dragonegg-emit-ir"); emit_ir_args.push_back("-S"); emit_ir_args.push_back(input); emit_ir_args.push_back("-o"); emit_ir_args.push_back("-"); if (verbose) { cout << llvm_compiler; for (list<string>::iterator iarg = emit_ir_args.begin(), iearg = emit_ir_args.end(); iarg != iearg; iarg++) cout << " " << *iarg; cout << endl; } int status = execute(llvm_compiler, emit_ir_args, "", &out, NULL); if (status) return status; } // // 3) Record existing module functions. // LLVMContext &context = getGlobalContext(); SMDiagnostic diag; MemoryBuffer* buffer1 = MemoryBuffer::getMemBuffer(out); auto_ptr<Module> m1; m1.reset(ParseIR(buffer1, diag, context)); //m1.get()->dump(); // // 4) Inline calls and extract loops into new functions. // MemoryBuffer* buffer2 = MemoryBuffer::getMemBuffer(out); auto_ptr<Module> m2; m2.reset(ParseIR(buffer2, diag, context)); { PassManager manager; manager.add(createInstructionCombiningPass()); manager.run(*m2.get()); } std::vector<CallInst *> LoopFuctionCalls; { PassManager manager; manager.add(createBranchedLoopExtractorPass(LoopFuctionCalls)); manager.run(*m2.get()); } //m2.get()->dump(); // // 5) Replace call to loop functions with call to launcher. // Append "always inline" attribute to all other functions. // Type* int32Ty = Type::getInt32Ty(context); Function* launch = Function::Create( TypeBuilder<types::i<32>(types::i<8>*, types::i<64>, types::i<32>*), true>::get(context), GlobalValue::ExternalLinkage, "kernelgen_launch", m2.get()); for (Module::iterator f1 = m2.get()->begin(), fe1 = m2.get()->end(); f1 != fe1; f1++) { Function* func = f1; if (func->isDeclaration()) continue; // Search for the current function in original module // functions list. // If function is not in list of original module, then // it is generated by the loop extractor. // Append "always inline" attribute to all other functions. if (m1.get()->getFunction(func->getName())) { const AttrListPtr attr = func->getAttributes(); const AttrListPtr attr_new = attr.addAttr(~0U, Attribute::AlwaysInline); func->setAttributes(attr_new); continue; } // Each such function must be extracted to the // standalone module and packed into resulting // object file data section. if (verbose) cout << "Preparing loop function " << func->getName().data() << " ..." << endl; // Reset to default visibility. func->setVisibility(GlobalValue::DefaultVisibility); // Reset to default linkage. func->setLinkage(GlobalValue::ExternalLinkage); // Replace call to this function in module with call to launcher. bool found = false; for (Module::iterator f2 = m2->begin(), fe2 = m2->end(); (f2 != fe2) && !found; f2++) for (Function::iterator bb = f2->begin(); (bb != f2->end()) && !found; bb++) for (BasicBlock::iterator i = bb->begin(); i != bb->end(); i++) { // Check if instruction in focus is a call. CallInst* call = dyn_cast<CallInst>(cast<Value>(i)); if (!call) continue; // Check if function is called (needs -instcombine pass). Function* callee = call->getCalledFunction(); if (!callee) continue; if (callee->isDeclaration()) continue; if (callee->getName() != func->getName()) continue; // Create a constant array holding original called // function name. Constant* name = ConstantArray::get( context, callee->getName(), true); // Create and initialize the memory buffer for name. ArrayType* nameTy = cast<ArrayType>(name->getType()); AllocaInst* nameAlloc = new AllocaInst(nameTy, "", call); StoreInst* nameInit = new StoreInst(name, nameAlloc, "", call); Value* Idx[2]; Idx[0] = Constant::getNullValue(Type::getInt32Ty(context)); Idx[1] = ConstantInt::get(Type::getInt32Ty(context), 0); GetElementPtrInst* namePtr = GetElementPtrInst::Create(nameAlloc, Idx, "", call); // Add pointer to the original function string name. SmallVector<Value*, 16> call_args; call_args.push_back(namePtr); // Add size of the aggregated arguments structure. { BitCastInst* BC = new BitCastInst( call->getArgOperand(0), Type::getInt64PtrTy(context), "", call); LoadInst* LI = new LoadInst(BC, "", call); call_args.push_back(LI); } // Add original aggregated structure argument. call_args.push_back(call->getArgOperand(0)); // Create new function call with new call arguments // and copy old call properties. CallInst* newcall = CallInst::Create(launch, call_args, "", call); //newcall->takeName(call); newcall->setCallingConv(call->getCallingConv()); newcall->setAttributes(call->getAttributes()); newcall->setDebugLoc(call->getDebugLoc()); // Replace old call with new one. call->replaceAllUsesWith(newcall); call->eraseFromParent(); found = true; break; } } //m2.get()->dump(); // // 6) Apply optimization passes to the resulting common // module. // { PassManager manager; manager.add(createLowerSetJmpPass()); PassManagerBuilder builder; builder.Inliner = createFunctionInliningPass(); builder.OptLevel = 3; builder.DisableSimplifyLibCalls = true; builder.populateModulePassManager(manager); manager.run(*m2.get()); } //m2.get()->dump(); // // 7) Embed the resulting module into object file. // { string ir_string; raw_string_ostream ir(ir_string); ir << (*m2.get()); celf e(tmp_output.getFilename(), output); e.getSection(".data")->addSymbol( "__kernelgen_" + string(input), ir_string.c_str(), ir_string.size() + 1); } return 0; }
void MutationGen::genSTDCall(Instruction * inst, StringRef fname, int index){ CallInst *call = cast<CallInst>(inst); Function *fun = call->getCalledFunction(); if(fun->getName().startswith("llvm")){ return; } Type *t = call->getCalledValue()->getType(); FunctionType* ft = cast<FunctionType>(cast<PointerType>(t)->getElementType()); Type *tt = ft->getReturnType(); //tt->dump(); if(tt->isIntegerTy(32)){ //1. if the func returns a int32 val, let it be 0, 1 or a random number //errs()<<"IT IS A 32 !!\n"; std::stringstream ss; ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<32<<":0\n"; muts_num++; ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<32<<":1\n"; muts_num++; //srand((int)time(0)); //int random = rand(); ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<32<<":"<<-1<<"\n"; muts_num++; ofresult<<ss.str(); ofresult.flush(); }else if(tt->isVoidTy()){ //2. if the func returns void, subsitute @llvm.donothing for the func //errs()<<"IT IS A VOID !!\n"; std::stringstream ss; ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<0<<'\n'; ofresult<<ss.str(); ofresult.flush(); muts_num++; }else if(tt->isIntegerTy(64)){ //1. if the func returns a int64 val, let it be 0, 1 or a random number //errs()<<"IT IS A 64 !!\n"; std::stringstream ss; ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<64<<":0\n"; muts_num++; ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<64<<":1\n"; muts_num++; //srand((int)time(0)); //int random = rand(); ss<<"STD:"<<std::string(fname)<<":"<<index<< ":"<<inst->getOpcode() << ":"<<64<<":"<<-1<<"\n"; muts_num++; ofresult<<ss.str(); ofresult.flush(); } }
/// InlineHalfPowrs - Inline a sequence of adjacent half_powr calls, rearranging /// their control flow to better facilitate subsequent optimization. Instruction * SimplifyHalfPowrLibCalls:: InlineHalfPowrs(const std::vector<Instruction *> &HalfPowrs, Instruction *InsertPt) { std::vector<BasicBlock *> Bodies; BasicBlock *NewBlock = 0; for (unsigned i = 0, e = HalfPowrs.size(); i != e; ++i) { CallInst *Call = cast<CallInst>(HalfPowrs[i]); Function *Callee = Call->getCalledFunction(); // Minimally sanity-check the CFG of half_powr to ensure that it contains // the kind of code we expect. If we're running this pass, we have // reason to believe it will be what we expect. Function::iterator I = Callee->begin(); BasicBlock *Prologue = I++; if (I == Callee->end()) break; BasicBlock *SubnormalHandling = I++; if (I == Callee->end()) break; BasicBlock *Body = I++; if (I != Callee->end()) break; if (SubnormalHandling->getSinglePredecessor() != Prologue) break; BranchInst *PBI = dyn_cast<BranchInst>(Prologue->getTerminator()); if (!PBI || !PBI->isConditional()) break; BranchInst *SNBI = dyn_cast<BranchInst>(SubnormalHandling->getTerminator()); if (!SNBI || SNBI->isConditional()) break; if (!isa<ReturnInst>(Body->getTerminator())) break; Instruction *NextInst = llvm::next(BasicBlock::iterator(Call)); // Inline the call, taking care of what code ends up where. NewBlock = SplitBlock(NextInst->getParent(), NextInst, this); InlineFunctionInfo IFI(0, TD); bool B = InlineFunction(Call, IFI); assert(B && "half_powr didn't inline?"); (void)B; BasicBlock *NewBody = NewBlock->getSinglePredecessor(); assert(NewBody); Bodies.push_back(NewBody); } if (!NewBlock) return InsertPt; // Put the code for all the bodies into one block, to facilitate // subsequent optimization. (void)SplitEdge(NewBlock->getSinglePredecessor(), NewBlock, this); for (unsigned i = 0, e = Bodies.size(); i != e; ++i) { BasicBlock *Body = Bodies[i]; Instruction *FNP = Body->getFirstNonPHI(); // Splice the insts from body into NewBlock. NewBlock->getInstList().splice(NewBlock->begin(), Body->getInstList(), FNP, Body->getTerminator()); } return NewBlock->begin(); }
// // 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; }
/// performLocalRetainMotion - Scan forward from the specified retain, moving it /// later in the function if possible, over instructions that provably can't /// release the object. If we get to a release of the object, zap both. /// /// NOTE: this handles both objc_retain and swift_retain. /// static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB, SwiftRCIdentity *RC) { // FIXME: Call classifier should identify the object for us. Too bad C++ // doesn't have nice Swift-style enums. Value *RetainedObject = RC->getSwiftRCIdentityRoot(Retain.getArgOperand(0)); BasicBlock::iterator BBI = Retain.getIterator(), BBE = BB.getTerminator()->getIterator(); bool isObjCRetain = Retain.getCalledFunction()->getName() == "objc_retain"; bool MadeProgress = false; // Scan until we get to the end of the block. for (++BBI; BBI != BBE; ++BBI) { Instruction &CurInst = *BBI; // Classify the instruction. This switch does a "break" when the instruction // can be skipped and is interesting, and a "continue" when it is a retain // of the same pointer. switch (classifyInstruction(CurInst)) { // These instructions should not reach here based on the pass ordering. // i.e. LLVMARCOpt -> LLVMContractOpt. case RT_RetainN: case RT_UnknownRetainN: case RT_BridgeRetainN: case RT_ReleaseN: case RT_UnknownReleaseN: case RT_BridgeReleaseN: llvm_unreachable("These are only created by LLVMARCContract !"); case RT_NoMemoryAccessed: case RT_AllocObject: case RT_CheckUnowned: // Skip over random instructions that don't touch memory. They don't need // protection by retain/release. break; case RT_FixLifetime: // This only stops release motion. Retains can move over it. break; case RT_Retain: case RT_UnknownRetain: case RT_BridgeRetain: case RT_RetainUnowned: case RT_ObjCRetain: { // swift_retain(obj) //CallInst &ThisRetain = cast<CallInst>(CurInst); //Value *ThisRetainedObject = ThisRetain.getArgOperand(0); // If we see a retain of the same object, we can skip over it, but we // can't count it as progress. Just pushing a retain(x) past a retain(y) // doesn't change the program. continue; } case RT_UnknownRelease: case RT_BridgeRelease: case RT_ObjCRelease: case RT_Release: { // If we get to a release that is provably to this object, then we can zap // it and the retain. CallInst &ThisRelease = cast<CallInst>(CurInst); Value *ThisReleasedObject = ThisRelease.getArgOperand(0); ThisReleasedObject = RC->getSwiftRCIdentityRoot(ThisReleasedObject); if (ThisReleasedObject == RetainedObject) { Retain.eraseFromParent(); ThisRelease.eraseFromParent(); if (isObjCRetain) { ++NumObjCRetainReleasePairs; } else { ++NumRetainReleasePairs; } return true; } // Otherwise, if this is some other pointer, we can only ignore it if we // can prove that the two objects don't alias. // Retain.dump(); ThisRelease.dump(); BB.getParent()->dump(); goto OutOfLoop; } case RT_Unknown: // Loads cannot affect the retain. if (isa<LoadInst>(CurInst)) continue; // Load, store, memcpy etc can't do a release. if (isa<LoadInst>(CurInst) || isa<StoreInst>(CurInst) || isa<MemIntrinsic>(CurInst)) break; // CurInst->dump(); BBI->dump(); // Otherwise, we get to something unknown/unhandled. Bail out for now. goto OutOfLoop; } // If the switch did a break, we made some progress moving this retain. MadeProgress = true; } OutOfLoop: // If we were able to move the retain down, move it now. // TODO: This is where we'd plug in some global algorithms someday. if (MadeProgress) { Retain.moveBefore(&*BBI); return true; } return false; }
void AMDGPUPromoteAlloca::visitAlloca(AllocaInst &I) { IRBuilder<> Builder(&I); // First try to replace the alloca with a vector Type *AllocaTy = I.getAllocatedType(); DEBUG(dbgs() << "Trying to promote " << I << '\n'); if (tryPromoteAllocaToVector(&I)) return; DEBUG(dbgs() << " alloca is not a candidate for vectorization.\n"); // FIXME: This is the maximum work group size. We should try to get // value from the reqd_work_group_size function attribute if it is // available. unsigned WorkGroupSize = 256; int AllocaSize = WorkGroupSize * Mod->getDataLayout()->getTypeAllocSize(AllocaTy); if (AllocaSize > LocalMemAvailable) { DEBUG(dbgs() << " Not enough local memory to promote alloca.\n"); return; } std::vector<Value*> WorkList; if (!collectUsesWithPtrTypes(&I, WorkList)) { DEBUG(dbgs() << " Do not know how to convert all uses\n"); return; } DEBUG(dbgs() << "Promoting alloca to local memory\n"); LocalMemAvailable -= AllocaSize; GlobalVariable *GV = new GlobalVariable( *Mod, ArrayType::get(I.getAllocatedType(), 256), false, GlobalValue::ExternalLinkage, 0, I.getName(), 0, GlobalVariable::NotThreadLocal, AMDGPUAS::LOCAL_ADDRESS); FunctionType *FTy = FunctionType::get( Type::getInt32Ty(Mod->getContext()), false); AttributeSet AttrSet; AttrSet.addAttribute(Mod->getContext(), 0, Attribute::ReadNone); Value *ReadLocalSizeY = Mod->getOrInsertFunction( "llvm.r600.read.local.size.y", FTy, AttrSet); Value *ReadLocalSizeZ = Mod->getOrInsertFunction( "llvm.r600.read.local.size.z", FTy, AttrSet); Value *ReadTIDIGX = Mod->getOrInsertFunction( "llvm.r600.read.tidig.x", FTy, AttrSet); Value *ReadTIDIGY = Mod->getOrInsertFunction( "llvm.r600.read.tidig.y", FTy, AttrSet); Value *ReadTIDIGZ = Mod->getOrInsertFunction( "llvm.r600.read.tidig.z", FTy, AttrSet); Value *TCntY = Builder.CreateCall(ReadLocalSizeY); Value *TCntZ = Builder.CreateCall(ReadLocalSizeZ); Value *TIdX = Builder.CreateCall(ReadTIDIGX); Value *TIdY = Builder.CreateCall(ReadTIDIGY); Value *TIdZ = Builder.CreateCall(ReadTIDIGZ); Value *Tmp0 = Builder.CreateMul(TCntY, TCntZ); Tmp0 = Builder.CreateMul(Tmp0, TIdX); Value *Tmp1 = Builder.CreateMul(TIdY, TCntZ); Value *TID = Builder.CreateAdd(Tmp0, Tmp1); TID = Builder.CreateAdd(TID, TIdZ); std::vector<Value*> Indices; Indices.push_back(Constant::getNullValue(Type::getInt32Ty(Mod->getContext()))); Indices.push_back(TID); Value *Offset = Builder.CreateGEP(GV, Indices); I.mutateType(Offset->getType()); I.replaceAllUsesWith(Offset); I.eraseFromParent(); for (std::vector<Value*>::iterator i = WorkList.begin(), e = WorkList.end(); i != e; ++i) { Value *V = *i; CallInst *Call = dyn_cast<CallInst>(V); if (!Call) { Type *EltTy = V->getType()->getPointerElementType(); PointerType *NewTy = PointerType::get(EltTy, AMDGPUAS::LOCAL_ADDRESS); // The operand's value should be corrected on its own. if (isa<AddrSpaceCastInst>(V)) continue; // FIXME: It doesn't really make sense to try to do this for all // instructions. V->mutateType(NewTy); continue; } IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(Call); if (!Intr) { std::vector<Type*> ArgTypes; for (unsigned ArgIdx = 0, ArgEnd = Call->getNumArgOperands(); ArgIdx != ArgEnd; ++ArgIdx) { ArgTypes.push_back(Call->getArgOperand(ArgIdx)->getType()); } Function *F = Call->getCalledFunction(); FunctionType *NewType = FunctionType::get(Call->getType(), ArgTypes, F->isVarArg()); Constant *C = Mod->getOrInsertFunction(StringRef(F->getName().str() + ".local"), NewType, F->getAttributes()); Function *NewF = cast<Function>(C); Call->setCalledFunction(NewF); continue; } Builder.SetInsertPoint(Intr); switch (Intr->getIntrinsicID()) { case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: // These intrinsics are for address space 0 only Intr->eraseFromParent(); continue; case Intrinsic::memcpy: { MemCpyInst *MemCpy = cast<MemCpyInst>(Intr); Builder.CreateMemCpy(MemCpy->getRawDest(), MemCpy->getRawSource(), MemCpy->getLength(), MemCpy->getAlignment(), MemCpy->isVolatile()); Intr->eraseFromParent(); continue; } case Intrinsic::memset: { MemSetInst *MemSet = cast<MemSetInst>(Intr); Builder.CreateMemSet(MemSet->getRawDest(), MemSet->getValue(), MemSet->getLength(), MemSet->getAlignment(), MemSet->isVolatile()); Intr->eraseFromParent(); continue; } default: Intr->dump(); llvm_unreachable("Don't know how to promote alloca intrinsic use."); } } }
void insertCallToAccessFunction(Function *F, Function *cF) { CallInst *I; Instruction *bI; std::vector<Value *> Args; std::vector<Type *> ArgsTy; Module *M = F->getParent(); std::string name; Function *nF, *tF; FunctionType *FTy; std::stringstream out; Value::user_iterator i = F->user_begin(), e = F->user_end(); while (i != e) { Args.clear(); ArgsTy.clear(); /************* C codes ***********/ if (isa<CallInst>(*i)) { I = dyn_cast<CallInst>(*i); // call to the access function F Args.push_back(I->getArgOperand(0)); ArgsTy.push_back(I->getArgOperand(0)->getType()); // call to the execute function cF Args.push_back(cF); ArgsTy.push_back(PointerType::get(cF->getFunctionType(), 0)); unsigned int t; for (t = 1; t < I->getNumArgOperands(); t++) { Args.push_back(I->getArgOperand(t)); ArgsTy.push_back(I->getArgOperand(t)->getType()); // errs() << *(I->getArgOperand(t)) << " is or not " << // isa<GlobalVariable>(I->getArgOperand(t)) << "\n"; } tF = dyn_cast<Function>(I->getCalledFunction()); FTy = FunctionType::get(tF->getReturnType(), ArgsTy, 0); out.str(std::string()); out << "task_DAE_" << I->getNumArgOperands() - 1; nF = (Function *)M->getOrInsertFunction(out.str(), FTy); CallInst *ci = CallInst::Create(nF, Args, I->getName(), I); i++; I->replaceAllUsesWith(ci); I->eraseFromParent(); } /************* C++ codes ***********/ else { Value::user_iterator bit = (*i)->user_begin(), bite = (*i)->user_end(); Type *iTy = (*i)->getType(); i++; while (bit != bite) { Args.clear(); ArgsTy.clear(); I = dyn_cast<CallInst>(*bit); bit++; // call to the access function F Args.push_back(I->getArgOperand(0)); ArgsTy.push_back(I->getArgOperand(0)->getType()); // call to the execute function cF bI = new BitCastInst(cF, (iTy), "_TPR", I); Args.push_back(bI); ArgsTy.push_back(bI->getType()); unsigned int t; for (t = 1; t < I->getNumArgOperands(); t++) { Args.push_back(I->getArgOperand(t)); ArgsTy.push_back(I->getArgOperand(t)->getType()); } tF = dyn_cast<Function>(I->getCalledFunction()); FTy = FunctionType::get(tF->getReturnType(), ArgsTy, 0); out.str(std::string()); out << "task_DAE_" << I->getNumArgOperands() - 1; nF = (Function *)M->getOrInsertFunction(out.str(), FTy); CallInst *ci = CallInst::Create(nF, Args, I->getName(), I); I->replaceAllUsesWith(ci); I->eraseFromParent(); } } } }
bool NVVMReflect::runOnFunction(Function &F) { if (!NVVMReflectEnabled) return false; if (F.getName() == NVVM_REFLECT_FUNCTION) { assert(F.isDeclaration() && "_reflect function should not have a body"); assert(F.getReturnType()->isIntegerTy() && "_reflect's return type should be integer"); return false; } SmallVector<Instruction *, 4> ToRemove; // Go through the calls in this function. Each call to __nvvm_reflect or // llvm.nvvm.reflect should be a CallInst with a ConstantArray argument. // First validate that. If the c-string corresponding to the ConstantArray can // be found successfully, see if it can be found in VarMap. If so, replace the // uses of CallInst with the value found in VarMap. If not, replace the use // with value 0. // The IR for __nvvm_reflect calls differs between CUDA versions. // // CUDA 6.5 and earlier uses this sequence: // %ptr = tail call i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8 // (i8 addrspace(4)* getelementptr inbounds // ([8 x i8], [8 x i8] addrspace(4)* @str, i32 0, i32 0)) // %reflect = tail call i32 @__nvvm_reflect(i8* %ptr) // // The value returned by Sym->getOperand(0) is a Constant with a // ConstantDataSequential operand which can be converted to string and used // for lookup. // // CUDA 7.0 does it slightly differently: // %reflect = call i32 @__nvvm_reflect(i8* addrspacecast // (i8 addrspace(1)* getelementptr inbounds // ([8 x i8], [8 x i8] addrspace(1)* @str, i32 0, i32 0) to i8*)) // // In this case, we get a Constant with a GlobalVariable operand and we need // to dig deeper to find its initializer with the string we'll use for lookup. for (Instruction &I : instructions(F)) { CallInst *Call = dyn_cast<CallInst>(&I); if (!Call) continue; Function *Callee = Call->getCalledFunction(); if (!Callee || (Callee->getName() != NVVM_REFLECT_FUNCTION && Callee->getIntrinsicID() != Intrinsic::nvvm_reflect)) continue; // FIXME: Improve error handling here and elsewhere in this pass. assert(Call->getNumOperands() == 2 && "Wrong number of operands to __nvvm_reflect function"); // In cuda 6.5 and earlier, we will have an extra constant-to-generic // conversion of the string. const Value *Str = Call->getArgOperand(0); if (const CallInst *ConvCall = dyn_cast<CallInst>(Str)) { // FIXME: Add assertions about ConvCall. Str = ConvCall->getArgOperand(0); } assert(isa<ConstantExpr>(Str) && "Format of __nvvm__reflect function not recognized"); const ConstantExpr *GEP = cast<ConstantExpr>(Str); const Value *Sym = GEP->getOperand(0); assert(isa<Constant>(Sym) && "Format of __nvvm_reflect function not recognized"); const Value *Operand = cast<Constant>(Sym)->getOperand(0); if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) { // For CUDA-7.0 style __nvvm_reflect calls, we need to find the operand's // initializer. assert(GV->hasInitializer() && "Format of _reflect function not recognized"); const Constant *Initializer = GV->getInitializer(); Operand = Initializer; } assert(isa<ConstantDataSequential>(Operand) && "Format of _reflect function not recognized"); assert(cast<ConstantDataSequential>(Operand)->isCString() && "Format of _reflect function not recognized"); StringRef ReflectArg = cast<ConstantDataSequential>(Operand)->getAsString(); ReflectArg = ReflectArg.substr(0, ReflectArg.size() - 1); LLVM_DEBUG(dbgs() << "Arg of _reflect : " << ReflectArg << "\n"); int ReflectVal = 0; // The default value is 0 if (ReflectArg == "__CUDA_FTZ") { // Try to pull __CUDA_FTZ from the nvvm-reflect-ftz module flag. Our // choice here must be kept in sync with AutoUpgrade, which uses the same // technique to detect whether ftz is enabled. if (auto *Flag = mdconst::extract_or_null<ConstantInt>( F.getParent()->getModuleFlag("nvvm-reflect-ftz"))) ReflectVal = Flag->getSExtValue(); } else if (ReflectArg == "__CUDA_ARCH") { ReflectVal = SmVersion * 10; } Call->replaceAllUsesWith(ConstantInt::get(Call->getType(), ReflectVal)); ToRemove.push_back(Call); } for (Instruction *I : ToRemove) I->eraseFromParent(); return ToRemove.size() > 0; }
/// \brief Recursively handle the condition leading to a loop Value *SIAnnotateControlFlow::handleLoopCondition(Value *Cond, PHINode *Broken, llvm::Loop *L) { // Only search through PHI nodes which are inside the loop. If we try this // with PHI nodes that are outside of the loop, we end up inserting new PHI // nodes outside of the loop which depend on values defined inside the loop. // This will break the module with // 'Instruction does not dominate all users!' errors. PHINode *Phi = nullptr; if ((Phi = dyn_cast<PHINode>(Cond)) && L->contains(Phi)) { BasicBlock *Parent = Phi->getParent(); PHINode *NewPhi = PHINode::Create(Int64, 0, "", &Parent->front()); Value *Ret = NewPhi; // Handle all non-constant incoming values first for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { Value *Incoming = Phi->getIncomingValue(i); BasicBlock *From = Phi->getIncomingBlock(i); if (isa<ConstantInt>(Incoming)) { NewPhi->addIncoming(Broken, From); continue; } Phi->setIncomingValue(i, BoolFalse); Value *PhiArg = handleLoopCondition(Incoming, Broken, L); NewPhi->addIncoming(PhiArg, From); } BasicBlock *IDom = DT->getNode(Parent)->getIDom()->getBlock(); for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { Value *Incoming = Phi->getIncomingValue(i); if (Incoming != BoolTrue) continue; BasicBlock *From = Phi->getIncomingBlock(i); if (From == IDom) { CallInst *OldEnd = dyn_cast<CallInst>(Parent->getFirstInsertionPt()); if (OldEnd && OldEnd->getCalledFunction() == EndCf) { Value *Args[] = { OldEnd->getArgOperand(0), NewPhi }; Ret = CallInst::Create(ElseBreak, Args, "", OldEnd); continue; } } TerminatorInst *Insert = From->getTerminator(); Value *PhiArg = CallInst::Create(Break, Broken, "", Insert); NewPhi->setIncomingValue(i, PhiArg); } eraseIfUnused(Phi); return Ret; } else if (Instruction *Inst = dyn_cast<Instruction>(Cond)) { BasicBlock *Parent = Inst->getParent(); Instruction *Insert; if (L->contains(Inst)) { Insert = Parent->getTerminator(); } else { Insert = L->getHeader()->getFirstNonPHIOrDbgOrLifetime(); } Value *Args[] = { Cond, Broken }; return CallInst::Create(IfBreak, Args, "", Insert); } else { llvm_unreachable("Unhandled loop condition!"); } return 0; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. Search for functions which could be called // indirectly and create clones for them which are only called by direct // calls. // // 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 IndClone::runOnModule(Module& M) { // Set of functions to clone std::vector<Function*> toClone; // // Check all of the functions in the module. If the function could be called // by an indirect function call, add it to our worklist of functions to // clone. // for (Module::iterator I = M.begin(); I != M.end(); ++I) { // Flag whether the function should be cloned bool pleaseCloneTheFunction = false; // // Only clone functions which are defined and cannot be replaced by another // function by the linker. // if (!I->isDeclaration() && !I->mayBeOverridden()) { for (Value::use_iterator ui = I->use_begin(), ue = I->use_end(); ui != ue; ++ui) { if (!isa<CallInst>(*ui) && !isa<InvokeInst>(*ui)) { if(!ui->use_empty()) // // If this function is used for anything other than a direct function // call, then we want to clone it. // pleaseCloneTheFunction = true; } else { // // This is a call instruction, but hold up ranger! We need to make // sure that the function isn't passed as an argument to *another* // function. That would make the function usable in an indirect // function call. // for (unsigned index = 1; index < ui->getNumOperands(); ++index) { if (ui->getOperand(index)->stripPointerCasts() == I) { pleaseCloneTheFunction = true; break; } } } // // If we've discovered that the function could be used by an indirect // call site, schedule it for cloning. // if (pleaseCloneTheFunction) { toClone.push_back(I); break; } } } } // // Update the statistics on the number of functions we'll be cloning. // We only update the statistic if we want to clone one or more functions; // due to the magic of how statistics work, avoiding assignment prevents it // from needlessly showing up. // if (toClone.size()) numCloned += toClone.size(); // // Go through the worklist and clone each function. After cloning a // function, change all direct calls to use the clone instead of using the // original function. // for (unsigned index = 0; index < toClone.size(); ++index) { // // Clone the function and give it a name indicating that it is a clone to // be used for direct function calls. // Function * Original = toClone[index]; Function* DirectF = CloneFunction(Original); DirectF->setName(Original->getName() + "_DIRECT"); // // Make the clone internal; external code can use the original function. // DirectF->setLinkage(GlobalValue::InternalLinkage); // // Link the cloned function into the set of functions belonging to the // module. // Original->getParent()->getFunctionList().push_back(DirectF); // // Find all uses of the function that use it as a direct call. Change // them to use the clone. // for (Value::use_iterator ui = Original->use_begin(), ue = Original->use_end(); ui != ue; ) { CallInst *CI = dyn_cast<CallInst>(*ui); ui++; if (CI) { if (CI->getCalledFunction() == Original) { ++numReplaced; CI->setCalledFunction(DirectF); } } } } // // Assume that we've cloned at least one function. // 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; }