예제 #1
0
	void PhiElimination::splitCriticalEdge(
		IRFunction * func, BasicBlock * block)
	{
		//if (block->numOfPrecursors() <= 1)
		//	return;

		auto GetInnerBlock = [func, block]
			(const std::string &from, const std::string &to) {
			BasicBlock *BB = func->createBasicBlock(from + "-" + to);
			Goto *go2 = IRContext::create<Goto>(block);
			BB->push_back(go2);
			BB->addSuccessor(block);
			go2->set_parent(BB);
			return BB;
		};

		size_t size = block->numOfPrecursors();
		for (auto pre = block->precursor_begin();
			pre != block->precursor_end();
			++pre) {
			BasicBlock *PBB = *pre;
			// Check whether split.
			if (PBB->numOfSuccessors() <= 1)
				continue;

			// split it.
			BasicBlock *BB = GetInnerBlock(
				PBB->getBlockName(), block->getBlockName());

			*pre = BB;

			PBB->successor_replace(block, BB);
			if (PBB->back()->is_goto()) {
				Goto *GT = static_cast<Goto*>(PBB->back());
				GT->setTarget(BB);
			}
			else if (PBB->back()->is_branch()) {
				Branch *branch = static_cast<Branch*>(PBB->back());
				if (branch->then() == block)
					branch->setThen(BB);
				else
					branch->setElse(BB);
			}
			else {
				assert(0 && "impossible");
			}
		}
	}
//
// Override the runOnLoop function provided by LoopPass.
// Return true because we intend on modifying the control flow graph.
//
bool LicmPass::runOnLoop(Loop *loop, LPPassManager &LPM) {
    unsigned int depth = loop->getLoopDepth();
    info = &getAnalysis<LoopInfo>();
    cout << "Loop<depth = " << depth << ">" << endl;

    // check if there is a preheader
    BasicBlock* preheader = loop->getLoopPreheader();
    if (!preheader) {
        return false;
    }

    // Run analysis passes on blocks.
    const BlockVector& blocks = loop->getBlocks();
    BlockStates states = dominance.runOnBlocks(blocks);
    showDominators(blocks, states, preheader);

    // Cache all the invariants we have found so far.
    Invariants invariants;
    findInvariants(loop, blocks, states, preheader, invariants);

    // Finally, hoist the invariants into the preheader.
    // We want to delete this instruction and move it to the end of the
    // preheader (before the branch). We can do with with moveBefore.
    for (Invariants::iterator I = invariants.begin(), IE = invariants.end();
            I != IE; ++I) {
        Instruction* end = &(preheader->back());
        Instruction* instr = *I;
        instr->moveBefore(end);
    }

    // assume we modified the loop
    return true;
};
예제 #3
0
bool CFGTree::identifySuccessorRelation(BasicBlock *predBB, 
                                        BasicBlock *succBB) {
  bool identify = false;
  BasicBlock *bb = predBB;
 
  while (true) {
    Instruction *inst = &(bb->back());
    if (inst->getOpcode() == Instruction::Br) {
      BranchInst *bi = dyn_cast<BranchInst>(inst);
      if (bi->isUnconditional()) {
        bb = bi->getSuccessor(0); 
        if (bb == succBB) {
          identify = true;
          break;
        }
      } else {
        identify = foundSameBrInstFromCFGTree(inst, root); 
        break;
      }
    } else {
      if (inst->getOpcode() == Instruction::Ret)
        break;
      else 
        assert(false && "Unsupported instruction!"); 
    }
  }
  
  return identify; 
}
예제 #4
0
// TransformLongJmpCall - Transform a longjmp call into a call to the
// internal __llvm_sjljeh_throw_longjmp function. It then takes care of
// throwing the exception for us.
void LowerSetJmp::TransformLongJmpCall(CallInst* Inst)
{
  const Type* SBPTy =
        PointerType::getUnqual(Type::getInt8Ty(Inst->getContext()));

  // Create the call to "__llvm_sjljeh_throw_longjmp". This takes the
  // same parameters as "longjmp", except that the buffer is cast to a
  // char*. It returns "void", so it doesn't need to replace any of
  // Inst's uses and doesn't get a name.
  CastInst* CI = 
    new BitCastInst(Inst->getOperand(1), SBPTy, "LJBuf", Inst);
  SmallVector<Value *, 2> Args;
  Args.push_back(CI);
  Args.push_back(Inst->getOperand(2));
  CallInst::Create(ThrowLongJmp, Args.begin(), Args.end(), "", Inst);

  SwitchValuePair& SVP = SwitchValMap[Inst->getParent()->getParent()];

  // If the function has a setjmp call in it (they are transformed first)
  // we should branch to the basic block that determines if this longjmp
  // is applicable here. Otherwise, issue an unwind.
  if (SVP.first)
    BranchInst::Create(SVP.first->getParent(), Inst);
  else
    new UnwindInst(Inst->getContext(), Inst);

  // Remove all insts after the branch/unwind inst.  Go from back to front to
  // avoid replaceAllUsesWith if possible.
  BasicBlock *BB = Inst->getParent();
  Instruction *Removed;
  do {
    Removed = &BB->back();
    // If the removed instructions have any users, replace them now.
    if (!Removed->use_empty())
      Removed->replaceAllUsesWith(UndefValue::get(Removed->getType()));
    Removed->eraseFromParent();
  } while (Removed != Inst);

  ++LongJmpsTransformed;
}
예제 #5
0
/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the location Loc.
///
bool AAResults::canBasicBlockModify(const BasicBlock &BB,
                                    const MemoryLocation &Loc) {
  return canInstructionRangeModRef(BB.front(), BB.back(), Loc, MRI_Mod);
}
예제 #6
0
파일: FuncAddrTaken.cpp 프로젝트: mcfi/MCFI
bool FuncAddrTaken::runOnModule(Module &M) {
  bool Changed = false;
  // add declaration of function __patch_at
  // declare void @__patch_at(void)
  FunctionType *FT = FunctionType::get(Type::getVoidTy(M.getContext()),
                                       false);
  Function* PatchAt = Function::Create(FT, Function::ExternalLinkage, "__patch_at", &M);
  if (PatchAt->getName() != "__patch_at") {
    PatchAt->eraseFromParent();
    return false;
  }
  Changed = true;

  // Simple optimization so that no function address will be taken twice
  // in the same basic block.
  std::map<BasicBlock*, std::set<std::string> > UniqPatchAt;

  // before each store instruction that manipulates a function, create a call
  // to __patch_at
  for (auto F = M.getFunctionList().begin(); F != M.getFunctionList().end(); F++) {
    for (auto BB = F->begin(); BB != F->end(); BB++) {
      for (auto MI = BB->begin(); MI != BB->end(); MI++) {
        if (isa<StoreInst>(MI)) {
          // check if the store inst moves a function to a variable
          Value *V = InnerMost(cast<StoreInst>(MI)->getValueOperand());
          addPatchAt(M, FT, V, MI, UniqPatchAt);
          if (isa<ConstantVector>(V)) {
            std::set<Value*> patched;
            for (unsigned i = 0; i < cast<ConstantVector>(V)->getNumOperands(); i++) {
              Value *VV = InnerMost(cast<ConstantVector>(V)->getOperand(i));
              if (patched.find(VV) == patched.end()) {
                addPatchAt(M, FT, VV, MI, UniqPatchAt);
                patched.insert(VV);
              }
            }
          } else if (isa<ConstantStruct>(V)) {
            std::set<Value*> patched;
            for (unsigned i = 0; i < cast<ConstantStruct>(V)->getNumOperands(); i++) {
              Value *VV = InnerMost(cast<ConstantStruct>(V)->getOperand(i));
              if (patched.find(VV) == patched.end()) {
                addPatchAt(M, FT, VV, MI, UniqPatchAt);
                patched.insert(VV);
              }
            }
          } else if (isa<ConstantArray>(V)) {
            std::set<Value*> patched;
            for (unsigned i = 0; i < cast<ConstantArray>(V)->getNumOperands(); i++) {
              Value *VV = InnerMost(cast<ConstantArray>(V)->getOperand(i));
              if (patched.find(VV) == patched.end()) {
                addPatchAt(M, FT, VV, MI, UniqPatchAt);
                patched.insert(VV);
              }
            }
          }
        } else if (isa<SelectInst>(MI)) {
          Value *V = InnerMost(cast<SelectInst>(MI)->getTrueValue());
          addPatchAt(M, FT, V, MI, UniqPatchAt);
          V = InnerMost(cast<SelectInst>(MI)->getFalseValue());
          addPatchAt(M, FT, V, MI, UniqPatchAt);
        } else if (isa<CallInst>(MI)) {
          CallInst* CI = cast<CallInst>(MI);
          for (unsigned i = 0; i < CI->getNumArgOperands(); i++) {
            Value *V = InnerMost(CI->getArgOperand(i));
            addPatchAt(M, FT, V, MI, UniqPatchAt);
          }
        } else if (isa<InvokeInst>(MI)) {
          InvokeInst* CI = cast<InvokeInst>(MI);
          for (unsigned i = 0; i < CI->getNumArgOperands(); i++) {
            Value *V = InnerMost(CI->getArgOperand(i));
            addPatchAt(M, FT, V, MI, UniqPatchAt);
          }
        } else if (isa<ReturnInst>(MI)) {
          Value *V = cast<ReturnInst>(MI)->getReturnValue();
          if (V) {
            V = InnerMost(V);
            addPatchAt(M, FT, V, MI, UniqPatchAt);
          }
        } else if (isa<PHINode>(MI)) {
          for (unsigned i = 0; i < cast<PHINode>(MI)->getNumIncomingValues(); i++) {
            Value *V = InnerMost(cast<PHINode>(MI)->getIncomingValue(i));
            BasicBlock* BB = cast<PHINode>(MI)->getIncomingBlock(i);
            // right before the last (maybe terminator) instruction.
            addPatchAt(M, FT, V, &(BB->back()), UniqPatchAt);
          }
        }
      }
    }
  }

  // TODO: separate the following virtual table traversal code into another pass
  for (auto G = M.getGlobalList().begin(); G != M.getGlobalList().end(); G++) {
    if (isa<GlobalVariable>(G) &&
        cast<GlobalVariable>(G)->hasInitializer()) {
      const GlobalVariable *GV = cast<GlobalVariable>(G);
      const Constant *C = GV->getInitializer();
      if (GV->hasName() && isa<ConstantArray>(C) && GV->getName().startswith("_ZTV")) {
        std::string VTName = CXXDemangledName(GV->getName().data());
        if (VTName.size() && VTName.find("vtable") == 0) {
          //llvm::errs() << VTName << "\n";
          VTName = VTName.substr(11); // get pass "vtable for "
          llvm::NamedMDNode* MD = M.getOrInsertNamedMetadata("MCFIVtable");
          std::string info = VTName;
          for (unsigned i = 0; i < cast<ConstantArray>(C)->getNumOperands(); i++) {
            Value *V = InnerMost(cast<ConstantArray>(C)->getOperand(i));
            if (isa<Function>(V) && cast<Function>(V)->hasName()) {
              //llvm::errs() << cast<Function>(V)->getName() << "\n";
              info += std::string("#") + cast<Function>(V)->getName().str();
            }
          }
          MD->addOperand(llvm::MDNode::get(M.getContext(),
                                           llvm::MDString::get(
                                             M.getContext(), info.c_str())));
        }
      }
    }
  }
  return Changed;
}
예제 #7
0
파일: AliasAnalysis.cpp 프로젝트: Drup/llvm
/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
                                        const Location &Loc) {
  return canInstructionRangeModify(BB.front(), BB.back(), Loc);
}
예제 #8
0
bool ObjCARCContract::runOnFunction(Function &F) {
  if (!EnableARCOpts)
    return false;

  // If nothing in the Module uses ARC, don't do anything.
  if (!Run)
    return false;

  Changed = false;
  AA = &getAnalysis<AliasAnalysis>();
  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();

  PA.setAA(&getAnalysis<AliasAnalysis>());

  DEBUG(llvm::dbgs() << "**** ObjCARC Contract ****\n");

  // Track whether it's ok to mark objc_storeStrong calls with the "tail"
  // keyword. Be conservative if the function has variadic arguments.
  // It seems that functions which "return twice" are also unsafe for the
  // "tail" argument, because they are setjmp, which could need to
  // return to an earlier stack state.
  bool TailOkForStoreStrongs =
      !F.isVarArg() && !F.callsFunctionThatReturnsTwice();

  // For ObjC library calls which return their argument, replace uses of the
  // argument with uses of the call return value, if it dominates the use. This
  // reduces register pressure.
  SmallPtrSet<Instruction *, 4> DependingInstructions;
  SmallPtrSet<const BasicBlock *, 4> Visited;
  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E;) {
    Instruction *Inst = &*I++;

    DEBUG(dbgs() << "Visiting: " << *Inst << "\n");

    // First try to peephole Inst. If there is nothing further we can do in
    // terms of undoing objc-arc-expand, process the next inst.
    if (tryToPeepholeInstruction(F, Inst, I, DependingInstructions, Visited,
                                 TailOkForStoreStrongs))
      continue;

    // Otherwise, try to undo objc-arc-expand.

    // Don't use GetArgRCIdentityRoot because we don't want to look through bitcasts
    // and such; to do the replacement, the argument must have type i8*.
    Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);

    // TODO: Change this to a do-while.
    for (;;) {
      // If we're compiling bugpointed code, don't get in trouble.
      if (!isa<Instruction>(Arg) && !isa<Argument>(Arg))
        break;
      // Look through the uses of the pointer.
      for (Value::use_iterator UI = Arg->use_begin(), UE = Arg->use_end();
           UI != UE; ) {
        // Increment UI now, because we may unlink its element.
        Use &U = *UI++;
        unsigned OperandNo = U.getOperandNo();

        // If the call's return value dominates a use of the call's argument
        // value, rewrite the use to use the return value. We check for
        // reachability here because an unreachable call is considered to
        // trivially dominate itself, which would lead us to rewriting its
        // argument in terms of its return value, which would lead to
        // infinite loops in GetArgRCIdentityRoot.
        if (DT->isReachableFromEntry(U) && DT->dominates(Inst, U)) {
          Changed = true;
          Instruction *Replacement = Inst;
          Type *UseTy = U.get()->getType();
          if (PHINode *PHI = dyn_cast<PHINode>(U.getUser())) {
            // For PHI nodes, insert the bitcast in the predecessor block.
            unsigned ValNo = PHINode::getIncomingValueNumForOperand(OperandNo);
            BasicBlock *BB = PHI->getIncomingBlock(ValNo);
            if (Replacement->getType() != UseTy)
              Replacement = new BitCastInst(Replacement, UseTy, "",
                                            &BB->back());
            // While we're here, rewrite all edges for this PHI, rather
            // than just one use at a time, to minimize the number of
            // bitcasts we emit.
            for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
              if (PHI->getIncomingBlock(i) == BB) {
                // Keep the UI iterator valid.
                if (UI != UE &&
                    &PHI->getOperandUse(
                        PHINode::getOperandNumForIncomingValue(i)) == &*UI)
                  ++UI;
                PHI->setIncomingValue(i, Replacement);
              }
          } else {
            if (Replacement->getType() != UseTy)
              Replacement = new BitCastInst(Replacement, UseTy, "",
                                            cast<Instruction>(U.getUser()));
            U.set(Replacement);
          }
        }
      }

      // If Arg is a no-op casted pointer, strip one level of casts and iterate.
      if (const BitCastInst *BI = dyn_cast<BitCastInst>(Arg))
        Arg = BI->getOperand(0);
      else if (isa<GEPOperator>(Arg) &&
               cast<GEPOperator>(Arg)->hasAllZeroIndices())
        Arg = cast<GEPOperator>(Arg)->getPointerOperand();
      else if (isa<GlobalAlias>(Arg) &&
               !cast<GlobalAlias>(Arg)->mayBeOverridden())
        Arg = cast<GlobalAlias>(Arg)->getAliasee();
      else
        break;
    }
  }

  // If this function has no escaping allocas or suspicious vararg usage,
  // objc_storeStrong calls can be marked with the "tail" keyword.
  if (TailOkForStoreStrongs)
    for (CallInst *CI : StoreStrongCalls)
      CI->setTailCall();
  StoreStrongCalls.clear();

  return Changed;
}
예제 #9
0
set<Strator::StratorWorker::LockSet>& Strator::StratorWorker::traverseStatement(const Function& f, 
		const BasicBlock::const_iterator& inst,
		const Strator::StratorWorker::LockSet& entryLockSet,
		Strator::StratorWorker::LockSet lockSet){
//	cerr << "@: ";
//	llvm::errs() << *inst;
//	cerr << endl;
	//if (f.getName() == "queueDelete")
	//	printMultithreaded();
	if(stratorStatementMap.find(&(*inst)) == stratorStatementMap.end()){
		stratorStatementMap[&(*inst)] = new StratorStatement();
	}
	StratorStatement* sStmt= stratorStatementMap[&(*inst)];

	/// Check the statement cache, if the lockset is in the cache, don't analyze
	if(sStmt->statementCache.isInCache(entryLockSet, lockSet)){
		set<Strator::StratorWorker::LockSet>* emptySet = new set<Strator::StratorWorker::LockSet>();
		return *emptySet;
	}

	/// Otherwise add (entryLockSet, lockSet) to the cache
	sStmt->statementCache.addToCache(entryLockSet, lockSet);

	/// Terminator instructions for our analysis:
	/// Ret
	/// IndirectBr: Probably this is one such instruction for us,
	/// as we evaluate more systems, we'll see what happens if we use it
	if(inst->getOpcode() == Instruction::IndirectBr){
		printLocation(*inst);
		assert(false && "We hit an indirect branch\n");
	}

	if(inst->getOpcode() == Instruction::Ret){
		set<Strator::StratorWorker::LockSet>* returnSet = new set<Strator::StratorWorker::LockSet>();
		returnSet->insert(lockSet);
		return *returnSet;
	}

#undef DEBUG_TYPE
#define DEBUG_TYPE "strator-parval"
	if(inst->getOpcode() == Instruction::BitCast){
		DEBUG(errs() << *inst << " = " << *inst->getOperand(0) << "\n");
		parentValue[&*inst] = inst->getOperand(0);
	}

	vector<LockSet>* workingList = new vector<StratorWorker::LockSet>();

	/// TODO: What do we do with invoke?
	if(inst->getOpcode() == Instruction::Call) {
		const CallInst* callInst = dyn_cast<CallInst>(&(*inst));
		assert(callInst && "Call inst pointer is NULL!!!, this shouldn't have happened");
		Function* calledFunc = callInst->getCalledFunction();

		StratorFunction* sFunc = NULL;
		if(UpwardPropagationLevel != 0 ){
			sFunc = getStratorFunction(calledFunc);
			sFunc->currentCaller = &f;
		}

		/// Since we don't have a lock intrinsic or anything like that,
		/// we will discover locks and unlocks upon function calls.
		assert((((int)inst->getNumOperands())-1) >= 0 &&
				"Something wrong with the operands of call instruction");
		if(isMultiThreadedAPI(inst->getOperand(inst->getNumOperands() -1 ))){
			multithreadedFunctionMap[f.getName().str()] = true;
			/// Now check if we also want to propagete the "multithreadedness" to callers:
			/// If the called function is a thread-related function, then the parent function(s)
			/// are added to a a multithreadedAPI set depending on the propagation level which is
			/// checked in subsequent calls to isMultiThreadedAPI
			if(UpwardPropagationLevel != 0){
				/// move up to the parents of this call to mark all of them as multithreaded
				for(unsigned i=0; i<UpwardPropagationLevel; ++i){
					const Function* caller = sFunc->currentCaller;
					if(!caller)
						break;
					else {
						/// The upper level function becomes a multithreaded API, son any
						/// subsequent caller of such functions also become multithreaded.
						multithreadedAPISet.insert(caller);
						/// They also become multithreaded functions themselves
						multithreadedFunctionMap[caller->getName().str()] = true;
						sFunc = getStratorFunction(caller);
					}
				}
			}
		}

		if(calledFunc){
			if (isLock(calledFunc)){
				Lock l = getLockValue(&(*inst));

				if(PrintLockUnlock)
					cerr << "lock inst:" << l << endl;

				if(l)
					lockSet.insert(l);
			} else if (isUnLock(calledFunc)){
				Lock l = getLockValue(&(*inst));

				if(PrintLockUnlock)
					cerr << "unlock inst:" << l << endl;

				if(l)
					lockSet.erase(l);
			} else{
				bool atThreadCreationFunction = false;
				/// Now check if we have a resolved call, that is a direct function call
				/// We have a resolved function call
				if(isThreadCreationFunction(calledFunc->getName().str())) {
					/// If the created function is a thread creation function we
					/// need to find the worker function operand and traverse it
					atThreadCreationFunction = true;
					calledFunc = getThreadWorkerFunction(callInst);
				}

				/// Check if the current function is a multithreaded API
				if(multithreadedFunctionMap[f.getName().str()]){
					/// If so, the current callee also becomes multithreaded
					multithreadedFunctionMap[calledFunc->getName().str()] = true;
				}

#undef DEBUG_TYPE
#define DEBUG_TYPE "strator-parval"
				/// We pass some values to the called function, updating flow sensitive value map
				CallSite cs(const_cast<CallInst*>(callInst));
				Function::arg_iterator calleeIt;
				CallSite::arg_iterator callerIt;
				if(atThreadCreationFunction) {
					/// this is only supported for pthread right now
					assert(cs.arg_size() == 4 && "pthread_create should have 4 operands!");
					assert(calledFunc->arg_size() == 1 && "pthread thread worker function should have 1 operand");
					DEBUG(errs() << *calledFunc->arg_begin() << " = " <<  *cs.getArgument(3) << "\n");
					parentValue[calledFunc->arg_begin()] = cs.getArgument(3);
				}else{
					for (callerIt = cs.arg_begin(), calleeIt = calledFunc->arg_begin();
							callerIt != cs.arg_end() && calleeIt != calledFunc->arg_end();
							callerIt++, calleeIt++){
							DEBUG(errs() <<  *calleeIt << " = " << *(callerIt->get()) << "\n");
							parentValue[calleeIt] = callerIt->get();
					}
				}


				set<StratorWorker::LockSet>& functionLockSets = traverseFunction(*calledFunc, lockSet);
				/// Maybe the called function was multi threaded: If so, the caller becomes multi
				/// threaded from this point on if the following two lines are uncommented.
				/// However, this support adds a large number of false positives
				/*
          if(multithreadedFunctionMap[calledFunc->getName().str()])
          multithreadedFunctionMap[f.getName().str()] = true;
				 */
				/// arguments of callee are no longer valid, updating flow sensitive value map
				for (calleeIt = calledFunc->arg_begin(); calleeIt != calledFunc->arg_end(); calleeIt++){
					parentValue.erase(calleeIt);
				}

				workingList->insert(workingList->begin(), functionLockSets.begin(), functionLockSets.end());
			}
		} else {
			/// call is not resolved, process the lockset at hand as the working set
			workingList->insert(workingList->begin(), lockSet);
		}
	}

	/// TODO: We can leverage the llvm function onlyreadsmemory maybe? At least look at the code
	if(inst->getOpcode() == Instruction::Load || inst->getOpcode() == Instruction::Store){
		detectRaces(*inst, (inst->getOpcode() == Instruction::Store), lockSet);
	}

	/// If this is the last instruction of the current BB
	/// it means from here we have successor nodes in the control flow.
	set<StratorWorker::LockSet>* returnSet = new set<StratorWorker::LockSet>();
	BasicBlock* bb = const_cast<BasicBlock*>(inst->getParent());
	/// TODO: try to check for terminator instruction here
	vector<StratorWorker::LockSet>::iterator workingListLockset;

	if(workingList->size() > 0){
		if(&(bb->back()) == &(*inst)){
			for(workingListLockset = workingList->begin();
					workingListLockset != workingList->end(); ++workingListLockset)
				for(succ_iterator child = succ_begin(bb), end = succ_end(bb);
						child != end; ++child){
					BasicBlock::iterator firstInstr = child->begin();
					set<Strator::StratorWorker::LockSet>& statementLockSets = traverseStatement(f, firstInstr, entryLockSet, *workingListLockset);
					returnSet->insert(statementLockSets.begin(), statementLockSets.end());
				}
		} else{
			/// not the last instruction, simply instruction pointer to the next instruction
			BasicBlock::const_iterator nextInst = inst;
			++nextInst;
			for(workingListLockset = workingList->begin();
					workingListLockset != workingList->end(); ++workingListLockset){
				set<Strator::StratorWorker::LockSet>& statementLockSets = traverseStatement(f, nextInst, entryLockSet, *workingListLockset);
				returnSet->insert(statementLockSets.begin(), statementLockSets.end());
			}
		}
	} else{
		if(&(bb->back()) == &(*inst)){
			for(succ_iterator child = succ_begin(bb), end = succ_end(bb);
					child != end; ++child){
				BasicBlock::iterator firstInstr = child->begin();
				set<LockSet>& statementLockSets = traverseStatement(f, firstInstr, entryLockSet, lockSet);

				returnSet->insert(statementLockSets.begin(), statementLockSets.end());
			}
		} else{
			BasicBlock::const_iterator nextInst = inst;
			++nextInst;
			set<Strator::StratorWorker::LockSet>& statementLockSets = traverseStatement(f, nextInst, entryLockSet, lockSet);

			returnSet->insert(statementLockSets.begin(), statementLockSets.end());
		}
	}

	return *returnSet;
}
예제 #10
0
bool ObjCARCContract::runOnFunction(Function &F) {
  if (!EnableARCOpts)
    return false;

  // If nothing in the Module uses ARC, don't do anything.
  if (!Run)
    return false;

  Changed = false;
  AA = &getAnalysis<AliasAnalysis>();
  DT = &getAnalysis<DominatorTree>();

  PA.setAA(&getAnalysis<AliasAnalysis>());

  // Track whether it's ok to mark objc_storeStrong calls with the "tail"
  // keyword. Be conservative if the function has variadic arguments.
  // It seems that functions which "return twice" are also unsafe for the
  // "tail" argument, because they are setjmp, which could need to
  // return to an earlier stack state.
  bool TailOkForStoreStrongs = !F.isVarArg() &&
                               !F.callsFunctionThatReturnsTwice();

  // For ObjC library calls which return their argument, replace uses of the
  // argument with uses of the call return value, if it dominates the use. This
  // reduces register pressure.
  SmallPtrSet<Instruction *, 4> DependingInstructions;
  SmallPtrSet<const BasicBlock *, 4> Visited;
  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
    Instruction *Inst = &*I++;

    DEBUG(dbgs() << "ObjCARCContract: Visiting: " << *Inst << "\n");

    // Only these library routines return their argument. In particular,
    // objc_retainBlock does not necessarily return its argument.
    InstructionClass Class = GetBasicInstructionClass(Inst);
    switch (Class) {
    case IC_Retain:
    case IC_FusedRetainAutorelease:
    case IC_FusedRetainAutoreleaseRV:
      break;
    case IC_Autorelease:
    case IC_AutoreleaseRV:
      if (ContractAutorelease(F, Inst, Class, DependingInstructions, Visited))
        continue;
      break;
    case IC_RetainRV: {
      // If we're compiling for a target which needs a special inline-asm
      // marker to do the retainAutoreleasedReturnValue optimization,
      // insert it now.
      if (!RetainRVMarker)
        break;
      BasicBlock::iterator BBI = Inst;
      BasicBlock *InstParent = Inst->getParent();

      // Step up to see if the call immediately precedes the RetainRV call.
      // If it's an invoke, we have to cross a block boundary. And we have
      // to carefully dodge no-op instructions.
      do {
        if (&*BBI == InstParent->begin()) {
          BasicBlock *Pred = InstParent->getSinglePredecessor();
          if (!Pred)
            goto decline_rv_optimization;
          BBI = Pred->getTerminator();
          break;
        }
        --BBI;
      } while (IsNoopInstruction(BBI));

      if (&*BBI == GetObjCArg(Inst)) {
        DEBUG(dbgs() << "ObjCARCContract: Adding inline asm marker for "
                        "retainAutoreleasedReturnValue optimization.\n");
        Changed = true;
        InlineAsm *IA =
          InlineAsm::get(FunctionType::get(Type::getVoidTy(Inst->getContext()),
                                           /*isVarArg=*/false),
                         RetainRVMarker->getString(),
                         /*Constraints=*/"", /*hasSideEffects=*/true);
        CallInst::Create(IA, "", Inst);
      }
    decline_rv_optimization:
      break;
    }
    case IC_InitWeak: {
      // objc_initWeak(p, null) => *p = null
      CallInst *CI = cast<CallInst>(Inst);
      if (IsNullOrUndef(CI->getArgOperand(1))) {
        Value *Null =
          ConstantPointerNull::get(cast<PointerType>(CI->getType()));
        Changed = true;
        new StoreInst(Null, CI->getArgOperand(0), CI);

        DEBUG(dbgs() << "OBJCARCContract: Old = " << *CI << "\n"
                     << "                 New = " << *Null << "\n");

        CI->replaceAllUsesWith(Null);
        CI->eraseFromParent();
      }
      continue;
    }
    case IC_Release:
      ContractRelease(Inst, I);
      continue;
    case IC_User:
      // Be conservative if the function has any alloca instructions.
      // Technically we only care about escaping alloca instructions,
      // but this is sufficient to handle some interesting cases.
      if (isa<AllocaInst>(Inst))
        TailOkForStoreStrongs = false;
      continue;
    case IC_IntrinsicUser:
      // Remove calls to @clang.arc.use(...).
      Inst->eraseFromParent();
      continue;
    default:
      continue;
    }

    DEBUG(dbgs() << "ObjCARCContract: Finished List.\n\n");

    // Don't use GetObjCArg because we don't want to look through bitcasts
    // and such; to do the replacement, the argument must have type i8*.
    const Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);
    for (;;) {
      // If we're compiling bugpointed code, don't get in trouble.
      if (!isa<Instruction>(Arg) && !isa<Argument>(Arg))
        break;
      // Look through the uses of the pointer.
      for (Value::const_use_iterator UI = Arg->use_begin(), UE = Arg->use_end();
           UI != UE; ) {
        Use &U = UI.getUse();
        unsigned OperandNo = UI.getOperandNo();
        ++UI; // Increment UI now, because we may unlink its element.

        // If the call's return value dominates a use of the call's argument
        // value, rewrite the use to use the return value. We check for
        // reachability here because an unreachable call is considered to
        // trivially dominate itself, which would lead us to rewriting its
        // argument in terms of its return value, which would lead to
        // infinite loops in GetObjCArg.
        if (DT->isReachableFromEntry(U) && DT->dominates(Inst, U)) {
          Changed = true;
          Instruction *Replacement = Inst;
          Type *UseTy = U.get()->getType();
          if (PHINode *PHI = dyn_cast<PHINode>(U.getUser())) {
            // For PHI nodes, insert the bitcast in the predecessor block.
            unsigned ValNo = PHINode::getIncomingValueNumForOperand(OperandNo);
            BasicBlock *BB = PHI->getIncomingBlock(ValNo);
            if (Replacement->getType() != UseTy)
              Replacement = new BitCastInst(Replacement, UseTy, "",
                                            &BB->back());
            // While we're here, rewrite all edges for this PHI, rather
            // than just one use at a time, to minimize the number of
            // bitcasts we emit.
            for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
              if (PHI->getIncomingBlock(i) == BB) {
                // Keep the UI iterator valid.
                if (&PHI->getOperandUse(
                      PHINode::getOperandNumForIncomingValue(i)) ==
                    &UI.getUse())
                  ++UI;
                PHI->setIncomingValue(i, Replacement);
              }
          } else {
            if (Replacement->getType() != UseTy)
              Replacement = new BitCastInst(Replacement, UseTy, "",
                                            cast<Instruction>(U.getUser()));
            U.set(Replacement);
          }
        }
      }

      // If Arg is a no-op casted pointer, strip one level of casts and iterate.
      if (const BitCastInst *BI = dyn_cast<BitCastInst>(Arg))
        Arg = BI->getOperand(0);
      else if (isa<GEPOperator>(Arg) &&
               cast<GEPOperator>(Arg)->hasAllZeroIndices())
        Arg = cast<GEPOperator>(Arg)->getPointerOperand();
      else if (isa<GlobalAlias>(Arg) &&
               !cast<GlobalAlias>(Arg)->mayBeOverridden())
        Arg = cast<GlobalAlias>(Arg)->getAliasee();
      else
        break;
    }
  }

  // If this function has no escaping allocas or suspicious vararg usage,
  // objc_storeStrong calls can be marked with the "tail" keyword.
  if (TailOkForStoreStrongs)
    for (SmallPtrSet<CallInst *, 8>::iterator I = StoreStrongCalls.begin(),
         E = StoreStrongCalls.end(); I != E; ++I)
      (*I)->setTailCall();
  StoreStrongCalls.clear();

  return Changed;
}
예제 #11
0
bool ObjCARCContract::runOnFunction(Function &F) {
  if (!EnableARCOpts)
    return false;

  // If nothing in the Module uses ARC, don't do anything.
  if (!Run)
    return false;

  Changed = false;
  AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();

  PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());

  DenseMap<BasicBlock *, ColorVector> BlockColors;
  if (F.hasPersonalityFn() &&
      isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
    BlockColors = colorEHFunclets(F);

  LLVM_DEBUG(llvm::dbgs() << "**** ObjCARC Contract ****\n");

  // Track whether it's ok to mark objc_storeStrong calls with the "tail"
  // keyword. Be conservative if the function has variadic arguments.
  // It seems that functions which "return twice" are also unsafe for the
  // "tail" argument, because they are setjmp, which could need to
  // return to an earlier stack state.
  bool TailOkForStoreStrongs =
      !F.isVarArg() && !F.callsFunctionThatReturnsTwice();

  // For ObjC library calls which return their argument, replace uses of the
  // argument with uses of the call return value, if it dominates the use. This
  // reduces register pressure.
  SmallPtrSet<Instruction *, 4> DependingInstructions;
  SmallPtrSet<const BasicBlock *, 4> Visited;
  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E;) {
    Instruction *Inst = &*I++;

    LLVM_DEBUG(dbgs() << "Visiting: " << *Inst << "\n");

    // First try to peephole Inst. If there is nothing further we can do in
    // terms of undoing objc-arc-expand, process the next inst.
    if (tryToPeepholeInstruction(F, Inst, I, DependingInstructions, Visited,
                                 TailOkForStoreStrongs, BlockColors))
      continue;

    // Otherwise, try to undo objc-arc-expand.

    // Don't use GetArgRCIdentityRoot because we don't want to look through bitcasts
    // and such; to do the replacement, the argument must have type i8*.

    // Function for replacing uses of Arg dominated by Inst.
    auto ReplaceArgUses = [Inst, this](Value *Arg) {
      // If we're compiling bugpointed code, don't get in trouble.
      if (!isa<Instruction>(Arg) && !isa<Argument>(Arg))
        return;

      // Look through the uses of the pointer.
      for (Value::use_iterator UI = Arg->use_begin(), UE = Arg->use_end();
           UI != UE; ) {
        // Increment UI now, because we may unlink its element.
        Use &U = *UI++;
        unsigned OperandNo = U.getOperandNo();

        // If the call's return value dominates a use of the call's argument
        // value, rewrite the use to use the return value. We check for
        // reachability here because an unreachable call is considered to
        // trivially dominate itself, which would lead us to rewriting its
        // argument in terms of its return value, which would lead to
        // infinite loops in GetArgRCIdentityRoot.
        if (!DT->isReachableFromEntry(U) || !DT->dominates(Inst, U))
          continue;

        Changed = true;
        Instruction *Replacement = Inst;
        Type *UseTy = U.get()->getType();
        if (PHINode *PHI = dyn_cast<PHINode>(U.getUser())) {
          // For PHI nodes, insert the bitcast in the predecessor block.
          unsigned ValNo = PHINode::getIncomingValueNumForOperand(OperandNo);
          BasicBlock *IncomingBB = PHI->getIncomingBlock(ValNo);
          if (Replacement->getType() != UseTy) {
            // A catchswitch is both a pad and a terminator, meaning a basic
            // block with a catchswitch has no insertion point. Keep going up
            // the dominator tree until we find a non-catchswitch.
            BasicBlock *InsertBB = IncomingBB;
            while (isa<CatchSwitchInst>(InsertBB->getFirstNonPHI())) {
              InsertBB = DT->getNode(InsertBB)->getIDom()->getBlock();
            }

            assert(DT->dominates(Inst, &InsertBB->back()) &&
                   "Invalid insertion point for bitcast");
            Replacement =
                new BitCastInst(Replacement, UseTy, "", &InsertBB->back());
          }

          // While we're here, rewrite all edges for this PHI, rather
          // than just one use at a time, to minimize the number of
          // bitcasts we emit.
          for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i)
            if (PHI->getIncomingBlock(i) == IncomingBB) {
              // Keep the UI iterator valid.
              if (UI != UE &&
                  &PHI->getOperandUse(
                      PHINode::getOperandNumForIncomingValue(i)) == &*UI)
                ++UI;
              PHI->setIncomingValue(i, Replacement);
            }
        } else {
          if (Replacement->getType() != UseTy)
            Replacement = new BitCastInst(Replacement, UseTy, "",
                                          cast<Instruction>(U.getUser()));
          U.set(Replacement);
        }
      }
    };


    Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);
    Value *OrigArg = Arg;

    // TODO: Change this to a do-while.
    for (;;) {
      ReplaceArgUses(Arg);

      // If Arg is a no-op casted pointer, strip one level of casts and iterate.
      if (const BitCastInst *BI = dyn_cast<BitCastInst>(Arg))
        Arg = BI->getOperand(0);
      else if (isa<GEPOperator>(Arg) &&
               cast<GEPOperator>(Arg)->hasAllZeroIndices())
        Arg = cast<GEPOperator>(Arg)->getPointerOperand();
      else if (isa<GlobalAlias>(Arg) &&
               !cast<GlobalAlias>(Arg)->isInterposable())
        Arg = cast<GlobalAlias>(Arg)->getAliasee();
      else {
        // If Arg is a PHI node, get PHIs that are equivalent to it and replace
        // their uses.
        if (PHINode *PN = dyn_cast<PHINode>(Arg)) {
          SmallVector<Value *, 1> PHIList;
          getEquivalentPHIs(*PN, PHIList);
          for (Value *PHI : PHIList)
            ReplaceArgUses(PHI);
        }
        break;
      }
    }

    // Replace bitcast users of Arg that are dominated by Inst.
    SmallVector<BitCastInst *, 2> BitCastUsers;

    // Add all bitcast users of the function argument first.
    for (User *U : OrigArg->users())
      if (auto *BC = dyn_cast<BitCastInst>(U))
        BitCastUsers.push_back(BC);

    // Replace the bitcasts with the call return. Iterate until list is empty.
    while (!BitCastUsers.empty()) {
      auto *BC = BitCastUsers.pop_back_val();
      for (User *U : BC->users())
        if (auto *B = dyn_cast<BitCastInst>(U))
          BitCastUsers.push_back(B);

      ReplaceArgUses(BC);
    }
  }

  // If this function has no escaping allocas or suspicious vararg usage,
  // objc_storeStrong calls can be marked with the "tail" keyword.
  if (TailOkForStoreStrongs)
    for (CallInst *CI : StoreStrongCalls)
      CI->setTailCall();
  StoreStrongCalls.clear();

  return Changed;
}
예제 #12
0
/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
                                        const Value *Ptr, unsigned Size) {
  return canInstructionRangeModify(BB.front(), BB.back(), Ptr, Size);
}
예제 #13
0
std::vector<SetOfFormulasPtr>
FaultLocalization::allDiagnosis(Formula *TF,
                                 std::vector<ProgramTrace*> traces,
                                 YicesSolver *yices) {
    std::vector<SetOfFormulasPtr> MCSes;
    int progress = 0;
    int total = traces.size();
    // Working formula
    Formula *WF = new Formula(TF);
    // For each E in WF, E tagged as soft do
    unsigned z = 0;
    std::vector<BoolVarExprPtr> AV;
    std::map<BoolVarExprPtr, ExprPtr> AVMap;
    std::vector<ExprPtr> clauses = WF->getExprs();
    for(ExprPtr e : clauses) {
        if (e->isSoft()) {
            // AI is a new auxiliary var. created
            std::ostringstream oss;
            oss << z++;
            BoolVarExprPtr ai = Expression::mkBoolVar("a_"+oss.str());
            ai->setInstruction(e->getInstruction());
            ai->setLine(e->getLine());
            AV.push_back(ai);
            AVMap[ai] = e;
            ExprPtr notai = Expression::mkNot(ai);
            //notai->setWeight(e->getWeight());
            notai->setLine(e->getLine());
            notai->setSoft();
            WF->add(notai);
            // Remove E and add EA as hard
            ExprPtr ea = Expression::mkOr(e, ai);
            WF->remove(e);
            ea->setHard();
            WF->add(ea);
        }
    }
    if (AV.empty()) {
        delete WF;
        std::cout << "No MaxSMT solution!\n";
        if (options->verbose()) {
            std::cout << "==============================================\n";
        }
        return MCSes;
    }
    yices->init();
    yices->addToContext(WF);
    for(ProgramTrace *E : traces) {
        if (options->verbose()) {
            displayProgressBar(progress, total);
        }
        // At this point there is only WF in the context
        yices->push();
        // Assert as hard the error-inducing input formula
        ExprPtr eiExpr = E->getProgramInputsFormula(TF);
        eiExpr->setHard();
        yices->addToContext(eiExpr);
        if (options->dbgMsg()) {
            std::cout << "-- Error-inducing Input: ";
            eiExpr->dump();
            std::cout << std::endl;
        }
        // Assert as hard the golden output (if any)
        // (= return_var golden_output)
        Value *goldenOutput = E->getExpectedOutput();
        if (goldenOutput) {
            BasicBlock *lastBB = &targetFun->back();
            Instruction *lastInst = &lastBB->back();
            if (ReturnInst *ret= dyn_cast<ReturnInst>(lastInst)) {
                Value *retVal = ret->getReturnValue();
                if (retVal) {
                    ExprPtr retExpr = Expression::getExprFromValue(retVal);
                    ExprPtr goExpr = Expression::getExprFromValue(goldenOutput);
                    ExprPtr eqExpr = Expression::mkEq(retExpr, goExpr);
                    eqExpr->setHard();
                    yices->addToContext(eqExpr);
                    if (options->dbgMsg()) {
                        std::cout << "-- Golden ouput: ";
                        eqExpr->dump();
                        std::cout << std::endl;
                    }
                }
            }
        }
        // Compute a MCS
        SetOfFormulasPtr M = allMinMCS(yices, AV, AVMap);
        if (!M->empty()) {
            SetOfFormulasPtr M2 = avToClauses(M, AVMap);
            MCSes.push_back(M2);
            if (options->printMCS()) {
                std::cout << "\n" << M2 << "\n" << std::endl;
            }
        } else {
            //if (options->verbose() || options->dbgMsg()) {
                std::cout << "Empty MCS!\n";
            //}
        }
        // Backtrack to the point where there
        // was no Pre/Post-conditions in the formula
        yices->pop();
        // Progress bar
        progress++;
    }
    yices->clean();
    delete WF;
    if (options->verbose()) {
        displayProgressBar(progress, total);
        std::cout << std::endl;
    }
    return MCSes;
}
예제 #14
0
/// [LIBUNWIND] Find the (possibly absent) call to @llvm.eh.selector
/// in the given landing pad.  In principle, llvm.eh.exception is
/// required to be in the landing pad; in practice, SplitCriticalEdge
/// can break that invariant, and then inlining can break it further.
/// There's a real need for a reliable solution here, but until that
/// happens, we have some fragile workarounds here.
static EHSelectorInst *findSelectorForLandingPad(BasicBlock *lpad) {
  // Look for an exception call in the actual landing pad.
  EHExceptionInst *exn = findExceptionInBlock(lpad);
  if (exn) return findSelectorForException(exn);

  // Okay, if that failed, look for one in an obvious successor.  If
  // we find one, we'll fix the IR by moving things back to the
  // landing pad.

  bool dominates = true; // does the lpad dominate the exn call
  BasicBlock *nonDominated = 0; // if not, the first non-dominated block
  BasicBlock *lastDominated = 0; // and the block which branched to it

  BasicBlock *exnBlock = lpad;

  // We need to protect against lpads that lead into infinite loops.
  SmallPtrSet<BasicBlock*,4> visited;
  visited.insert(exnBlock);

  do {
    // We're not going to apply this hack to anything more complicated
    // than a series of unconditional branches, so if the block
    // doesn't terminate in an unconditional branch, just fail.  More
    // complicated cases can arise when, say, sinking a call into a
    // split unwind edge and then inlining it; but that can do almost
    // *anything* to the CFG, including leaving the selector
    // completely unreachable.  The only way to fix that properly is
    // to (1) prohibit transforms which move the exception or selector
    // values away from the landing pad, e.g. by producing them with
    // instructions that are pinned to an edge like a phi, or
    // producing them with not-really-instructions, and (2) making
    // transforms which split edges deal with that.
    BranchInst *branch = dyn_cast<BranchInst>(&exnBlock->back());
    if (!branch || branch->isConditional()) return 0;

    BasicBlock *successor = branch->getSuccessor(0);

    // Fail if we found an infinite loop.
    if (!visited.insert(successor)) return 0;

    // If the successor isn't dominated by exnBlock:
    if (!successor->getSinglePredecessor()) {
      // We don't want to have to deal with threading the exception
      // through multiple levels of phi, so give up if we've already
      // followed a non-dominating edge.
      if (!dominates) return 0;

      // Otherwise, remember this as a non-dominating edge.
      dominates = false;
      nonDominated = successor;
      lastDominated = exnBlock;
    }

    exnBlock = successor;

    // Can we stop here?
    exn = findExceptionInBlock(exnBlock);
  } while (!exn);

  // Look for a selector call for the exception we found.
  EHSelectorInst *selector = findSelectorForException(exn);
  if (!selector) return 0;

  // The easy case is when the landing pad still dominates the
  // exception call, in which case we can just move both calls back to
  // the landing pad.
  if (dominates) {
    selector->moveBefore(lpad->getFirstNonPHI());
    exn->moveBefore(selector);
    return selector;
  }

  // Otherwise, we have to split at the first non-dominating block.
  // The CFG looks basically like this:
  //    lpad:
  //      phis_0
  //      insnsAndBranches_1
  //      br label %nonDominated
  //    nonDominated:
  //      phis_2
  //      insns_3
  //      %exn = call i8* @llvm.eh.exception()
  //      insnsAndBranches_4
  //      %selector = call @llvm.eh.selector(i8* %exn, ...
  // We need to turn this into:
  //    lpad:
  //      phis_0
  //      %exn0 = call i8* @llvm.eh.exception()
  //      %selector0 = call @llvm.eh.selector(i8* %exn0, ...
  //      insnsAndBranches_1
  //      br label %split // from lastDominated
  //    nonDominated:
  //      phis_2 (without edge from lastDominated)
  //      %exn1 = call i8* @llvm.eh.exception()
  //      %selector1 = call i8* @llvm.eh.selector(i8* %exn1, ...
  //      br label %split
  //    split:
  //      phis_2 (edge from lastDominated, edge from split)
  //      %exn = phi ...
  //      %selector = phi ...
  //      insns_3
  //      insnsAndBranches_4

  assert(nonDominated);
  assert(lastDominated);

  // First, make clones of the intrinsics to go in lpad.
  EHExceptionInst *lpadExn = cast<EHExceptionInst>(exn->clone());
  EHSelectorInst *lpadSelector = cast<EHSelectorInst>(selector->clone());
  lpadSelector->setArgOperand(0, lpadExn);
  lpadSelector->insertBefore(lpad->getFirstNonPHI());
  lpadExn->insertBefore(lpadSelector);

  // Split the non-dominated block.
  BasicBlock *split =
    nonDominated->splitBasicBlock(nonDominated->getFirstNonPHI(),
                                  nonDominated->getName() + ".lpad-fix");

  // Redirect the last dominated branch there.
  cast<BranchInst>(lastDominated->back()).setSuccessor(0, split);

  // Move the existing intrinsics to the end of the old block.
  selector->moveBefore(&nonDominated->back());
  exn->moveBefore(selector);

  Instruction *splitIP = &split->front();

  // For all the phis in nonDominated, make a new phi in split to join
  // that phi with the edge from lastDominated.
  for (BasicBlock::iterator
         i = nonDominated->begin(), e = nonDominated->end(); i != e; ++i) {
    PHINode *phi = dyn_cast<PHINode>(i);
    if (!phi) break;

    PHINode *splitPhi = PHINode::Create(phi->getType(), 2, phi->getName(),
                                        splitIP);
    phi->replaceAllUsesWith(splitPhi);
    splitPhi->addIncoming(phi, nonDominated);
    splitPhi->addIncoming(phi->removeIncomingValue(lastDominated),
                          lastDominated);
  }

  // Make new phis for the exception and selector.
  PHINode *exnPhi = PHINode::Create(exn->getType(), 2, "", splitIP);
  exn->replaceAllUsesWith(exnPhi);
  selector->setArgOperand(0, exn); // except for this use
  exnPhi->addIncoming(exn, nonDominated);
  exnPhi->addIncoming(lpadExn, lastDominated);

  PHINode *selectorPhi = PHINode::Create(selector->getType(), 2, "", splitIP);
  selector->replaceAllUsesWith(selectorPhi);
  selectorPhi->addIncoming(selector, nonDominated);
  selectorPhi->addIncoming(lpadSelector, lastDominated);

  return lpadSelector;
}
예제 #15
0
bool LoopRegionDump::visitLoop(Loop *L, Module *mod) {
  // Ensure we are working only on outermost loops
  if (L->getLoopDepth() > 1)
    return false;

  // Get the function we are in
  Function *currFunc = L->getHeader()->getParent();

  // Are we in an isolated Region
  std::size_t found = currFunc->getName().find("__cere__");
  if (found == std::string::npos)
    return false;

  // If we want to dump a particular region, look if it's this one
  if (!GlobalDump && RegionToDump != currFunc->getName()) {
    return false;
  } else if (ReadFromFile) {
    if (!(std::find(RegionsToDump.begin(), RegionsToDump.end(),
                    currFunc->getName()) != RegionsToDump.end()))
      return false;
  }
  // Create dump function
  Function *func_dump = mod->getFunction("dump");
  if (!func_dump) { // If function "dump" not found, creates it
    FunctionType *DumpFuncTy = createDumpFunctionType(mod);
    func_dump =
        Function::Create(DumpFuncTy, GlobalValue::ExternalLinkage, "dump", mod);
  }

  // Create after_dump function
  Function *func_after_dump = mod->getFunction("after_dump");
  if (!func_after_dump) { // If function "after_dump" not found, creates it
    // Create a void type
    std::vector<Type *> FuncTy_12_args;
    FunctionType *AfterDumpFuncTy = FunctionType::get(
        /*Result=*/Type::getVoidTy(mod->getContext()),
        /*Params=*/FuncTy_12_args,
        /*isVarArg=*/false);
    func_after_dump = Function::Create(
        AfterDumpFuncTy, GlobalValue::ExternalLinkage, "after_dump", mod);
  }
  // Get predecessor loop basic block
  BasicBlock *PredBB = L->getLoopPredecessor();
  // Get all exit blocks
  SmallVector<BasicBlock *, 8> exitblocks;
  L->getExitBlocks(exitblocks);

  if (PredBB == NULL || exitblocks.size() == 0)
    return false;

  ++RegionCounter;
  // Create arguments for the dump function
  std::vector<Value *> funcParameter =
      createDumpFunctionParameters(mod, currFunc, PredBB, InvocationToDump);

  // Call dump function just before the region
  CallInst::Create(func_dump, funcParameter, "", &PredBB->back());
  // Call after dump in each exit blocks
  for (SmallVectorImpl<BasicBlock *>::iterator I = exitblocks.begin(),
                                               E = exitblocks.end();
       I != E; ++I) {
    CallInst::Create(func_after_dump, "", &(*I)->front());
  }

  return true;
}