std::string to_string(const Argument<hns::Namespace>& ns) { std::ostringstream os; os << ns->getName() << " [" << ns->getID().short_string() << "] NS["; for(hns::Namespace::IDListType::const_iterator it = ns->accessChildNamespaceList().begin(); it != ns->accessChildNamespaceList().end(); it++) { os << ";" << it->short_string();; } return os.str(); }
Argument *Action::getArgument(const std::string &name) { ArgumentList *argList = getArgumentList(); int nArgs = argList->size(); for (int n = 0; n < nArgs; n++) { Argument *arg = argList->getArgument(n); const char *argName = arg->getName(); if (argName == NULL) continue; string argNameStr = argName; if (argNameStr.compare(name) == 0) return arg; } return NULL; }
ArgumentArea::ArgumentArea(QWidget *parent, Argument arg) : KHBox(parent) { prefix = arg.getPrefix(); QLabel *label = new QLabel(arg.getName(), this); label->setToolTip(arg.getDescription()); if(arg.getOptional() == true){ QCheckBox *enabled = new QCheckBox("", this); enabled->setCheckState(Qt::Unchecked); if(arg.getType() == Argument::Switch){ connect(enabled, SIGNAL(stateChanged(int)), this, SLOT(switchUpdate(int))); }
void PrintDeviceInfo(Device *dev, int indent) { string indentStr; GetIndentString(indent, indentStr); const char *devName = dev->getFriendlyName(); cout << indentStr << devName << endl; int i, n, j; ServiceList *serviceList = dev->getServiceList(); int serviceCnt = serviceList->size(); for (n=0; n<serviceCnt; n++) { Service *service = serviceList->getService(n); cout << indentStr << " service[" << n << "] = "<< service->getServiceType() << endl; ActionList *actionList = service->getActionList(); int actionCnt = actionList->size(); for (i=0; i<actionCnt; i++) { Action *action = actionList->getAction(i); cout << indentStr << " action[" << i << "] = "<< action->getName() << endl; ArgumentList *argList = action->getArgumentList(); int argCnt = argList->size(); for (j=0; j<argCnt; j++) { Argument *arg = argList->getArgument(j); cout << indentStr << " arg[" << j << "] = " << arg->getName() << "(" << arg->getDirection() << ")"; StateVariable *stateVar = arg->getRelatedStateVariable(); if (stateVar != NULL) cout << " - " << stateVar->getName(); cout << endl; } } ServiceStateTable *stateTable = service->getServiceStateTable(); int varCnt = stateTable->size(); for (i=0; i<varCnt; i++) { StateVariable *stateVar = stateTable->getStateVariable(i); cout << indentStr << " stateVar[" << i << "] = " << stateVar->getName() << endl; AllowedValueList *valueList = stateVar->getAllowedValueList(); int valueListCnt = valueList->size(); if (0 < valueListCnt) { for (j=0; j<valueListCnt; j++) cout << indentStr << " AllowedValueList[" << j << "] = " << valueList->getAllowedValue(j) << endl; } AllowedValueRange *valueRange = stateVar->getAllowedValueRange(); if (valueRange != NULL) { cout << indentStr << " AllowedRange[minimum] = " << valueRange->getMinimum() << endl; cout << indentStr << " AllowedRange[maximum] = " << valueRange->getMaximum() << endl; cout << indentStr << " AllowedRange[step] = " << valueRange->getStep() << endl; } } } }
Node *ActionRequest::createContentNode(Service *service, CyberLink::Action *action, ArgumentList *argList) { const char *actionName = action->getName(); const char *serviceType = service->getServiceType(); Node *actionNode = new Node(); actionNode->setName(Control::NS, actionName); actionNode->setNameSpace(Control::NS, serviceType); int argListCnt = argList->size(); for (int n = 0; n < argListCnt; n++) { Argument *arg = argList->getArgument(n); Node *argNode = new Node(); string name = arg->getName(); string value = arg->getValue(); argNode->setName(name.c_str()); argNode->setValue(value.c_str()); actionNode->addNode(argNode); } return actionNode; }
/// PromoteArguments - This method checks the specified function to see if there /// are any promotable arguments and if it is safe to promote the function (for /// example, all callers are direct). If safe to promote some arguments, it /// calls the DoPromotion method. /// CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { Function *F = CGN->getFunction(); // Make sure that it is local to this module. if (!F || !F->hasLocalLinkage()) return 0; // First check: see if there are any pointer arguments! If not, quick exit. SmallVector<std::pair<Argument*, unsigned>, 16> PointerArgs; unsigned ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgNo) if (I->getType()->isPointerTy()) PointerArgs.push_back(std::pair<Argument*, unsigned>(I, ArgNo)); if (PointerArgs.empty()) return 0; // Second check: make sure that all callers are direct callers. We can't // transform functions that have indirect callers. if (F->hasAddressTaken()) return 0; // Check to see which arguments are promotable. If an argument is promotable, // add it to ArgsToPromote. SmallPtrSet<Argument*, 8> ArgsToPromote; SmallPtrSet<Argument*, 8> ByValArgsToTransform; for (unsigned i = 0; i != PointerArgs.size(); ++i) { bool isByVal = F->paramHasAttr(PointerArgs[i].second+1, Attribute::ByVal); // If this is a byval argument, and if the aggregate type is small, just // pass the elements, which is always safe. Argument *PtrArg = PointerArgs[i].first; if (isByVal) { const Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType(); if (const StructType *STy = dyn_cast<StructType>(AgTy)) { if (maxElements > 0 && STy->getNumElements() > maxElements) { DEBUG(dbgs() << "argpromotion disable promoting argument '" << PtrArg->getName() << "' because it would require adding more" << " than " << maxElements << " arguments to the function.\n"); } else { // If all the elements are single-value types, we can promote it. bool AllSimple = true; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) if (!STy->getElementType(i)->isSingleValueType()) { AllSimple = false; break; } // Safe to transform, don't even bother trying to "promote" it. // Passing the elements as a scalar will allow scalarrepl to hack on // the new alloca we introduce. if (AllSimple) { ByValArgsToTransform.insert(PtrArg); continue; } } } } // Otherwise, see if we can promote the pointer to its value. if (isSafeToPromoteArgument(PtrArg, isByVal)) ArgsToPromote.insert(PtrArg); } // No promotable pointer arguments. if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) return 0; return DoPromotion(F, ArgsToPromote, ByValArgsToTransform); }
/// PromoteArguments - This method checks the specified function to see if there /// are any promotable arguments and if it is safe to promote the function (for /// example, all callers are direct). If safe to promote some arguments, it /// calls the DoPromotion method. /// CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { Function *F = CGN->getFunction(); // Make sure that it is local to this module. if (!F || !F->hasLocalLinkage()) return nullptr; // First check: see if there are any pointer arguments! If not, quick exit. SmallVector<Argument*, 16> PointerArgs; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) if (I->getType()->isPointerTy()) PointerArgs.push_back(I); if (PointerArgs.empty()) return nullptr; // Second check: make sure that all callers are direct callers. We can't // transform functions that have indirect callers. Also see if the function // is self-recursive. bool isSelfRecursive = false; for (Use &U : F->uses()) { CallSite CS(U.getUser()); // Must be a direct call. if (CS.getInstruction() == nullptr || !CS.isCallee(&U)) return nullptr; if (CS.getInstruction()->getParent()->getParent() == F) isSelfRecursive = true; } // Don't promote arguments for variadic functions. Adding, removing, or // changing non-pack parameters can change the classification of pack // parameters. Frontends encode that classification at the call site in the // IR, while in the callee the classification is determined dynamically based // on the number of registers consumed so far. if (F->isVarArg()) return nullptr; // Check to see which arguments are promotable. If an argument is promotable, // add it to ArgsToPromote. SmallPtrSet<Argument*, 8> ArgsToPromote; SmallPtrSet<Argument*, 8> ByValArgsToTransform; for (unsigned i = 0, e = PointerArgs.size(); i != e; ++i) { Argument *PtrArg = PointerArgs[i]; Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType(); // If this is a byval argument, and if the aggregate type is small, just // pass the elements, which is always safe, if the passed value is densely // packed or if we can prove the padding bytes are never accessed. This does // not apply to inalloca. bool isSafeToPromote = PtrArg->hasByValAttr() && (isDenselyPacked(AgTy) || !canPaddingBeAccessed(PtrArg)); if (isSafeToPromote) { if (StructType *STy = dyn_cast<StructType>(AgTy)) { if (maxElements > 0 && STy->getNumElements() > maxElements) { DEBUG(dbgs() << "argpromotion disable promoting argument '" << PtrArg->getName() << "' because it would require adding more" << " than " << maxElements << " arguments to the function.\n"); continue; } // If all the elements are single-value types, we can promote it. bool AllSimple = true; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { if (!STy->getElementType(i)->isSingleValueType()) { AllSimple = false; break; } } // Safe to transform, don't even bother trying to "promote" it. // Passing the elements as a scalar will allow scalarrepl to hack on // the new alloca we introduce. if (AllSimple) { ByValArgsToTransform.insert(PtrArg); continue; } } } // If the argument is a recursive type and we're in a recursive // function, we could end up infinitely peeling the function argument. if (isSelfRecursive) { if (StructType *STy = dyn_cast<StructType>(AgTy)) { bool RecursiveType = false; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { if (STy->getElementType(i) == PtrArg->getType()) { RecursiveType = true; break; } } if (RecursiveType) continue; } } // Otherwise, see if we can promote the pointer to its value. if (isSafeToPromoteArgument(PtrArg, PtrArg->hasByValOrInAllocaAttr())) ArgsToPromote.insert(PtrArg); } // No promotable pointer arguments. if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) return nullptr; return DoPromotion(F, ArgsToPromote, ByValArgsToTransform); }
/// PromoteArguments - This method checks the specified function to see if there /// are any promotable arguments and if it is safe to promote the function (for /// example, all callers are direct). If safe to promote some arguments, it /// calls the DoPromotion method. /// CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { Function *F = CGN->getFunction(); // Make sure that it is local to this module. if (!F || !F->hasLocalLinkage()) return nullptr; // Don't promote arguments for variadic functions. Adding, removing, or // changing non-pack parameters can change the classification of pack // parameters. Frontends encode that classification at the call site in the // IR, while in the callee the classification is determined dynamically based // on the number of registers consumed so far. if (F->isVarArg()) return nullptr; // First check: see if there are any pointer arguments! If not, quick exit. SmallVector<Argument*, 16> PointerArgs; for (Argument &I : F->args()) if (I.getType()->isPointerTy()) PointerArgs.push_back(&I); if (PointerArgs.empty()) return nullptr; // Second check: make sure that all callers are direct callers. We can't // transform functions that have indirect callers. Also see if the function // is self-recursive. bool isSelfRecursive = false; for (Use &U : F->uses()) { CallSite CS(U.getUser()); // Must be a direct call. if (CS.getInstruction() == nullptr || !CS.isCallee(&U)) return nullptr; if (CS.getInstruction()->getParent()->getParent() == F) isSelfRecursive = true; } const DataLayout &DL = F->getParent()->getDataLayout(); // We need to manually construct BasicAA directly in order to disable its use // of other function analyses. BasicAAResult BAR(createLegacyPMBasicAAResult(*this, *F)); // Construct our own AA results for this function. We do this manually to // work around the limitations of the legacy pass manager. AAResults AAR(createLegacyPMAAResults(*this, *F, BAR)); // Check to see which arguments are promotable. If an argument is promotable, // add it to ArgsToPromote. SmallPtrSet<Argument*, 8> ArgsToPromote; SmallPtrSet<Argument*, 8> ByValArgsToTransform; for (unsigned i = 0, e = PointerArgs.size(); i != e; ++i) { Argument *PtrArg = PointerArgs[i]; Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType(); // Replace sret attribute with noalias. This reduces register pressure by // avoiding a register copy. if (PtrArg->hasStructRetAttr()) { unsigned ArgNo = PtrArg->getArgNo(); F->setAttributes( F->getAttributes() .removeAttribute(F->getContext(), ArgNo + 1, Attribute::StructRet) .addAttribute(F->getContext(), ArgNo + 1, Attribute::NoAlias)); for (Use &U : F->uses()) { CallSite CS(U.getUser()); CS.setAttributes( CS.getAttributes() .removeAttribute(F->getContext(), ArgNo + 1, Attribute::StructRet) .addAttribute(F->getContext(), ArgNo + 1, Attribute::NoAlias)); } } // If this is a byval argument, and if the aggregate type is small, just // pass the elements, which is always safe, if the passed value is densely // packed or if we can prove the padding bytes are never accessed. This does // not apply to inalloca. bool isSafeToPromote = PtrArg->hasByValAttr() && (isDenselyPacked(AgTy, DL) || !canPaddingBeAccessed(PtrArg)); if (isSafeToPromote) { if (StructType *STy = dyn_cast<StructType>(AgTy)) { if (maxElements > 0 && STy->getNumElements() > maxElements) { DEBUG(dbgs() << "argpromotion disable promoting argument '" << PtrArg->getName() << "' because it would require adding more" << " than " << maxElements << " arguments to the function.\n"); continue; } // If all the elements are single-value types, we can promote it. bool AllSimple = true; for (const auto *EltTy : STy->elements()) { if (!EltTy->isSingleValueType()) { AllSimple = false; break; } } // Safe to transform, don't even bother trying to "promote" it. // Passing the elements as a scalar will allow sroa to hack on // the new alloca we introduce. if (AllSimple) { ByValArgsToTransform.insert(PtrArg); continue; } } } // If the argument is a recursive type and we're in a recursive // function, we could end up infinitely peeling the function argument. if (isSelfRecursive) { if (StructType *STy = dyn_cast<StructType>(AgTy)) { bool RecursiveType = false; for (const auto *EltTy : STy->elements()) { if (EltTy == PtrArg->getType()) { RecursiveType = true; break; } } if (RecursiveType) continue; } } // Otherwise, see if we can promote the pointer to its value. if (isSafeToPromoteArgument(PtrArg, PtrArg->hasByValOrInAllocaAttr(), AAR)) ArgsToPromote.insert(PtrArg); } // No promotable pointer arguments. if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) return nullptr; return DoPromotion(F, ArgsToPromote, ByValArgsToTransform); }
void HeterotbbTransform::gen_opt_code_per_f (Function* NF, Function* F) { // Get the names of the parameters for old function Function::arg_iterator FI = F->arg_begin(); Argument *classname = &*FI; FI++; Argument *numiters = &*FI; // Set the names of the parameters for new function Function::arg_iterator DestI = NF->arg_begin(); DestI->setName(classname->getName()); Argument *class_name = &(*DestI); //second argument DestI++; DestI->setName(numiters->getName()); Argument *num_iters = &(*DestI); #ifdef EXPLICIT_REWRITE DenseMap<const Value*, Value *> ValueMap; #else ValueToValueMapTy ValueMap; #endif #if EXPLICIT_REWRITE //get the old basic block and create a new one Function::const_iterator BI = F->begin(); const BasicBlock &FB = *BI; BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF); if (FB.hasName()) { NFBB->setName(FB.getName()); //DEBUG(dbgs()<<FB.getName()<<"\n"); } ValueMap[&FB] = NFBB; ValueMap[numiters] = num_iters; //must create a new instruction which casts i32* back to the class name CastInst *StrucRevCast = CastInst::Create(Instruction::BitCast, class_name, classname->getType(), classname->getName(), NFBB); ValueMap[classname] = StrucRevCast; for (BasicBlock::const_iterator II = FB.begin(), IE = FB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); // DEBUG(dbgs()<<*II<<"\n"); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } BI++; for (Function::const_iterator /*BI=F->begin(),*/BE = F->end(); BI != BE; ++BI) { const BasicBlock &FBB = *BI; BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF); ValueMap[&FBB] = NFBB; if (FBB.hasName()) { NFBB->setName(FBB.getName()); //DEBUG(dbgs()<<NFBB->getName()<<"\n"); } for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } } // Remap the instructions again to take care of forward jumps for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) { for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) { int opIdx = 0; //DEBUG(dbgs()<<*II<<"\n"); for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) { Value *V = *i; if (ValueMap[V] != NULL) { II->setOperand(opIdx, ValueMap[V]); } } } } #else Function::const_iterator BI = F->begin(); const BasicBlock &FB = *BI; BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF); if (FB.hasName()) { NFBB->setName(FB.getName()); } ValueMap[&FB] = NFBB; CastInst *StrucRevCast = CastInst::Create(Instruction::BitCast, class_name, classname->getType(), classname->getName(), NFBB); ValueMap[classname] = StrucRevCast; ValueMap[numiters] = num_iters; CloneFunctionWithExistingBBInto(NF, NFBB, F, ValueMap, ""); #endif }
/** * Generate code for */ void HeteroOMPTransform::gen_code_per_f (Function* NF, Function* F, Instruction *max_threads){ Function::arg_iterator FI = F->arg_begin(); Argument *ctxname = &*FI; Function::arg_iterator DestI = NF->arg_begin(); DestI->setName(ctxname->getName()); Argument *ctx_name = &(*DestI); DestI++; DestI->setName("tid"); Argument *num_iters = &(*DestI); #ifdef EXPLICIT_REWRITE DenseMap<const Value*, Value *> ValueMap; #else ValueToValueMapTy ValueMap; #endif //get the old basic block and create a new one Function::const_iterator BI = F->begin(); const BasicBlock &FB = *BI; BasicBlock *NFBB = BasicBlock::Create(FB.getContext(), "", NF); if (FB.hasName()){ NFBB->setName(FB.getName()); } ValueMap[&FB] = NFBB; //ValueMap[numiters] = num_iters; ValueMap[ctxname] = ctx_name; #if EXPLICIT_REWRITE for (BasicBlock::const_iterator II = FB.begin(), IE = FB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); // DEBUG(dbgs()<<*II<<"\n"); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } BI++; for (Function::const_iterator /*BI=F->begin(),*/BE = F->end();BI != BE; ++BI) { const BasicBlock &FBB = *BI; BasicBlock *NFBB = BasicBlock::Create(FBB.getContext(), "", NF); ValueMap[&FBB] = NFBB; if (FBB.hasName()){ NFBB->setName(FBB.getName()); //DEBUG(dbgs()<<NFBB->getName()<<"\n"); } for (BasicBlock::const_iterator II = FBB.begin(), IE = FBB.end(); II != IE; ++II) { Instruction *NFInst = II->clone(/*F->getContext()*/); if (II->hasName()) NFInst->setName(II->getName()); const Instruction *FInst = &(*II); rewrite_instruction((Instruction *)FInst, NFInst, ValueMap); NFBB->getInstList().push_back(NFInst); ValueMap[II] = NFInst; } } // Remap the instructions again to take care of forward jumps for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) { for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II){ int opIdx = 0; //DEBUG(dbgs()<<*II<<"\n"); for (User::op_iterator i = II->op_begin(), e = II->op_end(); i != e; ++i, opIdx++) { Value *V = *i; if (ValueMap[V] != NULL) { II->setOperand(opIdx, ValueMap[V]); } } } } #else SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned. CloneFunctionInto(NF, F, ValueMap, false, Returns, ""); #endif //max_threads->dump(); /* Remap openmp omp_num_threads() and omp_thread_num() */ /* * define internal void @_Z20initialize_variablesiPfS_.omp_fn.4(i8* nocapture %.omp_data_i) nounwind ssp { * entry: * %0 = bitcast i8* %.omp_data_i to i32* ; <i32*> [#uses=1] * %1 = load i32* %0, align 8 ; <i32> [#uses=2] * %2 = tail call i32 @omp_get_num_threads() nounwind readnone ; <i32> [#uses=2] * %3 = tail call i32 @omp_get_thread_num() nounwind readnone ; <i32> [#uses=2] %4 = sdiv i32 %1, %2 %5 = mul nsw i32 %4, %2 %6 = icmp ne i32 %5, %1 %7 = zext i1 %6 to i32 */ vector<Instruction *> toDelete; for (Function::iterator BB = NF->begin(), BE=NF->end(); BB != BE; ++ BB) { for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II){ if (isa<CallInst>(II)) { CallSite CI(cast<Instruction>(II)); if (CI.getCalledFunction() != NULL){ string called_func_name = CI.getCalledFunction()->getName(); if (called_func_name == OMP_GET_NUM_THREADS_NAME && CI.arg_size() == 0) { II->replaceAllUsesWith(ValueMap[max_threads]); toDelete.push_back(II); } else if (called_func_name == OMP_GET_THREAD_NUM_NAME && CI.arg_size() == 0) { II->replaceAllUsesWith(num_iters); toDelete.push_back(II); } } } } } /* Delete the last branch instruction of the first basic block -- Assuming it is safe */ Function::iterator nfBB = NF->begin(); TerminatorInst *lastI = nfBB->getTerminator(); BranchInst *bI; BasicBlock *returnBlock; if ((bI = dyn_cast<BranchInst>(lastI)) && bI->isConditional() && (returnBlock = bI->getSuccessor(1)) && (returnBlock->getName() == "return")) { /* modify to a unconditional branch to next basic block and not return */ Instruction *bbI = BranchInst::Create(bI->getSuccessor(0),lastI); bbI->dump(); toDelete.push_back(lastI); } //NF->dump(); while(!toDelete.empty()) { Instruction *g = toDelete.back(); //g->replaceAllUsesWith(UndefValue::get(g->getType())); toDelete.pop_back(); g->eraseFromParent(); } //NF->dump(); }
/// PromoteArguments - This method checks the specified function to see if there /// are any promotable arguments and if it is safe to promote the function (for /// example, all callers are direct). If safe to promote some arguments, it /// calls the DoPromotion method. /// CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { Function *F = CGN->getFunction(); // Make sure that it is local to this module. if (!F || !F->hasLocalLinkage()) return 0; // First check: see if there are any pointer arguments! If not, quick exit. SmallVector<Argument*, 16> PointerArgs; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) if (I->getType()->isPointerTy()) PointerArgs.push_back(I); if (PointerArgs.empty()) return 0; // Second check: make sure that all callers are direct callers. We can't // transform functions that have indirect callers. Also see if the function // is self-recursive. bool isSelfRecursive = false; for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E; ++UI) { CallSite CS(*UI); // Must be a direct call. if (CS.getInstruction() == 0 || !CS.isCallee(UI)) return 0; if (CS.getInstruction()->getParent()->getParent() == F) isSelfRecursive = true; } // Check to see which arguments are promotable. If an argument is promotable, // add it to ArgsToPromote. SmallPtrSet<Argument*, 8> ArgsToPromote; SmallPtrSet<Argument*, 8> ByValArgsToTransform; for (unsigned i = 0, e = PointerArgs.size(); i != e; ++i) { Argument *PtrArg = PointerArgs[i]; Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType(); // If this is a byval argument, and if the aggregate type is small, just // pass the elements, which is always safe. if (PtrArg->hasByValAttr()) { if (StructType *STy = dyn_cast<StructType>(AgTy)) { if (maxElements > 0 && STy->getNumElements() > maxElements) { DEBUG(dbgs() << "argpromotion disable promoting argument '" << PtrArg->getName() << "' because it would require adding more" << " than " << maxElements << " arguments to the function.\n"); continue; } // If all the elements are single-value types, we can promote it. bool AllSimple = true; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { if (!STy->getElementType(i)->isSingleValueType()) { AllSimple = false; break; } } // Safe to transform, don't even bother trying to "promote" it. // Passing the elements as a scalar will allow scalarrepl to hack on // the new alloca we introduce. if (AllSimple) { ByValArgsToTransform.insert(PtrArg); continue; } } } // If the argument is a recursive type and we're in a recursive // function, we could end up infinitely peeling the function argument. if (isSelfRecursive) { if (StructType *STy = dyn_cast<StructType>(AgTy)) { bool RecursiveType = false; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { if (STy->getElementType(i) == PtrArg->getType()) { RecursiveType = true; break; } } if (RecursiveType) continue; } } // Otherwise, see if we can promote the pointer to its value. if (isSafeToPromoteArgument(PtrArg, PtrArg->hasByValAttr())) ArgsToPromote.insert(PtrArg); } // No promotable pointer arguments. if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) return 0; return DoPromotion(F, ArgsToPromote, ByValArgsToTransform); }