// reuseOrInsertFastDiv - Reuses previously computed dividend or remainder if // operands and operation are identical. Otherwise call insertFastDiv to perform // the optimization and cache the resulting dividend and remainder. static bool reuseOrInsertFastDiv(Function &F, Function::iterator &I, BasicBlock::iterator &J, IntegerType *BypassType, bool UseDivOp, bool UseSignedOp, DivCacheTy &PerBBDivCache) { // Get instruction operands Instruction *Instr = J; DivOpInfo Key(UseSignedOp, Instr->getOperand(0), Instr->getOperand(1)); DivCacheTy::iterator CacheI = PerBBDivCache.find(Key); if (CacheI == PerBBDivCache.end()) { // If previous instance does not exist, insert fast div return insertFastDiv(F, I, J, BypassType, UseDivOp, UseSignedOp, PerBBDivCache); } // Replace operation value with previously generated phi node DivPhiNodes &Value = CacheI->second; if (UseDivOp) { // Replace all uses of div instruction with quotient phi node J->replaceAllUsesWith(Value.Quotient); } else { // Replace all uses of rem instruction with remainder phi node J->replaceAllUsesWith(Value.Remainder); } // Advance to next operation ++J; // Remove redundant operation Instr->eraseFromParent(); return true; }
/// ChangeToUnreachable - Insert an unreachable instruction before the specified /// instruction, making it and the rest of the code in the block dead. static void ChangeToUnreachable(Instruction *I, bool UseLLVMTrap) { BasicBlock *BB = I->getParent(); // Loop over all of the successors, removing BB's entry from any PHI // nodes. for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) (*SI)->removePredecessor(BB); // Insert a call to llvm.trap right before this. This turns the undefined // behavior into a hard fail instead of falling through into random code. if (UseLLVMTrap) { Function *TrapFn = Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap); CallInst *CallTrap = CallInst::Create(TrapFn, "", I); CallTrap->setDebugLoc(I->getDebugLoc()); } new UnreachableInst(I->getContext(), I); // All instructions after this are dead. BasicBlock::iterator BBI = I, BBE = BB->end(); while (BBI != BBE) { if (!BBI->use_empty()) BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); BB->getInstList().erase(BBI++); } }
virtual bool runOnFunction(Function& f) { CurrentFile::set(__FILE__); bool changed = false; // Make sure this is a function that we can use if (f.isDeclaration() /*|| !f.isDFFunction()*/ ) { return changed ; } for(Function::iterator BB = f.begin(); BB != f.end(); ++BB) { begin: for(BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) { if( !dynamic_cast<TerminatorInst*>(&*II) ) { II->replaceAllUsesWith(UndefValue::get(II->getType())); II->eraseFromParent(); goto begin; } } } changed = true; return changed; }
/// DeleteBasicBlock - remove the specified basic block from the program, /// updating the callgraph to reflect any now-obsolete edges due to calls that /// exist in the BB. void PruneEH::DeleteBasicBlock(BasicBlock *BB) { assert(pred_begin(BB) == pred_end(BB) && "BB is not dead!"); CallGraph &CG = getAnalysis<CallGraph>(); CallGraphNode *CGN = CG[BB->getParent()]; for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { --I; if (CallInst *CI = dyn_cast<CallInst>(I)) { if (Function *Callee = CI->getCalledFunction()) CGN->removeCallEdgeTo(CG[Callee]); } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) { if (Function *Callee = II->getCalledFunction()) CGN->removeCallEdgeTo(CG[Callee]); } if (!I->use_empty()) I->replaceAllUsesWith(UndefValue::get(I->getType())); } // Get the list of successors of this block. std::vector<BasicBlock*> Succs(succ_begin(BB), succ_end(BB)); for (unsigned i = 0, e = Succs.size(); i != e; ++i) Succs[i]->removePredecessor(BB); BB->eraseFromParent(); }
/// doConstantPropagation - If an instruction references constants, try to fold /// them together... /// bool llvm::doConstantPropagation(BasicBlock::iterator &II) { if (Constant *C = ConstantFoldInstruction(II)) { // Replaces all of the uses of a variable with uses of the constant. II->replaceAllUsesWith(C); // Remove the instruction from the basic block... II = II->getParent()->getInstList().erase(II); return true; } return false; }
/// ChangeToUnreachable - Insert an unreachable instruction before the specified /// instruction, making it and the rest of the code in the block dead. static void ChangeToUnreachable(Instruction *I) { BasicBlock *BB = I->getParent(); // Loop over all of the successors, removing BB's entry from any PHI // nodes. for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) (*SI)->removePredecessor(BB); new UnreachableInst(I); // All instructions after this are dead. BasicBlock::iterator BBI = I, BBE = BB->end(); while (BBI != BBE) { if (!BBI->use_empty()) BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); BB->getInstList().erase(BBI++); } }
/// DeleteBasicBlock - remove the specified basic block from the program, /// updating the callgraph to reflect any now-obsolete edges due to calls that /// exist in the BB. void PruneEH::DeleteBasicBlock(BasicBlock *BB) { assert(pred_empty(BB) && "BB is not dead!"); CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); Instruction *TokenInst = nullptr; CallGraphNode *CGN = CG[BB->getParent()]; for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { --I; if (I->getType()->isTokenTy()) { TokenInst = &*I; break; } if (auto CS = CallSite (&*I)) { const Function *Callee = CS.getCalledFunction(); if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID())) CGN->removeCallEdgeFor(CS); else if (!Callee->isIntrinsic()) CGN->removeCallEdgeFor(CS); } if (!I->use_empty()) I->replaceAllUsesWith(UndefValue::get(I->getType())); } if (TokenInst) { if (!isa<TerminatorInst>(TokenInst)) changeToUnreachable(TokenInst->getNextNode(), /*UseLLVMTrap=*/false); } else { // Get the list of successors of this block. std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB)); for (unsigned i = 0, e = Succs.size(); i != e; ++i) Succs[i]->removePredecessor(BB); BB->eraseFromParent(); } }
/// RemoveBlockIfDead - If the specified block is dead, remove it, update loop /// information, and remove any dead successors it has. /// void LoopUnswitch::RemoveBlockIfDead(BasicBlock *BB, std::vector<Instruction*> &Worklist, Loop *L) { if (pred_begin(BB) != pred_end(BB)) { // This block isn't dead, since an edge to BB was just removed, see if there // are any easy simplifications we can do now. if (BasicBlock *Pred = BB->getSinglePredecessor()) { // If it has one pred, fold phi nodes in BB. while (isa<PHINode>(BB->begin())) ReplaceUsesOfWith(BB->begin(), cast<PHINode>(BB->begin())->getIncomingValue(0), Worklist, L, LPM); // If this is the header of a loop and the only pred is the latch, we now // have an unreachable loop. if (Loop *L = LI->getLoopFor(BB)) if (loopHeader == BB && L->contains(Pred)) { // Remove the branch from the latch to the header block, this makes // the header dead, which will make the latch dead (because the header // dominates the latch). LPM->deleteSimpleAnalysisValue(Pred->getTerminator(), L); Pred->getTerminator()->eraseFromParent(); new UnreachableInst(BB->getContext(), Pred); // The loop is now broken, remove it from LI. RemoveLoopFromHierarchy(L); // Reprocess the header, which now IS dead. RemoveBlockIfDead(BB, Worklist, L); return; } // If pred ends in a uncond branch, add uncond branch to worklist so that // the two blocks will get merged. if (BranchInst *BI = dyn_cast<BranchInst>(Pred->getTerminator())) if (BI->isUnconditional()) Worklist.push_back(BI); } return; } DEBUG(dbgs() << "Nuking dead block: " << *BB); // Remove the instructions in the basic block from the worklist. for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { RemoveFromWorklist(I, Worklist); // Anything that uses the instructions in this basic block should have their // uses replaced with undefs. // If I is not void type then replaceAllUsesWith undef. // This allows ValueHandlers and custom metadata to adjust itself. if (!I->getType()->isVoidTy()) I->replaceAllUsesWith(UndefValue::get(I->getType())); } // If this is the edge to the header block for a loop, remove the loop and // promote all subloops. if (Loop *BBLoop = LI->getLoopFor(BB)) { if (BBLoop->getLoopLatch() == BB) RemoveLoopFromHierarchy(BBLoop); } // Remove the block from the loop info, which removes it from any loops it // was in. LI->removeBlock(BB); // Remove phi node entries in successors for this block. TerminatorInst *TI = BB->getTerminator(); SmallVector<BasicBlock*, 4> Succs; for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) { Succs.push_back(TI->getSuccessor(i)); TI->getSuccessor(i)->removePredecessor(BB); } // Unique the successors, remove anything with multiple uses. array_pod_sort(Succs.begin(), Succs.end()); Succs.erase(std::unique(Succs.begin(), Succs.end()), Succs.end()); // Remove the basic block, including all of the instructions contained in it. LPM->deleteSimpleAnalysisValue(BB, L); BB->eraseFromParent(); // Remove successor blocks here that are not dead, so that we know we only // have dead blocks in this list. Nondead blocks have a way of becoming dead, // then getting removed before we revisit them, which is badness. // for (unsigned i = 0; i != Succs.size(); ++i) if (pred_begin(Succs[i]) != pred_end(Succs[i])) { // One exception is loop headers. If this block was the preheader for a // loop, then we DO want to visit the loop so the loop gets deleted. // We know that if the successor is a loop header, that this loop had to // be the preheader: the case where this was the latch block was handled // above and headers can only have two predecessors. if (!LI->isLoopHeader(Succs[i])) { Succs.erase(Succs.begin()+i); --i; } } for (unsigned i = 0, e = Succs.size(); i != e; ++i) RemoveBlockIfDead(Succs[i], Worklist, L); }
void HeterotbbTransform::edit_template_function (Module &M,Function* F,Function* new_join,GlobalVariable *old_gb,Value *gb) { SmallVector<Value*, 16> Args; // Argument lists to the new call vector<Instruction *> toDelete; // old_gb->dump(); // gb->dump(); Constant *Ids[2]; for (Function::iterator BI=F->begin(),BE = F->end(); BI != BE; ++BI) { for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE; ++II) { GetElementPtrInst *GEP; GlobalVariable *op; if (isa<CallInst>(II) || isa<InvokeInst>(II)) { CallSite CI(cast<Instruction>(II)); //replace dummy reduce with new reduce if(CI.getCalledFunction()->getName().equals("__join_reduce_hetero")) { Args.clear(); CastInst *newarg1 = CastInst::Create(Instruction::BitCast, CI.getArgument(0), new_join->arg_begin()->getType(), "arg1",CI.getInstruction()); Args.push_back(newarg1); CastInst *newarg2 = CastInst::Create(Instruction::BitCast, CI.getArgument(1), new_join->arg_begin()->getType(), "arg2", CI.getInstruction()); Args.push_back(newarg2); //no need to set attributes Instruction *NewCall = CallInst::Create(new_join, Args, "", CI.getInstruction()); cast<CallInst>(NewCall)->setCallingConv(CI.getCallingConv()); toDelete.push_back(CI.getInstruction()); DEBUG(dbgs()<<"Joins Replaced\n"); } } /* %arrayidx18 = getelementptr inbounds i32 addrspace(3)* getelementptr inbounds ([192 x i32] addrspace(3)* @opencl_kernel_join_name_local_arr, i32 0, i32 0), i64 %idxprom1 */ if((GEP = dyn_cast<GetElementPtrInst>(II)) /*&& (op = dyn_cast<GlobalVariable>(GEP->getOperand(0)))*/ /*&& (op->getName().equals("opencl_kernel_join_name_local_arr"))*/) { //II->dump(); Value *val= II->getOperand(0); if(Constant *op=dyn_cast<ConstantExpr>(val)) { //II->dump(); //II->getOperand(1)->dump(); /*Ids[0]=cast<Constant>(op->getOperand(1)); Ids[1]=cast<Constant>(op->getOperand(1)); Constant *new_op = ConstantExpr::getInBoundsGetElementPtr(cast<Constant>(gb),Ids,2); new_op->dump(); Instruction *inst = GetElementPtrInst::CreateInBounds(new_op, II->getOperand(1), II->getName()+"_temp",II); Value *Elts[] = {MDString::get(M.getContext(), "local_access")}; MDNode *Node = MDNode::get(M.getContext(), Elts); inst->setMetadata("local_access",Node); inst->dump(); II->replaceAllUsesWith(inst); toDelete.push_back(II); */ Value *Idxs[2] = {ConstantInt::get(Type::getInt32Ty(M.getContext()), 0), ConstantInt::get(Type::getInt32Ty(M.getContext()), 0) }; //gb->getType()->dump(); //gb->dump(); Instruction *inst_= GetElementPtrInst::CreateInBounds(gb, Idxs, /*Idxs+2,*/ II->getName()+"_temp_",II); //inst_->dump(); Instruction *inst= GetElementPtrInst::CreateInBounds(inst_, II->getOperand(1), II->getName()+"_temp",II); Value *Elts[] = {MDString::get(M.getContext(), inst->getName())}; MDNode *Node = MDNode::get(M.getContext(), Elts); inst->setMetadata("local_access",Node); //inst->dump(); II->replaceAllUsesWith(inst); toDelete.push_back(II); } } } } while(!toDelete.empty()) { Instruction *g = toDelete.back(); toDelete.pop_back(); g->eraseFromParent(); } }
void ArrayObfs::ArrObfuscate ( Function *F ) { // Iterate the whole Function Function *f = F; for ( Function::iterator bb = f->begin(); bb != f->end(); ++bb ) { for ( BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ) { if ( inst->getOpcode() == 29 ) // getelementptr { //errs() << "INST : " << *inst << "\n"; GetElementPtrInst *Ary = dyn_cast<GetElementPtrInst>(&*inst); Value *ptrVal = Ary->getOperand(0); Type *type = ptrVal->getType(); unsigned numOfOprand = Ary->getNumOperands(); unsigned lastOprand = numOfOprand - 1; // Check Type Array if ( PointerType *ptrType = dyn_cast<PointerType>( type ) ) { Type *elementType = ptrType->getElementType(); if ( elementType->isArrayTy() ) { // Skip if Index is a Variable if ( dyn_cast<ConstantInt>( Ary->getOperand( lastOprand ) ) ) { ////////////////////////////////////////////////////////////////////////////// // Do Real Stuff Value *oprand = Ary->getOperand( lastOprand ); Value *basePtr = Ary->getOperand( 0 ); APInt offset = dyn_cast<ConstantInt>(oprand)->getValue(); Value *prevPtr = basePtr; // Enter a Loop to Perform Random Obfuscation unsigned cnt = 100; // Prelog : Clone the Original Inst unsigned ObfsIdx = cryptoutils->get_uint64_t() & 0xffff; Value *newOprand = ConstantInt::get( oprand->getType(), ObfsIdx ); Instruction *gep = inst->clone(); gep->setOperand( lastOprand, newOprand ); gep->setOperand( 0, prevPtr ); gep->insertBefore( inst ); prevPtr = gep; offset = offset - ObfsIdx; // Create a Global Variable to Avoid Optimization Module *M = f->getParent(); Constant *initGV = ConstantInt::get( prevPtr->getType(), 0 ); GlobalVariable *gv = new GlobalVariable( *M, prevPtr->getType(), false, GlobalValue::CommonLinkage, initGV ); while ( cnt-- ) { // Iteratively Generate Obfuscated Code switch( cryptoutils->get_uint64_t() & 7 ) { // Random Indexing Obfuscation case 0 : case 1 : case 2 : { //errs() << "=> Random Index \n"; // Create New Instruction // Create Obfuscated New Oprand in ConstantInt Type unsigned ObfsIdx = cryptoutils->get_uint64_t() & 0xffff; Value *newOprand = ConstantInt::get( oprand->getType(), ObfsIdx ); // Create GetElementPtrInst Instruction GetElementPtrInst *gep = GetElementPtrInst::Create( prevPtr, newOprand, "", inst ); //Set prevPtr prevPtr = gep; //errs() << "Created : " << *prevPtr << "\n"; offset = offset - ObfsIdx; break; } // Ptr Dereference case 3 : case 4 : { //errs() << "=> Ptr Dereference \n"; Module *M = f->getParent(); Value *ONE = ConstantInt::get( Type::getInt32Ty( M->getContext() ), 1 ); Value *tmp = new AllocaInst( prevPtr->getType(), ONE, "", inst ); new StoreInst( prevPtr, tmp, inst ); prevPtr = new LoadInst( tmp, "", inst ); break; } // Ptr Value Transform case 5 : case 6 : case 7 : { //errs() << "=> Ptr Value Trans \n"; unsigned RandNum = cryptoutils->get_uint64_t(); Value *ObfsVal = ConstantInt::get( prevPtr->getType(), RandNum ); BinaryOperator *op = BinaryOperator::Create( Instruction::FAdd, prevPtr, ObfsVal, "", inst ); new StoreInst( prevPtr, gv, inst ); BinaryOperator::Create( Instruction::FSub, gv, ObfsVal, "", inst ); prevPtr = new LoadInst( gv, "", inst ); break; } } } // Postlog : Fix the Original Indexing { Value *fixOprand = ConstantInt::get( oprand->getType(), offset ); // Refine the Last Instruction GetElementPtrInst *gep = GetElementPtrInst::Create( prevPtr, fixOprand, "", inst ); // Fix the Relationship inst->replaceAllUsesWith( gep ); // Finally : Unlink This Instruction From Parent Instruction *DI = inst++; //errs() << "user_back : " << *(DI->user_back()) << "\n"; DI->removeFromParent(); } ////////////////////////////////////////////////////////////////////////////// // End : Variable Index } else { inst++; } // End : Check Array Type } else { inst++; } // End : Check Pointer Type } else { inst++; } // End : Check Opcode GetElementPtr } else { inst++; } } } ++ArrayMod; }
/** * Generate code for */ void HeteroOMPTransform::gen_code_per_f (Function* NF, Function* F, Instruction *max_threads){ Function::arg_iterator FI = F->arg_begin(); Argument *ctxname = &*FI; Function::arg_iterator DestI = NF->arg_begin(); DestI->setName(ctxname->getName()); Argument *ctx_name = &(*DestI); DestI++; DestI->setName("tid"); Argument *num_iters = &(*DestI); #ifdef EXPLICIT_REWRITE DenseMap<const Value*, Value *> ValueMap; #else ValueToValueMapTy ValueMap; #endif //get the old basic block and create a new one Function::const_iterator BI = F->begin(); const BasicBlock &FB = *BI; BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF); if (FB.hasName()){ NFBB->setName(FB.getName()); } ValueMap[&FB] = NFBB; //ValueMap[numiters] = num_iters; ValueMap[ctxname] = ctx_name; #if EXPLICIT_REWRITE for (BasicBlock::const_iterator II = FB.begin(), IE = FB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); // DEBUG(dbgs()<<*II<<"\n"); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } BI++; for (Function::const_iterator /*BI=F->begin(),*/BE = F->end();BI != BE; ++BI) { const BasicBlock &FBB = *BI; BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF); ValueMap[&FBB] = NFBB; if (FBB.hasName()){ NFBB->setName(FBB.getName()); //DEBUG(dbgs()<<NFBB->getName()<<"\n"); } for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } } // Remap the instructions again to take care of forward jumps for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) { for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II){ int opIdx = 0; //DEBUG(dbgs()<<*II<<"\n"); for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) { Value *V = *i; if (ValueMap[V] != NULL) { II->setOperand(opIdx, ValueMap[V]); } } } } #else SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned. CloneFunctionInto(NF, F, ValueMap, false, Returns, ""); #endif //max_threads->dump(); /* Remap openmp omp_num_threads() and omp_thread_num() */ /* * define internal void @_Z20initialize_variablesiPfS_.omp_fn.4(i8* nocapture %.omp_data_i) nounwind ssp { * entry: * %0 = bitcast i8* %.omp_data_i to i32* ; <i32*> [#uses=1] * %1 = load i32* %0, align 8 ; <i32> [#uses=2] * %2 = tail call i32 @omp_get_num_threads() nounwind readnone ; <i32> [#uses=2] * %3 = tail call i32 @omp_get_thread_num() nounwind readnone ; <i32> [#uses=2] %4 = sdiv i32 %1, %2 %5 = mul nsw i32 %4, %2 %6 = icmp ne i32 %5, %1 %7 = zext i1 %6 to i32 */ vector<Instruction *> toDelete; for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) { for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II){ if (isa<CallInst>(II)) { CallSite CI(cast<Instruction>(II)); if (CI.getCalledFunction() != NULL){ string called_func_name = CI.getCalledFunction()->getName(); if (called_func_name == OMP_GET_NUM_THREADS_NAME && CI.arg_size() == 0) { II->replaceAllUsesWith(ValueMap[max_threads]); toDelete.push_back(II); } else if (called_func_name == OMP_GET_THREAD_NUM_NAME && CI.arg_size() == 0) { II->replaceAllUsesWith(num_iters); toDelete.push_back(II); } } } } } /* Delete the last branch instruction of the first basic block -- Assuming it is safe */ Function::iterator nfBB = NF->begin(); TerminatorInst *lastI = nfBB->getTerminator(); BranchInst *bI; BasicBlock *returnBlock; if ((bI = dyn_cast<BranchInst>(lastI)) && bI->isConditional() && (returnBlock = bI->getSuccessor(1)) && (returnBlock->getName() == "return")) { /* modify to a unconditional branch to next basic block and not return */ Instruction *bbI = BranchInst::Create(bI->getSuccessor(0),lastI); bbI->dump(); toDelete.push_back(lastI); } //NF->dump(); while(!toDelete.empty()) { Instruction *g = toDelete.back(); //g->replaceAllUsesWith(UndefValue::get(g->getType())); toDelete.pop_back(); g->eraseFromParent(); } //NF->dump(); }
virtual bool runOnFunction(Function &F) { DEBUG(errs() << "Running on " << F.getName() << "\n"); DEBUG(F.dump()); Changed = false; BaseMap.clear(); BoundsMap.clear(); AbrtBB = 0; valid = true; if (!rootNode) { rootNode = getAnalysis<CallGraph>().getRoot(); // No recursive functions for now. // In the future we may insert runtime checks for stack depth. for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode), E = scc_end(rootNode); SCCI != E; ++SCCI) { const std::vector<CallGraphNode*> &nextSCC = *SCCI; if (nextSCC.size() > 1 || SCCI.hasLoop()) { errs() << "INVALID: Recursion detected, callgraph SCC components: "; for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(), E = nextSCC.end(); I != E; ++I) { Function *FF = (*I)->getFunction(); if (FF) { errs() << FF->getName() << ", "; badFunctions.insert(FF); } } if (SCCI.hasLoop()) errs() << "(self-loop)"; errs() << "\n"; } // we could also have recursion via function pointers, but we don't // allow calls to unknown functions, see runOnFunction() below } } BasicBlock::iterator It = F.getEntryBlock().begin(); while (isa<AllocaInst>(It) || isa<PHINode>(It)) ++It; EP = &*It; TD = &getAnalysis<TargetData>(); SE = &getAnalysis<ScalarEvolution>(); PT = &getAnalysis<PointerTracking>(); DT = &getAnalysis<DominatorTree>(); std::vector<Instruction*> insns; BasicBlock *LastBB = 0; bool skip = false; for (inst_iterator I=inst_begin(F),E=inst_end(F); I != E;++I) { Instruction *II = &*I; if (II->getParent() != LastBB) { LastBB = II->getParent(); skip = DT->getNode(LastBB) == 0; } if (skip) continue; if (isa<LoadInst>(II) || isa<StoreInst>(II) || isa<MemIntrinsic>(II)) insns.push_back(II); if (CallInst *CI = dyn_cast<CallInst>(II)) { Value *V = CI->getCalledValue()->stripPointerCasts(); Function *F = dyn_cast<Function>(V); if (!F) { printLocation(CI, true); errs() << "Could not determine call target\n"; valid = 0; continue; } if (!F->isDeclaration()) continue; insns.push_back(CI); } } while (!insns.empty()) { Instruction *II = insns.back(); insns.pop_back(); DEBUG(dbgs() << "checking " << *II << "\n"); if (LoadInst *LI = dyn_cast<LoadInst>(II)) { const Type *Ty = LI->getType(); valid &= validateAccess(LI->getPointerOperand(), TD->getTypeAllocSize(Ty), LI); } else if (StoreInst *SI = dyn_cast<StoreInst>(II)) { const Type *Ty = SI->getOperand(0)->getType(); valid &= validateAccess(SI->getPointerOperand(), TD->getTypeAllocSize(Ty), SI); } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(II)) { valid &= validateAccess(MI->getDest(), MI->getLength(), MI); if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) { valid &= validateAccess(MTI->getSource(), MI->getLength(), MI); } } else if (CallInst *CI = dyn_cast<CallInst>(II)) { Value *V = CI->getCalledValue()->stripPointerCasts(); Function *F = cast<Function>(V); const FunctionType *FTy = F->getFunctionType(); CallSite CS(CI); if (F->getName().equals("memcmp") && FTy->getNumParams() == 3) { valid &= validateAccess(CS.getArgument(0), CS.getArgument(2), CI); valid &= validateAccess(CS.getArgument(1), CS.getArgument(2), CI); continue; } unsigned i; #ifdef CLAMBC_COMPILER i = 0; #else i = 1;// skip hidden ctx* #endif for (;i<FTy->getNumParams();i++) { if (isa<PointerType>(FTy->getParamType(i))) { Value *Ptr = CS.getArgument(i); if (i+1 >= FTy->getNumParams()) { printLocation(CI, false); errs() << "Call to external function with pointer parameter last cannot be analyzed\n"; errs() << *CI << "\n"; valid = 0; break; } Value *Size = CS.getArgument(i+1); if (!Size->getType()->isIntegerTy()) { printLocation(CI, false); errs() << "Pointer argument must be followed by integer argument representing its size\n"; errs() << *CI << "\n"; valid = 0; break; } valid &= validateAccess(Ptr, Size, CI); } } } } if (badFunctions.count(&F)) valid = 0; if (!valid) { DEBUG(F.dump()); ClamBCModule::stop("Verification found errors!", &F); // replace function with call to abort std::vector<const Type*>args; FunctionType* abrtTy = FunctionType::get( Type::getVoidTy(F.getContext()),args,false); Constant *func_abort = F.getParent()->getOrInsertFunction("abort", abrtTy); BasicBlock *BB = &F.getEntryBlock(); Instruction *I = &*BB->begin(); Instruction *UI = new UnreachableInst(F.getContext(), I); CallInst *AbrtC = CallInst::Create(func_abort, "", UI); AbrtC->setCallingConv(CallingConv::C); AbrtC->setTailCall(true); AbrtC->setDoesNotReturn(true); AbrtC->setDoesNotThrow(true); // remove all instructions from entry BasicBlock::iterator BBI = I, BBE=BB->end(); while (BBI != BBE) { if (!BBI->use_empty()) BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); BB->getInstList().erase(BBI++); } } return Changed; }
bool ModuloSchedulerDriverPass::runOnLoop(Loop *IncomingLoop, LPPassManager &LPM_Ref) { subscripts subs(IncomingLoop); if (!loop_is_ms_able(IncomingLoop) ) return false; // The header before the parallelized loop will be placed here BasicBlock* preheader = IncomingLoop->getLoopPreheader(); assert(preheader && "Unable to get a hold of the preheader"); // Balance all BasicBlocks in this loop for (Loop::block_iterator it=IncomingLoop->block_begin(); it!=IncomingLoop->block_end();++it) { duplicateValuesWithMultipleUses(*it,subs.getInductionVar()); } // For each BB in loop for (Loop::block_iterator it=IncomingLoop->block_begin(); it!=IncomingLoop->block_end();++it) { instructionPriority ip(*it); (*it)->setName("PipelinedLoop"); // ++++++++ Preheader part +++++++++ // Make a copy of the body for each instruction. Place a pointer to the // parallel cloned instruction in the map below. Later on we will replace it // with a PHINode. DenseMap<const Value *, Value *> InstToPreheader; // For each Instruction in body of the loop, clone, store, etc. for (BasicBlock::iterator ib = (*it)->begin(), eb = (*it)->end(); ib!=eb; ++ib) { // If this is NOT a phi node if (!dyn_cast<PHINode>(ib)) { // Get the priority of the instruction unsigned int p = ip.getPriority(ib); // This is the header version of each variable that goes into a PHI node. // The other edge needs to come from the 'prev' iteration // We subtract -1 because this is one iteration before // Store the result into the map of the cloned InstToPreheader[ib] = copyLoopBodyToHeader(ib, subs.getInductionVar(), preheader, p-1); } } // ++++++++ Loop body part +++++++++ // For each of the cloned increment the indexs if needed and place the PHINode. for (BasicBlock::iterator ib = (*it)->begin(), eb = (*it)->end(); ib!=eb; ++ib) { // If this is NOT a phi node if (!dyn_cast<PHINode>(ib)) { unsigned int p = ip.getPriority(ib); // If this variable is not dependent on i (not i:=i+1) // then we need to replace each i to i+5 ... // We also do not need to create a PHI node, etc. if (!subs.isUsedByInductionVariable(ib)) { incrementInductionVarIfUsed(ib,subs.getInductionVar(),p); // Create the new PHI Node to replace the node if (!dyn_cast<StoreInst>(ib) && !ib->isTerminator()) { std::string newname = "glue" + (*it)->getName(); //PHINode* np = PHINode::Create(ib->getType(), "glue", *it); PHINode* np = PHINode::Create(ib->getType(), newname, *it); ib->replaceAllUsesWith(np); np->reserveOperandSpace(2); np->addIncoming(InstToPreheader[ib], preheader); np->addIncoming(ib, *it); np->moveBefore((*it)->begin()); } }// end of if this is not an IV node (i:=i+1) } } } eliminateDuplicatedLoads(preheader); for (Loop::block_iterator it=IncomingLoop->block_begin(); it!=IncomingLoop->block_end();++it) { eliminateDuplicatedLoads(*it); for (BasicBlock::iterator in = (*it)->begin(); in != (*it)->end(); ++in) { foldAddInstructions(in); } } return true; }