diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2012-10-04 10:39:28 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2012-10-04 10:39:28 +0000 |
commit | aa3cb334af09ae30a3283f748cacb4a919785035 (patch) | |
tree | 1a8890d729c97a6f68c4ae1da5794af1b59f4fa4 /lib/Transforms/Scalar/SROA.cpp | |
parent | 47a3395d1d2b5fb2829462ca399458ea3214fe22 (diff) | |
download | external_llvm-aa3cb334af09ae30a3283f748cacb4a919785035.zip external_llvm-aa3cb334af09ae30a3283f748cacb4a919785035.tar.gz external_llvm-aa3cb334af09ae30a3283f748cacb4a919785035.tar.bz2 |
Teach the integer-promotion rewrite strategy to be endianness aware.
Sorry for this being broken so long. =/
As part of this, switch all of the existing tests to be Little Endian,
which is the behavior I was asserting in them anyways! Add in a new
big-endian test that checks the interesting behavior there.
Another part of this is to tighten the rules abotu when we perform the
full-integer promotion. This logic now rejects cases where there fully
promoted integer is a non-multiple-of-8 bitwidth or cases where the
loads or stores touch bits which are in the allocated space of the
alloca but are not loaded or stored when accessing the integer. Sadly,
these aren't really observable today as the rest of the pass will
already ensure the invariants hold. However, the latter situation is
likely to become a potential concern in the future.
Thanks to Benjamin and Duncan for early review of this patch. I'm still
looking into whether there are further endianness issues, please let me
know if anyone sees BE failures persisting past this.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165219 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/SROA.cpp')
-rw-r--r-- | lib/Transforms/Scalar/SROA.cpp | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index f4fd857..11b8d2e 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -1737,11 +1737,12 @@ static bool isVectorPromotionViable(const TargetData &TD, /// that the result will be promotable, so we have an early test here. static bool isIntegerPromotionViable(const TargetData &TD, Type *AllocaTy, + uint64_t AllocBeginOffset, AllocaPartitioning &P, AllocaPartitioning::const_use_iterator I, AllocaPartitioning::const_use_iterator E) { IntegerType *Ty = dyn_cast<IntegerType>(AllocaTy); - if (!Ty) + if (!Ty || 8*TD.getTypeStoreSize(Ty) != Ty->getBitWidth()) return false; // Check the uses to ensure the uses are (likely) promoteable integer uses. @@ -1752,6 +1753,12 @@ static bool isIntegerPromotionViable(const TargetData &TD, for (; I != E; ++I) { if (!I->U) continue; // Skip dead use. + + // We can't reasonably handle cases where the load or store extends past + // the end of the aloca's type and into its padding. + if ((I->EndOffset - AllocBeginOffset) > TD.getTypeStoreSize(Ty)) + return false; + if (LoadInst *LI = dyn_cast<LoadInst>(I->U->getUser())) { if (LI->isVolatile() || !LI->getType()->isIntegerTy()) return false; @@ -2130,7 +2137,7 @@ public: "Only multiple-of-8 sized vector elements are viable"); ElementSize = VecTy->getScalarSizeInBits() / 8; } else if (isIntegerPromotionViable(TD, NewAI.getAllocatedType(), - P, I, E)) { + NewAllocaBeginOffset, P, I, E)) { IntPromotionTy = cast<IntegerType>(NewAI.getAllocatedType()); } bool CanSROA = true; @@ -2218,8 +2225,15 @@ private: getName(".load")); assert(Offset >= NewAllocaBeginOffset && "Out of bounds offset"); uint64_t RelOffset = Offset - NewAllocaBeginOffset; - if (RelOffset) - V = IRB.CreateLShr(V, RelOffset*8, getName(".shift")); + assert(TD.getTypeStoreSize(TargetTy) + RelOffset <= + TD.getTypeStoreSize(IntPromotionTy) && + "Element load outside of alloca store"); + uint64_t ShAmt = 8*RelOffset; + if (TD.isBigEndian()) + ShAmt = 8*(TD.getTypeStoreSize(IntPromotionTy) - + TD.getTypeStoreSize(TargetTy) - RelOffset); + if (ShAmt) + V = IRB.CreateLShr(V, ShAmt, getName(".shift")); if (TargetTy != IntPromotionTy) { assert(TargetTy->getBitWidth() < IntPromotionTy->getBitWidth() && "Cannot extract to a larger integer!"); @@ -2238,11 +2252,17 @@ private: V = IRB.CreateZExt(V, IntPromotionTy, getName(".ext")); assert(Offset >= NewAllocaBeginOffset && "Out of bounds offset"); uint64_t RelOffset = Offset - NewAllocaBeginOffset; - if (RelOffset) - V = IRB.CreateShl(V, RelOffset*8, getName(".shift")); - - APInt Mask = ~Ty->getMask().zext(IntPromotionTy->getBitWidth()) - .shl(RelOffset*8); + assert(TD.getTypeStoreSize(Ty) + RelOffset <= + TD.getTypeStoreSize(IntPromotionTy) && + "Element store outside of alloca store"); + uint64_t ShAmt = 8*RelOffset; + if (TD.isBigEndian()) + ShAmt = 8*(TD.getTypeStoreSize(IntPromotionTy) - TD.getTypeStoreSize(Ty) + - RelOffset); + if (ShAmt) + V = IRB.CreateShl(V, ShAmt, getName(".shift")); + + APInt Mask = ~Ty->getMask().zext(IntPromotionTy->getBitWidth()).shl(ShAmt); Value *Old = IRB.CreateAnd(IRB.CreateAlignedLoad(&NewAI, NewAI.getAlignment(), getName(".oldload")), |