Add a number of threshold arguments to the SRA pass.

A patch by Tom Stellard with minor changes.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158918 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nadav Rotem 2012-06-21 13:44:31 +00:00
parent e42e9ce20f
commit 2114a8aaba
2 changed files with 64 additions and 19 deletions

View File

@ -74,7 +74,10 @@ FunctionPass *createAggressiveDCEPass();
// if possible. // if possible.
// //
FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1, FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1,
bool UseDomTree = true); bool UseDomTree = true,
signed StructMemberThreshold = -1,
signed ArrayElementThreshold = -1,
signed ScalarLoadThreshold = -1);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //

View File

@ -60,12 +60,25 @@ STATISTIC(NumGlobals, "Number of allocas copied from constant global");
namespace { namespace {
struct SROA : public FunctionPass { struct SROA : public FunctionPass {
SROA(int T, bool hasDT, char &ID) SROA(int T, bool hasDT, char &ID, int ST, int AT, int SLT)
: FunctionPass(ID), HasDomTree(hasDT) { : FunctionPass(ID), HasDomTree(hasDT) {
if (T == -1) if (T == -1)
SRThreshold = 128; SRThreshold = 128;
else else
SRThreshold = T; SRThreshold = T;
if (ST == -1)
StructMemberThreshold = 32;
else
StructMemberThreshold = ST;
if (AT == -1)
ArrayElementThreshold = 8;
else
ArrayElementThreshold = AT;
if (SLT == -1)
// Do not limit the scalar integer load size if no threshold is given.
ScalarLoadThreshold = -1;
else
ScalarLoadThreshold = SLT;
} }
bool runOnFunction(Function &F); bool runOnFunction(Function &F);
@ -116,8 +129,21 @@ namespace {
hasSubelementAccess(false), hasALoadOrStore(false) {} hasSubelementAccess(false), hasALoadOrStore(false) {}
}; };
/// SRThreshold - The maximum alloca size to considered for SROA.
unsigned SRThreshold; unsigned SRThreshold;
/// StructMemberThreshold - The maximum number of members a struct can
/// contain to be considered for SROA.
unsigned StructMemberThreshold;
/// ArrayElementThreshold - The maximum number of elements an array can
/// have to be considered for SROA.
unsigned ArrayElementThreshold;
/// ScalarLoadThreshold - The maximum size in bits of scalars to load when
/// converting to scalar
unsigned ScalarLoadThreshold;
void MarkUnsafe(AllocaInfo &I, Instruction *User) { void MarkUnsafe(AllocaInfo &I, Instruction *User) {
I.isUnsafe = true; I.isUnsafe = true;
DEBUG(dbgs() << " Transformation preventing inst: " << *User << '\n'); DEBUG(dbgs() << " Transformation preventing inst: " << *User << '\n');
@ -156,6 +182,7 @@ namespace {
SmallVector<AllocaInst*, 32> &NewElts); SmallVector<AllocaInst*, 32> &NewElts);
void RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, void RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI,
SmallVector<AllocaInst*, 32> &NewElts); SmallVector<AllocaInst*, 32> &NewElts);
bool ShouldAttemptScalarRepl(AllocaInst *AI);
static MemTransferInst *isOnlyCopiedFromConstantGlobal( static MemTransferInst *isOnlyCopiedFromConstantGlobal(
AllocaInst *AI, SmallVector<Instruction*, 4> &ToDelete); AllocaInst *AI, SmallVector<Instruction*, 4> &ToDelete);
@ -165,7 +192,8 @@ namespace {
struct SROA_DT : public SROA { struct SROA_DT : public SROA {
static char ID; static char ID;
public: public:
SROA_DT(int T = -1) : SROA(T, true, ID) { SROA_DT(int T = -1, int ST = -1, int AT = -1, int SLT = -1) :
SROA(T, true, ID, ST, AT, SLT) {
initializeSROA_DTPass(*PassRegistry::getPassRegistry()); initializeSROA_DTPass(*PassRegistry::getPassRegistry());
} }
@ -181,7 +209,8 @@ namespace {
struct SROA_SSAUp : public SROA { struct SROA_SSAUp : public SROA {
static char ID; static char ID;
public: public:
SROA_SSAUp(int T = -1) : SROA(T, false, ID) { SROA_SSAUp(int T = -1, int ST = -1, int AT = -1, int SLT = -1) :
SROA(T, false, ID, ST, AT, SLT) {
initializeSROA_SSAUpPass(*PassRegistry::getPassRegistry()); initializeSROA_SSAUpPass(*PassRegistry::getPassRegistry());
} }
@ -210,10 +239,15 @@ INITIALIZE_PASS_END(SROA_SSAUp, "scalarrepl-ssa",
// Public interface to the ScalarReplAggregates pass // Public interface to the ScalarReplAggregates pass
FunctionPass *llvm::createScalarReplAggregatesPass(int Threshold, FunctionPass *llvm::createScalarReplAggregatesPass(int Threshold,
bool UseDomTree) { bool UseDomTree,
int StructMemberThreshold,
int ArrayElementThreshold,
int ScalarLoadThreshold) {
if (UseDomTree) if (UseDomTree)
return new SROA_DT(Threshold); return new SROA_DT(Threshold, StructMemberThreshold, ArrayElementThreshold,
return new SROA_SSAUp(Threshold); ScalarLoadThreshold);
return new SROA_SSAUp(Threshold, StructMemberThreshold,
ArrayElementThreshold, ScalarLoadThreshold);
} }
@ -229,6 +263,7 @@ class ConvertToScalarInfo {
/// AllocaSize - The size of the alloca being considered in bytes. /// AllocaSize - The size of the alloca being considered in bytes.
unsigned AllocaSize; unsigned AllocaSize;
const TargetData &TD; const TargetData &TD;
unsigned ScalarLoadThreshold;
/// IsNotTrivial - This is set to true if there is some access to the object /// IsNotTrivial - This is set to true if there is some access to the object
/// which means that mem2reg can't promote it. /// which means that mem2reg can't promote it.
@ -270,9 +305,11 @@ class ConvertToScalarInfo {
bool HadDynamicAccess; bool HadDynamicAccess;
public: public:
explicit ConvertToScalarInfo(unsigned Size, const TargetData &td) explicit ConvertToScalarInfo(unsigned Size, const TargetData &td,
: AllocaSize(Size), TD(td), IsNotTrivial(false), ScalarKind(Unknown), unsigned SLT)
VectorTy(0), HadNonMemTransferAccess(false), HadDynamicAccess(false) { } : AllocaSize(Size), TD(td), ScalarLoadThreshold(SLT), IsNotTrivial(false),
ScalarKind(Unknown), VectorTy(0), HadNonMemTransferAccess(false),
HadDynamicAccess(false) { }
AllocaInst *TryConvert(AllocaInst *AI); AllocaInst *TryConvert(AllocaInst *AI);
@ -324,6 +361,12 @@ AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) {
NewTy = VectorTy; // Use the vector type. NewTy = VectorTy; // Use the vector type.
} else { } else {
unsigned BitWidth = AllocaSize * 8; unsigned BitWidth = AllocaSize * 8;
// Do not convert to scalar integer if the alloca size exceeds the
// scalar load threshold.
if (BitWidth > ScalarLoadThreshold)
return 0;
if ((ScalarKind == ImplicitVector || ScalarKind == Integer) && if ((ScalarKind == ImplicitVector || ScalarKind == Integer) &&
!HadNonMemTransferAccess && !TD.fitsInLegalInteger(BitWidth)) !HadNonMemTransferAccess && !TD.fitsInLegalInteger(BitWidth))
return 0; return 0;
@ -1406,15 +1449,14 @@ bool SROA::performPromotion(Function &F) {
/// ShouldAttemptScalarRepl - Decide if an alloca is a good candidate for /// ShouldAttemptScalarRepl - Decide if an alloca is a good candidate for
/// SROA. It must be a struct or array type with a small number of elements. /// SROA. It must be a struct or array type with a small number of elements.
static bool ShouldAttemptScalarRepl(AllocaInst *AI) { bool SROA::ShouldAttemptScalarRepl(AllocaInst *AI) {
Type *T = AI->getAllocatedType(); Type *T = AI->getAllocatedType();
// Do not promote any struct into more than 32 separate vars. // Do not promote any struct that has too many members.
if (StructType *ST = dyn_cast<StructType>(T)) if (StructType *ST = dyn_cast<StructType>(T))
return ST->getNumElements() <= 32; return ST->getNumElements() <= StructMemberThreshold;
// Arrays are much less likely to be safe for SROA; only consider // Do not promote any array that has too many elements.
// them if they are very small.
if (ArrayType *AT = dyn_cast<ArrayType>(T)) if (ArrayType *AT = dyn_cast<ArrayType>(T))
return AT->getNumElements() <= 8; return AT->getNumElements() <= ArrayElementThreshold;
return false; return false;
} }
@ -1519,8 +1561,8 @@ bool SROA::performScalarRepl(Function &F) {
// promoted itself. If so, we don't want to transform it needlessly. Note // promoted itself. If so, we don't want to transform it needlessly. Note
// that we can't just check based on the type: the alloca may be of an i32 // that we can't just check based on the type: the alloca may be of an i32
// but that has pointer arithmetic to set byte 3 of it or something. // but that has pointer arithmetic to set byte 3 of it or something.
if (AllocaInst *NewAI = if (AllocaInst *NewAI = ConvertToScalarInfo(
ConvertToScalarInfo((unsigned)AllocaSize, *TD).TryConvert(AI)) { (unsigned)AllocaSize, *TD, ScalarLoadThreshold).TryConvert(AI)) {
NewAI->takeName(AI); NewAI->takeName(AI);
AI->eraseFromParent(); AI->eraseFromParent();
++NumConverted; ++NumConverted;