Allow argpromote to promote struct arguments with a specified number

of elements.  Patch by Matthijs Kooijman!

llvm-svn: 49962
This commit is contained in:
Chris Lattner 2008-04-19 19:50:01 +00:00
parent 575f24ef73
commit eb6bb803a7
2 changed files with 20 additions and 12 deletions

View File

@ -123,9 +123,10 @@ ModulePass *createDeadArgHackingPass();
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// createArgumentPromotionPass - This pass promotes "by reference" arguments to /// createArgumentPromotionPass - This pass promotes "by reference" arguments to
/// be passed by value. /// be passed by value if the number of elements passed is smaller or
/// equal to maxElements (maxElements == 0 means always promote).
/// ///
Pass *createArgumentPromotionPass(); Pass *createArgumentPromotionPass(unsigned maxElements = 3);
Pass *createStructRetPromotionPass(); Pass *createStructRetPromotionPass();
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -17,9 +17,10 @@
// //
// This pass also handles aggregate arguments that are passed into a function, // This pass also handles aggregate arguments that are passed into a function,
// scalarizing them if the elements of the aggregate are only loaded. Note that // scalarizing them if the elements of the aggregate are only loaded. Note that
// it refuses to scalarize aggregates which would require passing in more than // by default it refuses to scalarize aggregates which would require passing in more than
// three operands to the function, because passing thousands of operands for a // three operands to the function, because passing thousands of operands for a
// large array or structure is unprofitable! // large array or structure is unprofitable! This limit is can be configured or
// disabled, however.
// //
// Note that this transformation could also be done for arguments that are only // Note that this transformation could also be done for arguments that are only
// stored to (returning the value instead), but does not currently. This case // stored to (returning the value instead), but does not currently. This case
@ -65,7 +66,7 @@ namespace {
virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC); virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC);
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
ArgPromotion() : CallGraphSCCPass((intptr_t)&ID) {} ArgPromotion(unsigned maxElements = 3) : CallGraphSCCPass((intptr_t)&ID), maxElements(maxElements) {}
private: private:
bool PromoteArguments(CallGraphNode *CGN); bool PromoteArguments(CallGraphNode *CGN);
@ -73,6 +74,8 @@ namespace {
Function *DoPromotion(Function *F, Function *DoPromotion(Function *F,
SmallPtrSet<Argument*, 8> &ArgsToPromote, SmallPtrSet<Argument*, 8> &ArgsToPromote,
SmallPtrSet<Argument*, 8> &ByValArgsToTransform); SmallPtrSet<Argument*, 8> &ByValArgsToTransform);
/// The maximum number of elements to expand, or 0 for unlimited.
unsigned maxElements;
}; };
char ArgPromotion::ID = 0; char ArgPromotion::ID = 0;
@ -80,8 +83,8 @@ namespace {
"Promote 'by reference' arguments to scalars"); "Promote 'by reference' arguments to scalars");
} }
Pass *llvm::createArgumentPromotionPass() { Pass *llvm::createArgumentPromotionPass(unsigned maxElements) {
return new ArgPromotion(); return new ArgPromotion(maxElements);
} }
bool ArgPromotion::runOnSCC(const std::vector<CallGraphNode *> &SCC) { bool ArgPromotion::runOnSCC(const std::vector<CallGraphNode *> &SCC) {
@ -145,7 +148,11 @@ bool ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
if (isByVal) { if (isByVal) {
const Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType(); const Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
if (const StructType *STy = dyn_cast<StructType>(AgTy)) if (const StructType *STy = dyn_cast<StructType>(AgTy))
if (STy->getNumElements() <= 3) { if (maxElements > 0 && STy->getNumElements() > maxElements) {
DOUT << "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 first class types, we can promote it. // If all the elements are first class types, we can promote it.
bool AllSimple = true; bool AllSimple = true;
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
@ -278,12 +285,12 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg, bool isByVal) const {
// to do. // to do.
if (std::find(GEPIndices.begin(), GEPIndices.end(), Operands) == if (std::find(GEPIndices.begin(), GEPIndices.end(), Operands) ==
GEPIndices.end()) { GEPIndices.end()) {
if (GEPIndices.size() == 3) { if (maxElements > 0 && GEPIndices.size() == maxElements) {
DOUT << "argpromotion disable promoting argument '" DOUT << "argpromotion disable promoting argument '"
<< Arg->getName() << "' because it would require adding more " << Arg->getName() << "' because it would require adding more "
<< "than 3 arguments to the function.\n"; << "than " << maxElements << " arguments to the function.\n";
// We limit aggregate promotion to only promoting up to three elements // We limit aggregate promotion to only promoting up to a fixed number
// of the aggregate. // of elements of the aggregate.
return false; return false;
} }
GEPIndices.push_back(Operands); GEPIndices.push_back(Operands);