本文整理汇总了C++中CallInst::getNumOperands方法的典型用法代码示例。如果您正苦于以下问题:C++ CallInst::getNumOperands方法的具体用法?C++ CallInst::getNumOperands怎么用?C++ CallInst::getNumOperands使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类CallInst
的用法示例。
在下文中一共展示了CallInst::getNumOperands方法的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: AddCatchInfo
/// AddCatchInfo - Extract the personality and type infos from an eh.selector
/// call, and add them to the specified machine basic block.
void llvm::AddCatchInfo(CallInst &I, MachineModuleInfo *MMI,
MachineBasicBlock *MBB) {
// Inform the MachineModuleInfo of the personality for this landing pad.
ConstantExpr *CE = cast<ConstantExpr>(I.getOperand(2));
assert(CE->getOpcode() == Instruction::BitCast &&
isa<Function>(CE->getOperand(0)) &&
"Personality should be a function");
MMI->addPersonality(MBB, cast<Function>(CE->getOperand(0)));
// Gather all the type infos for this landing pad and pass them along to
// MachineModuleInfo.
std::vector<GlobalVariable *> TyInfo;
unsigned N = I.getNumOperands();
for (unsigned i = N - 1; i > 2; --i) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(i))) {
unsigned FilterLength = CI->getZExtValue();
unsigned FirstCatch = i + FilterLength + !FilterLength;
assert (FirstCatch <= N && "Invalid filter length");
if (FirstCatch < N) {
TyInfo.reserve(N - FirstCatch);
for (unsigned j = FirstCatch; j < N; ++j)
TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
MMI->addCatchTypeInfo(MBB, TyInfo);
TyInfo.clear();
}
if (!FilterLength) {
// Cleanup.
MMI->addCleanup(MBB);
} else {
// Filter.
TyInfo.reserve(FilterLength - 1);
for (unsigned j = i + 1; j < FirstCatch; ++j)
TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
MMI->addFilterTypeInfo(MBB, TyInfo);
TyInfo.clear();
}
N = i;
}
}
if (N > 3) {
TyInfo.reserve(N - 3);
for (unsigned j = 3; j < N; ++j)
TyInfo.push_back(ExtractTypeInfo(I.getOperand(j)));
MMI->addCatchTypeInfo(MBB, TyInfo);
}
}
示例2: handleInlineAsm
void LLVMDefUseAnalysis::handleInlineAsm(LLVMNode *callNode)
{
CallInst *CI = cast<CallInst>(callNode->getValue());
LLVMDependenceGraph *dg = callNode->getDG();
// the last operand is the asm itself, so iterate only to e - 1
for (unsigned i = 0, e = CI->getNumOperands(); i < e - 1; ++i) {
Value *opVal = CI->getOperand(i);
if (!opVal->getType()->isPointerTy())
continue;
LLVMNode *opNode = dg->getNode(opVal->stripInBoundsOffsets());
if (!opNode) {
// FIXME: ConstantExpr
llvmutils::printerr("WARN: unhandled inline asm operand: ", opVal);
continue;
}
assert(opNode && "Do not have an operand for inline asm");
// if nothing else, this call at least uses the operands
opNode->addDataDependence(callNode);
}
}
示例3: runOnModule
bool NVVMReflect::runOnModule(Module &M) {
if (!NVVMReflectEnabled)
return false;
setVarMap();
ReflectFunction = M.getFunction(NVVM_REFLECT_FUNCTION);
// If reflect function is not used, then there will be
// no entry in the module.
if (ReflectFunction == 0)
return false;
// Validate _reflect function
assert(ReflectFunction->isDeclaration() &&
"_reflect function should not have a body");
assert(ReflectFunction->getReturnType()->isIntegerTy() &&
"_reflect's return type should be integer");
std::vector<Instruction *> ToRemove;
// Go through the uses of ReflectFunction in this Function.
// Each of them should a CallInst with a ConstantArray argument.
// First validate that. If the c-string corresponding to the
// ConstantArray can be found successfully, see if it can be
// found in VarMap. If so, replace the uses of CallInst with the
// value found in VarMap. If not, replace the use with value 0.
for (User *U : ReflectFunction->users()) {
assert(isa<CallInst>(U) && "Only a call instruction can use _reflect");
CallInst *Reflect = cast<CallInst>(U);
assert((Reflect->getNumOperands() == 2) &&
"Only one operand expect for _reflect function");
// In cuda, we will have an extra constant-to-generic conversion of
// the string.
const Value *conv = Reflect->getArgOperand(0);
assert(isa<CallInst>(conv) && "Expected a const-to-gen conversion");
const CallInst *ConvCall = cast<CallInst>(conv);
const Value *str = ConvCall->getArgOperand(0);
assert(isa<ConstantExpr>(str) &&
"Format of _reflect function not recognized");
const ConstantExpr *GEP = cast<ConstantExpr>(str);
const Value *Sym = GEP->getOperand(0);
assert(isa<Constant>(Sym) && "Format of _reflect function not recognized");
const Constant *SymStr = cast<Constant>(Sym);
assert(isa<ConstantDataSequential>(SymStr->getOperand(0)) &&
"Format of _reflect function not recognized");
assert(cast<ConstantDataSequential>(SymStr->getOperand(0))->isCString() &&
"Format of _reflect function not recognized");
std::string ReflectArg =
cast<ConstantDataSequential>(SymStr->getOperand(0))->getAsString();
ReflectArg = ReflectArg.substr(0, ReflectArg.size() - 1);
DEBUG(dbgs() << "Arg of _reflect : " << ReflectArg << "\n");
int ReflectVal = 0; // The default value is 0
if (VarMap.find(ReflectArg) != VarMap.end()) {
ReflectVal = VarMap[ReflectArg];
}
Reflect->replaceAllUsesWith(
ConstantInt::get(Reflect->getType(), ReflectVal));
ToRemove.push_back(Reflect);
}
if (ToRemove.size() == 0)
return false;
for (unsigned i = 0, e = ToRemove.size(); i != e; ++i)
ToRemove[i]->eraseFromParent();
return true;
}
示例4: parseName
string esp::parseName(Value *value){
// has existed
if(names.find(value) != names.end())
return names[value];
string name = "";
Value *current = value;
/*
bool continueFlag = true;
do{
if(isa<Instruction > (current)){
Instruction* inst = dyn_cast<Instruction>(current);
unsigned op = inst->getOpcode();
switch(op){
case Instruction::Ret :{
break;
}
case Instruction::Br :{
break;
}
case Instruction::Switch :{
break;
}
case Instruction::Call :{
CallInst *callinst = (CallInst*) current;
if (((CallInst*) current)->getCalledFunction() != NULL) {
name += string("@")+((CallInst*) current)->getCalledFunction()->getNameStr() + "(";
} else {
name += string("@[funcPTR](");
name += ((CallInst*) current)->getCalledValue()->getNameStr();
}
for (unsigned i = 1; i < callinst->getNumOperands(); i++) {
name += esp::parseName(callinst->getOperand(i));
}
name += string(")");
continueFlag = false;
break;
}
case Instruction::PHI :{
name += string("PHI[");
name += current->getNameStr();
PHINode *phi = (PHINode*) current;
for (unsigned i = 0; i < phi->getNumIncomingValues(); i++) {
Value *incoming = phi->getIncomingValue(i);
if (i != 0) name += ",";
if (!hasLoop(incoming)) {
if (!incoming->hasName()) {
name += esp::parseName(incoming);
} else {
name += incoming->getNameStr();
}
}
}
name += std::string("]");
continueFlag = false;
break;
}
case Instruction::Select :{
break;
}
case Instruction::Add :{
name += "+";
name += parseBinaryOpName(inst);
break;
}
case Instruction::Sub :{
name += "-";
name += parseBinaryOpName(inst);
break;
}
case Instruction::Mul :{
name += "*";
name += parseBinaryOpName(inst);
break;
}
case Instruction::UDiv :{
name += "/";
name += parseBinaryOpName(inst);
break;
}
case Instruction::SDiv :{
name += "//";
name += parseBinaryOpName(inst);
break;
//.........这里部分代码省略.........
示例5: runOnFunction
bool NVVMReflect::runOnFunction(Function &F) {
if (!NVVMReflectEnabled)
return false;
if (F.getName() == NVVM_REFLECT_FUNCTION) {
assert(F.isDeclaration() && "_reflect function should not have a body");
assert(F.getReturnType()->isIntegerTy() &&
"_reflect's return type should be integer");
return false;
}
SmallVector<Instruction *, 4> ToRemove;
// Go through the calls in this function. Each call to __nvvm_reflect or
// llvm.nvvm.reflect should be a CallInst with a ConstantArray argument.
// First validate that. If the c-string corresponding to the ConstantArray can
// be found successfully, see if it can be found in VarMap. If so, replace the
// uses of CallInst with the value found in VarMap. If not, replace the use
// with value 0.
// The IR for __nvvm_reflect calls differs between CUDA versions.
//
// CUDA 6.5 and earlier uses this sequence:
// %ptr = tail call i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8
// (i8 addrspace(4)* getelementptr inbounds
// ([8 x i8], [8 x i8] addrspace(4)* @str, i32 0, i32 0))
// %reflect = tail call i32 @__nvvm_reflect(i8* %ptr)
//
// The value returned by Sym->getOperand(0) is a Constant with a
// ConstantDataSequential operand which can be converted to string and used
// for lookup.
//
// CUDA 7.0 does it slightly differently:
// %reflect = call i32 @__nvvm_reflect(i8* addrspacecast
// (i8 addrspace(1)* getelementptr inbounds
// ([8 x i8], [8 x i8] addrspace(1)* @str, i32 0, i32 0) to i8*))
//
// In this case, we get a Constant with a GlobalVariable operand and we need
// to dig deeper to find its initializer with the string we'll use for lookup.
for (Instruction &I : instructions(F)) {
CallInst *Call = dyn_cast<CallInst>(&I);
if (!Call)
continue;
Function *Callee = Call->getCalledFunction();
if (!Callee || (Callee->getName() != NVVM_REFLECT_FUNCTION &&
Callee->getIntrinsicID() != Intrinsic::nvvm_reflect))
continue;
// FIXME: Improve error handling here and elsewhere in this pass.
assert(Call->getNumOperands() == 2 &&
"Wrong number of operands to __nvvm_reflect function");
// In cuda 6.5 and earlier, we will have an extra constant-to-generic
// conversion of the string.
const Value *Str = Call->getArgOperand(0);
if (const CallInst *ConvCall = dyn_cast<CallInst>(Str)) {
// FIXME: Add assertions about ConvCall.
Str = ConvCall->getArgOperand(0);
}
assert(isa<ConstantExpr>(Str) &&
"Format of __nvvm__reflect function not recognized");
const ConstantExpr *GEP = cast<ConstantExpr>(Str);
const Value *Sym = GEP->getOperand(0);
assert(isa<Constant>(Sym) &&
"Format of __nvvm_reflect function not recognized");
const Value *Operand = cast<Constant>(Sym)->getOperand(0);
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) {
// For CUDA-7.0 style __nvvm_reflect calls, we need to find the operand's
// initializer.
assert(GV->hasInitializer() &&
"Format of _reflect function not recognized");
const Constant *Initializer = GV->getInitializer();
Operand = Initializer;
}
assert(isa<ConstantDataSequential>(Operand) &&
"Format of _reflect function not recognized");
assert(cast<ConstantDataSequential>(Operand)->isCString() &&
"Format of _reflect function not recognized");
StringRef ReflectArg = cast<ConstantDataSequential>(Operand)->getAsString();
ReflectArg = ReflectArg.substr(0, ReflectArg.size() - 1);
LLVM_DEBUG(dbgs() << "Arg of _reflect : " << ReflectArg << "\n");
int ReflectVal = 0; // The default value is 0
if (ReflectArg == "__CUDA_FTZ") {
// Try to pull __CUDA_FTZ from the nvvm-reflect-ftz module flag. Our
// choice here must be kept in sync with AutoUpgrade, which uses the same
// technique to detect whether ftz is enabled.
if (auto *Flag = mdconst::extract_or_null<ConstantInt>(
F.getParent()->getModuleFlag("nvvm-reflect-ftz")))
ReflectVal = Flag->getSExtValue();
} else if (ReflectArg == "__CUDA_ARCH") {
ReflectVal = SmVersion * 10;
}
Call->replaceAllUsesWith(ConstantInt::get(Call->getType(), ReflectVal));
ToRemove.push_back(Call);
}
//.........这里部分代码省略.........
示例6: runOnModule
//
// 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);
}
//.........这里部分代码省略.........
示例7: visitSpecialCall
//.........这里部分代码省略.........
// Get the number of bytes that will be written into the buffer.
Value *NumElts = BinaryOperator::Create(BinaryOperator::Mul,
CI.getOperand(0),
CI.getOperand(1),
"calloc par1 * par2",
&CI);
// Get the destination pointer and cast it to a void pointer.
// Instruction * dstPointerInst;
Value *dstPointer = castTo(&CI, VoidPtrType, CI.getName(), &CI);
/* // To move after call inst, we need to know if cast is a constant expr or inst
if ((dstPointerInst = dyn_cast<Instruction>(dstPointer))) {
CI.moveBefore(dstPointerInst); // dstPointerInst->insertAfter(&CI);
// ((Instruction *)NumElts)->insertAfter(dstPointerInst);
}
else {
CI.moveBefore((Instruction *)NumElts); // ((Instruction *)NumElts)->insertAfter(&CI);
}
dstPointer = dstPointerInst; // Assign to dstPointer for instrn or non-instrn values
*/
// Get the ID of the external funtion call instruction.
Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI));
//
// Create the call to the run-time to record the external call instruction.
//
std::vector<Value *> args = make_vector(CallID, dstPointer, NumElts, 0);
CallInst *recStore = CallInst::Create(RecordStore, args, "", &CI);
CI.moveBefore(recStore); //recStore->insertAfter((Instruction *)NumElts);
// Moove cast, #byte computation and store to after call inst
CI.moveBefore(cast<Instruction>(NumElts));
instrumentUnlock(&CI);
++NumExtFuns; // Update statistics
return true;
} else if (name == "tolower" || name == "toupper") {
// Not needed as there are no loads and stores
/* } else if (name == "strncpy/itoa/stdarg/scanf/fscanf/sscanf/fread/complex/strftime/strptime/asctime/ctime") { */
} else if (name == "fscanf") {
// TODO
// In stead of parsing format string, can we use the type of the arguments??
} else if (name == "sscanf") {
// TODO
} else if (name == "sprintf") {
instrumentLock(&CI);
// Get the pointer to the destination buffer.
Value *dstPointer = CI.getOperand(0);
dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI);
// Get the ID of the call instruction.
Value *CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI));
// Scan through the arguments looking for what appears to be a character
// string. Generate load records for each of these strings.
for (unsigned index = 2; index < CI.getNumOperands(); ++index) {
if (CI.getOperand(index)->getType() == VoidPtrType) {
// Create the call to the run-time to record the load from the string.
// What about other loads??
Value *Ptr = CI.getOperand(index);
std::vector<Value *> args = make_vector(CallID, Ptr, 0);
CallInst::Create(RecordStrLoad, args, "", &CI);
++NumLoadStrings; // Update statistics
}
}
// Create the call to the run-time to record the external call instruction.
std::vector<Value *> args = make_vector(CallID, dstPointer, 0);
CallInst *recStore = CallInst::Create(RecordStrStore, args, "", &CI);
CI.moveBefore(recStore);
instrumentUnlock(&CI);
++NumStoreStrings; // Update statistics
return true;
} else if (name == "fgets") {
instrumentLock(&CI);
// Get the pointer to the destination buffer.
Value * dstPointer = CI.getOperand(0);
dstPointer = castTo(dstPointer, VoidPtrType, dstPointer->getName(), &CI);
// Get the ID of the ext fun call instruction.
Value * CallID = ConstantInt::get(Int32Type, lsNumPass->getID(&CI));
// Create the call to the run-time to record the external call instruction.
std::vector<Value *> args = make_vector(CallID, dstPointer, 0);
CallInst *recStore = CallInst::Create(RecordStrStore, args, "", &CI);
CI.moveBefore(recStore);
instrumentUnlock(&CI);
// Update statistics
++NumStoreStrings;
return true;
}
return false;
}
示例8: handleFunction
bool NVVMReflect::handleFunction(Function *ReflectFunction) {
// Validate _reflect function
assert(ReflectFunction->isDeclaration() &&
"_reflect function should not have a body");
assert(ReflectFunction->getReturnType()->isIntegerTy() &&
"_reflect's return type should be integer");
std::vector<Instruction *> ToRemove;
// Go through the uses of ReflectFunction in this Function.
// Each of them should a CallInst with a ConstantArray argument.
// First validate that. If the c-string corresponding to the
// ConstantArray can be found successfully, see if it can be
// found in VarMap. If so, replace the uses of CallInst with the
// value found in VarMap. If not, replace the use with value 0.
// IR for __nvvm_reflect calls differs between CUDA versions:
// CUDA 6.5 and earlier uses this sequence:
// %ptr = tail call i8* @llvm.nvvm.ptr.constant.to.gen.p0i8.p4i8
// (i8 addrspace(4)* getelementptr inbounds
// ([8 x i8], [8 x i8] addrspace(4)* @str, i32 0, i32 0))
// %reflect = tail call i32 @__nvvm_reflect(i8* %ptr)
//
// Value returned by Sym->getOperand(0) is a Constant with a
// ConstantDataSequential operand which can be converted to string and used
// for lookup.
//
// CUDA 7.0 does it slightly differently:
// %reflect = call i32 @__nvvm_reflect(i8* addrspacecast
// (i8 addrspace(1)* getelementptr inbounds
// ([8 x i8], [8 x i8] addrspace(1)* @str, i32 0, i32 0) to i8*))
//
// In this case, we get a Constant with a GlobalVariable operand and we need
// to dig deeper to find its initializer with the string we'll use for lookup.
for (User *U : ReflectFunction->users()) {
assert(isa<CallInst>(U) && "Only a call instruction can use _reflect");
CallInst *Reflect = cast<CallInst>(U);
assert((Reflect->getNumOperands() == 2) &&
"Only one operand expect for _reflect function");
// In cuda, we will have an extra constant-to-generic conversion of
// the string.
const Value *Str = Reflect->getArgOperand(0);
if (isa<CallInst>(Str)) {
// CUDA path
const CallInst *ConvCall = cast<CallInst>(Str);
Str = ConvCall->getArgOperand(0);
}
assert(isa<ConstantExpr>(Str) &&
"Format of _reflect function not recognized");
const ConstantExpr *GEP = cast<ConstantExpr>(Str);
const Value *Sym = GEP->getOperand(0);
assert(isa<Constant>(Sym) && "Format of _reflect function not recognized");
const Value *Operand = cast<Constant>(Sym)->getOperand(0);
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand)) {
// For CUDA-7.0 style __nvvm_reflect calls we need to find operand's
// initializer.
assert(GV->hasInitializer() &&
"Format of _reflect function not recognized");
const Constant *Initializer = GV->getInitializer();
Operand = Initializer;
}
assert(isa<ConstantDataSequential>(Operand) &&
"Format of _reflect function not recognized");
assert(cast<ConstantDataSequential>(Operand)->isCString() &&
"Format of _reflect function not recognized");
std::string ReflectArg =
cast<ConstantDataSequential>(Operand)->getAsString();
ReflectArg = ReflectArg.substr(0, ReflectArg.size() - 1);
DEBUG(dbgs() << "Arg of _reflect : " << ReflectArg << "\n");
int ReflectVal = 0; // The default value is 0
if (VarMap.find(ReflectArg) != VarMap.end()) {
ReflectVal = VarMap[ReflectArg];
}
Reflect->replaceAllUsesWith(
ConstantInt::get(Reflect->getType(), ReflectVal));
ToRemove.push_back(Reflect);
}
if (ToRemove.size() == 0)
return false;
for (unsigned i = 0, e = ToRemove.size(); i != e; ++i)
ToRemove[i]->eraseFromParent();
return true;
}
示例9: runOnModule
//
// Method: runOnModule()
//
// Description:
// Entry point for this LLVM pass.
// Search for all call sites to casted functions.
// Check if they only differ in an argument type
// Cast the argument, and call the original function
//
// 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 ArgCast::runOnModule(Module& M) {
std::vector<CallInst*> worklist;
for (Module::iterator I = M.begin(); I != M.end(); ++I) {
if (I->mayBeOverridden())
continue;
// Find all uses of this function
for(Value::user_iterator ui = I->user_begin(), ue = I->user_end(); ui != ue; ) {
// check if is ever casted to a different function type
ConstantExpr *CE = dyn_cast<ConstantExpr>(*ui++);
if(!CE)
continue;
if (CE->getOpcode() != Instruction::BitCast)
continue;
if(CE->getOperand(0) != I)
continue;
const PointerType *PTy = dyn_cast<PointerType>(CE->getType());
if (!PTy)
continue;
const Type *ETy = PTy->getElementType();
const FunctionType *FTy = dyn_cast<FunctionType>(ETy);
if(!FTy)
continue;
// casting to a varargs funtion
// or function with same number of arguments
// possibly varying types of arguments
if(FTy->getNumParams() != I->arg_size() && !FTy->isVarArg())
continue;
for(Value::user_iterator uii = CE->user_begin(),
uee = CE->user_end(); uii != uee; ++uii) {
// Find all uses of the casted value, and check if it is
// used in a Call Instruction
if (CallInst* CI = dyn_cast<CallInst>(*uii)) {
// Check that it is the called value, and not an argument
if(CI->getCalledValue() != CE)
continue;
// Check that the number of arguments passed, and expected
// by the function are the same.
if(!I->isVarArg()) {
if(CI->getNumOperands() != I->arg_size() + 1)
continue;
} else {
if(CI->getNumOperands() < I->arg_size() + 1)
continue;
}
// If so, add to worklist
worklist.push_back(CI);
}
}
}
}
// Proces the worklist of potential call sites to transform
while(!worklist.empty()) {
CallInst *CI = worklist.back();
worklist.pop_back();
// Get the called Function
Function *F = cast<Function>(CI->getCalledValue()->stripPointerCasts());
const FunctionType *FTy = F->getFunctionType();
SmallVector<Value*, 8> Args;
unsigned i =0;
for(i =0; i< FTy->getNumParams(); ++i) {
Type *ArgType = CI->getOperand(i+1)->getType();
Type *FormalType = FTy->getParamType(i);
// If the types for this argument match, just add it to the
// parameter list. No cast needs to be inserted.
if(ArgType == FormalType) {
Args.push_back(CI->getOperand(i+1));
}
else if(ArgType->isPointerTy() && FormalType->isPointerTy()) {
CastInst *CastI = CastInst::CreatePointerCast(CI->getOperand(i+1),
FormalType, "", CI);
Args.push_back(CastI);
} else if (ArgType->isIntegerTy() && FormalType->isIntegerTy()) {
unsigned SrcBits = ArgType->getScalarSizeInBits();
unsigned DstBits = FormalType->getScalarSizeInBits();
if(SrcBits > DstBits) {
CastInst *CastI = CastInst::CreateIntegerCast(CI->getOperand(i+1),
FormalType, true, "", CI);
//.........这里部分代码省略.........
示例10: runOnModule
//.........这里部分代码省略.........
std::vector<Type*>TP;
TP.push_back(NewArgType);
for (Function::arg_iterator ii = F->arg_begin(), ee = F->arg_end();
ii != ee; ++ii) {
TP.push_back(ii->getType());
}
FunctionType *NFTy = FunctionType::get(F->getReturnType(), TP, F->isVarArg());
// Create the new function body and insert it into the module.
Function *NF = Function::Create(NFTy,
F->getLinkage(),
F->getName(), &M);
ValueToValueMapTy ValueMap;
Function::arg_iterator NI = NF->arg_begin();
NI->setName("ret");
++NI;
for (Function::arg_iterator II = F->arg_begin(); II != F->arg_end(); ++II, ++NI) {
ValueMap[II] = NI;
NI->setName(II->getName());
AttributeSet attrs = F->getAttributes().getParamAttributes(II->getArgNo() + 1);
if (!attrs.isEmpty())
NI->addAttr(attrs);
}
// Perform the cloning.
SmallVector<ReturnInst*,100> Returns;
if (!F->isDeclaration())
CloneFunctionInto(NF, F, ValueMap, false, Returns);
std::vector<Value*> fargs;
for(Function::arg_iterator ai = NF->arg_begin(),
ae= NF->arg_end(); ai != ae; ++ai) {
fargs.push_back(ai);
}
NF->setAttributes(NF->getAttributes().addAttributes(
M.getContext(), 0, F->getAttributes().getRetAttributes()));
NF->setAttributes(NF->getAttributes().addAttributes(
M.getContext(), ~0, F->getAttributes().getFnAttributes()));
for (Function::iterator B = NF->begin(), FE = NF->end(); B != FE; ++B) {
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) {
ReturnInst * RI = dyn_cast<ReturnInst>(I++);
if(!RI)
continue;
LoadInst *LI = dyn_cast<LoadInst>(RI->getOperand(0));
assert(LI && "Return should be preceded by a load instruction");
IRBuilder<> Builder(RI);
Builder.CreateMemCpy(fargs.at(0),
LI->getPointerOperand(),
targetData.getTypeStoreSize(LI->getType()),
targetData.getPrefTypeAlignment(LI->getType()));
}
}
for(Value::use_iterator ui = F->use_begin(), ue = F->use_end();
ui != ue; ) {
CallInst *CI = dyn_cast<CallInst>(*ui++);
if(!CI)
continue;
if(CI->getCalledFunction() != F)
continue;
if(CI->hasByValArgument())
continue;
AllocaInst *AllocaNew = new AllocaInst(F->getReturnType(), 0, "", CI);
SmallVector<Value*, 8> Args;
//this should probably be done in a different manner
AttributeSet NewCallPAL=AttributeSet();
// Get the initial attributes of the call
AttributeSet CallPAL = CI->getAttributes();
AttributeSet RAttrs = CallPAL.getRetAttributes();
AttributeSet FnAttrs = CallPAL.getFnAttributes();
if (!RAttrs.isEmpty())
NewCallPAL=NewCallPAL.addAttributes(F->getContext(),0, RAttrs);
Args.push_back(AllocaNew);
for(unsigned j = 0; j < CI->getNumOperands()-1; j++) {
Args.push_back(CI->getOperand(j));
// position in the NewCallPAL
AttributeSet Attrs = CallPAL.getParamAttributes(j);
if (!Attrs.isEmpty())
NewCallPAL=NewCallPAL.addAttributes(F->getContext(),Args.size(), Attrs);
}
// Create the new attributes vec.
if (!FnAttrs.isEmpty())
NewCallPAL=NewCallPAL.addAttributes(F->getContext(),~0, FnAttrs);
CallInst *CallI = CallInst::Create(NF, Args, "", CI);
CallI->setCallingConv(CI->getCallingConv());
CallI->setAttributes(NewCallPAL);
LoadInst *LI = new LoadInst(AllocaNew, "", CI);
CI->replaceAllUsesWith(LI);
CI->eraseFromParent();
}
if(F->use_empty())
F->eraseFromParent();
}
return true;
}
示例11: ProcessReturningBlock
bool TailCallElim::ProcessReturningBlock(ReturnInst *Ret, BasicBlock *&OldEntry,
bool &TailCallsAreMarkedTail,
SmallVector<PHINode*, 8> &ArgumentPHIs,
bool CannotTailCallElimCallsMarkedTail) {
BasicBlock *BB = Ret->getParent();
Function *F = BB->getParent();
if (&BB->front() == Ret) // Make sure there is something before the ret...
return false;
// If the return is in the entry block, then making this transformation would
// turn infinite recursion into an infinite loop. This transformation is ok
// in theory, but breaks some code like:
// double fabs(double f) { return __builtin_fabs(f); } // a 'fabs' call
// disable this xform in this case, because the code generator will lower the
// call to fabs into inline code.
if (BB == &F->getEntryBlock())
return false;
// Scan backwards from the return, checking to see if there is a tail call in
// this block. If so, set CI to it.
CallInst *CI;
BasicBlock::iterator BBI = Ret;
while (1) {
CI = dyn_cast<CallInst>(BBI);
if (CI && CI->getCalledFunction() == F)
break;
if (BBI == BB->begin())
return false; // Didn't find a potential tail call.
--BBI;
}
// If this call is marked as a tail call, and if there are dynamic allocas in
// the function, we cannot perform this optimization.
if (CI->isTailCall() && CannotTailCallElimCallsMarkedTail)
return false;
// If we are introducing accumulator recursion to eliminate associative
// operations after the call instruction, this variable contains the initial
// value for the accumulator. If this value is set, we actually perform
// accumulator recursion elimination instead of simple tail recursion
// elimination.
Value *AccumulatorRecursionEliminationInitVal = 0;
Instruction *AccumulatorRecursionInstr = 0;
// Ok, we found a potential tail call. We can currently only transform the
// tail call if all of the instructions between the call and the return are
// movable to above the call itself, leaving the call next to the return.
// Check that this is the case now.
for (BBI = CI, ++BBI; &*BBI != Ret; ++BBI)
if (!CanMoveAboveCall(BBI, CI)) {
// If we can't move the instruction above the call, it might be because it
// is an associative operation that could be tranformed using accumulator
// recursion elimination. Check to see if this is the case, and if so,
// remember the initial accumulator value for later.
if ((AccumulatorRecursionEliminationInitVal =
CanTransformAccumulatorRecursion(BBI, CI))) {
// Yes, this is accumulator recursion. Remember which instruction
// accumulates.
AccumulatorRecursionInstr = BBI;
} else {
return false; // Otherwise, we cannot eliminate the tail recursion!
}
}
// We can only transform call/return pairs that either ignore the return value
// of the call and return void, ignore the value of the call and return a
// constant, return the value returned by the tail call, or that are being
// accumulator recursion variable eliminated.
if (Ret->getNumOperands() == 1 && Ret->getReturnValue() != CI &&
!isa<UndefValue>(Ret->getReturnValue()) &&
AccumulatorRecursionEliminationInitVal == 0 &&
!getCommonReturnValue(Ret, CI))
return false;
// OK! We can transform this tail call. If this is the first one found,
// create the new entry block, allowing us to branch back to the old entry.
if (OldEntry == 0) {
OldEntry = &F->getEntryBlock();
BasicBlock *NewEntry = BasicBlock::Create(F->getContext(), "", F, OldEntry);
NewEntry->takeName(OldEntry);
OldEntry->setName("tailrecurse");
BranchInst::Create(OldEntry, NewEntry);
// If this tail call is marked 'tail' and if there are any allocas in the
// entry block, move them up to the new entry block.
TailCallsAreMarkedTail = CI->isTailCall();
if (TailCallsAreMarkedTail)
// Move all fixed sized allocas from OldEntry to NewEntry.
for (BasicBlock::iterator OEBI = OldEntry->begin(), E = OldEntry->end(),
NEBI = NewEntry->begin(); OEBI != E; )
if (AllocaInst *AI = dyn_cast<AllocaInst>(OEBI++))
if (isa<ConstantInt>(AI->getArraySize()))
AI->moveBefore(NEBI);
// Now that we have created a new block, which jumps to the entry
// block, insert a PHI node for each argument of the function.
// For now, we initialize each PHI to only have the real arguments
// which are passed in.
//.........这里部分代码省略.........