bool OptimizeFastMemoryChecks::runOnFunction(Function &F) { ABA = &getAnalysis<ArrayBoundsAnalysis>(); MSCI = &getAnalysis<MSCInfo>(); // Visit all call instructions in the function to find the checks. visit(F); for (size_t i = 0, N = FastCheckCalls.size(); i < N; ++i) { CallInst *CI = FastCheckCalls[i]; CheckInfoType *Info = MSCI->getCheckInfo(CI->getCalledFunction()); assert(Info && Info->isFastMemoryCheck() && "expecting fast memory checks"); Value *AccessPtr = CI->getArgOperand(Info->PtrArgNo); Value *AccessSize = CI->getArgOperand(Info->SizeArgNo); Value *ObjectPtr = CI->getArgOperand(Info->ObjArgNo); Value *ObjectSize = CI->getArgOperand(Info->ObjSizeArgNo); if (ABA->isAlwaysInBounds(AccessPtr, AccessSize, ObjectPtr, ObjectSize)) { CI->eraseFromParent(); ++FastMemoryChecksRemoved; } } bool ChangedAnything = !FastCheckCalls.empty(); FastCheckCalls.clear(); return ChangedAnything; }
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(); const Type *Int32Ty = Type::getInt32Ty(Context); unsigned caseNo = SI->findCaseValue(ExpectedValue); std::vector<Value *> Vec; unsigned n = SI->getNumCases(); Vec.resize(n + 1); // +1 for MDString Vec[0] = MDString::get(Context, "branch_weights"); for (unsigned i = 0; i < n; ++i) { Vec[i + 1] = ConstantInt::get(Int32Ty, i == caseNo ? LikelyBranchWeight : UnlikelyBranchWeight); } MDNode *WeightsNode = llvm::MDNode::get(Context, Vec); SI->setMetadata(LLVMContext::MD_prof, WeightsNode); SI->setCondition(ArgValue); return true; }
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; SwitchInst::CaseIt Case = SI->findCaseValue(ExpectedValue); unsigned n = SI->getNumCases(); // +1 for default case. std::vector<uint32_t> Weights(n + 1); Weights[0] = Case == SI->case_default() ? LikelyBranchWeight : UnlikelyBranchWeight; for (unsigned i = 0; i != n; ++i) Weights[i + 1] = i == Case.getCaseIndex() ? LikelyBranchWeight : UnlikelyBranchWeight; SI->setMetadata(LLVMContext::MD_prof, MDBuilder(CI->getContext()).createBranchWeights(Weights)); SI->setCondition(ArgValue); return true; }
/// \brief Check call has a unary float signature /// It checks following: /// a) call should have a single argument /// b) argument type should be floating point type /// c) call instruction type and argument type should be same /// d) call should only reads memory. /// If all these condition is met then return ValidIntrinsicID /// else return not_intrinsic. Intrinsic::ID llvm::checkUnaryFloatSignature(const CallInst &I, Intrinsic::ID ValidIntrinsicID) { if (I.getNumArgOperands() != 1 || !I.getArgOperand(0)->getType()->isFloatingPointTy() || I.getType() != I.getArgOperand(0)->getType() || !I.onlyReadsMemory()) return Intrinsic::not_intrinsic; return ValidIntrinsicID; }
static bool ExpandOpForIntSize(Module *M, unsigned Bits, bool Mul) { IntegerType *IntTy = IntegerType::get(M->getContext(), Bits); SmallVector<Type *, 1> Types; Types.push_back(IntTy); Intrinsic::ID ID = (Mul ? Intrinsic::umul_with_overflow : Intrinsic::uadd_with_overflow); std::string Name = Intrinsic::getName(ID, Types); Function *Intrinsic = M->getFunction(Name); if (!Intrinsic) return false; for (Value::use_iterator CallIter = Intrinsic->use_begin(), E = Intrinsic->use_end(); CallIter != E; ) { CallInst *Call = dyn_cast<CallInst>(*CallIter++); if (!Call) { report_fatal_error("ExpandArithWithOverflow: Taking the address of a " "*.with.overflow intrinsic is not allowed"); } Value *VariableArg; ConstantInt *ConstantArg; if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(0))) { VariableArg = Call->getArgOperand(1); ConstantArg = C; } else if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(1))) { VariableArg = Call->getArgOperand(0); ConstantArg = C; } else { errs() << "Use: " << *Call << "\n"; report_fatal_error("ExpandArithWithOverflow: At least one argument of " "*.with.overflow must be a constant"); } Value *ArithResult = BinaryOperator::Create( (Mul ? Instruction::Mul : Instruction::Add), VariableArg, ConstantArg, Call->getName() + ".arith", Call); uint64_t ArgMax; if (Mul) { ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue(); } else { ArgMax = UintTypeMax(Bits) - ConstantArg->getZExtValue(); } Value *OverflowResult = new ICmpInst( Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax), Call->getName() + ".overflow"); // Construct the struct result. Value *NewStruct = UndefValue::get(Call->getType()); NewStruct = CreateInsertValue(NewStruct, 0, ArithResult, Call); NewStruct = CreateInsertValue(NewStruct, 1, OverflowResult, Call); Call->replaceAllUsesWith(NewStruct); Call->eraseFromParent(); } Intrinsic->eraseFromParent(); return true; }
bool LowerExpectIntrinsic::HandleIfExpect(BranchInst *BI) { if (BI->isUnconditional()) return false; // Handle non-optimized IR code like: // %expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1) // %tobool = icmp ne i64 %expval, 0 // br i1 %tobool, label %if.then, label %if.end // // Or the following simpler case: // %expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1) // br i1 %expval, label %if.then, label %if.end CallInst *CI; ICmpInst *CmpI = dyn_cast<ICmpInst>(BI->getCondition()); if (!CmpI) { CI = dyn_cast<CallInst>(BI->getCondition()); } else { if (CmpI->getPredicate() != CmpInst::ICMP_NE) return false; CI = dyn_cast<CallInst>(CmpI->getOperand(0)); } 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; MDBuilder MDB(CI->getContext()); MDNode *Node; // If expect value is equal to 1 it means that we are more likely to take // branch 0, in other case more likely is branch 1. if (ExpectedValue->isOne()) Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight); else Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight); BI->setMetadata(LLVMContext::MD_prof, Node); if (CmpI) CmpI->setOperand(0, ArgValue); else BI->setCondition(ArgValue); return true; }
// llvm.ptx.memcpy.const and llvm.ptx.memmove.const need to be modeled as // TgtMemIntrinsic // because we need the information that is only available in the "Value" type // of destination // pointer. In particular, the address space information. bool NVPTXTargetLowering::getTgtMemIntrinsic(IntrinsicInfo& Info, const CallInst &I, unsigned Intrinsic) const { switch (Intrinsic) { default: return false; case Intrinsic::nvvm_atomic_load_add_f32: Info.opc = ISD::INTRINSIC_W_CHAIN; Info.memVT = MVT::f32; Info.ptrVal = I.getArgOperand(0); Info.offset = 0; Info.vol = 0; Info.readMem = true; Info.writeMem = true; Info.align = 0; return true; case Intrinsic::nvvm_atomic_load_inc_32: case Intrinsic::nvvm_atomic_load_dec_32: Info.opc = ISD::INTRINSIC_W_CHAIN; Info.memVT = MVT::i32; Info.ptrVal = I.getArgOperand(0); Info.offset = 0; Info.vol = 0; Info.readMem = true; Info.writeMem = true; Info.align = 0; return true; case Intrinsic::nvvm_ldu_global_i: case Intrinsic::nvvm_ldu_global_f: case Intrinsic::nvvm_ldu_global_p: Info.opc = ISD::INTRINSIC_W_CHAIN; if (Intrinsic == Intrinsic::nvvm_ldu_global_i) Info.memVT = MVT::i32; else if (Intrinsic == Intrinsic::nvvm_ldu_global_p) Info.memVT = getPointerTy(); else Info.memVT = MVT::f32; Info.ptrVal = I.getArgOperand(0); Info.offset = 0; Info.vol = 0; Info.readMem = true; Info.writeMem = false; Info.align = 0; return true; } return false; }
/// AddCatchInfo - Extract the personality and type infos from an eh.selector /// call, and add them to the specified machine basic block. void llvm::AddCatchInfo(const CallInst &I, MachineModuleInfo *MMI, MachineBasicBlock *MBB) { // Inform the MachineModuleInfo of the personality for this landing pad. const ConstantExpr *CE = cast<ConstantExpr>(I.getArgOperand(1)); assert(CE->getOpcode() == Instruction::BitCast && isa<Function>(CE->getOperand(0)) && "Personality should be a function"); MMI->addPersonality(MBB, cast<Function>(CE->getOperand(0))); // Gather all the type infos for this landing pad and pass them along to // MachineModuleInfo. std::vector<const GlobalVariable *> TyInfo; unsigned N = I.getNumArgOperands(); for (unsigned i = N - 1; i > 1; --i) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getArgOperand(i))) { unsigned FilterLength = CI->getZExtValue(); unsigned FirstCatch = i + FilterLength + !FilterLength; assert(FirstCatch <= N && "Invalid filter length"); if (FirstCatch < N) { TyInfo.reserve(N - FirstCatch); for (unsigned j = FirstCatch; j < N; ++j) TyInfo.push_back(ExtractTypeInfo(I.getArgOperand(j))); MMI->addCatchTypeInfo(MBB, TyInfo); TyInfo.clear(); } if (!FilterLength) { // Cleanup. MMI->addCleanup(MBB); } else { // Filter. TyInfo.reserve(FilterLength - 1); for (unsigned j = i + 1; j < FirstCatch; ++j) TyInfo.push_back(ExtractTypeInfo(I.getArgOperand(j))); MMI->addFilterTypeInfo(MBB, TyInfo); TyInfo.clear(); } N = i; } } if (N > 2) { TyInfo.reserve(N - 2); for (unsigned j = 2; j < N; ++j) TyInfo.push_back(ExtractTypeInfo(I.getArgOperand(j))); MMI->addCatchTypeInfo(MBB, TyInfo); } }
static bool expandIntrinsic(Module *M, Intrinsic::ID ID) { SmallVector<Type *, 3> Types; Types.push_back(Type::getInt8PtrTy(M->getContext())); if (ID != Intrinsic::memset) Types.push_back(Type::getInt8PtrTy(M->getContext())); unsigned LengthTypePos = Types.size(); Types.push_back(Type::getInt64Ty(M->getContext())); std::string OldName = Intrinsic::getName(ID, Types); Function *OldIntrinsic = M->getFunction(OldName); if (!OldIntrinsic) return false; Types[LengthTypePos] = Type::getInt32Ty(M->getContext()); Function *NewIntrinsic = Intrinsic::getDeclaration(M, ID, Types); for (Value::use_iterator CallIter = OldIntrinsic->use_begin(), E = OldIntrinsic->use_end(); CallIter != E; ) { CallInst *Call = dyn_cast<CallInst>(*CallIter++); if (!Call) { report_fatal_error("CanonicalizeMemIntrinsics: Taking the address of an " "intrinsic is not allowed: " + OldName); } // This temporarily leaves Call non-well-typed. Call->setCalledFunction(NewIntrinsic); // Truncate the "len" argument. No overflow check. IRBuilder<> Builder(Call); Value *Length = Builder.CreateTrunc(Call->getArgOperand(2), Type::getInt32Ty(M->getContext()), "mem_len_truncate"); Call->setArgOperand(2, Length); } OldIntrinsic->eraseFromParent(); return true; }
virtual bool runOnFunction(Function& F) { int num_changed = 0; StatCounter sc_num_unnescessary_boxes("opt_unnescessary_boxes"); std::unordered_map<CallInst*, CallInst*> dead_boxing_call; for (inst_iterator inst_it = inst_begin(F), _inst_end = inst_end(F); inst_it != _inst_end; ++inst_it) { CallInst* CI = dyn_cast<CallInst>(&*inst_it); if (!CI) continue; // We are only interested in boxInt, boxFloat and boxBool calls void* func = getCalledFuncAddr(CI); if (func != boxInt && func != boxFloat && func != boxBool) continue; CallInst* CI2 = dyn_cast<CallInst>(CI->getArgOperand(0)); if (!CI2) continue; // Check if the value passed as argument to the boxing call is coming from the corresponding unbox call void* func2 = getCalledFuncAddr(CI2); if ((func == boxInt && func2 == unboxInt) || (func == boxFloat && func2 == unboxFloat) || (func == boxBool && func2 == unboxBool)) dead_boxing_call[CI] = CI2; } for (auto&& I : dead_boxing_call) { I.first->replaceAllUsesWith(new BitCastInst(I.second->getArgOperand(0), I.first->getType(), "", I.first)); I.first->eraseFromParent(); ++num_changed; sc_num_unnescessary_boxes.log(); } return num_changed > 0; }
bool LowerExpectIntrinsic::runOnFunction(Function &F) { for (Function::iterator I = F.begin(), E = F.end(); I != E;) { BasicBlock *BB = I++; // Create "block_weights" metadata. if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) { if (HandleIfExpect(BI)) IfHandled++; } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) { if (HandleSwitchExpect(SI)) IfHandled++; } // remove llvm.expect intrinsics. for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ) { CallInst *CI = dyn_cast<CallInst>(BI++); if (!CI) continue; Function *Fn = CI->getCalledFunction(); if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) { Value *Exp = CI->getArgOperand(0); CI->replaceAllUsesWith(Exp); CI->eraseFromParent(); } } } return false; }
void Executor::executeAtomicDec(ExecutionState &state, KInstruction *target, std::vector< ref<Expr> > &arguments, unsigned seqNum) { // Load the value from addr ref<Expr> base = arguments[0]; CallInst *ci = static_cast<CallInst*>(target->inst); updateCType(state, ci->getArgOperand(0), base, state.tinfo.is_GPU_mode); executeMemoryOperation(state, false, base, 0, target, seqNum, true); // (old == 0) | (old > val) ref<Expr> zeroExpr = klee::ConstantExpr::create(0, arguments[1]->getWidth()); ref<Expr> oneExpr = klee::ConstantExpr::create(1, arguments[1]->getWidth()); ref<Expr> compCond = OrExpr::create(EqExpr::create(atomicRes, zeroExpr), UgtExpr::create(atomicRes, arguments[1])); Executor::StatePair branches = fork(state, compCond, true); if (branches.first) { executeMemoryOperation(*branches.first, true, base, arguments[1], target, seqNum, true); bindLocal(target, *branches.first, atomicRes); } if (branches.second) { executeMemoryOperation(*branches.second, true, base, SubExpr::create(atomicRes, oneExpr), target, seqNum, true); bindLocal(target, *branches.second, atomicRes); } }
void Executor::executeAtomicCAS(ExecutionState &state, KInstruction *target, std::vector< ref<Expr> > &arguments, unsigned seqNum) { // Load the value from addr ref<Expr> base = arguments[0]; CallInst *ci = static_cast<CallInst*>(target->inst); updateCType(state, ci->getArgOperand(0), base, state.tinfo.is_GPU_mode); executeMemoryOperation(state, false, base, 0, target, seqNum, true); // old == compare ref<Expr> compCond = EqExpr::create(atomicRes, arguments[1]); state.tinfo.is_Atomic_op = 1; Executor::StatePair branches = fork(state, compCond, true); if (branches.first) { executeMemoryOperation(*branches.first, true, base, arguments[2], target, seqNum, true); bindLocal(target, *branches.first, atomicRes); } if (branches.second) { //executeMemoryOperation(*branches.second, true, base, atomicRes, // target, seqNum, true, true); bindLocal(target, *branches.second, atomicRes); } state.tinfo.is_Atomic_op = 0; }
void Aa::LowerConstantExpr::process(Instruction *inst) { if(isa<llvm::CallInst>(inst)) { CallInst* ci = dyn_cast<CallInst>(inst); for(int idx = 0; idx < ci->getNumArgOperands(); idx++) { llvm::Value *opnd = ci->getArgOperand(idx); if (ConstantExpr *ce = dyn_cast<ConstantExpr>(opnd)) { lower(ce, inst); } } } else { for (unsigned oi = 0, oe = inst->getNumOperands(); oi != oe; oi++) { llvm::Value *opnd = inst->getOperand(oi); if (ConstantExpr *ce = dyn_cast<ConstantExpr>(opnd)) { lower(ce, inst); } } } }
static unsigned get_datatype_index(StringRef Name, const CallInst& I) { GlobalVariable* datatype; unsigned C = lle::get_mpi_count_idx(&I); if(C==0){ errs()<<"WARNNING: doesn't consider "<<Name<<" mpi call\n"; return 0; } datatype = dyn_cast<GlobalVariable>(I.getArgOperand(C+1)); // this is p2p communication auto CI = dyn_cast<ConstantInt>(datatype->getInitializer()); if(CI == NULL){ errs()<<"WARNNING: not a constant number "<<*I.getArgOperand(C+1)<<"\n"; return 0; } return CI->getZExtValue(); // datatype -> sizeof }
void SelectionDAGBuilder::visitGCResult(const CallInst &CI) { // The result value of the gc_result is simply the result of the actual // call. We've already emitted this, so just grab the value. Instruction *I = cast<Instruction>(CI.getArgOperand(0)); assert(isStatepoint(I) && "first argument must be a statepoint token"); if (I->getParent() != CI.getParent()) { // Statepoint is in different basic block so we should have stored call // result in a virtual register. // We can not use default getValue() functionality to copy value from this // register because statepoint and actuall call return types can be // different, and getValue() will use CopyFromReg of the wrong type, // which is always i32 in our case. PointerType *CalleeType = cast<PointerType>( ImmutableStatepoint(I).getCalledValue()->getType()); Type *RetTy = cast<FunctionType>(CalleeType->getElementType())->getReturnType(); SDValue CopyFromReg = getCopyFromRegs(I, RetTy); assert(CopyFromReg.getNode()); setValue(&CI, CopyFromReg); } else { setValue(&CI, getValue(I)); } }
void RuntimeHelperFixupPass::FixArrayInit(Function *F) { Module *M = F->getParent(); LLVMContext &ctx = F->getContext(); for (auto it = F->use_begin(), end = F->use_end(); it != end; ++it) { CallInst *CI = dyn_cast<CallInst>(*it); assert (CI && "Unknown usage for array init helper"); Instruction *field_runtime_handle = dyn_cast<Instruction>(CI->getArgOperand(1)); assert (field_runtime_handle); MDNode *md = field_runtime_handle->getMetadata("silk_runtime_field_handle"); assert (md); ConstantInt *handle = dyn_cast<ConstantInt>(md->getOperand(0)); assert(handle); auto vm_field = reinterpret_cast<VMField*>(handle->getValue().getLimitedValue()); auto field_map = vm_field->field_mapping(); auto vm_named_class = dynamic_cast<VMNamedClass*>(vm_field->type()); auto size = vm_named_class->type_def()->class_size(); raw_istream is(field_map.start(), size); std::vector<uint8_t> buf; buf.resize(size); is.read((char*)buf.data(), size); Constant *predefined_value = ConstantDataArray::get(ctx, buf); auto GV = new GlobalVariable(*M, predefined_value->getType(), true, GlobalValue::InternalLinkage, predefined_value, ".initdata"); Value *array_ptr = CI->getArgOperand(0); IRBuilder<> builder(CI); auto intrinsic_array_base = intrinsic_->array_base_pointer(); auto array_ptr_casted = builder.CreateBitCast(array_ptr, builder.getInt8PtrTy()); auto array_base_ptr = builder.CreateCall(intrinsic_array_base, array_ptr_casted); builder.CreateMemCpy(array_base_ptr, GV, ConstantInt::get(Type::getInt64Ty(ctx), size), 0); CI->eraseFromParent(); } }
bool LowerExpectIntrinsic::HandleIfExpect(BranchInst *BI) { if (BI->isUnconditional()) return false; // Handle non-optimized IR code like: // %expval = call i64 @llvm.expect.i64.i64(i64 %conv1, i64 1) // %tobool = icmp ne i64 %expval, 0 // br i1 %tobool, label %if.then, label %if.end ICmpInst *CmpI = dyn_cast<ICmpInst>(BI->getCondition()); if (!CmpI || CmpI->getPredicate() != CmpInst::ICMP_NE) return false; CallInst *CI = dyn_cast<CallInst>(CmpI->getOperand(0)); 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(); const Type *Int32Ty = Type::getInt32Ty(Context); bool Likely = ExpectedValue->isOne(); // If expect value is equal to 1 it means that we are more likely to take // branch 0, in other case more likely is branch 1. Value *Ops[] = { MDString::get(Context, "branch_weights"), ConstantInt::get(Int32Ty, Likely ? LikelyBranchWeight : UnlikelyBranchWeight), ConstantInt::get(Int32Ty, Likely ? UnlikelyBranchWeight : LikelyBranchWeight) }; MDNode *WeightsNode = MDNode::get(Context, Ops); BI->setMetadata(LLVMContext::MD_prof, WeightsNode); CmpI->setOperand(0, ArgValue); return true; }
/// \brief Recursively handle the condition leading to a loop Value *SIAnnotateControlFlow::handleLoopCondition(Value *Cond, PHINode *Broken) { if (PHINode *Phi = dyn_cast<PHINode>(Cond)) { 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); 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(); TerminatorInst *Insert = Parent->getTerminator(); Value *Args[] = { Cond, Broken }; return CallInst::Create(IfBreak, Args, "", Insert); } else { llvm_unreachable("Unhandled loop condition!"); } return 0; }
bool IRTranslator::translateMemcpy(const CallInst &CI) { LLT SizeTy{*CI.getArgOperand(2)->getType(), *DL}; if (cast<PointerType>(CI.getArgOperand(0)->getType())->getAddressSpace() != 0 || cast<PointerType>(CI.getArgOperand(1)->getType())->getAddressSpace() != 0 || SizeTy.getSizeInBits() != DL->getPointerSizeInBits(0)) return false; SmallVector<CallLowering::ArgInfo, 8> Args; for (int i = 0; i < 3; ++i) { const auto &Arg = CI.getArgOperand(i); Args.emplace_back(getOrCreateVReg(*Arg), Arg->getType()); } MachineOperand Callee = MachineOperand::CreateES("memcpy"); return CLI->lowerCall(MIRBuilder, Callee, CallLowering::ArgInfo(0, CI.getType()), Args); }
/// \brief Recursively handle the condition leading to a loop void SIAnnotateControlFlow::handleLoopCondition(Value *Cond) { if (PHINode *Phi = dyn_cast<PHINode>(Cond)) { // Handle all non-constant incoming values first for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) { Value *Incoming = Phi->getIncomingValue(i); if (isa<ConstantInt>(Incoming)) continue; Phi->setIncomingValue(i, BoolFalse); handleLoopCondition(Incoming); } BasicBlock *Parent = Phi->getParent(); 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), PhiInserter.GetValueAtEndOfBlock(Parent) }; Value *Ret = CallInst::Create(ElseBreak, Args, "", OldEnd); PhiInserter.AddAvailableValue(Parent, Ret); continue; } } TerminatorInst *Insert = From->getTerminator(); Value *Arg = PhiInserter.GetValueAtEndOfBlock(From); Value *Ret = CallInst::Create(Break, Arg, "", Insert); PhiInserter.AddAvailableValue(From, Ret); } eraseIfUnused(Phi); } else if (Instruction *Inst = dyn_cast<Instruction>(Cond)) { BasicBlock *Parent = Inst->getParent(); TerminatorInst *Insert = Parent->getTerminator(); Value *Args[] = { Cond, PhiInserter.GetValueAtEndOfBlock(Parent) }; Value *Ret = CallInst::Create(IfBreak, Args, "", Insert); PhiInserter.AddAvailableValue(Parent, Ret); } else { llvm_unreachable("Unhandled loop condition!"); } }
void OptimizeGEPChecks::visitCallInst(CallInst &CI) { CheckInfoType *Info = MSCI->getCheckInfo(CI.getCalledFunction()); if (!Info || !Info->isGEPCheck()) return; // Check whether it is a GEP instruction just in case it has been converted // to a constant already. Value *GEPArg = CI.getArgOperand(Info->DestPtrArgNo); if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(GEPArg)) { if (ABC->isGEPSafe(GEP)) ToRemove.push_back(&CI); } }
void ExtractContracts::visitCallInst(CallInst &I) { if (auto F = I.getCalledFunction()) { auto name = F->getName(); if (name == Naming::CONTRACT_REQUIRES || name == Naming::CONTRACT_ENSURES || name == Naming::CONTRACT_INVARIANT) { validateAnnotation(I); if (auto J = dyn_cast<CallInst>(I.getArgOperand(0))) if (auto G = J->getCalledFunction()) if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos) return; Function* EF; std::vector<Value*> Args; tie(EF, Args) = extractExpression(I.getArgOperand(0), I.getParent()); I.setArgOperand(0, CallInst::Create(EF, Args, "", &I)); modified = true; // TODO can we somehow force LLVM to consider calls to the obsoleted // forall, exists, etc., to be dead code? } else if (name == Naming::CONTRACT_FORALL || name == Naming::CONTRACT_EXISTS) { if (auto J = dyn_cast<CallInst>(I.getArgOperand(1))) if (auto G = J->getCalledFunction()) if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos) return; Function* EF; std::vector<Value*> Args; tie(EF, Args) = extractExpression(I.getArgOperand(1), I.getParent()); I.setArgOperand(1, CallInst::Create(EF, Args, "", &I)); modified = true; } } }
void Executor::executeAtomicMax(ExecutionState &state, KInstruction *target, std::string fName, std::vector< ref<Expr> > &arguments, unsigned seqNum) { // Load the value from addr ref<Expr> base = arguments[0]; CallInst *ci = static_cast<CallInst*>(target->inst); updateCType(state, ci->getArgOperand(0), base, state.tinfo.is_GPU_mode); executeMemoryOperation(state, false, base, 0, target, seqNum, true); // compare and store the value compareValue(state, target, fName, arguments, seqNum, base, false); }
void RuntimeHelperFixupPass::FixStringConstructor(Function *old_construct, Function *new_construct) { for (auto it = old_construct->use_begin(), end = old_construct->use_end(); it != end; ++it) { CallInst *CI = dyn_cast<CallInst>(*it); assert (CI); auto num_ops = CI->getNumArgOperands(); SmallVector<Value*, 4> ops; for (size_t i = 1; i < num_ops; ++i) ops.push_back(CI->getArgOperand(i)); IRBuilder<> builder(CI); auto new_call = builder.CreateCall(new_construct, ops); BitCastInst *this_ptr = cast<BitCastInst>(CI->getArgOperand(0)); auto alloc = cast<Instruction>(this_ptr->llvm::User::getOperand(0)); this_ptr->replaceAllUsesWith(new_call); CI->eraseFromParent(); this_ptr->eraseFromParent(); alloc->eraseFromParent(); } }
void llvm::computeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo &MMI) { FunctionType *FT = cast<FunctionType>(I.getCalledValue()->getType()->getContainedType(0)); if (FT->isVarArg() && !MMI.usesVAFloatArgument()) { for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { Type *T = I.getArgOperand(i)->getType(); for (auto i : post_order(T)) { if (i->isFloatingPointTy()) { MMI.setUsesVAFloatArgument(true); return; } } } } }
void LLSTDebuggingPass::insertSelfInSendMessageCheck(Function& F) { Value* BrokenSelfMessage = m_builder->CreateGlobalStringPtr("\nself is broken\n"); InstructionVector Calls; for (Function::iterator BB = F.begin(); BB != F.end(); ++BB) { for(BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) { if (CallInst* Call = dyn_cast<CallInst>(II)) { if (Call->getCalledFunction()->getName() == "sendMessage") Calls.push_back(Call); } } } for(std::size_t i = 0; i < Calls.size(); i++) { CallInst* Call = dyn_cast<CallInst>(Calls[i]); BasicBlock* PointerIsOkBB = Call->getParent()->splitBasicBlock( static_cast<BasicBlock::iterator>(Call) ); BasicBlock* PointerIsBrokenBB = BasicBlock::Create(m_module->getContext(), "", &F, PointerIsOkBB); BasicBlock* PointerIsNotSmallIntBB = BasicBlock::Create(m_module->getContext(), "", &F, PointerIsBrokenBB); Instruction* branchToPointerIsOkBB = & PointerIsOkBB->getSinglePredecessor()->back(); m_builder->SetInsertPoint(branchToPointerIsOkBB); Value* argsPtr = m_builder->CreateBitCast( Call->getArgOperand(2), m_baseTypes.object->getPointerTo()); Value* self = m_builder->CreateCall2(getObjectField, argsPtr, m_builder->getInt32(0)); Value* isSmallInt = m_builder->CreateCall(isSmallInteger, self); m_builder->CreateCondBr(isSmallInt, PointerIsOkBB, PointerIsNotSmallIntBB); m_builder->SetInsertPoint(PointerIsNotSmallIntBB); Value* klassPtr = m_builder->CreateCall(getObjectClass, self); Value* pointerIsNull = m_builder->CreateICmpEQ(klassPtr, ConstantPointerNull::get(m_baseTypes.klass->getPointerTo()) ); m_builder->CreateCondBr(pointerIsNull, PointerIsBrokenBB, PointerIsOkBB); branchToPointerIsOkBB->eraseFromParent(); m_builder->SetInsertPoint(PointerIsBrokenBB); m_builder->CreateCall(_printf, BrokenSelfMessage); m_builder->CreateBr(PointerIsOkBB); } }
void Executor::executeAtomicExch(ExecutionState &state, KInstruction *target, std::vector< ref<Expr> > &arguments, unsigned seqNum) { // Load the value from addr ref<Expr> base = arguments[0]; CallInst *ci = static_cast<CallInst*>(target->inst); updateCType(state, ci->getArgOperand(0), base, state.tinfo.is_GPU_mode); executeMemoryOperation(state, false, base, 0, target, seqNum, true); // Store back to original place executeMemoryOperation(state, true, base, arguments[1], target, seqNum, true); bindLocal(target, state, atomicRes); return; }
/// ComputeUsesVAFloatArgument - Determine if any floating-point values are /// being passed to this variadic function, and set the MachineModuleInfo's /// usesVAFloatArgument flag if so. This flag is used to emit an undefined /// reference to _fltused on Windows, which will link in MSVCRT's /// floating-point support. void llvm::ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI) { FunctionType *FT = cast<FunctionType>( I.getCalledValue()->getType()->getContainedType(0)); if (FT->isVarArg() && !MMI->usesVAFloatArgument()) { for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { Type* T = I.getArgOperand(i)->getType(); for (po_iterator<Type*> i = po_begin(T), e = po_end(T); i != e; ++i) { if (i->isFloatingPointTy()) { MMI->setUsesVAFloatArgument(true); return; } } } } }
bool OptimizeGEPChecks::runOnFunction(Function &F) { ABC = &getAnalysis<ArrayBoundsCheckLocal>(); MSCI = &getAnalysis<MSCInfo>(); // Visit all call instructions in the function. visit(F); for (size_t i = 0, N = ToRemove.size(); i < N; ++i) { CallInst *CI = ToRemove[i]; CheckInfoType *Info = MSCI->getCheckInfo(CI->getCalledFunction()); CI->replaceAllUsesWith(CI->getArgOperand(Info->DestPtrArgNo)); CI->eraseFromParent(); ++SafeGEPs; } bool ChangedAnything = !ToRemove.empty(); ToRemove.clear(); return ChangedAnything; }