mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-24 22:24:54 +00:00
[SROA] Start more deeply moving SROA to use ranges rather than just
iterators. There are a ton of places where it essentially wants ranges rather than just iterators. This is just the first step that adds the core slice range typedefs and uses them in a couple of places. I still have to explicitly construct them because they've not been punched throughout the entire set of code. More range-based cleanups incoming. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219955 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -225,10 +225,12 @@ public:
|
|||||||
/// \brief Support for iterating over the slices.
|
/// \brief Support for iterating over the slices.
|
||||||
/// @{
|
/// @{
|
||||||
typedef SmallVectorImpl<Slice>::iterator iterator;
|
typedef SmallVectorImpl<Slice>::iterator iterator;
|
||||||
|
typedef iterator_range<iterator> range;
|
||||||
iterator begin() { return Slices.begin(); }
|
iterator begin() { return Slices.begin(); }
|
||||||
iterator end() { return Slices.end(); }
|
iterator end() { return Slices.end(); }
|
||||||
|
|
||||||
typedef SmallVectorImpl<Slice>::const_iterator const_iterator;
|
typedef SmallVectorImpl<Slice>::const_iterator const_iterator;
|
||||||
|
typedef iterator_range<const_iterator> const_range;
|
||||||
const_iterator begin() const { return Slices.begin(); }
|
const_iterator begin() const { return Slices.begin(); }
|
||||||
const_iterator end() const { return Slices.end(); }
|
const_iterator end() const { return Slices.end(); }
|
||||||
/// @}
|
/// @}
|
||||||
@@ -1629,38 +1631,38 @@ static Value *convertValue(const DataLayout &DL, IRBuilderTy &IRB, Value *V,
|
|||||||
///
|
///
|
||||||
/// This function is called to test each entry in a partioning which is slated
|
/// This function is called to test each entry in a partioning which is slated
|
||||||
/// for a single slice.
|
/// for a single slice.
|
||||||
static bool isVectorPromotionViableForSlice(
|
static bool
|
||||||
const DataLayout &DL, AllocaSlices &S, uint64_t SliceBeginOffset,
|
isVectorPromotionViableForSlice(const DataLayout &DL, uint64_t SliceBeginOffset,
|
||||||
uint64_t SliceEndOffset, VectorType *Ty, uint64_t ElementSize,
|
uint64_t SliceEndOffset, VectorType *Ty,
|
||||||
AllocaSlices::const_iterator I) {
|
uint64_t ElementSize, const Slice &S) {
|
||||||
// First validate the slice offsets.
|
// First validate the slice offsets.
|
||||||
uint64_t BeginOffset =
|
uint64_t BeginOffset =
|
||||||
std::max(I->beginOffset(), SliceBeginOffset) - SliceBeginOffset;
|
std::max(S.beginOffset(), SliceBeginOffset) - SliceBeginOffset;
|
||||||
uint64_t BeginIndex = BeginOffset / ElementSize;
|
uint64_t BeginIndex = BeginOffset / ElementSize;
|
||||||
if (BeginIndex * ElementSize != BeginOffset ||
|
if (BeginIndex * ElementSize != BeginOffset ||
|
||||||
BeginIndex >= Ty->getNumElements())
|
BeginIndex >= Ty->getNumElements())
|
||||||
return false;
|
return false;
|
||||||
uint64_t EndOffset =
|
uint64_t EndOffset =
|
||||||
std::min(I->endOffset(), SliceEndOffset) - SliceBeginOffset;
|
std::min(S.endOffset(), SliceEndOffset) - SliceBeginOffset;
|
||||||
uint64_t EndIndex = EndOffset / ElementSize;
|
uint64_t EndIndex = EndOffset / ElementSize;
|
||||||
if (EndIndex * ElementSize != EndOffset || EndIndex > Ty->getNumElements())
|
if (EndIndex * ElementSize != EndOffset || EndIndex > Ty->getNumElements())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert(EndIndex > BeginIndex && "Empty vector!");
|
assert(EndIndex > BeginIndex && "Empty vector!");
|
||||||
uint64_t NumElements = EndIndex - BeginIndex;
|
uint64_t NumElements = EndIndex - BeginIndex;
|
||||||
Type *SliceTy =
|
Type *SliceTy = (NumElements == 1)
|
||||||
(NumElements == 1) ? Ty->getElementType()
|
? Ty->getElementType()
|
||||||
: VectorType::get(Ty->getElementType(), NumElements);
|
: VectorType::get(Ty->getElementType(), NumElements);
|
||||||
|
|
||||||
Type *SplitIntTy =
|
Type *SplitIntTy =
|
||||||
Type::getIntNTy(Ty->getContext(), NumElements * ElementSize * 8);
|
Type::getIntNTy(Ty->getContext(), NumElements * ElementSize * 8);
|
||||||
|
|
||||||
Use *U = I->getUse();
|
Use *U = S.getUse();
|
||||||
|
|
||||||
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U->getUser())) {
|
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U->getUser())) {
|
||||||
if (MI->isVolatile())
|
if (MI->isVolatile())
|
||||||
return false;
|
return false;
|
||||||
if (!I->isSplittable())
|
if (!S.isSplittable())
|
||||||
return false; // Skip any unsplittable intrinsics.
|
return false; // Skip any unsplittable intrinsics.
|
||||||
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
|
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
|
||||||
if (II->getIntrinsicID() != Intrinsic::lifetime_start &&
|
if (II->getIntrinsicID() != Intrinsic::lifetime_start &&
|
||||||
@@ -1673,8 +1675,7 @@ static bool isVectorPromotionViableForSlice(
|
|||||||
if (LI->isVolatile())
|
if (LI->isVolatile())
|
||||||
return false;
|
return false;
|
||||||
Type *LTy = LI->getType();
|
Type *LTy = LI->getType();
|
||||||
if (SliceBeginOffset > I->beginOffset() ||
|
if (SliceBeginOffset > S.beginOffset() || SliceEndOffset < S.endOffset()) {
|
||||||
SliceEndOffset < I->endOffset()) {
|
|
||||||
assert(LTy->isIntegerTy());
|
assert(LTy->isIntegerTy());
|
||||||
LTy = SplitIntTy;
|
LTy = SplitIntTy;
|
||||||
}
|
}
|
||||||
@@ -1684,8 +1685,7 @@ static bool isVectorPromotionViableForSlice(
|
|||||||
if (SI->isVolatile())
|
if (SI->isVolatile())
|
||||||
return false;
|
return false;
|
||||||
Type *STy = SI->getValueOperand()->getType();
|
Type *STy = SI->getValueOperand()->getType();
|
||||||
if (SliceBeginOffset > I->beginOffset() ||
|
if (SliceBeginOffset > S.beginOffset() || SliceEndOffset < S.endOffset()) {
|
||||||
SliceEndOffset < I->endOffset()) {
|
|
||||||
assert(STy->isIntegerTy());
|
assert(STy->isIntegerTy());
|
||||||
STy = SplitIntTy;
|
STy = SplitIntTy;
|
||||||
}
|
}
|
||||||
@@ -1708,10 +1708,9 @@ static bool isVectorPromotionViableForSlice(
|
|||||||
/// don't want to do the rewrites unless we are confident that the result will
|
/// don't want to do the rewrites unless we are confident that the result will
|
||||||
/// be promotable, so we have an early test here.
|
/// be promotable, so we have an early test here.
|
||||||
static bool
|
static bool
|
||||||
isVectorPromotionViable(const DataLayout &DL, Type *AllocaTy, AllocaSlices &S,
|
isVectorPromotionViable(const DataLayout &DL, Type *AllocaTy,
|
||||||
uint64_t SliceBeginOffset, uint64_t SliceEndOffset,
|
uint64_t SliceBeginOffset, uint64_t SliceEndOffset,
|
||||||
AllocaSlices::const_iterator I,
|
AllocaSlices::const_range Slices,
|
||||||
AllocaSlices::const_iterator E,
|
|
||||||
ArrayRef<AllocaSlices::iterator> SplitUses) {
|
ArrayRef<AllocaSlices::iterator> SplitUses) {
|
||||||
VectorType *Ty = dyn_cast<VectorType>(AllocaTy);
|
VectorType *Ty = dyn_cast<VectorType>(AllocaTy);
|
||||||
if (!Ty)
|
if (!Ty)
|
||||||
@@ -1727,16 +1726,14 @@ isVectorPromotionViable(const DataLayout &DL, Type *AllocaTy, AllocaSlices &S,
|
|||||||
"vector size not a multiple of element size?");
|
"vector size not a multiple of element size?");
|
||||||
ElementSize /= 8;
|
ElementSize /= 8;
|
||||||
|
|
||||||
for (; I != E; ++I)
|
for (const auto &S : Slices)
|
||||||
if (!isVectorPromotionViableForSlice(DL, S, SliceBeginOffset,
|
if (!isVectorPromotionViableForSlice(DL, SliceBeginOffset, SliceEndOffset,
|
||||||
SliceEndOffset, Ty, ElementSize, I))
|
Ty, ElementSize, S))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ArrayRef<AllocaSlices::iterator>::const_iterator SUI = SplitUses.begin(),
|
for (const auto &SI : SplitUses)
|
||||||
SUE = SplitUses.end();
|
if (!isVectorPromotionViableForSlice(DL, SliceBeginOffset, SliceEndOffset,
|
||||||
SUI != SUE; ++SUI)
|
Ty, ElementSize, *SI))
|
||||||
if (!isVectorPromotionViableForSlice(DL, S, SliceBeginOffset,
|
|
||||||
SliceEndOffset, Ty, ElementSize, *SUI))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1749,18 +1746,18 @@ isVectorPromotionViable(const DataLayout &DL, Type *AllocaTy, AllocaSlices &S,
|
|||||||
static bool isIntegerWideningViableForSlice(const DataLayout &DL,
|
static bool isIntegerWideningViableForSlice(const DataLayout &DL,
|
||||||
Type *AllocaTy,
|
Type *AllocaTy,
|
||||||
uint64_t AllocBeginOffset,
|
uint64_t AllocBeginOffset,
|
||||||
uint64_t Size, AllocaSlices &S,
|
uint64_t Size,
|
||||||
AllocaSlices::const_iterator I,
|
const Slice &S,
|
||||||
bool &WholeAllocaOp) {
|
bool &WholeAllocaOp) {
|
||||||
uint64_t RelBegin = I->beginOffset() - AllocBeginOffset;
|
uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
|
||||||
uint64_t RelEnd = I->endOffset() - AllocBeginOffset;
|
uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
|
||||||
|
|
||||||
// We can't reasonably handle cases where the load or store extends past
|
// We can't reasonably handle cases where the load or store extends past
|
||||||
// the end of the aloca's type and into its padding.
|
// the end of the aloca's type and into its padding.
|
||||||
if (RelEnd > Size)
|
if (RelEnd > Size)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Use *U = I->getUse();
|
Use *U = S.getUse();
|
||||||
|
|
||||||
if (LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
|
if (LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
|
||||||
if (LI->isVolatile())
|
if (LI->isVolatile())
|
||||||
@@ -1794,7 +1791,7 @@ static bool isIntegerWideningViableForSlice(const DataLayout &DL,
|
|||||||
} else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U->getUser())) {
|
} else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U->getUser())) {
|
||||||
if (MI->isVolatile() || !isa<Constant>(MI->getLength()))
|
if (MI->isVolatile() || !isa<Constant>(MI->getLength()))
|
||||||
return false;
|
return false;
|
||||||
if (!I->isSplittable())
|
if (!S.isSplittable())
|
||||||
return false; // Skip any unsplittable intrinsics.
|
return false; // Skip any unsplittable intrinsics.
|
||||||
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
|
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
|
||||||
if (II->getIntrinsicID() != Intrinsic::lifetime_start &&
|
if (II->getIntrinsicID() != Intrinsic::lifetime_start &&
|
||||||
@@ -1815,9 +1812,8 @@ static bool isIntegerWideningViableForSlice(const DataLayout &DL,
|
|||||||
/// promote the resulting alloca.
|
/// promote the resulting alloca.
|
||||||
static bool
|
static bool
|
||||||
isIntegerWideningViable(const DataLayout &DL, Type *AllocaTy,
|
isIntegerWideningViable(const DataLayout &DL, Type *AllocaTy,
|
||||||
uint64_t AllocBeginOffset, AllocaSlices &S,
|
uint64_t AllocBeginOffset,
|
||||||
AllocaSlices::const_iterator I,
|
AllocaSlices::const_range Slices,
|
||||||
AllocaSlices::const_iterator E,
|
|
||||||
ArrayRef<AllocaSlices::iterator> SplitUses) {
|
ArrayRef<AllocaSlices::iterator> SplitUses) {
|
||||||
uint64_t SizeInBits = DL.getTypeSizeInBits(AllocaTy);
|
uint64_t SizeInBits = DL.getTypeSizeInBits(AllocaTy);
|
||||||
// Don't create integer types larger than the maximum bitwidth.
|
// Don't create integer types larger than the maximum bitwidth.
|
||||||
@@ -1843,18 +1839,17 @@ isIntegerWideningViable(const DataLayout &DL, Type *AllocaTy,
|
|||||||
// promote due to some other unsplittable entry (which we may make splittable
|
// promote due to some other unsplittable entry (which we may make splittable
|
||||||
// later). However, if there are only splittable uses, go ahead and assume
|
// later). However, if there are only splittable uses, go ahead and assume
|
||||||
// that we cover the alloca.
|
// that we cover the alloca.
|
||||||
bool WholeAllocaOp = (I != E) ? false : DL.isLegalInteger(SizeInBits);
|
bool WholeAllocaOp =
|
||||||
|
Slices.begin() != Slices.end() ? false : DL.isLegalInteger(SizeInBits);
|
||||||
|
|
||||||
for (; I != E; ++I)
|
for (const auto &S : Slices)
|
||||||
if (!isIntegerWideningViableForSlice(DL, AllocaTy, AllocBeginOffset, Size,
|
if (!isIntegerWideningViableForSlice(DL, AllocaTy, AllocBeginOffset, Size,
|
||||||
S, I, WholeAllocaOp))
|
S, WholeAllocaOp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ArrayRef<AllocaSlices::iterator>::const_iterator SUI = SplitUses.begin(),
|
for (const auto &SI : SplitUses)
|
||||||
SUE = SplitUses.end();
|
|
||||||
SUI != SUE; ++SUI)
|
|
||||||
if (!isIntegerWideningViableForSlice(DL, AllocaTy, AllocBeginOffset, Size,
|
if (!isIntegerWideningViableForSlice(DL, AllocaTy, AllocBeginOffset, Size,
|
||||||
S, *SUI, WholeAllocaOp))
|
*SI, WholeAllocaOp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return WholeAllocaOp;
|
return WholeAllocaOp;
|
||||||
@@ -3147,12 +3142,14 @@ bool SROA::rewritePartition(AllocaInst &AI, AllocaSlices &S,
|
|||||||
SliceTy = ArrayType::get(Type::getInt8Ty(*C), SliceSize);
|
SliceTy = ArrayType::get(Type::getInt8Ty(*C), SliceSize);
|
||||||
assert(DL->getTypeAllocSize(SliceTy) >= SliceSize);
|
assert(DL->getTypeAllocSize(SliceTy) >= SliceSize);
|
||||||
|
|
||||||
bool IsVectorPromotable = isVectorPromotionViable(
|
bool IsVectorPromotable =
|
||||||
*DL, SliceTy, S, BeginOffset, EndOffset, B, E, SplitUses);
|
isVectorPromotionViable(*DL, SliceTy, BeginOffset, EndOffset,
|
||||||
|
AllocaSlices::const_range(B, E), SplitUses);
|
||||||
|
|
||||||
bool IsIntegerPromotable =
|
bool IsIntegerPromotable =
|
||||||
!IsVectorPromotable &&
|
!IsVectorPromotable &&
|
||||||
isIntegerWideningViable(*DL, SliceTy, BeginOffset, S, B, E, SplitUses);
|
isIntegerWideningViable(*DL, SliceTy, BeginOffset,
|
||||||
|
AllocaSlices::const_range(B, E), SplitUses);
|
||||||
|
|
||||||
// Check for the case where we're going to rewrite to a new alloca of the
|
// Check for the case where we're going to rewrite to a new alloca of the
|
||||||
// exact same type as the original, and with the same access offsets. In that
|
// exact same type as the original, and with the same access offsets. In that
|
||||||
|
Reference in New Issue
Block a user