void WorklessInstrument::CreateIfElseBlock(Loop * pLoop, vector<BasicBlock *> & vecAdded) { BasicBlock * pPreHeader = pLoop->getLoopPreheader(); BasicBlock * pHeader = pLoop->getHeader(); Function * pInnerFunction = pPreHeader->getParent(); Module * pModule = pPreHeader->getParent()->getParent(); BasicBlock * pElseBody = NULL; TerminatorInst * pTerminator = NULL; BranchInst * pBranch = NULL; LoadInst * pLoad1 = NULL; LoadInst * pLoad2 = NULL; LoadInst * pLoadnumGlobalCounter = NULL; BinaryOperator * pAddOne = NULL; StoreInst * pStoreNew = NULL; CmpInst * pCmp = NULL; CallInst * pCall = NULL; StoreInst * pStore = NULL; AttributeSet emptySet; pTerminator = pPreHeader->getTerminator(); pLoadnumGlobalCounter = new LoadInst(this->numGlobalCounter, "", false, pTerminator); pLoadnumGlobalCounter->setAlignment(8); pAddOne = BinaryOperator::Create(Instruction::Add, pLoadnumGlobalCounter, this->ConstantLong1, "add", pTerminator); pStoreNew = new StoreInst(pAddOne, this->numGlobalCounter, false, pTerminator); pStoreNew->setAlignment(8); pElseBody = BasicBlock::Create(pModule->getContext(), ".else.body.CPI", pInnerFunction, 0); pLoad2 = new LoadInst(this->CURRENT_SAMPLE, "", false, pTerminator); pLoad2->setAlignment(8); pCmp = new ICmpInst(pTerminator, ICmpInst::ICMP_SLT, pAddOne, pLoad2, ""); pBranch = BranchInst::Create(pHeader, pElseBody, pCmp ); ReplaceInstWithInst(pTerminator, pBranch); pLoad1 = new LoadInst(this->SAMPLE_RATE, "", false, pElseBody); pCall = CallInst::Create(this->geo, pLoad1, "", pElseBody); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); CastInst * pCast = CastInst::CreateIntegerCast(pCall, this->LongType, true, "", pElseBody); //pBinary = BinaryOperator::Create(Instruction::Add, pLoad2, pCast, "add", pIfBody); pStore = new StoreInst(pCast, this->CURRENT_SAMPLE, false, pElseBody); pStore->setAlignment(8); pStore = new StoreInst(this->ConstantLong0, this->numGlobalCounter, false, pElseBody); pStore->setAlignment(8); pLoad1 = new LoadInst(this->numInstances, "", false, pElseBody); pLoad1->setAlignment(8); pAddOne = BinaryOperator::Create(Instruction::Add, pLoad1, this->ConstantLong1, "add", pElseBody); pStore = new StoreInst(pAddOne, this->numInstances, false, pElseBody); pStore->setAlignment(8); vecAdded.push_back(pPreHeader); vecAdded.push_back(pElseBody); }
void VectorBlockGenerator::copyStore(ScopStmt &Stmt, const StoreInst *Store, ValueMapT &VectorMap, VectorValueMapT &ScalarMaps) { const MemoryAccess &Access = Stmt.getAccessFor(Store); const Value *Pointer = Store->getPointerOperand(); Value *Vector = getVectorValue(Stmt, Store->getValueOperand(), VectorMap, ScalarMaps, getLoopForInst(Store)); // Make sure we have scalar values available to access the pointer to // the data location. extractScalarValues(Store, VectorMap, ScalarMaps); if (Access.isStrideOne(isl_map_copy(Schedule))) { Type *VectorPtrType = getVectorPtrTy(Pointer, getVectorWidth()); Value *NewPointer = generateLocationAccessed( Stmt, Store, Pointer, ScalarMaps[0], GlobalMaps[0], VLTS[0]); Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); StoreInst *Store = Builder.CreateStore(Vector, VectorPtr); if (!Aligned) Store->setAlignment(8); } else { for (unsigned i = 0; i < ScalarMaps.size(); i++) { Value *Scalar = Builder.CreateExtractElement(Vector, Builder.getInt32(i)); Value *NewPointer = generateLocationAccessed( Stmt, Store, Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]); Builder.CreateStore(Scalar, NewPointer); } } }
extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef val, LLVMValueRef target, AtomicOrdering order, unsigned alignment) { StoreInst* si = new StoreInst(unwrap(val),unwrap(target)); si->setAtomic(order); si->setAlignment(alignment); return wrap(unwrap(B)->Insert(si)); }
extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef V, LLVMValueRef Target, LLVMAtomicOrdering Order, unsigned Alignment) { StoreInst *SI = new StoreInst(unwrap(V), unwrap(Target)); SI->setAtomic(fromRust(Order)); SI->setAlignment(Alignment); return wrap(unwrap(B)->Insert(SI)); }
extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef val, LLVMValueRef target, AtomicOrdering order) { StoreInst* si = new StoreInst(unwrap(val),unwrap(target)); si->setVolatile(true); si->setAtomic(order); si->setAlignment(sizeof(intptr_t)); return wrap(unwrap(B)->Insert(si)); }
LLVMValueRef mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal, gboolean is_volatile, int alignment) { StoreInst *ins; ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile); ins->setAlignment (alignment); return wrap (ins); }
/// Convert an atomic store of a non-integral type to an integer store of the /// equivelent bitwidth. We used to not support floating point or vector /// atomics in the IR at all. The backends learned to deal with the bitcast /// idiom because that was the only way of expressing the notion of a atomic /// float or vector store. The long term plan is to teach each backend to /// instruction select from the original atomic store, but as a migration /// mechanism, we convert back to the old format which the backends understand. /// Each backend will need individual work to recognize the new format. StoreInst *AtomicExpand::convertAtomicStoreToIntegerType(StoreInst *SI) { IRBuilder<> Builder(SI); auto *M = SI->getModule(); Type *NewTy = getCorrespondingIntegerType(SI->getValueOperand()->getType(), M->getDataLayout()); Value *NewVal = Builder.CreateBitCast(SI->getValueOperand(), NewTy); Value *Addr = SI->getPointerOperand(); Type *PT = PointerType::get(NewTy, Addr->getType()->getPointerAddressSpace()); Value *NewAddr = Builder.CreateBitCast(Addr, PT); StoreInst *NewSI = Builder.CreateStore(NewVal, NewAddr); NewSI->setAlignment(SI->getAlignment()); NewSI->setVolatile(SI->isVolatile()); NewSI->setAtomic(SI->getOrdering(), SI->getSynchScope()); DEBUG(dbgs() << "Replaced " << *SI << " with " << *NewSI << "\n"); SI->eraseFromParent(); return NewSI; }
/// tryAggregating - When scanning forward over instructions, we look for /// other loads or stores that could be aggregated with this one. /// Returns the last instruction added (if one was added) since we might have /// removed some loads or stores and that might invalidate an iterator. Instruction *AggregateGlobalOpsOpt::tryAggregating(Instruction *StartInst, Value *StartPtr, bool DebugThis) { if (TD == 0) return 0; Module* M = StartInst->getParent()->getParent()->getParent(); LLVMContext& Context = StartInst->getContext(); Type* int8Ty = Type::getInt8Ty(Context); Type* sizeTy = Type::getInt64Ty(Context); Type* globalInt8PtrTy = int8Ty->getPointerTo(globalSpace); bool isLoad = isa<LoadInst>(StartInst); bool isStore = isa<StoreInst>(StartInst); Instruction *lastAddedInsn = NULL; Instruction *LastLoadOrStore = NULL; SmallVector<Instruction*, 8> toRemove; // Okay, so we now have a single global load/store. Scan to find // all subsequent stores of the same value to offset from the same pointer. // Join these together into ranges, so we can decide whether contiguous blocks // are stored. MemOpRanges Ranges(*TD); // Put the first store in since we want to preserve the order. Ranges.addInst(0, StartInst); BasicBlock::iterator BI = StartInst; for (++BI; !isa<TerminatorInst>(BI); ++BI) { if( isGlobalLoadOrStore(BI, globalSpace, isLoad, isStore) ) { // OK! } else { // If the instruction is readnone, ignore it, otherwise bail out. We // don't even allow readonly here because we don't want something like: // A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A). if (BI->mayWriteToMemory()) break; if (isStore && BI->mayReadFromMemory()) break; continue; } if ( isStore && isa<StoreInst>(BI) ) { StoreInst *NextStore = cast<StoreInst>(BI); // If this is a store, see if we can merge it in. if (!NextStore->isSimple()) break; // Check to see if this store is to a constant offset from the start ptr. int64_t Offset; if (!IsPointerOffset(StartPtr, NextStore->getPointerOperand(), Offset, *TD)) break; Ranges.addStore(Offset, NextStore); LastLoadOrStore = NextStore; } else { LoadInst *NextLoad = cast<LoadInst>(BI); if (!NextLoad->isSimple()) break; // Check to see if this load is to a constant offset from the start ptr. int64_t Offset; if (!IsPointerOffset(StartPtr, NextLoad->getPointerOperand(), Offset, *TD)) break; Ranges.addLoad(Offset, NextLoad); LastLoadOrStore = NextLoad; } } // If we have no ranges, then we just had a single store with nothing that // could be merged in. This is a very common case of course. if (!Ranges.moreThanOneOp()) return 0; // Divide the instructions between StartInst and LastLoadOrStore into // addressing, memops, and uses of memops (uses of loads) reorderAddressingMemopsUses(StartInst, LastLoadOrStore, DebugThis); Instruction* insertBefore = StartInst; IRBuilder<> builder(insertBefore); // Now that we have full information about ranges, loop over the ranges and // emit memcpy's for anything big enough to be worthwhile. for (MemOpRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { const MemOpRange &Range = *I; Value* oldBaseI = NULL; Value* newBaseI = NULL; if (Range.TheStores.size() == 1) continue; // Don't bother if there's only one thing... builder.SetInsertPoint(insertBefore); // Otherwise, we do want to transform this! Create a new memcpy. // Get the starting pointer of the block. StartPtr = Range.StartPtr; if( DebugThis ) { errs() << "base is:"; StartPtr->dump(); } // Determine alignment unsigned Alignment = Range.Alignment; if (Alignment == 0) { Type *EltType = cast<PointerType>(StartPtr->getType())->getElementType(); Alignment = TD->getABITypeAlignment(EltType); } Instruction *alloc = NULL; Value *globalPtr = NULL; // create temporary alloca space to communicate to/from. alloc = makeAlloca(int8Ty, "agg.tmp", insertBefore, Range.End-Range.Start, Alignment); // Generate the old and new base pointers before we output // anything else. { Type* iPtrTy = TD->getIntPtrType(alloc->getType()); Type* iNewBaseTy = TD->getIntPtrType(alloc->getType()); oldBaseI = builder.CreatePtrToInt(StartPtr, iPtrTy, "agg.tmp.oldb.i"); newBaseI = builder.CreatePtrToInt(alloc, iNewBaseTy, "agg.tmp.newb.i"); } // If storing, do the stores we had into our alloca'd region. if( isStore ) { for (SmallVector<Instruction*, 16>::const_iterator SI = Range.TheStores.begin(), SE = Range.TheStores.end(); SI != SE; ++SI) { StoreInst* oldStore = cast<StoreInst>(*SI); if( DebugThis ) { errs() << "have store in range:"; oldStore->dump(); } Value* ptrToAlloc = rebasePointer(oldStore->getPointerOperand(), StartPtr, alloc, "agg.tmp", &builder, *TD, oldBaseI, newBaseI); // Old load must not be volatile or atomic... or we shouldn't have put // it in ranges assert(!(oldStore->isVolatile() || oldStore->isAtomic())); StoreInst* newStore = builder.CreateStore(oldStore->getValueOperand(), ptrToAlloc); newStore->setAlignment(oldStore->getAlignment()); newStore->takeName(oldStore); } } // cast the pointer that was load/stored to i8 if necessary. if( StartPtr->getType()->getPointerElementType() == int8Ty ) { globalPtr = StartPtr; } else { globalPtr = builder.CreatePointerCast(StartPtr, globalInt8PtrTy, "agg.cast"); } // Get a Constant* for the length. Constant* len = ConstantInt::get(sizeTy, Range.End-Range.Start, false); // Now add the memcpy instruction unsigned addrSpaceDst,addrSpaceSrc; addrSpaceDst = addrSpaceSrc = 0; if( isStore ) addrSpaceDst = globalSpace; if( isLoad ) addrSpaceSrc = globalSpace; Type *types[3]; types[0] = PointerType::get(int8Ty, addrSpaceDst); types[1] = PointerType::get(int8Ty, addrSpaceSrc); types[2] = sizeTy; Function *func = Intrinsic::getDeclaration(M, Intrinsic::memcpy, types); Value* args[5]; // dst src len alignment isvolatile if( isStore ) { // it's a store (ie put) args[0] = globalPtr; args[1] = alloc; } else { // it's a load (ie get) args[0] = alloc; args[1] = globalPtr; } args[2] = len; // alignment args[3] = ConstantInt::get(Type::getInt32Ty(Context), 0, false); // isvolatile args[4] = ConstantInt::get(Type::getInt1Ty(Context), 0, false); Instruction* aMemCpy = builder.CreateCall(func, args); /* DEBUG(dbgs() << "Replace ops:\n"; for (unsigned i = 0, e = Range.TheStores.size(); i != e; ++i) dbgs() << *Range.TheStores[i] << '\n'; dbgs() << "With: " << *AMemSet << '\n'); */ if (!Range.TheStores.empty()) aMemCpy->setDebugLoc(Range.TheStores[0]->getDebugLoc()); lastAddedInsn = aMemCpy; // If loading, load from the memcpy'd region if( isLoad ) { for (SmallVector<Instruction*, 16>::const_iterator SI = Range.TheStores.begin(), SE = Range.TheStores.end(); SI != SE; ++SI) { LoadInst* oldLoad = cast<LoadInst>(*SI); if( DebugThis ) { errs() << "have load in range:"; oldLoad->dump(); } Value* ptrToAlloc = rebasePointer(oldLoad->getPointerOperand(), StartPtr, alloc, "agg.tmp", &builder, *TD, oldBaseI, newBaseI); // Old load must not be volatile or atomic... or we shouldn't have put // it in ranges assert(!(oldLoad->isVolatile() || oldLoad->isAtomic())); LoadInst* newLoad = builder.CreateLoad(ptrToAlloc); newLoad->setAlignment(oldLoad->getAlignment()); oldLoad->replaceAllUsesWith(newLoad); newLoad->takeName(oldLoad); lastAddedInsn = newLoad; } } // Save old loads/stores for removal for (SmallVector<Instruction*, 16>::const_iterator SI = Range.TheStores.begin(), SE = Range.TheStores.end(); SI != SE; ++SI) { Instruction* insn = *SI; toRemove.push_back(insn); } } // Zap all the old loads/stores for (SmallVector<Instruction*, 16>::const_iterator SI = toRemove.begin(), SE = toRemove.end(); SI != SE; ++SI) { (*SI)->eraseFromParent(); } return lastAddedInsn; }
/// /// runOnFunction /// bool LongLongMemAccessLowering::runOnFunction(Function &F) { std::vector<StoreInst *> storeInstV; std::vector<LoadInst *> loadInstV; for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { for (BasicBlock::iterator BI = I->begin(), BE = I->end(); BI != BE; ++BI) { Instruction *inst = BI; if (StoreInst *storeInst = dyn_cast<StoreInst>(inst)) { if (!storeInst->getValueOperand()->getType()->isIntegerTy(64)) { continue; } assert(cast<PointerType>(storeInst->getPointerOperand()->getType()) ->getElementType()->isIntegerTy(64)); storeInstV.push_back(storeInst); } else if (LoadInst *loadInst = dyn_cast<LoadInst>(inst)) { if (!loadInst->getType()->isIntegerTy(64)) { continue; } assert(cast<PointerType>(loadInst->getPointerOperand()->getType()) ->getElementType()->isIntegerTy(64)); loadInstV.push_back(loadInst); } } } for (unsigned i = 0; i < storeInstV.size(); ++i) { StoreInst *inst = storeInstV.at(i); Value *storeVal = inst->getValueOperand(); Value *storePointer = inst->getPointerOperand(); // Insert new instructions BitCastInst *storeAddrLo = new BitCastInst(storePointer, Type::getInt32PtrTy(F.getContext()), "", inst); ConstantInt *offsetConst = ConstantInt::getSigned(Type::getInt32Ty(F.getContext()), 1); std::vector<Value *> gepIdxList(1, offsetConst); GetElementPtrInst *storeAddrHi = GetElementPtrInst::Create(storeAddrLo, gepIdxList, "", inst); TruncInst *storeValLo = new TruncInst(storeVal, Type::getInt32Ty(F.getContext()), "", inst); Value *aShrOffset = ConstantInt::getSigned(Type::getInt64Ty(F.getContext()), 32); BinaryOperator *storeValAShr = BinaryOperator::Create(Instruction::AShr, storeVal, aShrOffset, "", inst); TruncInst *storeValHi = new TruncInst(storeValAShr, Type::getInt32Ty(F.getContext()), "", inst); StoreInst *storeLo = new StoreInst(storeValLo, storeAddrLo, inst); StoreInst *storeHi = new StoreInst(storeValHi, storeAddrHi, inst); storeLo->setAlignment(4); storeHi->setAlignment(4); // Remove inst inst->eraseFromParent(); } for (unsigned i = 0; i < loadInstV.size(); ++i) { LoadInst *inst = loadInstV.at(i); Value *loadPointer = inst->getPointerOperand(); // Insert new instructions BitCastInst *loadAddrLo = new BitCastInst(loadPointer, Type::getInt32PtrTy(F.getContext()), "", inst); ConstantInt *offsetConst = ConstantInt::getSigned(Type::getInt32Ty(F.getContext()), 1); std::vector<Value *> gepIdxList(1, offsetConst); GetElementPtrInst *loadAddrHi = GetElementPtrInst::Create(loadAddrLo, gepIdxList, "", inst); LoadInst *loadLo = new LoadInst(loadAddrLo, "", inst); LoadInst *loadHi = new LoadInst(loadAddrHi, "", inst); ZExtInst *loadLoLL = new ZExtInst(loadLo, Type::getInt64Ty(F.getContext()), "", inst); ZExtInst *loadHiLL = new ZExtInst(loadHi, Type::getInt64Ty(F.getContext()), "", inst); Value *shlOffset = ConstantInt::getSigned(Type::getInt64Ty(F.getContext()), 32); BinaryOperator *loadHiLLShl = BinaryOperator::Create(Instruction::Shl, loadHiLL, shlOffset, "", inst); BinaryOperator *loadValue = BinaryOperator::Create(Instruction::Or, loadLoLL, loadHiLLShl, ""); // Replace inst with new "loaded" value, the old value is deleted ReplaceInstWithInst(inst, loadValue); } return true; // function is modified }
void WorklessInstrument::InstrumentWorkless0Or1Star(Module * pModule, Loop * pLoop, set<string> & setWorkingBlocks) { LoadInst * pLoad0 = NULL; LoadInst * pLoad1 = NULL; //BinaryOperator* pAdd = NULL; StoreInst * pStore = NULL; CallInst * pCall = NULL; Function * pMain = NULL; if(strMainName != "" ) { pMain = pModule->getFunction(strMainName.c_str()); } else { pMain = pModule->getFunction("main"); } for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { if(BB->getName().equals("entry")) { CallInst * pCall; StoreInst * pStore; Instruction * II = BB->begin(); pCall = CallInst::Create(this->InitHooks, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet emptySet; pCall->setAttributes(emptySet); pCall = CallInst::Create(this->getenv, this->SAMPLE_RATE_ptr, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet AS; { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pCall = CallInst::Create(this->function_atoi, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); B.addAttribute(Attribute::ReadOnly); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pStore = new StoreInst(pCall, this->SAMPLE_RATE, false, II); pStore->setAlignment(4); pCall = CallInst::Create(this->geo, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); CastInst * pCast = CastInst::CreateIntegerCast(pCall, this->LongType, true, "", II); pStore = new StoreInst(pCast, this->CURRENT_SAMPLE, false, II); pStore->setAlignment(8); vector<Value *> vecParam; vecParam.push_back(this->Output_Format_String); vecParam.push_back(pCall); pCall = CallInst::Create(this->printf, vecParam, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); break; } } for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<ReturnInst>(Ins) || isa<ResumeInst>(Ins)) { vector<Value*> vecParams; pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numInstances, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); vecParams.clear(); pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numWorkingIterations, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(PrintWorkingRatio, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(aSet); } else if(isa<CallInst>(Ins) || isa<InvokeInst>(Ins)) { CallSite cs(Ins); Function * pCalled = cs.getCalledFunction(); if(pCalled == NULL) { continue; } if(pCalled->getName() == "exit" || pCalled->getName() == "_ZL9mysql_endi") { vector<Value*> vecParams; pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numInstances, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); vecParams.clear(); pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numWorkingIterations, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(PrintWorkingRatio, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(aSet); } } } } Function * pFunction = pLoop->getHeader()->getParent(); BasicBlock * pEntry = &(pFunction->getEntryBlock()); AllocaInst * pAlloc = new AllocaInst(this->LongType, "bWorkingIteration.local", pEntry->getFirstInsertionPt()); vector<BasicBlock *> vecWorkingBlock; for(Function::iterator BB = pFunction->begin(); BB != pFunction->end(); ++ BB) { if(setWorkingBlocks.find(BB->getName()) != setWorkingBlocks.end() ) { vecWorkingBlock.push_back(BB); } } errs() << "working block number: " << vecWorkingBlock.size() << "\n"; BasicBlock * pHeader = pLoop->getHeader(); set<BasicBlock *> setExitBlock; CollectExitBlock(pLoop, setExitBlock); vector<BasicBlock *> vecAdded; CreateIfElseBlock(pLoop, vecAdded); ValueToValueMapTy VMap; set<BasicBlock *> setCloned; CloneInnerLoop(pLoop, vecAdded, VMap, setCloned); //BasicBlock * pPreHeader = vecAdded[0]; BasicBlock * pElseBody = vecAdded[1]; vector<BasicBlock *>::iterator itVecBegin = vecWorkingBlock.begin(); vector<BasicBlock *>::iterator itVecEnd = vecWorkingBlock.end(); for(; itVecBegin != itVecEnd; itVecBegin++ ) { BasicBlock * pClonedBlock = cast<BasicBlock>(VMap[*itVecBegin]); pStore = new StoreInst(this->ConstantLong1, pAlloc, false, pClonedBlock->getFirstInsertionPt()); pStore->setAlignment(8); pClonedBlock->dump(); } pStore = new StoreInst(this->ConstantLong0, pAlloc, false, pElseBody->getTerminator()); pStore->setAlignment(8); pLoad0 = new LoadInst(this->numIterations, "", false, pElseBody->getTerminator()); pLoad0->setAlignment(8); pLoad1 = new LoadInst(this->numWorkingIterations, "", false, pElseBody->getTerminator()); pLoad1->setAlignment(8); BasicBlock * pClonedHeader = cast<BasicBlock>(VMap[pHeader]); set<BasicBlock *> setPredBlocks; for(pred_iterator PI = pred_begin(pClonedHeader), E = pred_end(pClonedHeader); PI != E; ++PI) { setPredBlocks.insert(*PI); } BasicBlock::iterator itInsert = pClonedHeader->getFirstInsertionPt(); PHINode * pNewIterations = PHINode::Create(pLoad0->getType(), setPredBlocks.size(), "numIterations.2", itInsert); PHINode * pNewWorkingIterations = PHINode::Create(pLoad1->getType(), setPredBlocks.size(), "WorkingIterations.2", itInsert); BinaryOperator * pIterationAdd = BinaryOperator::Create(Instruction::Add, pNewIterations, this->ConstantLong1, "Iterations.add.2", itInsert); set<BasicBlock *>::iterator itSetBegin = setPredBlocks.begin(); set<BasicBlock *>::iterator itSetEnd = setPredBlocks.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { if((*itSetBegin) == pElseBody) { pNewIterations->addIncoming(pLoad0, pElseBody); } else { pNewIterations->addIncoming(pIterationAdd, *itSetBegin); } } pLoad0 = new LoadInst(pAlloc, "", false, itInsert); BinaryOperator * pWorkingAdd = BinaryOperator::Create(Instruction::Add, pNewWorkingIterations, pLoad0, "Working.add.2", itInsert); itSetBegin = setPredBlocks.begin(); itSetEnd = setPredBlocks.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { if((*itSetBegin) == pElseBody) { pNewWorkingIterations->addIncoming(pLoad1, pElseBody); } else { pNewWorkingIterations->addIncoming(pWorkingAdd, *itSetBegin); } } pStore = new StoreInst(this->ConstantLong0, pAlloc, false, itInsert); pStore->setAlignment(8); itSetBegin = setExitBlock.begin(); itSetEnd = setExitBlock.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { SmallVector<BasicBlock*, 8> LoopBlocks; for(pred_iterator PI = pred_begin(*itSetBegin), E = pred_end(*itSetBegin); PI != E; ++PI) { if(setCloned.find(*PI) != setCloned.end()) { LoopBlocks.push_back(*PI); } } BasicBlock * NewExitBB = SplitBlockPredecessors(*itSetBegin, LoopBlocks, ".WL.loopexit", this); pStore = new StoreInst(pIterationAdd, this->numIterations, false, NewExitBB->getFirstInsertionPt()); pStore->setAlignment(8); pStore = new StoreInst(pWorkingAdd, this->numWorkingIterations, false, NewExitBB->getFirstInsertionPt()); pStore->setAlignment(8); } //pFunction->dump(); DominatorTree * DT = &(getAnalysis<DominatorTree>(*pFunction)); vector<AllocaInst *> vecAlloc; vecAlloc.push_back(pAlloc); PromoteMemToReg(vecAlloc, *DT); pFunction->dump(); }
void WorklessInstrument::InstrumentWorkless0Star1(Module * pModule, Loop * pLoop) { Function * pMain = NULL; if(strMainName != "" ) { pMain = pModule->getFunction(strMainName.c_str()); } else { pMain = pModule->getFunction("main"); } LoadInst * pLoad; BinaryOperator* pAdd = NULL; StoreInst * pStore = NULL; for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { if(BB->getName().equals("entry")) { CallInst * pCall; StoreInst * pStore; Instruction * II = BB->begin(); pCall = CallInst::Create(this->InitHooks, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet emptySet; pCall->setAttributes(emptySet); pCall = CallInst::Create(this->getenv, this->SAMPLE_RATE_ptr, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet AS; { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pCall = CallInst::Create(this->function_atoi, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); B.addAttribute(Attribute::ReadOnly); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pStore = new StoreInst(pCall, this->SAMPLE_RATE, false, II); pStore->setAlignment(4); pCall = CallInst::Create(this->geo, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); CastInst * pCast = CastInst::CreateIntegerCast(pCall, this->LongType, true, "", II); pStore = new StoreInst(pCast, this->CURRENT_SAMPLE, false, II); pStore->setAlignment(8); vector<Value *> vecParam; vecParam.push_back(this->Output_Format_String); vecParam.push_back(pCall); pCall = CallInst::Create(this->printf, vecParam, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); break; } } for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<ReturnInst>(Ins) || isa<ResumeInst>(Ins)) { vector<Value*> vecParams; pLoad = new LoadInst(numIterations, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); pLoad = new LoadInst(numInstances, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); CallInst* pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); } else if(isa<CallInst>(Ins) || isa<InvokeInst>(Ins)) { CallSite cs(Ins); Function * pCalled = cs.getCalledFunction(); if(pCalled == NULL) { continue; } if(pCalled->getName() == "exit" || pCalled->getName() == "_ZL9mysql_endi") { vector<Value*> vecParams; pLoad = new LoadInst(numIterations, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); pLoad = new LoadInst(numInstances, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); CallInst* pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); } } } } BasicBlock * pHeader = pLoop->getHeader(); set<BasicBlock *> setExitBlock; CollectExitBlock(pLoop, setExitBlock); vector<BasicBlock *> vecAdded; CreateIfElseBlock(pLoop, vecAdded); ValueToValueMapTy VMap; set<BasicBlock *> setCloned; CloneInnerLoop(pLoop, vecAdded, VMap, setCloned); BasicBlock * pPreHeader = vecAdded[1]; pLoad = new LoadInst(this->numIterations, "", false, pPreHeader->getTerminator()); pLoad->setAlignment(8); BasicBlock * pClonedHeader = cast<BasicBlock>(VMap[pHeader]); set<BasicBlock *> setPredBlocks; for(pred_iterator PI = pred_begin(pClonedHeader), E = pred_end(pClonedHeader); PI != E; ++PI) { setPredBlocks.insert(*PI); } PHINode * pNew = PHINode::Create(pLoad->getType(), setPredBlocks.size(), "numIterations", pClonedHeader->getFirstInsertionPt()); pAdd = BinaryOperator::Create(Instruction::Add, pNew, this->ConstantLong1, "add", pClonedHeader->getFirstInsertionPt()); set<BasicBlock *>::iterator itSetBegin = setPredBlocks.begin(); set<BasicBlock *>::iterator itSetEnd = setPredBlocks.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { if((*itSetBegin) == pPreHeader) { pNew->addIncoming(pLoad, pPreHeader); } else { pNew->addIncoming(pAdd, *itSetBegin); } } itSetBegin = setExitBlock.begin(); itSetEnd = setExitBlock.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { SmallVector<BasicBlock*, 8> LoopBlocks; for(pred_iterator PI = pred_begin(*itSetBegin), E = pred_end(*itSetBegin); PI != E; ++PI) { if(setCloned.find(*PI) != setCloned.end()) { LoopBlocks.push_back(*PI); } } BasicBlock * NewExitBB = SplitBlockPredecessors(*itSetBegin, LoopBlocks, ".WL.loopexit", this); pStore = new StoreInst(pAdd, this->numIterations, false, NewExitBB->getFirstInsertionPt()); pStore->setAlignment(8); } pPreHeader->getParent()->dump(); }
// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the // upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Function *F = CI->getCalledFunction(); LLVMContext &C = CI->getContext(); ImmutableCallSite CS(CI); assert(F && "CallInst has no function associated with it."); if (!NewFn) { if (F->getName() == "llvm.x86.sse.loadu.ps" || F->getName() == "llvm.x86.sse2.loadu.dq" || F->getName() == "llvm.x86.sse2.loadu.pd") { // Convert to a native, unaligned load. const Type *VecTy = CI->getType(); const Type *IntTy = IntegerType::get(C, 128); IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), PointerType::getUnqual(IntTy), "cast"); LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); LI->setAlignment(1); // Unaligned load. BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); // Fix up all the uses with our new load. if (!CI->use_empty()) CI->replaceAllUsesWith(BC); // Remove intrinsic. CI->eraseFromParent(); } else if (F->getName() == "llvm.x86.sse.movnt.ps" || F->getName() == "llvm.x86.sse2.movnt.dq" || F->getName() == "llvm.x86.sse2.movnt.pd" || F->getName() == "llvm.x86.sse2.movnt.i") { IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); Module *M = F->getParent(); SmallVector<Value *, 1> Elts; Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1)); MDNode *Node = MDNode::get(C, Elts); Value *Arg0 = CI->getArgOperand(0); Value *Arg1 = CI->getArgOperand(1); // Convert the type of the pointer to a pointer to the stored type. Value *BC = Builder.CreateBitCast(Arg0, PointerType::getUnqual(Arg1->getType()), "cast"); StoreInst *SI = Builder.CreateStore(Arg1, BC); SI->setMetadata(M->getMDKindID("nontemporal"), Node); SI->setAlignment(16); // Remove intrinsic. CI->eraseFromParent(); } else { llvm_unreachable("Unknown function for CallInst upgrade."); } return; } switch (NewFn->getIntrinsicID()) { case Intrinsic::prefetch: { IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CI->getContext()); // Add the extra "data cache" argument Value *Operands[4] = { CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), llvm::ConstantInt::get(I32Ty, 1) }; CallInst *NewCI = CallInst::Create(NewFn, Operands, CI->getName(), CI); NewCI->setTailCall(CI->isTailCall()); NewCI->setCallingConv(CI->getCallingConv()); // Handle any uses of the old CallInst. if (!CI->use_empty()) // Replace all uses of the old call with the new cast which has the // correct type. CI->replaceAllUsesWith(NewCI); // Clean up the old call now that it has been completely upgraded. CI->eraseFromParent(); break; } } }