コード例 #1
0
/// Remove redundant runtime calls for stack allocated buffers.
/// If a buffer is allocated on the stack it's not needed to explicitly set
/// the RC_DEALLOCATING_FLAG flag (except there is code which may depend on it).
/// Also the a call to swift_deallocClassInstance (which stems from an inlined
/// deallocator) is not needed.
///
///   %0 = alloca
///     ...
///   call @swift_setDeallocating(%0) // not needed
///     // code which does not depend on the RC_DEALLOCATING_FLAG flag.
///   call @swift_deallocClassInstance(%0) // not needed
///   call @llvm.lifetime.end(%0)
///
static void removeRedundantRTCalls(CallInst *DeallocCall) {
  BasicBlock::iterator Iter(DeallocCall);
  BasicBlock::iterator Begin = DeallocCall->getParent()->begin();
  Value *Buffer = DeallocCall->getArgOperand(0);
  CallInst *RedundantDealloc = nullptr;
  CallInst *RedundantSetFlag = nullptr;
  SmallVector<Instruction *, 2> ToDelete;
  while (Iter != Begin) {
    --Iter;
    Instruction *I = &*Iter;
    if (auto *CI = dyn_cast<CallInst>(I)) {

      // Check if we have a runtime function with the buffer as argument.
      if (CI->getNumArgOperands() < 1)
        break;
      if (CI->getArgOperand(0)->stripPointerCasts() != Buffer)
        break;
      auto *Callee = dyn_cast<Constant>(CI->getCalledValue());
      if (!Callee)
        break;

      // The callee function my be a bitcast constant expression.
      if (auto *U = dyn_cast<ConstantExpr>(Callee)) {
        if (U->getOpcode() == Instruction::BitCast)
          Callee = U->getOperand(0);
      }
      auto *RTFunc = dyn_cast<Function>(Callee);
      if (!RTFunc)
        break;

      if (RTFunc->getName() == "swift_setDeallocating") {
        assert(RedundantDealloc && "dealloc call must follow setDeallocating");
        assert(!RedundantSetFlag && "multiple setDeallocating calls");
        RedundantSetFlag = CI;
        continue;
      }
      if (RTFunc->getName() == "swift_deallocClassInstance") {
        assert(!RedundantSetFlag && "dealloc call must follow setDeallocating");
        assert(!RedundantDealloc && "multiple deallocClassInstance calls");
        RedundantDealloc = CI;
        continue;
      }
      break;
    }
    // Bail if we have an instruction which may read the RC_DEALLOCATING_FLAG
    // flag.
    if (I->mayReadFromMemory())
      break;
  }
  if (RedundantDealloc)
    RedundantDealloc->eraseFromParent();
  if (RedundantSetFlag)
    RedundantSetFlag->eraseFromParent();
}
コード例 #2
0
bool LowerExpectIntrinsic::runOnFunction(Function &F) {
  for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
    BasicBlock *BB = I++;

    // Create "block_weights" metadata.
    if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
      if (HandleIfExpect(BI))
        IfHandled++;
    } else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
      if (HandleSwitchExpect(SI))
        IfHandled++;
    }

    // remove llvm.expect intrinsics.
    for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
         BI != BE; ) {
      CallInst *CI = dyn_cast<CallInst>(BI++);
      if (!CI)
        continue;

      Function *Fn = CI->getCalledFunction();
      if (Fn && Fn->getIntrinsicID() == Intrinsic::expect) {
        Value *Exp = CI->getArgOperand(0);
        CI->replaceAllUsesWith(Exp);
        CI->eraseFromParent();
      }
    }
  }

  return false;
}
コード例 #3
0
ファイル: LowerSetJmp.cpp プロジェクト: Killfrra/llvm-kernel
// visitCallInst - This converts all LLVM call instructions into invoke
// instructions. The except part of the invoke goes to the "LongJmpBlkPre"
// that grabs the exception and proceeds to determine if it's a longjmp
// exception or not.
void LowerSetJmp::visitCallInst(CallInst& CI)
{
  if (CI.getCalledFunction())
    if (!IsTransformableFunction(CI.getCalledFunction()->getName()) ||
        CI.getCalledFunction()->isIntrinsic()) return;

  BasicBlock* OldBB = CI.getParent();

  // If not reachable from a setjmp call, don't transform.
  if (!DFSBlocks.count(OldBB)) return;

  BasicBlock* NewBB = OldBB->splitBasicBlock(CI);
  assert(NewBB && "Couldn't split BB of \"call\" instruction!!");
  DFSBlocks.insert(NewBB);
  NewBB->setName("Call2Invoke");

  Function* Func = OldBB->getParent();

  // Construct the new "invoke" instruction.
  TerminatorInst* Term = OldBB->getTerminator();
  std::vector<Value*> Params(CI.op_begin() + 1, CI.op_end());
  InvokeInst* II =
    InvokeInst::Create(CI.getCalledValue(), NewBB, PrelimBBMap[Func],
                       Params.begin(), Params.end(), CI.getName(), Term);
  II->setCallingConv(CI.getCallingConv());
  II->setAttributes(CI.getAttributes());

  // Replace the old call inst with the invoke inst and remove the call.
  CI.replaceAllUsesWith(II);
  CI.eraseFromParent();

  // The old terminator is useless now that we have the invoke inst.
  Term->eraseFromParent();
  ++CallsTransformed;
}
コード例 #4
0
bool OptimizeFastMemoryChecks::runOnFunction(Function &F) {
  ABA = &getAnalysis<ArrayBoundsAnalysis>();
  MSCI = &getAnalysis<MSCInfo>();

  // Visit all call instructions in the function to find the checks.
  visit(F);

  for (size_t i = 0, N = FastCheckCalls.size(); i < N; ++i) {
    CallInst *CI = FastCheckCalls[i];
    CheckInfoType *Info = MSCI->getCheckInfo(CI->getCalledFunction());
    assert(Info && Info->isFastMemoryCheck() && "expecting fast memory checks");

    Value *AccessPtr = CI->getArgOperand(Info->PtrArgNo);
    Value *AccessSize = CI->getArgOperand(Info->SizeArgNo);
    Value *ObjectPtr = CI->getArgOperand(Info->ObjArgNo);
    Value *ObjectSize = CI->getArgOperand(Info->ObjSizeArgNo);
    if (ABA->isAlwaysInBounds(AccessPtr, AccessSize, ObjectPtr, ObjectSize)) {
      CI->eraseFromParent();
      ++FastMemoryChecksRemoved;
    }
  }

  bool ChangedAnything = !FastCheckCalls.empty();
  FastCheckCalls.clear();
  return ChangedAnything;
}
コード例 #5
0
ファイル: StripSymbols.cpp プロジェクト: jyasskin/llvm-mirror
// StripDebugInfo - Strip debug info in the module if it exists.  
// To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and 
// llvm.dbg.region.end calls, and any globals they point to if now dead.
static bool StripDebugInfo(Module &M) {

  bool Changed = false;

  // Remove all of the calls to the debugger intrinsics, and remove them from
  // the module.
  if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      CI->eraseFromParent();
    }
    Declare->eraseFromParent();
    Changed = true;
  }

  if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
    while (!DbgVal->use_empty()) {
      CallInst *CI = cast<CallInst>(DbgVal->use_back());
      CI->eraseFromParent();
    }
    DbgVal->eraseFromParent();
    Changed = true;
  }

  for (Module::named_metadata_iterator NMI = M.named_metadata_begin(),
         NME = M.named_metadata_end(); NMI != NME;) {
    NamedMDNode *NMD = NMI;
    ++NMI;
    if (NMD->getName().startswith("llvm.dbg.")) {
      NMD->eraseFromParent();
      Changed = true;
    }
  }

  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE;
         ++FI)
      for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE;
           ++BI) {
        if (!BI->getDebugLoc().isUnknown()) {
          Changed = true;
          BI->setDebugLoc(DebugLoc());
        }
      }

  return Changed;
}
コード例 #6
0
/**
 * removeUndefCalls -- remove calls with undef function
 *
 * These are irrelevant to the code, so may be removed completely.
 */
void FunctionStaticSlicer::removeUndefCalls(ModulePass *MP, Function &F) {
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E;) {
    CallInst *CI = dyn_cast<CallInst>(&*I);
    ++I;
    if (CI && isa<UndefValue>(CI->getCalledValue())) {
      CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
      CI->eraseFromParent();
    }
  }
}
コード例 #7
0
static bool ExpandOpForIntSize(Module *M, unsigned Bits, bool Mul) {
  IntegerType *IntTy = IntegerType::get(M->getContext(), Bits);
  SmallVector<Type *, 1> Types;
  Types.push_back(IntTy);
  Intrinsic::ID ID = (Mul ? Intrinsic::umul_with_overflow
                          : Intrinsic::uadd_with_overflow);
  std::string Name = Intrinsic::getName(ID, Types);
  Function *Intrinsic = M->getFunction(Name);
  if (!Intrinsic)
    return false;
  for (Value::use_iterator CallIter = Intrinsic->use_begin(),
         E = Intrinsic->use_end(); CallIter != E; ) {
    CallInst *Call = dyn_cast<CallInst>(*CallIter++);
    if (!Call) {
      report_fatal_error("ExpandArithWithOverflow: Taking the address of a "
                         "*.with.overflow intrinsic is not allowed");
    }
    Value *VariableArg;
    ConstantInt *ConstantArg;
    if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(0))) {
      VariableArg = Call->getArgOperand(1);
      ConstantArg = C;
    } else if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(1))) {
      VariableArg = Call->getArgOperand(0);
      ConstantArg = C;
    } else {
      errs() << "Use: " << *Call << "\n";
      report_fatal_error("ExpandArithWithOverflow: At least one argument of "
                         "*.with.overflow must be a constant");
    }

    Value *ArithResult = BinaryOperator::Create(
        (Mul ? Instruction::Mul : Instruction::Add), VariableArg, ConstantArg,
        Call->getName() + ".arith", Call);

    uint64_t ArgMax;
    if (Mul) {
      ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue();
    } else {
      ArgMax = UintTypeMax(Bits) - ConstantArg->getZExtValue();
    }
    Value *OverflowResult = new ICmpInst(
        Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax),
        Call->getName() + ".overflow");

    // Construct the struct result.
    Value *NewStruct = UndefValue::get(Call->getType());
    NewStruct = CreateInsertValue(NewStruct, 0, ArithResult, Call);
    NewStruct = CreateInsertValue(NewStruct, 1, OverflowResult, Call);
    Call->replaceAllUsesWith(NewStruct);
    Call->eraseFromParent();
  }
  Intrinsic->eraseFromParent();
  return true;
}
コード例 #8
0
ファイル: DebugInfo.cpp プロジェクト: kunhuahuang/llvm
bool llvm::StripDebugInfo(Module &M) {
  bool Changed = false;

  // Remove all of the calls to the debugger intrinsics, and remove them from
  // the module.
  if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->user_back());
      CI->eraseFromParent();
    }
    Declare->eraseFromParent();
    Changed = true;
  }

  if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
    while (!DbgVal->use_empty()) {
      CallInst *CI = cast<CallInst>(DbgVal->user_back());
      CI->eraseFromParent();
    }
    DbgVal->eraseFromParent();
    Changed = true;
  }

  for (Module::named_metadata_iterator NMI = M.named_metadata_begin(),
         NME = M.named_metadata_end(); NMI != NME;) {
    NamedMDNode *NMD = NMI;
    ++NMI;
    if (NMD->getName().startswith("llvm.dbg.")) {
      NMD->eraseFromParent();
      Changed = true;
    }
  }

  for (Function &F : M)
    Changed |= stripDebugInfo(F);

  if (GVMaterializer *Materializer = M.getMaterializer())
    Materializer->setStripDebugInfo();

  return Changed;
}
コード例 #9
0
void AsmDirectivesVisitor::visitCallInst(CallInst &CI) {
  if (!CI.isInlineAsm() ||
      !cast<InlineAsm>(CI.getCalledValue())->isAsmMemory())
    return;

  // In NaCl ``asm("":::"memory")`` always comes in pairs, straddling a
  // sequentially consistent fence. Other passes rewrite this fence to
  // an equivalent stable NaCl intrinsic, meaning that this assembly can
  // be removed.
  CI.eraseFromParent();
  ModifiedFunction = true;
}
コード例 #10
0
CallInst* FunctionCalls::changeFunctionCall(Module &module, Change* change) {
  FunctionChange *funChange = (FunctionChange*)change;
  CallInst *oldCallInst = dyn_cast<CallInst>(funChange->getValue());
  CallInst *newCallInst = NULL;
  string oldFunction = oldCallInst->getCalledFunction()->getName();
  string newFunction = funChange->getSwitch();

  // TODO: use the types vector to not assume signature
  Function *newCallee = module.getFunction(newFunction);
  if (newCallee) {
    errs() << "Changing function call from " << oldFunction << " to " << newFunction << "\n";
    
    if (oldFunction != newFunction) {
      // retrieving original operand
      Value *oldOperand = oldCallInst->getOperand(0);
      
      // downcasting operand    
      Type *fType = Type::getFloatTy(module.getContext());
      FPTruncInst *newOperand = new FPTruncInst(oldOperand, fType, "", oldCallInst);
      
      // populating array of operands
      vector<Value*> operands;
      operands.push_back(newOperand);
      ArrayRef<Value*> *arrayRefOperands = new ArrayRef<Value*>(operands);
      
      // creating the new CallInst
      newCallInst = CallInst::Create(newCallee, *arrayRefOperands, "newCall", oldCallInst);
      
      // casting result to double
      Type *dType = Type::getDoubleTy(module.getContext());
      FPExtInst *result = new FPExtInst(newCallInst, dType, "", oldCallInst);
      
      // replacing all uses of call instruction
      oldCallInst->replaceAllUsesWith(result);
    
      // deleting old callInst
      oldCallInst->eraseFromParent();
      
      errs() << "\tChange was successful\n";
    }
    else {
      errs() << "\tNo change required\n";
    }
  }
  else {
    errs() << "\tDid not find function " << newFunction << "\n";
  }
  
  return newCallInst;
}
コード例 #11
0
    void RuntimeHelperFixupPass::FixArrayInit(Function *F)
    {
        Module *M = F->getParent();
        LLVMContext &ctx = F->getContext();
        
        for (auto it = F->use_begin(), end = F->use_end(); it != end; ++it)
        {
            CallInst *CI = dyn_cast<CallInst>(*it);
            assert (CI && "Unknown usage for array init helper");
            
            Instruction *field_runtime_handle = dyn_cast<Instruction>(CI->getArgOperand(1));
            assert (field_runtime_handle);
            
            MDNode *md = field_runtime_handle->getMetadata("silk_runtime_field_handle");
            assert (md);
            
            ConstantInt *handle = dyn_cast<ConstantInt>(md->getOperand(0));
            assert(handle);
            
            auto vm_field = reinterpret_cast<VMField*>(handle->getValue().getLimitedValue());
            auto field_map = vm_field->field_mapping();
            
            auto vm_named_class = dynamic_cast<VMNamedClass*>(vm_field->type());
            auto size = vm_named_class->type_def()->class_size();

            raw_istream is(field_map.start(), size);

            std::vector<uint8_t> buf;
            buf.resize(size);
            is.read((char*)buf.data(), size);
            
            Constant *predefined_value = ConstantDataArray::get(ctx, buf);
            auto GV = new GlobalVariable(*M, predefined_value->getType(),
                                         true, GlobalValue::InternalLinkage,
                                         predefined_value, ".initdata");
            
            Value *array_ptr = CI->getArgOperand(0);
            IRBuilder<> builder(CI);
            
            auto intrinsic_array_base = intrinsic_->array_base_pointer();
            auto array_ptr_casted = builder.CreateBitCast(array_ptr, builder.getInt8PtrTy());
            auto array_base_ptr = builder.CreateCall(intrinsic_array_base, array_ptr_casted);
            builder.CreateMemCpy(array_base_ptr, GV, ConstantInt::get(Type::getInt64Ty(ctx), size), 0);
            CI->eraseFromParent();
        }
    }
コード例 #12
0
ファイル: OptimizeGEPChecks.cpp プロジェクト: otinn/safecode
bool OptimizeGEPChecks::runOnFunction(Function &F) {
  ABC = &getAnalysis<ArrayBoundsCheckLocal>();
  MSCI = &getAnalysis<MSCInfo>();

  // Visit all call instructions in the function.
  visit(F);

  for (size_t i = 0, N = ToRemove.size(); i < N; ++i) {
    CallInst *CI = ToRemove[i];
    CheckInfoType *Info = MSCI->getCheckInfo(CI->getCalledFunction());
    CI->replaceAllUsesWith(CI->getArgOperand(Info->DestPtrArgNo));
    CI->eraseFromParent();
    ++SafeGEPs;
  }

  bool ChangedAnything = !ToRemove.empty();
  ToRemove.clear();
  return ChangedAnything;
}
コード例 #13
0
ファイル: pass_argrec.cpp プロジェクト: samghub/fcd
void ArgumentRecovery::fixCallSites(Function& base, Function& newTarget, const CallInformation& ci)
{
	auto targetInfo = TargetInfo::getTargetInfo(*base.getParent());
	
	// loop over callers and transform call sites.
	while (!base.use_empty())
	{
		CallInst* call = cast<CallInst>(base.user_back());
		Function* caller = call->getParent()->getParent();
		auto registers = getRegisterPtr(*caller);
		auto newCall = createCallSite(*targetInfo, ci, newTarget, *registers, *call);
		
		// replace call
		newCall->takeName(call);
		call->eraseFromParent();
		
		md::incrementFunctionVersion(*caller);
	}
}
コード例 #14
0
/// Replaces
///
///   strong_retain_unowned %x
///   ... // speculatively executable instructions, including loads from %x
///   strong_release %x
///
/// with
///
///   ... // speculatively executable instructions, including loads from %x
///   check_unowned %x
///
static bool performLocalRetainUnownedOpt(CallInst *Retain, BasicBlock &BB,
                                         ARCEntryPointBuilder &B) {
  Value *RetainedObject = Retain->getArgOperand(0);
  Value *LoadBaseAddr = getBaseAddress(RetainedObject);

  auto BBI = Retain->getIterator(), BBE = BB.getTerminator()->getIterator();

  // Scan until we get to the end of the block.
  for (++BBI; BBI != BBE; ++BBI) {
    Instruction &I = *BBI;
    
    if (classifyInstruction(I) == RT_Release) {
      CallInst *ThisRelease = cast<CallInst>(&I);
      
      // Is this the trailing release of the unowned-retained reference?
      if (ThisRelease->getArgOperand(0) != RetainedObject)
        return false;
      
      // Replace the trailing release with a check_unowned.
      B.setInsertPoint(ThisRelease);
      B.createCheckUnowned(RetainedObject, ThisRelease);
      Retain->eraseFromParent();
      ThisRelease->eraseFromParent();
      ++NumRetainReleasePairs;
      return true;
    }
    if (auto *LI = dyn_cast<LoadInst>(&I)) {
      // Accept loads from the unowned-referenced object. This may load garbage
      // values, but they are not used until the final check_unowned succeeds.
      if (getBaseAddress(LI->getPointerOperand()) == LoadBaseAddr)
        continue;
    }
    // Other than loads from the unowned-referenced object we only accept
    // speculatively executable instructions.
    if (!isSafeToSpeculativelyExecute(&I))
      return false;
  }
  return false;
}
コード例 #15
0
ファイル: StripSymbols.cpp プロジェクト: crabtw/llvm
bool StripDebugDeclare::runOnModule(Module &M) {
  if (skipModule(M))
    return false;

  Function *Declare = M.getFunction("llvm.dbg.declare");
  std::vector<Constant*> DeadConstants;

  if (Declare) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->user_back());
      Value *Arg1 = CI->getArgOperand(0);
      Value *Arg2 = CI->getArgOperand(1);
      assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
      CI->eraseFromParent();
      if (Arg1->use_empty()) {
        if (Constant *C = dyn_cast<Constant>(Arg1))
          DeadConstants.push_back(C);
        else
          RecursivelyDeleteTriviallyDeadInstructions(Arg1);
      }
      if (Arg2->use_empty())
        if (Constant *C = dyn_cast<Constant>(Arg2))
          DeadConstants.push_back(C);
    }
    Declare->eraseFromParent();
  }

  while (!DeadConstants.empty()) {
    Constant *C = DeadConstants.back();
    DeadConstants.pop_back();
    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
      if (GV->hasLocalLinkage())
        RemoveDeadConstant(GV);
    } else
      RemoveDeadConstant(C);
  }

  return true;
}
コード例 #16
0
/// This function strips all debug info intrinsics, except for llvm.dbg.declare.
/// If an llvm.dbg.declare intrinsic is invalid, then this function simply
/// strips that use.
void llvm::CheckDebugInfoIntrinsics(Module *M) {
  if (Function *FuncStart = M->getFunction("llvm.dbg.func.start")) {
    while (!FuncStart->use_empty())
      cast<CallInst>(FuncStart->use_back())->eraseFromParent();
    FuncStart->eraseFromParent();
  }
  
  if (Function *StopPoint = M->getFunction("llvm.dbg.stoppoint")) {
    while (!StopPoint->use_empty())
      cast<CallInst>(StopPoint->use_back())->eraseFromParent();
    StopPoint->eraseFromParent();
  }

  if (Function *RegionStart = M->getFunction("llvm.dbg.region.start")) {
    while (!RegionStart->use_empty())
      cast<CallInst>(RegionStart->use_back())->eraseFromParent();
    RegionStart->eraseFromParent();
  }

  if (Function *RegionEnd = M->getFunction("llvm.dbg.region.end")) {
    while (!RegionEnd->use_empty())
      cast<CallInst>(RegionEnd->use_back())->eraseFromParent();
    RegionEnd->eraseFromParent();
  }
  
  if (Function *Declare = M->getFunction("llvm.dbg.declare")) {
    if (!Declare->use_empty()) {
      DbgDeclareInst *DDI = cast<DbgDeclareInst>(Declare->use_back());
      if (!isa<MDNode>(DDI->getArgOperand(0)) ||
          !isa<MDNode>(DDI->getArgOperand(1))) {
        while (!Declare->use_empty()) {
          CallInst *CI = cast<CallInst>(Declare->use_back());
          CI->eraseFromParent();
        }
        Declare->eraseFromParent();
      }
    }
  }
}
コード例 #17
0
ファイル: inlineSpecials.cpp プロジェクト: 0xDEC0DE8/mcsema
bool InlineSpecials::runOnFunction(Function &F) {

    std::set<CallInst*> worklist;

  for(inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
    Instruction *I = &*i;

    if(CallInst *C = dyn_cast<CallInst>(I)) {
      //get the target of the call, if known
      Function  *invoked = C->getCalledFunction();
      
      if(invoked != NULL) {
        worklist.insert(C);
      }
    }
  }

  for(std::set<CallInst*>::iterator itr = worklist.begin();
          itr != worklist.end();
          itr++)
  {
      CallInst *C = *itr;
      Function  *invoked = C->getCalledFunction();
      string                                  invokedFuncName = invoked->getName();
      map<string,ReplaceFunctionPt>::iterator it = specialMap.find(invokedFuncName);

      if(it != specialMap.end()) {
          ReplaceFunctionPt func = it->second; 

          Value *newv = func(F.getParent(), C, this);

          C->replaceAllUsesWith(newv);
          C->eraseFromParent();
      }
  }
  
  return false;
}
コード例 #18
0
 void RuntimeHelperFixupPass::FixStringConstructor(Function *old_construct, Function *new_construct)
 {
     for (auto it = old_construct->use_begin(), end = old_construct->use_end(); it != end; ++it)
     {
         CallInst *CI = dyn_cast<CallInst>(*it);
         assert (CI);
         
         auto num_ops = CI->getNumArgOperands();
         SmallVector<Value*, 4> ops;
         for (size_t i = 1; i < num_ops; ++i)
             ops.push_back(CI->getArgOperand(i));
         
         IRBuilder<> builder(CI);
         auto new_call = builder.CreateCall(new_construct, ops);
         
         BitCastInst *this_ptr = cast<BitCastInst>(CI->getArgOperand(0));
         auto alloc = cast<Instruction>(this_ptr->llvm::User::getOperand(0));
         this_ptr->replaceAllUsesWith(new_call);
         CI->eraseFromParent();
         this_ptr->eraseFromParent();
         alloc->eraseFromParent();
     }
 }
コード例 #19
0
  void visitCallInst(CallInst &I) {
    string intrinsic = I.getCalledFunction()->getName().str();

    if(intrinsic.find("modmul") != -1) {

      CallInst *enterMontpro1 = enterMontgomery(I.getOperand(0), I.getOperand(2), &I);
      CallInst *enterMontpro2 = enterMontgomery(I.getOperand(1), I.getOperand(2), &I);
      CallInst *mulMontpro = mulMontgomery(I.getName().str(), enterMontpro1, enterMontpro2, I.getOperand(2), &I);
      CallInst *exitMontpro = leaveMontgomery(mulMontpro, I.getOperand(2), &I);

      I.replaceAllUsesWith(exitMontpro);

      I.removeFromParent();
    } else if(intrinsic.find("modexp") != -1) {
      
      CallInst *enterMontpro1 = enterMontgomery(I.getOperand(0), I.getOperand(2), &I);
      CallInst *expMontpro = expMontgomery(I.getName().str(), enterMontpro1, I.getOperand(1), I.getOperand(2), &I);
      CallInst *exitMontpro = leaveMontgomery(expMontpro, I.getOperand(2), &I);

      I.replaceAllUsesWith(exitMontpro);

      I.eraseFromParent();
    }
  }
コード例 #20
0
ファイル: ObjCARCContract.cpp プロジェクト: IanLee1521/ares
bool ObjCARCContract::tryToPeepholeInstruction(
  Function &F, Instruction *Inst, inst_iterator &Iter,
  SmallPtrSetImpl<Instruction *> &DependingInsts,
  SmallPtrSetImpl<const BasicBlock *> &Visited,
  bool &TailOkForStoreStrongs) {
    // Only these library routines return their argument. In particular,
    // objc_retainBlock does not necessarily return its argument.
  ARCInstKind Class = GetBasicARCInstKind(Inst);
    switch (Class) {
    case ARCInstKind::FusedRetainAutorelease:
    case ARCInstKind::FusedRetainAutoreleaseRV:
      return false;
    case ARCInstKind::Autorelease:
    case ARCInstKind::AutoreleaseRV:
      return contractAutorelease(F, Inst, Class, DependingInsts, Visited);
    case ARCInstKind::Retain:
      // Attempt to convert retains to retainrvs if they are next to function
      // calls.
      if (!optimizeRetainCall(F, Inst))
        return false;
      // If we succeed in our optimization, fall through.
      // FALLTHROUGH
    case ARCInstKind::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)
        return false;
      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 == GetArgRCIdentityRoot(Inst)) {
        DEBUG(dbgs() << "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:
      return false;
    }
    case ARCInstKind::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();
      }
      return true;
    }
    case ARCInstKind::Release:
      // Try to form an objc store strong from our release. If we fail, there is
      // nothing further to do below, so continue.
      tryToContractReleaseIntoStoreStrong(Inst, Iter);
      return true;
    case ARCInstKind::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;
      return true;
    case ARCInstKind::IntrinsicUser:
      // Remove calls to @clang.arc.use(...).
      Inst->eraseFromParent();
      return true;
    default:
      return true;
    }
}
コード例 #21
0
/// processMemCpy - perform simplication of memcpy's.  If we have memcpy A which
/// copies X to Y, and memcpy B which copies Y to Z, then we can rewrite B to be
/// a memcpy from X to Z (or potentially a memmove, depending on circumstances).
///  This allows later passes to remove the first memcpy altogether.
bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
  MemoryDependenceAnalysis &MD = getAnalysis<MemoryDependenceAnalysis>();

  // The are two possible optimizations we can do for memcpy:
  //   a) memcpy-memcpy xform which exposes redundance for DSE.
  //   b) call-memcpy xform for return slot optimization.
  MemDepResult dep = MD.getDependency(M);
  if (!dep.isClobber())
    return false;
  if (!isa<MemCpyInst>(dep.getInst())) {
    if (CallInst *C = dyn_cast<CallInst>(dep.getInst()))
      return performCallSlotOptzn(M, C);
    return false;
  }
  
  MemCpyInst *MDep = cast<MemCpyInst>(dep.getInst());
  
  // We can only transforms memcpy's where the dest of one is the source of the
  // other
  if (M->getSource() != MDep->getDest())
    return false;
  
  // Second, the length of the memcpy's must be the same, or the preceeding one
  // must be larger than the following one.
  ConstantInt *C1 = dyn_cast<ConstantInt>(MDep->getLength());
  ConstantInt *C2 = dyn_cast<ConstantInt>(M->getLength());
  if (!C1 || !C2)
    return false;
  
  uint64_t DepSize = C1->getValue().getZExtValue();
  uint64_t CpySize = C2->getValue().getZExtValue();
  
  if (DepSize < CpySize)
    return false;
  
  // Finally, we have to make sure that the dest of the second does not
  // alias the source of the first
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  if (AA.alias(M->getRawDest(), CpySize, MDep->getRawSource(), DepSize) !=
      AliasAnalysis::NoAlias)
    return false;
  else if (AA.alias(M->getRawDest(), CpySize, M->getRawSource(), CpySize) !=
           AliasAnalysis::NoAlias)
    return false;
  else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize)
           != AliasAnalysis::NoAlias)
    return false;
  
  // If all checks passed, then we can transform these memcpy's
  const Type *ArgTys[3] = { M->getRawDest()->getType(),
                            MDep->getRawSource()->getType(),
                            M->getLength()->getType() };
  Function *MemCpyFun = Intrinsic::getDeclaration(
                                 M->getParent()->getParent()->getParent(),
                                 M->getIntrinsicID(), ArgTys, 3);
    
  Value *Args[5] = {
    M->getRawDest(), MDep->getRawSource(), M->getLength(),
    M->getAlignmentCst(), M->getVolatileCst()
  };
  
  CallInst *C = CallInst::Create(MemCpyFun, Args, Args+5, "", M);
  
  
  // If C and M don't interfere, then this is a valid transformation.  If they
  // did, this would mean that the two sources overlap, which would be bad.
  if (MD.getDependency(C) == dep) {
    MD.removeInstruction(M);
    M->eraseFromParent();
    ++NumMemCpyInstr;
    return true;
  }
  
  // Otherwise, there was no point in doing this, so we remove the call we
  // inserted and act like nothing happened.
  MD.removeInstruction(C);
  C->eraseFromParent();
  return false;
}
コード例 #22
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;
}
コード例 #23
0
int compile(list<string> args, list<string> kgen_args,
            string merge, list<string> merge_args,
            string input, string output, int arch,
            string host_compiler, string fileprefix)
{
    //
    // The LLVM compiler to emit IR.
    //
    const char* llvm_compiler = "kernelgen-gfortran";

    //
    // Interpret kernelgen compile options.
    //
    for (list<string>::iterator iarg = kgen_args.begin(),
            iearg = kgen_args.end(); iarg != iearg; iarg++)
    {
        const char* arg = (*iarg).c_str();
        if (!strncmp(arg, "-Wk,--llvm-compiler=", 20))
            llvm_compiler = arg + 20;
    }

    //
    // Generate temporary output file.
    // Check if output file is specified in the command line.
    // Replace or add output to the temporary file.
    //
    cfiledesc tmp_output = cfiledesc::mktemp(fileprefix);
    bool output_specified = false;
    for (list<string>::iterator iarg = args.begin(),
            iearg = args.end(); iarg != iearg; iarg++)
    {
        const char* arg = (*iarg).c_str();
        if (!strcmp(arg, "-o"))
        {
            iarg++;
            *iarg = tmp_output.getFilename();
            output_specified = true;
            break;
        }
    }
    if (!output_specified)
    {
        args.push_back("-o");
        args.push_back(tmp_output.getFilename());
    }

    //
    // 1) Compile source code using regular host compiler.
    //
    {
        if (verbose)
        {
            cout << host_compiler;
            for (list<string>::iterator iarg = args.begin(),
                    iearg = args.end(); iarg != iearg; iarg++)
                cout << " " << *iarg;
            cout << endl;
        }
        int status = execute(host_compiler, args, "", NULL, NULL);
        if (status) return status;
    }

    //
    // 2) Emit LLVM IR.
    //
    string out = "";
    {
        list<string> emit_ir_args;
        for (list<string>::iterator iarg = args.begin(),
                iearg = args.end(); iarg != iearg; iarg++)
        {
            const char* arg = (*iarg).c_str();
            if (!strcmp(arg, "-c") || !strcmp(arg, "-o"))
            {
                iarg++;
                continue;
            }
            if (!strcmp(arg, "-g"))
            {
                continue;
            }
            emit_ir_args.push_back(*iarg);
        }
        emit_ir_args.push_back("-fplugin=/opt/kernelgen/lib/dragonegg.so");
        emit_ir_args.push_back("-fplugin-arg-dragonegg-emit-ir");
        emit_ir_args.push_back("-S");
        emit_ir_args.push_back(input);
        emit_ir_args.push_back("-o");
        emit_ir_args.push_back("-");
        if (verbose)
        {
            cout << llvm_compiler;
            for (list<string>::iterator iarg = emit_ir_args.begin(),
                    iearg = emit_ir_args.end(); iarg != iearg; iarg++)
                cout << " " << *iarg;
            cout << endl;
        }
        int status = execute(llvm_compiler, emit_ir_args, "", &out, NULL);
        if (status) return status;
    }

    //
    // 3) Record existing module functions.
    //
    LLVMContext &context = getGlobalContext();
    SMDiagnostic diag;
    MemoryBuffer* buffer1 = MemoryBuffer::getMemBuffer(out);
    auto_ptr<Module> m1;
    m1.reset(ParseIR(buffer1, diag, context));

    //m1.get()->dump();

    //
    // 4) Inline calls and extract loops into new functions.
    //
    MemoryBuffer* buffer2 = MemoryBuffer::getMemBuffer(out);
    auto_ptr<Module> m2;
    m2.reset(ParseIR(buffer2, diag, context));
    {
        PassManager manager;
        manager.add(createInstructionCombiningPass());
        manager.run(*m2.get());
    }
    std::vector<CallInst *> LoopFuctionCalls;
    {
        PassManager manager;
        manager.add(createBranchedLoopExtractorPass(LoopFuctionCalls));
        manager.run(*m2.get());
    }

    //m2.get()->dump();

    //
    // 5) Replace call to loop functions with call to launcher.
    // Append "always inline" attribute to all other functions.
    //
    Type* int32Ty = Type::getInt32Ty(context);
    Function* launch = Function::Create(
                           TypeBuilder<types::i<32>(types::i<8>*, types::i<64>, types::i<32>*), true>::get(context),
                           GlobalValue::ExternalLinkage, "kernelgen_launch", m2.get());
    for (Module::iterator f1 = m2.get()->begin(), fe1 = m2.get()->end(); f1 != fe1; f1++)
    {
        Function* func = f1;
        if (func->isDeclaration()) continue;

        // Search for the current function in original module
        // functions list.
        // If function is not in list of original module, then
        // it is generated by the loop extractor.
        // Append "always inline" attribute to all other functions.
        if (m1.get()->getFunction(func->getName()))
        {
            const AttrListPtr attr = func->getAttributes();
            const AttrListPtr attr_new = attr.addAttr(~0U, Attribute::AlwaysInline);
            func->setAttributes(attr_new);
            continue;
        }

        // Each such function must be extracted to the
        // standalone module and packed into resulting
        // object file data section.
        if (verbose)
            cout << "Preparing loop function " << func->getName().data() <<
                 " ..." << endl;

        // Reset to default visibility.
        func->setVisibility(GlobalValue::DefaultVisibility);

        // Reset to default linkage.
        func->setLinkage(GlobalValue::ExternalLinkage);

        // Replace call to this function in module with call to launcher.
        bool found = false;
        for (Module::iterator f2 = m2->begin(), fe2 = m2->end(); (f2 != fe2) && !found; f2++)
            for (Function::iterator bb = f2->begin(); (bb != f2->end()) && !found; bb++)
                for (BasicBlock::iterator i = bb->begin(); i != bb->end(); i++)
                {
                    // Check if instruction in focus is a call.
                    CallInst* call = dyn_cast<CallInst>(cast<Value>(i));
                    if (!call) continue;

                    // Check if function is called (needs -instcombine pass).
                    Function* callee = call->getCalledFunction();
                    if (!callee) continue;
                    if (callee->isDeclaration()) continue;
                    if (callee->getName() != func->getName()) continue;

                    // Create a constant array holding original called
                    // function name.
                    Constant* name = ConstantArray::get(
                                         context, callee->getName(), true);

                    // Create and initialize the memory buffer for name.
                    ArrayType* nameTy = cast<ArrayType>(name->getType());
                    AllocaInst* nameAlloc = new AllocaInst(nameTy, "", call);
                    StoreInst* nameInit = new StoreInst(name, nameAlloc, "", call);
                    Value* Idx[2];
                    Idx[0] = Constant::getNullValue(Type::getInt32Ty(context));
                    Idx[1] = ConstantInt::get(Type::getInt32Ty(context), 0);
                    GetElementPtrInst* namePtr = GetElementPtrInst::Create(nameAlloc, Idx, "", call);

                    // Add pointer to the original function string name.
                    SmallVector<Value*, 16> call_args;
                    call_args.push_back(namePtr);

                    // Add size of the aggregated arguments structure.
                    {
                        BitCastInst* BC = new BitCastInst(
                            call->getArgOperand(0), Type::getInt64PtrTy(context),
                            "", call);

                        LoadInst* LI = new LoadInst(BC, "", call);
                        call_args.push_back(LI);
                    }

                    // Add original aggregated structure argument.
                    call_args.push_back(call->getArgOperand(0));

                    // Create new function call with new call arguments
                    // and copy old call properties.
                    CallInst* newcall = CallInst::Create(launch, call_args, "", call);
                    //newcall->takeName(call);
                    newcall->setCallingConv(call->getCallingConv());
                    newcall->setAttributes(call->getAttributes());
                    newcall->setDebugLoc(call->getDebugLoc());

                    // Replace old call with new one.
                    call->replaceAllUsesWith(newcall);
                    call->eraseFromParent();

                    found = true;
                    break;
                }
    }

    //m2.get()->dump();

    //
    // 6) Apply optimization passes to the resulting common
    // module.
    //
    {
        PassManager manager;
        manager.add(createLowerSetJmpPass());
        PassManagerBuilder builder;
        builder.Inliner = createFunctionInliningPass();
        builder.OptLevel = 3;
        builder.DisableSimplifyLibCalls = true;
        builder.populateModulePassManager(manager);
        manager.run(*m2.get());
    }

    //m2.get()->dump();

    //
    // 7) Embed the resulting module into object file.
    //
    {
        string ir_string;
        raw_string_ostream ir(ir_string);
        ir << (*m2.get());
        celf e(tmp_output.getFilename(), output);
        e.getSection(".data")->addSymbol(
            "__kernelgen_" + string(input),
            ir_string.c_str(), ir_string.size() + 1);
    }

    return 0;
}
コード例 #24
0
/// performLocalReleaseMotion - Scan backwards from the specified release,
/// moving it earlier in the function if possible, over instructions that do not
/// access the released object.  If we get to a retain or allocation of the
/// object, zap both.
static bool performLocalReleaseMotion(CallInst &Release, BasicBlock &BB,
                                      SwiftRCIdentity *RC) {
  // FIXME: Call classifier should identify the object for us.  Too bad C++
  // doesn't have nice Swift-style enums.
  Value *ReleasedObject = RC->getSwiftRCIdentityRoot(Release.getArgOperand(0));

  BasicBlock::iterator BBI = Release.getIterator();

  // Scan until we get to the top of the block.
  while (BBI != BB.begin()) {
    --BBI;

    // Don't analyze PHI nodes.  We can't move retains before them and they
    // aren't "interesting".
    if (isa<PHINode>(BBI) ||
        // If we found the instruction that defines the value we're releasing,
        // don't push the release past it.
        &*BBI == Release.getArgOperand(0)) {
      ++BBI;
      goto OutOfLoop;
    }

    switch (classifyInstruction(*BBI)) {
    // These instructions should not reach here based on the pass ordering.
    // i.e. LLVMARCOpt -> LLVMContractOpt.
    case RT_UnknownRetainN:
    case RT_BridgeRetainN:
    case RT_RetainN:
    case RT_UnknownReleaseN:
    case RT_BridgeReleaseN:
    case RT_ReleaseN:
        llvm_unreachable("These are only created by LLVMARCContract !");
    case RT_NoMemoryAccessed:
      // Skip over random instructions that don't touch memory.  They don't need
      // protection by retain/release.
      continue;

    case RT_UnknownRelease:
    case RT_BridgeRelease:
    case RT_ObjCRelease:
    case RT_Release: {
      // If we get to a release, we can generally ignore it and scan past it.
      // However, if we get to a release of obviously the same object, we stop
      // scanning here because it should have already be moved as early as
      // possible, so there is no reason to move its friend to the same place.
      //
      // NOTE: If this occurs frequently, maybe we can have a release(Obj, N)
      // API to drop multiple retain counts at once.
      CallInst &ThisRelease = cast<CallInst>(*BBI);
      Value *ThisReleasedObject = ThisRelease.getArgOperand(0);
      ThisReleasedObject = RC->getSwiftRCIdentityRoot(ThisReleasedObject);
      if (ThisReleasedObject == ReleasedObject) {
        //Release.dump(); ThisRelease.dump(); BB.getParent()->dump();
        ++BBI;
        goto OutOfLoop;
      }
      continue;
    }

    case RT_UnknownRetain:
    case RT_BridgeRetain:
    case RT_ObjCRetain:
    case RT_Retain: {  // swift_retain(obj)
      CallInst &Retain = cast<CallInst>(*BBI);
      Value *RetainedObject = Retain.getArgOperand(0);
      RetainedObject = RC->getSwiftRCIdentityRoot(RetainedObject);

      // Since we canonicalized earlier, we know that if our retain has any
      // uses, they were replaced already. This assertion documents this
      // assumption.
      assert(Retain.use_empty() && "Retain should have been canonicalized to "
             "have no uses.");

      // If the retain and release are to obviously pointer-equal objects, then
      // we can delete both of them.  We have proven that they do not protect
      // anything of value.
      if (RetainedObject == ReleasedObject) {
        Retain.eraseFromParent();
        Release.eraseFromParent();
        ++NumRetainReleasePairs;
        return true;
      }

      // Otherwise, this is a retain of an object that is not statically known
      // to be the same object.  It may still be dynamically the same object
      // though.  In this case, we can't move the release past it.
      // TODO: Strengthen analysis.
      //Release.dump(); ThisRelease.dump(); BB.getParent()->dump();
     ++BBI;
      goto OutOfLoop;
    }

    case RT_AllocObject: {   // %obj = swift_alloc(...)
      CallInst &Allocation = cast<CallInst>(*BBI);

      // If this is an allocation of an unrelated object, just ignore it.
      // TODO: This is not safe without proving the object being released is not
      // related to the allocated object.  Consider something silly like this:
      //   A = allocate()
      //   B = bitcast A to object
      //   release(B)
      if (ReleasedObject != &Allocation) {
        // Release.dump(); BB.getParent()->dump();
        ++BBI;
        goto OutOfLoop;
      }

      // If this is a release right after an allocation of the object, then we
      // can zap both.
      Allocation.replaceAllUsesWith(UndefValue::get(Allocation.getType()));
      Allocation.eraseFromParent();
      Release.eraseFromParent();
      ++NumAllocateReleasePairs;
      return true;
    }

    case RT_FixLifetime:
    case RT_RetainUnowned:
    case RT_CheckUnowned:
    case RT_Unknown:
      // Otherwise, we have reached something that we do not understand. Do not
      // attempt to shorten the lifetime of this object beyond this point so we
      // are conservative.
      ++BBI;
      goto OutOfLoop;
    }
  }
OutOfLoop:


  // If we got to the top of the block, (and if the instruction didn't start
  // there) move the release to the top of the block.
  // TODO: This is where we'd plug in some global algorithms someday.
  if (&*BBI != &Release) {
    Release.moveBefore(&*BBI);
    return true;
  }

  return false;
}
コード例 #25
0
bool GambasPass::runOnFunction(Function &F){
	IRBuilder<> Builder(F.getContext());
	
	bool changed = false;
	for(Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
		for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ){
			ICmpInst* ICI = dyn_cast<ICmpInst>(I);
			CallInst* CI = dyn_cast<CallInst>(I++);
			
			if (ICI && ICI->hasMetadata() && ICI->getMetadata("unref_slt") && dyn_cast<LoadInst>(ICI->getOperand(0))){
				ICI->replaceAllUsesWith(ConstantInt::get(ICI->getType(), false));
				ICI->eraseFromParent();
				changed = true;
				continue;
			}
			
			if (!CI)
				continue;
			
			Function* callee = CI->getCalledFunction();
			if (callee == NULL || !callee->isDeclaration())
				continue;
			
			StringRef name = callee->getName();
			if (name == "JR_release_variant" || name == "JR_borrow_variant"){
				ConstantInt* vtype_int = dyn_cast<ConstantInt>(CI->getArgOperand(0));
				if (!vtype_int)
					continue;
				
				uint64_t vtype = vtype_int->getZExtValue();
				if (TYPE_is_string(vtype) || TYPE_is_object(vtype))
					continue;
				
				CI->eraseFromParent();
				changed = true;
			} else if (name == FUNCTION_NAME(__finite)){
				ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0));
				if (!op)
					continue;
				
				int val = __finite(op->getValueAPF().convertToDouble());
				Constant* res = ConstantInt::get(CI->getType(), val);
				CI->replaceAllUsesWith(res);
				CI->eraseFromParent();
				changed = true;
			} else if (name == FUNCTION_NAME(__isnan)){
				ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0));
				if (!op)
					continue;
				
				int val = __isnan(op->getValueAPF().convertToDouble());
				Constant* res = ConstantInt::get(CI->getType(), val);
				CI->replaceAllUsesWith(res);
				CI->eraseFromParent();
				changed = true;
			} else if (name == FUNCTION_NAME(__isinf)){
				ConstantFP* op = dyn_cast<ConstantFP>(CI->getArgOperand(0));
				if (!op)
					continue;
				
				int val = __isinf(op->getValueAPF().convertToDouble());
				Constant* res = ConstantInt::get(CI->getType(), val);
				CI->replaceAllUsesWith(res);
				CI->eraseFromParent();
				changed = true;
			}
		}
	}
	return changed;
}
コード例 #26
0
/// performLocalRetainMotion - Scan forward from the specified retain, moving it
/// later in the function if possible, over instructions that provably can't
/// release the object.  If we get to a release of the object, zap both.
///
/// NOTE: this handles both objc_retain and swift_retain.
///
static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB,
                                     SwiftRCIdentity *RC) {
  // FIXME: Call classifier should identify the object for us.  Too bad C++
  // doesn't have nice Swift-style enums.
  Value *RetainedObject = RC->getSwiftRCIdentityRoot(Retain.getArgOperand(0));

  BasicBlock::iterator BBI = Retain.getIterator(),
                       BBE = BB.getTerminator()->getIterator();

  bool isObjCRetain = Retain.getCalledFunction()->getName() == "objc_retain";

  bool MadeProgress = false;

  // Scan until we get to the end of the block.
  for (++BBI; BBI != BBE; ++BBI) {
    Instruction &CurInst = *BBI;

    // Classify the instruction. This switch does a "break" when the instruction
    // can be skipped and is interesting, and a "continue" when it is a retain
    // of the same pointer.
    switch (classifyInstruction(CurInst)) {
    // These instructions should not reach here based on the pass ordering.
    // i.e. LLVMARCOpt -> LLVMContractOpt.
    case RT_RetainN:
    case RT_UnknownRetainN:
    case RT_BridgeRetainN:
    case RT_ReleaseN:
    case RT_UnknownReleaseN:
    case RT_BridgeReleaseN:
        llvm_unreachable("These are only created by LLVMARCContract !");
    case RT_NoMemoryAccessed:
    case RT_AllocObject:
    case RT_CheckUnowned:
      // Skip over random instructions that don't touch memory.  They don't need
      // protection by retain/release.
      break;

    case RT_FixLifetime: // This only stops release motion. Retains can move over it.
      break;

    case RT_Retain:
    case RT_UnknownRetain:
    case RT_BridgeRetain:
    case RT_RetainUnowned:
    case RT_ObjCRetain: {  // swift_retain(obj)
      //CallInst &ThisRetain = cast<CallInst>(CurInst);
      //Value *ThisRetainedObject = ThisRetain.getArgOperand(0);

      // If we see a retain of the same object, we can skip over it, but we
      // can't count it as progress.  Just pushing a retain(x) past a retain(y)
      // doesn't change the program.
      continue;
    }


    case RT_UnknownRelease:
    case RT_BridgeRelease:
    case RT_ObjCRelease:
    case RT_Release: {
      // If we get to a release that is provably to this object, then we can zap
      // it and the retain.
      CallInst &ThisRelease = cast<CallInst>(CurInst);
      Value *ThisReleasedObject = ThisRelease.getArgOperand(0);
      ThisReleasedObject = RC->getSwiftRCIdentityRoot(ThisReleasedObject);
      if (ThisReleasedObject == RetainedObject) {
        Retain.eraseFromParent();
        ThisRelease.eraseFromParent();
        if (isObjCRetain) {
          ++NumObjCRetainReleasePairs;
        } else {
          ++NumRetainReleasePairs;
        }
        return true;
      }

      // Otherwise, if this is some other pointer, we can only ignore it if we
      // can prove that the two objects don't alias.
      // Retain.dump(); ThisRelease.dump(); BB.getParent()->dump();
      goto OutOfLoop;
    }

    case RT_Unknown:
      // Loads cannot affect the retain.
      if (isa<LoadInst>(CurInst))
        continue;

      // Load, store, memcpy etc can't do a release.
      if (isa<LoadInst>(CurInst) || isa<StoreInst>(CurInst) ||
          isa<MemIntrinsic>(CurInst))
        break;

      // CurInst->dump(); BBI->dump();
      // Otherwise, we get to something unknown/unhandled.  Bail out for now.
      goto OutOfLoop;
    }

    // If the switch did a break, we made some progress moving this retain.
    MadeProgress = true;
  }
OutOfLoop:

  // If we were able to move the retain down, move it now.
  // TODO: This is where we'd plug in some global algorithms someday.
  if (MadeProgress) {
    Retain.moveBefore(&*BBI);
    return true;
  }

  return false;
}
コード例 #27
0
ファイル: GEPExprArgs.cpp プロジェクト: brills/pfpa
//
// Method: runOnModule()
//
// Description:
//  Entry point for this LLVM pass.
//  Clone functions that take GEPs as arguments
//
// Inputs:
//  M - A reference to the LLVM module to transform
//
// Outputs:
//  M - The transformed LLVM module.
//
// Return value:
//  true  - The module was modified.
//  false - The module was not modified.
//
bool GEPExprArgs::runOnModule(Module& M) {
  bool changed;
  do {
    changed = false;
    for (Module::iterator F = M.begin(); F != M.end(); ++F){
      for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
        for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) {
          CallInst *CI = dyn_cast<CallInst>(I++);
          if(!CI)
            continue;

          if(CI->hasByValArgument())
            continue;
          // if the GEP calls a function, that is externally defined,
          // or might be changed, ignore this call site.
          Function *F = CI->getCalledFunction();

          if (!F || (F->isDeclaration() || F->mayBeOverridden())) 
            continue;
          if(F->hasStructRetAttr())
            continue;
          if(F->isVarArg())
            continue;

          // find the argument we must replace
          Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end();
          unsigned argNum = 1;
          for(; argNum < CI->getNumOperands();argNum++, ++ai) {
            if(ai->use_empty())
              continue;
            if (isa<GEPOperator>(CI->getOperand(argNum)))
              break;
          }

          // if no argument was a GEP operator to be changed 
          if(ai == ae)
            continue;

          GEPOperator *GEP = dyn_cast<GEPOperator>(CI->getOperand(argNum));
          if(!GEP->hasAllConstantIndices())
            continue;

          // Construct the new Type
          // Appends the struct Type at the beginning
          std::vector<Type*>TP;
          TP.push_back(GEP->getPointerOperand()->getType());
          for(unsigned c = 1; c < CI->getNumOperands();c++) {
            TP.push_back(CI->getOperand(c)->getType());
          }

          //return type is same as that of original instruction
          FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false);
          Function *NewF;
          numSimplified++;
          if(numSimplified > 800) 
            return true;

          NewF = Function::Create(NewFTy,
                                  GlobalValue::InternalLinkage,
                                  F->getName().str() + ".TEST",
                                  &M);

          Function::arg_iterator NI = NewF->arg_begin();
          NI->setName("GEParg");
          ++NI;

          ValueToValueMapTy ValueMap;

          for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++II, ++NI) {
            ValueMap[II] = NI;
            NI->setName(II->getName());
            NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1));
          }
          NewF->setAttributes(NewF->getAttributes().addAttr(
              0, F->getAttributes().getRetAttributes()));
          // Perform the cloning.
          SmallVector<ReturnInst*,100> Returns;
          CloneFunctionInto(NewF, F, ValueMap, false, Returns);
          std::vector<Value*> fargs;
          for(Function::arg_iterator ai = NewF->arg_begin(), 
              ae= NewF->arg_end(); ai != ae; ++ai) {
            fargs.push_back(ai);
          }

          NewF->setAttributes(NewF->getAttributes().addAttr(
              ~0, F->getAttributes().getFnAttributes()));
          //Get the point to insert the GEP instr.
          SmallVector<Value*, 8> Ops(CI->op_begin()+1, CI->op_end());
          Instruction *InsertPoint;
          for (BasicBlock::iterator insrt = NewF->front().begin(); 
               isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;}

          NI = NewF->arg_begin();
          SmallVector<Value*, 8> Indices;
          Indices.append(GEP->op_begin()+1, GEP->op_end());
          GetElementPtrInst *GEP_new = GetElementPtrInst::Create(cast<Value>(NI),
                                                                 Indices, 
                                                                 "", InsertPoint);
          fargs.at(argNum)->replaceAllUsesWith(GEP_new);
          unsigned j = argNum + 1;
          for(; j < CI->getNumOperands();j++) {
            if(CI->getOperand(j) == GEP)
              fargs.at(j)->replaceAllUsesWith(GEP_new);
          }

          SmallVector<AttributeWithIndex, 8> AttributesVec;

          // Get the initial attributes of the call
          AttrListPtr CallPAL = CI->getAttributes();
          Attributes RAttrs = CallPAL.getRetAttributes();
          Attributes FnAttrs = CallPAL.getFnAttributes();
          if (RAttrs)
            AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs));

          SmallVector<Value*, 8> Args;
          Args.push_back(GEP->getPointerOperand());
          for(unsigned j =1;j<CI->getNumOperands();j++) {
            Args.push_back(CI->getOperand(j));
            // position in the AttributesVec
            if (Attributes Attrs = CallPAL.getParamAttributes(j))
              AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
          }
          // Create the new attributes vec.
          if (FnAttrs != Attribute::None)
            AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));

          AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(),
                                                    AttributesVec.end());

          CallInst *CallI = CallInst::Create(NewF,Args,"", CI);
          CallI->setCallingConv(CI->getCallingConv());
          CallI->setAttributes(NewCallPAL);
          CI->replaceAllUsesWith(CallI);
          CI->eraseFromParent();
          changed = true;
        }
      }
    }
  } while(changed);
  return true;
}
コード例 #28
0
ファイル: llvm-lower-handlers.cpp プロジェクト: KDr2/julia
bool LowerExcHandlers::runOnFunction(Function &F) {
    if (!except_enter_func)
        return false; // No EH frames in this module

    /* Step 1: EH Depth Numbering */
    std::map<llvm::CallInst *, int> EnterDepth;
    std::map<llvm::CallInst *, int> LeaveDepth;
    std::map<BasicBlock *, int> ExitDepth;
    int MaxDepth = 0;
    // Compute EH Depth at each basic block using a DFS traversal.
    for (df_iterator<BasicBlock *> I = df_begin(&F.getEntryBlock()),
            E = df_end(&F.getEntryBlock()); I != E; ++I) {
        auto *BB = *I;
        int Depth = 0;
        /* Here we use the assumption that all incoming edges have the same
         * EH depth.
         */
        for (auto *Pred : predecessors(BB)) {
            auto it = ExitDepth.find(Pred);
            if (it != ExitDepth.end()) {
                Depth = it->second;
                break;
            }
        }
        /* Compute the depth within the basic block */
        for (auto &I : *BB) {
            auto *CI = dyn_cast<CallInst>(&I);
            if (!CI)
                continue;
            Function *Callee = CI->getCalledFunction();
            if (!Callee)
                continue;
            if (Callee == except_enter_func)
                EnterDepth[CI] = Depth++;
            else if (Callee == leave_func) {
                LeaveDepth[CI] = Depth;
                Depth -= cast<ConstantInt>(CI->getArgOperand(0))->getLimitedValue();
            }
            assert(Depth >= 0);
            if (Depth > MaxDepth)
                MaxDepth = Depth;
        }
        /* Remember the depth at the BB boundary */
        ExitDepth[BB] = Depth;
    }

    /* Step 2: EH Frame lowering */
    // Allocate stack space for each handler. We allocate these as separate
    // allocas so the optimizer can later merge and reaarange them if it wants
    // to.
    Value *handler_sz = ConstantInt::get(Type::getInt32Ty(F.getContext()),
                                         sizeof(jl_handler_t));
    Value *handler_sz64 = ConstantInt::get(Type::getInt64Ty(F.getContext()),
                                           sizeof(jl_handler_t));
    Instruction *firstInst = &F.getEntryBlock().front();
    std::vector<AllocaInst *> buffs;
    for (int i = 0; i < MaxDepth; ++i) {
        auto *buff = new AllocaInst(Type::getInt8Ty(F.getContext()),
                                       0,
                                       handler_sz, "", firstInst);
        buff->setAlignment(16);
        buffs.push_back(buff);
    }

    // Lower enter funcs
    for (auto it : EnterDepth) {
        assert(it.second >= 0);
        AllocaInst *buff = buffs[it.second];
        CallInst *enter = it.first;
        auto new_enter = CallInst::Create(jlenter_func, buff, "", enter);
        Value *lifetime_args[] = {
            handler_sz64,
            buff
        };
        CallInst::Create(lifetime_start, lifetime_args, "", new_enter);
#ifndef _OS_WINDOWS_
        // For LLVM 3.3 compatibility
        Value *args[] = {buff,
                         ConstantInt::get(Type::getInt32Ty(F.getContext()), 0)};
        auto sj = CallInst::Create(setjmp_func, args, "", enter);
#else
        auto sj = CallInst::Create(setjmp_func, buff, "", enter);
#endif
        // We need to mark this on the call site as well. See issue #6757
        sj->setCanReturnTwice();
        if (auto dbg = enter->getMetadata(LLVMContext::MD_dbg)) {
            new_enter->setMetadata(LLVMContext::MD_dbg, dbg);
            sj->setMetadata(LLVMContext::MD_dbg, dbg);
        }
        enter->replaceAllUsesWith(sj);
        enter->eraseFromParent();
    }
    // Insert lifetime end intrinsics after every leave.
    for (auto it : LeaveDepth) {
        int StartDepth = it.second - 1;
        int npops = cast<ConstantInt>(it.first->getArgOperand(0))->getLimitedValue();
        for (int i = 0; i < npops; ++i) {
            assert(StartDepth-i >= 0);
            Value *lifetime_args[] = {
                handler_sz64,
                buffs[StartDepth-i]
            };
            auto LifetimeEnd = CallInst::Create(lifetime_end, lifetime_args);
            LifetimeEnd->insertAfter(it.first);
        }
    }
    return true;
}
コード例 #29
0
	int CGGraph::solve(std::vector<CallInst*> boundsChecks) {

		std::vector<CallInst*>::iterator callIt;
		std::string varOne;
		std::string varTwo;
		bool rCheck;

		vector<CallInst*> toRemove;
		for (callIt = boundsChecks.begin(); callIt != boundsChecks.end(); ++callIt) {

			if(std::find(owner->callInstsRemoved.begin(), owner->callInstsRemoved.end(), (*callIt)) != owner->callInstsRemoved.end()) 
			{
				continue;
			} 
			else 
			{
		    	
				if ((*callIt)->getParent()->getParent()->getName() == this->funcName) {
					
					Value *v0 = (*callIt)->getArgOperand(0);
					Value *v1 = (*callIt)->getArgOperand(1);
					if (ConstantInt *c0 = dyn_cast<ConstantInt>(v0)) {
						if (ConstantInt *c1 = dyn_cast<ConstantInt>(v1)) {
							totalChecked++;
							if ((c0->getSExtValue() >= 0) && (c0->getSExtValue() < c1->getSExtValue())) {
								//trivial constant case
								totalRemoved++;
								toRemove.push_back(*callIt);
								
							}
						} 
					} 
					else {
					
						varOne = getNameFromValue((*callIt)->getArgOperand(1), (*callIt)); //length of array
						varTwo = getNameFromValue((*callIt)->getArgOperand(0), (*callIt)); //indexing variable

						if (hasNode(varOne) && hasNode(varTwo)) {
							rCheck = doTraverse(varOne, varTwo);
							totalChecked++;
							if (rCheck) {
								totalRemoved++;
								toRemove.push_back(*callIt);
							}

						}
					}
				}
			}
		}

		// Remove them outside the traversal loop so you don't screw the iterator.
		for(size_t i = 0; i < toRemove.size(); i++)
		{
			CallInst *deadCall = toRemove[i];
			deadCall->eraseFromParent();
			owner->callInstsRemoved.push_back(deadCall);
		}

		//errs() << "Total number of checks performed for function: " << totalChecked << "\n";
		//errs() << "Total number of checks removed for function: " << totalRemoved << "\n";

		return totalRemoved;

	}
コード例 #30
0
void insertCallToAccessFunction(Function *F, Function *cF) {
  CallInst *I;
  Instruction *bI;
  std::vector<Value *> Args;
  std::vector<Type *> ArgsTy;
  Module *M = F->getParent();
  std::string name;
  Function *nF, *tF;
  FunctionType *FTy;
  std::stringstream out;

  Value::user_iterator i = F->user_begin(), e = F->user_end();
  while (i != e) {
    Args.clear();
    ArgsTy.clear();
    /*************  C codes  ***********/

    if (isa<CallInst>(*i)) {

      I = dyn_cast<CallInst>(*i);
      // call to the access function F
      Args.push_back(I->getArgOperand(0));
      ArgsTy.push_back(I->getArgOperand(0)->getType());

      // call to the execute function cF
      Args.push_back(cF);
      ArgsTy.push_back(PointerType::get(cF->getFunctionType(), 0));

      unsigned int t;
      for (t = 1; t < I->getNumArgOperands(); t++) {
        Args.push_back(I->getArgOperand(t));
        ArgsTy.push_back(I->getArgOperand(t)->getType());
        // errs() << *(I->getArgOperand(t)) << " is or not " <<
        // isa<GlobalVariable>(I->getArgOperand(t)) << "\n";
      }
      tF = dyn_cast<Function>(I->getCalledFunction());
      FTy = FunctionType::get(tF->getReturnType(), ArgsTy, 0);

      out.str(std::string());
      out << "task_DAE_" << I->getNumArgOperands() - 1;
      nF = (Function *)M->getOrInsertFunction(out.str(), FTy);
      CallInst *ci = CallInst::Create(nF, Args, I->getName(), I);

      i++;
      I->replaceAllUsesWith(ci);
      I->eraseFromParent();
    }
    /*************  C++ codes  ***********/
    else {

      Value::user_iterator bit = (*i)->user_begin(), bite = (*i)->user_end();

      Type *iTy = (*i)->getType();
      i++;
      while (bit != bite) {
        Args.clear();
        ArgsTy.clear();
        I = dyn_cast<CallInst>(*bit);

        bit++;

        // call to the access function F
        Args.push_back(I->getArgOperand(0));
        ArgsTy.push_back(I->getArgOperand(0)->getType());

        // call to the execute function cF
        bI = new BitCastInst(cF, (iTy), "_TPR", I);
        Args.push_back(bI);
        ArgsTy.push_back(bI->getType());

        unsigned int t;
        for (t = 1; t < I->getNumArgOperands(); t++) {
          Args.push_back(I->getArgOperand(t));
          ArgsTy.push_back(I->getArgOperand(t)->getType());
        }
        tF = dyn_cast<Function>(I->getCalledFunction());
        FTy = FunctionType::get(tF->getReturnType(), ArgsTy, 0);

        out.str(std::string());
        out << "task_DAE_" << I->getNumArgOperands() - 1;
        nF = (Function *)M->getOrInsertFunction(out.str(), FTy);
        CallInst *ci = CallInst::Create(nF, Args, I->getName(), I);

        I->replaceAllUsesWith(ci);
        I->eraseFromParent();
      }
    }
  }
}