mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
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:
parent
e42e9ce20f
commit
2114a8aaba
@ -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);
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user