47#include "llvm/Config/llvm-config.h"
102#define DEBUG_TYPE "sroa"
104STATISTIC(NumAllocasAnalyzed,
"Number of allocas analyzed for replacement");
105STATISTIC(NumAllocaPartitions,
"Number of alloca partitions formed");
106STATISTIC(MaxPartitionsPerAlloca,
"Maximum number of partitions per alloca");
107STATISTIC(NumAllocaPartitionUses,
"Number of alloca partition uses rewritten");
108STATISTIC(MaxUsesPerAllocaPartition,
"Maximum number of uses of a partition");
109STATISTIC(NumNewAllocas,
"Number of new, smaller allocas introduced");
110STATISTIC(NumPromoted,
"Number of allocas promoted to SSA values");
111STATISTIC(NumLoadsSpeculated,
"Number of loads speculated to allow promotion");
113 "Number of loads rewritten into predicated loads to allow promotion");
116 "Number of stores rewritten into predicated loads to allow promotion");
118STATISTIC(NumVectorized,
"Number of vectorized aggregates");
125class AllocaSliceRewriter;
129class SelectHandSpeculativity {
130 unsigned char Storage = 0;
134 SelectHandSpeculativity() =
default;
135 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
136 bool isSpeculatable(
bool isTrueVal)
const;
137 bool areAllSpeculatable()
const;
138 bool areAnySpeculatable()
const;
139 bool areNoneSpeculatable()
const;
141 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
142 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
144static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
146using PossiblySpeculatableLoad =
149using RewriteableMemOp =
150 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
233 static std::optional<RewriteableMemOps>
234 isSafeSelectToSpeculate(
SelectInst &SI,
bool PreserveCFG);
239 :
C(
C), DTU(DTU), AC(AC),
243 std::pair<
bool ,
bool > runSROA(
Function &
F);
246 friend class AllocaSliceRewriter;
248 bool presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS);
250 bool splitAlloca(
AllocaInst &AI, AllocaSlices &AS);
251 bool propagateStoredValuesToLoads(
AllocaInst &AI, AllocaSlices &AS);
252 std::pair<
bool ,
bool > runOnAlloca(
AllocaInst &AI);
253 void clobberUse(
Use &U);
269enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
273 uint64_t NewStorageSliceOffsetInBits,
275 std::optional<DIExpression::FragmentInfo> StorageFragment,
276 std::optional<DIExpression::FragmentInfo> CurrentFragment,
280 if (StorageFragment) {
282 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
284 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
286 Target.SizeInBits = NewStorageSliceSizeInBits;
287 Target.OffsetInBits = NewStorageSliceOffsetInBits;
293 if (!CurrentFragment) {
297 if (
Target == CurrentFragment)
304 if (!CurrentFragment || *CurrentFragment ==
Target)
310 if (
Target.startInBits() < CurrentFragment->startInBits() ||
311 Target.endInBits() > CurrentFragment->endInBits())
361 if (MarkerRange.empty() && DVRAssignMarkerRange.empty())
367 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
369 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
381 DAI->getExpression()->getFragmentInfo();
384 DVR->getExpression()->getFragmentInfo();
394 auto MigrateDbgAssign = [&](
auto *DbgAssign) {
397 auto *Expr = DbgAssign->getExpression();
398 bool SetKillLocation =
false;
401 std::optional<DIExpression::FragmentInfo> BaseFragment;
404 if (R == BaseFragments.
end())
406 BaseFragment = R->second;
408 std::optional<DIExpression::FragmentInfo> CurrentFragment =
409 Expr->getFragmentInfo();
412 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
413 BaseFragment, CurrentFragment, NewFragment);
417 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
418 if (CurrentFragment) {
423 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
434 DIExpression::get(Expr->getContext(), {}),
436 SetKillLocation =
true;
444 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
450 Dest, DIExpression::get(Expr->getContext(), {}),
451 DbgAssign->getDebugLoc()),
465 Value && (DbgAssign->hasArgList() ||
466 !DbgAssign->getExpression()->isSingleLocationExpression());
468 NewAssign->setKillLocation();
483 NewAssign->moveBefore(DbgAssign);
485 NewAssign->setDebugLoc(DbgAssign->getDebugLoc());
486 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
489 for_each(MarkerRange, MigrateDbgAssign);
490 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
538 : BeginOffset(BeginOffset), EndOffset(EndOffset),
539 UseAndIsSplittable(
U, IsSplittable) {}
541 uint64_t beginOffset()
const {
return BeginOffset; }
542 uint64_t endOffset()
const {
return EndOffset; }
544 bool isSplittable()
const {
return UseAndIsSplittable.
getInt(); }
545 void makeUnsplittable() { UseAndIsSplittable.
setInt(
false); }
547 Use *getUse()
const {
return UseAndIsSplittable.
getPointer(); }
549 bool isDead()
const {
return getUse() ==
nullptr; }
550 void kill() { UseAndIsSplittable.
setPointer(
nullptr); }
559 if (beginOffset() <
RHS.beginOffset())
561 if (beginOffset() >
RHS.beginOffset())
563 if (isSplittable() !=
RHS.isSplittable())
564 return !isSplittable();
565 if (endOffset() >
RHS.endOffset())
573 return LHS.beginOffset() < RHSOffset;
577 return LHSOffset <
RHS.beginOffset();
581 return isSplittable() ==
RHS.isSplittable() &&
582 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
603 bool isEscaped()
const {
return PointerEscapingInstr; }
604 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
612 iterator
end() {
return Slices.
end(); }
622 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
630 int OldSize = Slices.size();
631 Slices.append(NewSlices.
begin(), NewSlices.
end());
632 auto SliceI = Slices.begin() + OldSize;
633 std::stable_sort(SliceI, Slices.end());
634 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
639 class partition_iterator;
647 return DeadUseIfPromotable;
658#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
670 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
675#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
730 friend class AllocaSlices;
733 using iterator = AllocaSlices::iterator;
737 uint64_t BeginOffset = 0, EndOffset = 0;
747 Partition(iterator SI) :
SI(
SI), SJ(
SI) {}
753 uint64_t beginOffset()
const {
return BeginOffset; }
758 uint64_t endOffset()
const {
return EndOffset; }
764 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
765 return EndOffset - BeginOffset;
770 bool empty()
const {
return SI == SJ; }
781 iterator
begin()
const {
return SI; }
782 iterator
end()
const {
return SJ; }
814 AllocaSlices::iterator SE;
818 uint64_t MaxSplitSliceEndOffset = 0;
834 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
835 "Cannot advance past the end of the slices!");
838 if (!
P.SplitTails.empty()) {
839 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
841 P.SplitTails.clear();
842 MaxSplitSliceEndOffset = 0;
848 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
851 return S->endOffset() == MaxSplitSliceEndOffset;
853 "Could not find the current max split slice offset!");
856 return S->endOffset() <= MaxSplitSliceEndOffset;
858 "Max split slice end offset is not actually the max!");
865 assert(
P.SplitTails.empty() &&
"Failed to clear the split slices!");
875 if (S.isSplittable() && S.endOffset() >
P.EndOffset) {
876 P.SplitTails.push_back(&S);
877 MaxSplitSliceEndOffset =
878 std::max(S.endOffset(), MaxSplitSliceEndOffset);
886 P.BeginOffset =
P.EndOffset;
887 P.EndOffset = MaxSplitSliceEndOffset;
894 if (!
P.SplitTails.empty() &&
P.SI->beginOffset() !=
P.EndOffset &&
895 !
P.SI->isSplittable()) {
896 P.BeginOffset =
P.EndOffset;
897 P.EndOffset =
P.SI->beginOffset();
907 P.BeginOffset =
P.SplitTails.empty() ?
P.SI->beginOffset() :
P.EndOffset;
908 P.EndOffset =
P.SI->endOffset();
913 if (!
P.SI->isSplittable()) {
916 assert(
P.BeginOffset ==
P.SI->beginOffset());
920 while (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset) {
921 if (!
P.SJ->isSplittable())
922 P.EndOffset = std::max(
P.EndOffset,
P.SJ->endOffset());
934 assert(
P.SI->isSplittable() &&
"Forming a splittable partition!");
937 while (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset &&
938 P.SJ->isSplittable()) {
939 P.EndOffset = std::max(
P.EndOffset,
P.SJ->endOffset());
946 if (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset) {
948 P.EndOffset =
P.SJ->beginOffset();
955 "End iterators don't match between compared partition iterators!");
962 if (
P.SI ==
RHS.P.SI &&
P.SplitTails.empty() ==
RHS.P.SplitTails.empty()) {
964 "Same set of slices formed two different sized partitions!");
965 assert(
P.SplitTails.size() ==
RHS.P.SplitTails.size() &&
966 "Same slice position with differently sized non-empty split "
989 return make_range(partition_iterator(begin(), end()),
990 partition_iterator(end(), end()));
997 if (
ConstantInt *CI = dyn_cast<ConstantInt>(SI.getCondition()))
998 return SI.getOperand(1 + CI->isZero());
999 if (SI.getOperand(1) == SI.getOperand(2))
1000 return SI.getOperand(1);
1007 if (
PHINode *PN = dyn_cast<PHINode>(&
I)) {
1009 return PN->hasConstantValue();
1036 AllocSize(
DL.getTypeAllocSize(AI.getAllocatedType()).getFixedValue()),
1041 if (VisitedDeadInsts.
insert(&
I).second)
1042 AS.DeadUsers.push_back(&
I);
1046 bool IsSplittable =
false) {
1052 <<
" which has zero size or starts outside of the "
1053 << AllocSize <<
" byte alloca:\n"
1054 <<
" alloca: " << AS.AI <<
"\n"
1055 <<
" use: " <<
I <<
"\n");
1056 return markAsDead(
I);
1068 assert(AllocSize >= BeginOffset);
1069 if (
Size > AllocSize - BeginOffset) {
1071 <<
Offset <<
" to remain within the " << AllocSize
1072 <<
" byte alloca:\n"
1073 <<
" alloca: " << AS.AI <<
"\n"
1074 <<
" use: " <<
I <<
"\n");
1075 EndOffset = AllocSize;
1078 AS.Slices.push_back(Slice(BeginOffset, EndOffset,
U, IsSplittable));
1083 return markAsDead(BC);
1090 return markAsDead(ASC);
1097 return markAsDead(GEPI);
1115 "All simple FCA loads should have been pre-split");
1121 if (
Size.isScalable())
1129 Value *ValOp =
SI.getValueOperand();
1150 <<
Offset <<
" which extends past the end of the "
1151 << AllocSize <<
" byte alloca:\n"
1152 <<
" alloca: " << AS.AI <<
"\n"
1153 <<
" use: " << SI <<
"\n");
1154 return markAsDead(SI);
1158 "All simple FCA stores should have been pre-split");
1163 assert(
II.getRawDest() == *
U &&
"Pointer use is not the destination?");
1168 return markAsDead(
II);
1183 return markAsDead(
II);
1187 if (VisitedDeadInsts.
count(&
II))
1200 MemTransferSliceMap.
find(&
II);
1201 if (MTPI != MemTransferSliceMap.
end())
1202 AS.Slices[MTPI->second].kill();
1203 return markAsDead(
II);
1211 if (*
U ==
II.getRawDest() && *
U ==
II.getRawSource()) {
1213 if (!
II.isVolatile())
1214 return markAsDead(
II);
1223 std::tie(MTPI, Inserted) =
1224 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1225 unsigned PrevIdx = MTPI->second;
1227 Slice &PrevP = AS.Slices[PrevIdx];
1231 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1233 return markAsDead(
II);
1238 PrevP.makeUnsplittable();
1245 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1246 "Map index doesn't point back to a slice with this user.");
1254 if (
II.isDroppable()) {
1255 AS.DeadUseIfPromotable.push_back(
U);
1262 if (
II.isLifetimeStartOrEnd()) {
1265 Length->getLimitedValue());
1270 if (
II.isLaunderOrStripInvariantGroup()) {
1271 insertUse(
II,
Offset, AllocSize,
true);
1287 Uses.push_back(std::make_pair(cast<Instruction>(*
U), Root));
1294 std::tie(UsedI,
I) =
Uses.pop_back_val();
1296 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
1305 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1319 if (!
GEP->hasAllZeroIndices())
1321 }
else if (!isa<BitCastInst>(
I) && !isa<PHINode>(
I) &&
1322 !isa<SelectInst>(
I) && !isa<AddrSpaceCastInst>(
I)) {
1326 for (
User *
U :
I->users())
1327 if (Visited.
insert(cast<Instruction>(
U)).second)
1328 Uses.push_back(std::make_pair(
I, cast<Instruction>(
U)));
1329 }
while (!
Uses.empty());
1335 assert(isa<PHINode>(
I) || isa<SelectInst>(
I));
1337 return markAsDead(
I);
1342 if (isa<PHINode>(
I) &&
1343 I.getParent()->getFirstInsertionPt() ==
I.getParent()->end())
1362 AS.DeadOperands.push_back(
U);
1385 AS.DeadOperands.push_back(
U);
1392 void visitPHINode(
PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1394 void visitSelectInst(
SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1415#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1418 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1419 SliceBuilder
PB(
DL, AI, *
this);
1420 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1421 if (PtrI.isEscaped() || PtrI.isAborted()) {
1424 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1425 : PtrI.getAbortingInst();
1426 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1429 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1431 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1438#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1442 printSlice(
OS,
I, Indent);
1444 printUse(
OS,
I, Indent);
1449 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1450 <<
" slice #" << (
I -
begin())
1451 << (
I->isSplittable() ?
" (splittable)" :
"");
1456 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1460 if (PointerEscapingInstr) {
1461 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1462 <<
" A pointer to this alloca escaped by:\n"
1463 <<
" " << *PointerEscapingInstr <<
"\n";
1467 if (PointerEscapingInstrReadOnly)
1468 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1470 OS <<
"Slices of alloca: " << AI <<
"\n";
1484static std::pair<Type *, IntegerType *>
1488 bool TyIsCommon =
true;
1493 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1494 Use *U =
I->getUse();
1495 if (isa<IntrinsicInst>(*U->getUser()))
1497 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1500 Type *UserTy =
nullptr;
1501 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
1503 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
1504 UserTy = SI->getValueOperand()->getType();
1507 if (
IntegerType *UserITy = dyn_cast_or_null<IntegerType>(UserTy)) {
1512 if (UserITy->getBitWidth() % 8 != 0 ||
1513 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1518 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1524 if (!UserTy || (Ty && Ty != UserTy))
1530 return {TyIsCommon ? Ty :
nullptr, ITy};
1561 Type *LoadType =
nullptr;
1563 LoadInst *LI = dyn_cast<LoadInst>(U);
1574 if (LoadType != LI->
getType())
1583 if (BBI->mayWriteToMemory())
1586 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1593 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1630 IRB.SetInsertPoint(&PN);
1632 PN.
getName() +
".sroa.speculated");
1662 IRB.SetInsertPoint(TI);
1664 LoadInst *Load = IRB.CreateAlignedLoad(
1665 LoadTy, InVal, Alignment,
1667 ++NumLoadsSpeculated;
1669 Load->setAAMetadata(AATags);
1671 InjectedLoads[Pred] = Load;
1678SelectHandSpeculativity &
1679SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1681 Bitfield::set<SelectHandSpeculativity::TrueVal>(Storage,
true);
1683 Bitfield::set<SelectHandSpeculativity::FalseVal>(Storage,
true);
1687bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1688 return isTrueVal ? Bitfield::get<SelectHandSpeculativity::TrueVal>(Storage)
1692bool SelectHandSpeculativity::areAllSpeculatable()
const {
1693 return isSpeculatable(
true) &&
1694 isSpeculatable(
false);
1697bool SelectHandSpeculativity::areAnySpeculatable()
const {
1698 return isSpeculatable(
true) ||
1699 isSpeculatable(
false);
1701bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1702 return !areAnySpeculatable();
1705static SelectHandSpeculativity
1708 SelectHandSpeculativity
Spec;
1711 for (
Value *
Value : {SI.getTrueValue(), SI.getFalseValue()})
1714 Spec.setAsSpeculatable(
Value == SI.getTrueValue());
1721std::optional<RewriteableMemOps>
1723 RewriteableMemOps Ops;
1725 for (
User *U :
SI.users()) {
1726 if (
auto *BC = dyn_cast<BitCastInst>(U); BC && BC->
hasOneUse())
1729 if (
auto *Store = dyn_cast<StoreInst>(U)) {
1735 Ops.emplace_back(Store);
1739 auto *LI = dyn_cast<LoadInst>(U);
1746 PossiblySpeculatableLoad
Load(LI);
1752 Ops.emplace_back(Load);
1756 SelectHandSpeculativity
Spec =
1762 Ops.emplace_back(Load);
1772 Value *TV = SI.getTrueValue();
1773 Value *FV = SI.getFalseValue();
1778 IRB.SetInsertPoint(&LI);
1782 LI.
getName() +
".sroa.speculate.load.true");
1785 LI.
getName() +
".sroa.speculate.load.false");
1786 NumLoadsSpeculated += 2;
1798 Value *V = IRB.CreateSelect(SI.getCondition(), TL, FL,
1799 LI.
getName() +
".sroa.speculated");
1805template <
typename T>
1807 SelectHandSpeculativity
Spec,
1809 assert((isa<LoadInst>(
I) || isa<StoreInst>(
I)) &&
"Only for load and store!");
1814 if (
Spec.areNoneSpeculatable())
1816 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1819 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1821 if (
Spec.isSpeculatable(
true))
1829 if (isa<LoadInst>(
I))
1832 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1833 int SuccIdx = IsThen ? 0 : 1;
1834 auto *NewMemOpBB = SuccBB ==
Tail ? Head : SuccBB;
1835 auto &CondMemOp = cast<T>(*
I.clone());
1836 if (NewMemOpBB != Head) {
1837 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1838 if (isa<LoadInst>(
I))
1839 ++NumLoadsPredicated;
1841 ++NumStoresPredicated;
1843 CondMemOp.dropUBImplyingAttrsAndMetadata();
1844 ++NumLoadsSpeculated;
1846 CondMemOp.insertBefore(NewMemOpBB->getTerminator());
1847 Value *
Ptr = SI.getOperand(1 + SuccIdx);
1848 CondMemOp.setOperand(
I.getPointerOperandIndex(),
Ptr);
1849 if (isa<LoadInst>(
I)) {
1850 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1855 if (isa<LoadInst>(
I)) {
1858 I.replaceAllUsesWith(PN);
1863 SelectHandSpeculativity
Spec,
1865 if (
auto *LI = dyn_cast<LoadInst>(&
I))
1867 else if (
auto *SI = dyn_cast<StoreInst>(&
I))
1874 const RewriteableMemOps &Ops,
1876 bool CFGChanged =
false;
1879 for (
const RewriteableMemOp &
Op : Ops) {
1880 SelectHandSpeculativity
Spec;
1882 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
1885 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
1886 I = PSL.getPointer();
1887 Spec = PSL.getInt();
1889 if (
Spec.areAllSpeculatable()) {
1892 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
1896 I->eraseFromParent();
1900 cast<BitCastInst>(U)->eraseFromParent();
1901 SI.eraseFromParent();
1909 const Twine &NamePrefix) {
1911 Ptr = IRB.CreateInBoundsPtrAdd(
Ptr, IRB.getInt(
Offset),
1912 NamePrefix +
"sroa_idx");
1913 return IRB.CreatePointerBitCastOrAddrSpaceCast(
Ptr,
PointerTy,
1914 NamePrefix +
"sroa_cast");
1935 if (isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) {
1938 "We can't have the same bitwidth for different int types");
1942 if (
DL.getTypeSizeInBits(NewTy).getFixedValue() !=
1943 DL.getTypeSizeInBits(OldTy).getFixedValue())
1959 return OldAS == NewAS ||
1960 (!
DL.isNonIntegralAddressSpace(OldAS) &&
1961 !
DL.isNonIntegralAddressSpace(NewAS) &&
1962 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
1968 return !
DL.isNonIntegralPointerType(NewTy);
1972 if (!
DL.isNonIntegralPointerType(OldTy))
1992 Type *OldTy = V->getType();
1998 assert(!(isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) &&
1999 "Integer types must be the exact same to convert.");
2007 return IRB.CreateIntToPtr(IRB.CreateBitCast(V,
DL.getIntPtrType(NewTy)),
2017 return IRB.CreateBitCast(IRB.CreatePtrToInt(V,
DL.getIntPtrType(OldTy)),
2030 if (OldAS != NewAS) {
2031 assert(
DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2032 return IRB.CreateIntToPtr(IRB.CreatePtrToInt(V,
DL.getIntPtrType(OldTy)),
2037 return IRB.CreateBitCast(V, NewTy);
2050 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2051 uint64_t BeginIndex = BeginOffset / ElementSize;
2052 if (BeginIndex * ElementSize != BeginOffset ||
2055 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2056 uint64_t EndIndex = EndOffset / ElementSize;
2057 if (EndIndex * ElementSize != EndOffset ||
2061 assert(EndIndex > BeginIndex &&
"Empty vector!");
2062 uint64_t NumElements = EndIndex - BeginIndex;
2063 Type *SliceTy = (NumElements == 1)
2064 ? Ty->getElementType()
2070 Use *U = S.getUse();
2073 if (
MI->isVolatile())
2075 if (!S.isSplittable())
2077 }
else if (
IntrinsicInst *
II = dyn_cast<IntrinsicInst>(U->getUser())) {
2078 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2080 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2087 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2093 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2094 if (SI->isVolatile())
2096 Type *STy = SI->getValueOperand()->getType();
2100 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2121 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2125 if (ElementSize % 8)
2127 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2128 "vector size not a multiple of element size?");
2131 for (
const Slice &S :
P)
2135 for (
const Slice *S :
P.splitSliceTails())
2149 bool HaveCommonEltTy,
Type *CommonEltTy,
2150 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2153 if (CandidateTys.
empty())
2160 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2164 if (!HaveCommonEltTy && HaveVecPtrTy) {
2166 CandidateTys.
clear();
2168 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2171 if (!VTy->getElementType()->isIntegerTy())
2172 VTy = cast<VectorType>(VTy->getWithNewType(IntegerType::getIntNTy(
2173 VTy->getContext(), VTy->getScalarSizeInBits())));
2180 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2181 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2182 "Cannot have vector types of different sizes!");
2183 assert(RHSTy->getElementType()->isIntegerTy() &&
2184 "All non-integer types eliminated!");
2185 assert(LHSTy->getElementType()->isIntegerTy() &&
2186 "All non-integer types eliminated!");
2187 return cast<FixedVectorType>(RHSTy)->getNumElements() <
2188 cast<FixedVectorType>(LHSTy)->getNumElements();
2192 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2193 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2194 "Cannot have vector types of different sizes!");
2195 assert(RHSTy->getElementType()->isIntegerTy() &&
2196 "All non-integer types eliminated!");
2197 assert(LHSTy->getElementType()->isIntegerTy() &&
2198 "All non-integer types eliminated!");
2199 return cast<FixedVectorType>(RHSTy)->getNumElements() ==
2200 cast<FixedVectorType>(LHSTy)->getNumElements();
2202 llvm::sort(CandidateTys, RankVectorTypesComp);
2203 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2204 CandidateTys.end());
2210 assert(VTy->getElementType() == CommonEltTy &&
2211 "Unaccounted for element type!");
2212 assert(VTy == CandidateTys[0] &&
2213 "Different vector types with the same element type!");
2216 CandidateTys.resize(1);
2222 return cast<FixedVectorType>(VTy)->getNumElements() >
2223 std::numeric_limits<unsigned short>::max();
2237 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2238 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy) {
2240 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2243 for (
Type *Ty : OtherTys) {
2244 if (!VectorType::isValidElementType(Ty))
2246 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2249 for (
VectorType *
const VTy : CandidateTysCopy) {
2251 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2252 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2253 unsigned ElementSize =
2254 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2258 CheckCandidateType(NewVTy);
2264 CommonEltTy, HaveVecPtrTy,
2265 HaveCommonVecPtrTy, CommonVecPtrTy);
2283 Type *CommonEltTy =
nullptr;
2285 bool HaveVecPtrTy =
false;
2286 bool HaveCommonEltTy =
true;
2287 bool HaveCommonVecPtrTy =
true;
2288 auto CheckCandidateType = [&](
Type *Ty) {
2289 if (
auto *VTy = dyn_cast<VectorType>(Ty)) {
2291 if (!CandidateTys.
empty()) {
2293 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2294 DL.getTypeSizeInBits(V).getFixedValue()) {
2295 CandidateTys.
clear();
2300 Type *EltTy = VTy->getElementType();
2303 CommonEltTy = EltTy;
2304 else if (CommonEltTy != EltTy)
2305 HaveCommonEltTy =
false;
2308 HaveVecPtrTy =
true;
2309 if (!CommonVecPtrTy)
2310 CommonVecPtrTy = VTy;
2311 else if (CommonVecPtrTy != VTy)
2312 HaveCommonVecPtrTy =
false;
2318 for (
const Slice &S :
P) {
2320 if (
auto *LI = dyn_cast<LoadInst>(S.getUse()->getUser()))
2322 else if (
auto *SI = dyn_cast<StoreInst>(S.getUse()->getUser()))
2323 Ty = SI->getValueOperand()->getType();
2328 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2329 S.endOffset() !=
P.endOffset())) {
2336 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2337 CheckCandidateType(Ty);
2342 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2343 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2344 HaveCommonVecPtrTy, CommonVecPtrTy))
2347 CandidateTys.
clear();
2349 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2350 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2362 bool &WholeAllocaOp) {
2365 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2366 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2368 Use *U = S.getUse();
2375 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2384 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2388 if (
DL.getTypeStoreSize(LI->
getType()).getFixedValue() >
Size)
2392 if (S.beginOffset() < AllocBeginOffset)
2397 if (!isa<VectorType>(LI->
getType()) && RelBegin == 0 && RelEnd ==
Size)
2398 WholeAllocaOp =
true;
2400 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2402 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2408 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2409 Type *ValueTy = SI->getValueOperand()->getType();
2410 if (SI->isVolatile())
2413 if (
DL.getTypeStoreSize(ValueTy).getFixedValue() >
Size)
2417 if (S.beginOffset() < AllocBeginOffset)
2422 if (!isa<VectorType>(ValueTy) && RelBegin == 0 && RelEnd ==
Size)
2423 WholeAllocaOp =
true;
2424 if (
IntegerType *ITy = dyn_cast<IntegerType>(ValueTy)) {
2425 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2427 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2433 }
else if (
MemIntrinsic *
MI = dyn_cast<MemIntrinsic>(U->getUser())) {
2434 if (
MI->isVolatile() || !isa<Constant>(
MI->getLength()))
2436 if (!S.isSplittable())
2453 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2459 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2477 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2479 for (
const Slice &S :
P)
2484 for (
const Slice *S :
P.splitSliceTails())
2489 return WholeAllocaOp;
2496 IntegerType *IntTy = cast<IntegerType>(V->getType());
2498 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2499 "Element extends past full value");
2501 if (
DL.isBigEndian())
2502 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2503 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2505 V = IRB.CreateLShr(V, ShAmt,
Name +
".shift");
2509 "Cannot extract to a larger integer!");
2511 V = IRB.CreateTrunc(V, Ty,
Name +
".trunc");
2520 IntegerType *Ty = cast<IntegerType>(V->getType());
2522 "Cannot insert a larger integer!");
2525 V = IRB.CreateZExt(V, IntTy,
Name +
".ext");
2529 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2530 "Element store outside of alloca store");
2532 if (
DL.isBigEndian())
2533 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2534 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2536 V = IRB.CreateShl(V, ShAmt,
Name +
".shift");
2542 Old = IRB.CreateAnd(Old, Mask,
Name +
".mask");
2544 V = IRB.CreateOr(Old, V,
Name +
".insert");
2552 auto *VecTy = cast<FixedVectorType>(V->getType());
2553 unsigned NumElements = EndIndex - BeginIndex;
2556 if (NumElements == VecTy->getNumElements())
2559 if (NumElements == 1) {
2560 V = IRB.CreateExtractElement(V, IRB.getInt32(BeginIndex),
2566 auto Mask = llvm::to_vector<8>(llvm::seq<int>(BeginIndex, EndIndex));
2567 V = IRB.CreateShuffleVector(V, Mask,
Name +
".extract");
2573 unsigned BeginIndex,
const Twine &
Name) {
2575 assert(VecTy &&
"Can only insert a vector into a vector");
2577 VectorType *Ty = dyn_cast<VectorType>(V->getType());
2580 V = IRB.CreateInsertElement(Old, V, IRB.getInt32(BeginIndex),
2588 "Too many elements!");
2591 assert(V->getType() == VecTy &&
"Vector type mismatch");
2594 unsigned EndIndex = BeginIndex + cast<FixedVectorType>(Ty)->getNumElements();
2602 for (
unsigned i = 0; i != cast<FixedVectorType>(VecTy)->getNumElements(); ++i)
2603 if (i >= BeginIndex && i < EndIndex)
2604 Mask.push_back(i - BeginIndex);
2607 V = IRB.CreateShuffleVector(V, Mask,
Name +
".expand");
2612 for (
unsigned i = 0; i != cast<FixedVectorType>(VecTy)->getNumElements(); ++i)
2613 Mask2.
push_back(IRB.getInt1(i >= BeginIndex && i < EndIndex));
2629class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2639 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2668 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2671 bool IsSplittable =
false;
2672 bool IsSplit =
false;
2673 Use *OldUse =
nullptr;
2686 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2690 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2691 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2698 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2702 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2703 NewAllocaBeginOffset(NewAllocaBeginOffset),
2704 NewAllocaEndOffset(NewAllocaEndOffset),
2705 NewAllocaTy(NewAI.getAllocatedType()),
2708 ?
Type::getIntNTy(NewAI.getContext(),
2709 DL.getTypeSizeInBits(NewAI.getAllocatedType())
2712 VecTy(PromotableVecTy),
2713 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2714 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2716 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2719 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2720 "Only multiple-of-8 sized vector elements are viable");
2723 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2726 bool visit(AllocaSlices::const_iterator
I) {
2727 bool CanSROA =
true;
2728 BeginOffset =
I->beginOffset();
2729 EndOffset =
I->endOffset();
2730 IsSplittable =
I->isSplittable();
2732 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2733 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2738 assert(BeginOffset < NewAllocaEndOffset);
2739 assert(EndOffset > NewAllocaBeginOffset);
2740 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2741 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2743 SliceSize = NewEndOffset - NewBeginOffset;
2744 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2745 <<
") NewBegin:(" << NewBeginOffset <<
", "
2746 << NewEndOffset <<
") NewAllocaBegin:("
2747 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2749 assert(IsSplit || NewBeginOffset == BeginOffset);
2750 OldUse =
I->getUse();
2751 OldPtr = cast<Instruction>(OldUse->get());
2753 Instruction *OldUserI = cast<Instruction>(OldUse->getUser());
2754 IRB.SetInsertPoint(OldUserI);
2755 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2756 IRB.getInserter().SetNamePrefix(
Twine(NewAI.
getName()) +
"." +
2757 Twine(BeginOffset) +
".");
2759 CanSROA &=
visit(cast<Instruction>(OldUse->getUser()));
2778 assert(IsSplit || BeginOffset == NewBeginOffset);
2784 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
2786 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
2791 OldName = OldName.
substr(IndexEnd + 1);
2795 OldName = OldName.
substr(OffsetEnd + 1);
2799 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
2806 Twine(OldName) +
"."
2818 Align getSliceAlign() {
2820 NewBeginOffset - NewAllocaBeginOffset);
2824 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
2826 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
2832 void deleteIfTriviallyDead(
Value *V) {
2835 Pass.DeadInsts.push_back(
I);
2839 unsigned BeginIndex = getIndex(NewBeginOffset);
2840 unsigned EndIndex = getIndex(NewEndOffset);
2841 assert(EndIndex > BeginIndex &&
"Empty vector!");
2846 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
2847 LLVMContext::MD_access_group});
2848 return extractVector(IRB, Load, BeginIndex, EndIndex,
"vec");
2852 assert(IntTy &&
"We cannot insert an integer to the alloca");
2857 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
2859 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
2868 assert(cast<IntegerType>(LI.
getType())->getBitWidth() >= SliceSize * 8 &&
2869 "Can only handle an extract for an overly wide load");
2870 if (cast<IntegerType>(LI.
getType())->getBitWidth() > SliceSize * 8)
2871 V = IRB.CreateZExt(V, LI.
getType());
2886 const bool IsLoadPastEnd =
2887 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize;
2888 bool IsPtrAdjusted =
false;
2891 V = rewriteVectorizedLoadInst(LI);
2893 V = rewriteIntegerLoad(LI);
2894 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
2895 NewEndOffset == NewAllocaEndOffset &&
2917 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
2925 if (
auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
2926 if (
auto *TITy = dyn_cast<IntegerType>(TargetTy))
2927 if (AITy->getBitWidth() < TITy->getBitWidth()) {
2928 V = IRB.CreateZExt(V, TITy,
"load.ext");
2929 if (
DL.isBigEndian())
2930 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
2934 Type *LTy = IRB.getPtrTy(AS);
2936 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
2941 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
2945 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
2946 LLVMContext::MD_access_group});
2949 IsPtrAdjusted =
true;
2956 "Only integer type loads and stores are split");
2957 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
2958 "Split load isn't smaller than original load");
2960 "Non-byte-multiple bit width");
2966 LIIt.setHeadBit(
true);
2967 IRB.SetInsertPoint(LI.
getParent(), LIIt);
2972 Value *Placeholder =
2978 Placeholder->replaceAllUsesWith(&LI);
2979 Placeholder->deleteValue();
2984 Pass.DeadInsts.push_back(&LI);
2985 deleteIfTriviallyDead(OldOp);
2995 if (
V->getType() != VecTy) {
2996 unsigned BeginIndex = getIndex(NewBeginOffset);
2997 unsigned EndIndex = getIndex(NewEndOffset);
2998 assert(EndIndex > BeginIndex &&
"Empty vector!");
2999 unsigned NumElements = EndIndex - BeginIndex;
3001 "Too many elements!");
3002 Type *SliceTy = (NumElements == 1)
3005 if (
V->getType() != SliceTy)
3014 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3015 LLVMContext::MD_access_group});
3019 Pass.DeadInsts.push_back(&SI);
3023 Store,
Store->getPointerOperand(), OrigV,
DL);
3029 assert(IntTy &&
"We cannot extract an integer from the alloca");
3031 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3036 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3042 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3043 LLVMContext::MD_access_group});
3049 Store,
Store->getPointerOperand(),
3050 Store->getValueOperand(),
DL);
3052 Pass.DeadInsts.push_back(&SI);
3059 Value *OldOp =
SI.getOperand(1);
3067 if (
V->getType()->isPointerTy())
3068 if (
AllocaInst *AI = dyn_cast<AllocaInst>(
V->stripInBoundsOffsets()))
3069 Pass.PostPromotionWorklist.insert(AI);
3071 if (SliceSize <
DL.getTypeStoreSize(
V->getType()).getFixedValue()) {
3073 assert(
V->getType()->isIntegerTy() &&
3074 "Only integer type loads and stores are split");
3075 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3076 "Non-byte-multiple bit width");
3083 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3084 if (IntTy &&
V->getType()->isIntegerTy())
3085 return rewriteIntegerStore(V, SI, AATags);
3088 if (NewBeginOffset == NewAllocaBeginOffset &&
3089 NewEndOffset == NewAllocaEndOffset &&
3093 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3096 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3098 unsigned AS =
SI.getPointerAddressSpace();
3099 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3101 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3103 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3104 LLVMContext::MD_access_group});
3108 if (
SI.isVolatile())
3117 Pass.DeadInsts.push_back(&SI);
3118 deleteIfTriviallyDead(OldOp);
3136 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3144 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3154 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3167 if (!isa<ConstantInt>(
II.getLength())) {
3169 assert(NewBeginOffset == BeginOffset);
3170 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3171 II.setDestAlignment(getSliceAlign());
3177 "AT: Unexpected link to non-const GEP");
3178 deleteIfTriviallyDead(OldPtr);
3183 Pass.DeadInsts.push_back(&
II);
3188 const bool CanContinue = [&]() {
3191 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3194 auto *
C = cast<ConstantInt>(
II.getLength());
3196 if (Len > std::numeric_limits<unsigned>::max())
3198 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3201 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3207 Type *SizeTy =
II.getLength()->getType();
3208 unsigned Sz = NewEndOffset - NewBeginOffset;
3211 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3218 New,
New->getRawDest(),
nullptr,
DL);
3233 assert(ElementTy == ScalarTy);
3235 unsigned BeginIndex = getIndex(NewBeginOffset);
3236 unsigned EndIndex = getIndex(NewEndOffset);
3237 assert(EndIndex > BeginIndex &&
"Empty vector!");
3238 unsigned NumElements = EndIndex - BeginIndex;
3240 "Too many elements!");
3243 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3245 if (NumElements > 1)
3257 V = getIntegerSplat(
II.getValue(),
Size);
3259 if (IntTy && (BeginOffset != NewAllocaBeginOffset ||
3260 EndOffset != NewAllocaBeginOffset)) {
3267 assert(
V->getType() == IntTy &&
3268 "Wrong type for an alloca wide integer!");
3273 assert(NewBeginOffset == NewAllocaBeginOffset);
3274 assert(NewEndOffset == NewAllocaEndOffset);
3276 V = getIntegerSplat(
II.getValue(),
3277 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3278 if (
VectorType *AllocaVecTy = dyn_cast<VectorType>(AllocaTy))
3285 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3287 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3288 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3289 LLVMContext::MD_access_group});
3295 New,
New->getPointerOperand(), V,
DL);
3298 return !
II.isVolatile();
3309 bool IsDest = &
II.getRawDestUse() == OldUse;
3310 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3311 (!IsDest &&
II.getRawSource() == OldPtr));
3313 Align SliceAlign = getSliceAlign();
3321 if (!IsSplittable) {
3322 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3325 auto UpdateAssignAddress = [&](
auto *DbgAssign) {
3327 DbgAssign->getAddress() ==
II.getDest())
3328 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3332 II.setDest(AdjustedPtr);
3333 II.setDestAlignment(SliceAlign);
3335 II.setSource(AdjustedPtr);
3336 II.setSourceAlignment(SliceAlign);
3340 deleteIfTriviallyDead(OldPtr);
3353 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3362 if (EmitMemCpy && &OldAI == &NewAI) {
3364 assert(NewBeginOffset == BeginOffset);
3367 if (NewEndOffset != EndOffset)
3368 II.setLength(ConstantInt::get(
II.getLength()->getType(),
3369 NewEndOffset - NewBeginOffset));
3373 Pass.DeadInsts.push_back(&
II);
3377 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3380 assert(AI != &OldAI && AI != &NewAI &&
3381 "Splittable transfers cannot reach the same alloca on both ends.");
3382 Pass.Worklist.insert(AI);
3389 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3390 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3392 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
3394 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
3402 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3403 Type *SizeTy =
II.getLength()->getType();
3404 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
3406 Value *DestPtr, *SrcPtr;
3411 DestAlign = SliceAlign;
3413 SrcAlign = OtherAlign;
3416 DestAlign = OtherAlign;
3418 SrcAlign = SliceAlign;
3420 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
3423 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
3428 &
II, New, DestPtr,
nullptr,
DL);
3433 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
3439 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
3440 NewEndOffset == NewAllocaEndOffset;
3442 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
3443 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
3444 unsigned NumElements = EndIndex - BeginIndex;
3451 if (VecTy && !IsWholeAlloca) {
3452 if (NumElements == 1)
3453 OtherTy = VecTy->getElementType();
3456 }
else if (IntTy && !IsWholeAlloca) {
3459 OtherTy = NewAllocaTy;
3473 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3477 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
3481 if (VecTy && !IsWholeAlloca && !IsDest) {
3485 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
3492 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
3493 II.isVolatile(),
"copyload");
3494 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3495 LLVMContext::MD_access_group});
3502 if (VecTy && !IsWholeAlloca && IsDest) {
3506 }
else if (IntTy && !IsWholeAlloca && IsDest) {
3516 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
3517 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3518 LLVMContext::MD_access_group});
3521 Src->getType(),
DL));
3527 Store, DstPtr, Src,
DL);
3532 &
II, Store, DstPtr, Src,
DL);
3536 return !
II.isVolatile();
3540 assert((
II.isLifetimeStartOrEnd() ||
II.isLaunderOrStripInvariantGroup() ||
3541 II.isDroppable()) &&
3542 "Unexpected intrinsic!");
3546 Pass.DeadInsts.push_back(&
II);
3548 if (
II.isDroppable()) {
3549 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
3555 if (
II.isLaunderOrStripInvariantGroup())
3558 assert(
II.getArgOperand(1) == OldPtr);
3566 if (NewBeginOffset != NewAllocaBeginOffset ||
3567 NewEndOffset != NewAllocaEndOffset)
3571 ConstantInt::get(cast<IntegerType>(
II.getArgOperand(0)->getType()),
3572 NewEndOffset - NewBeginOffset);
3578 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
3596 Uses.push_back(&Root);
3600 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
3604 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
3605 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
3609 assert(isa<BitCastInst>(
I) || isa<AddrSpaceCastInst>(
I) ||
3610 isa<PHINode>(
I) || isa<SelectInst>(
I) ||
3611 isa<GetElementPtrInst>(
I));
3612 for (
User *U :
I->users())
3613 if (Visited.
insert(cast<Instruction>(U)).second)
3614 Uses.push_back(cast<Instruction>(U));
3615 }
while (!
Uses.empty());
3618 bool visitPHINode(
PHINode &PN) {
3620 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
3621 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
3628 if (isa<PHINode>(OldPtr))
3630 OldPtr->
getParent()->getFirstInsertionPt());
3632 IRB.SetInsertPoint(OldPtr);
3633 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
3635 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3637 std::replace(PN.
op_begin(), PN.
op_end(), cast<Value>(OldPtr), NewPtr);
3640 deleteIfTriviallyDead(OldPtr);
3643 fixLoadStoreAlign(PN);
3654 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
3655 "Pointer isn't an operand!");
3656 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
3657 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
3659 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3661 if (
SI.getOperand(1) == OldPtr)
3662 SI.setOperand(1, NewPtr);
3663 if (
SI.getOperand(2) == OldPtr)
3664 SI.setOperand(2, NewPtr);
3667 deleteIfTriviallyDead(OldPtr);
3670 fixLoadStoreAlign(SI);
3685class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
3705 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
3706 :
DL(
DL), IRB(IRB) {}
3713 bool Changed =
false;
3714 while (!
Queue.empty()) {
3715 U =
Queue.pop_back_val();
3716 Changed |=
visit(cast<Instruction>(
U->getUser()));
3725 for (
Use &U :
I.uses())
3726 if (Visited.
insert(
U.getUser()).second)
3727 Queue.push_back(&U);
3731 bool visitInstruction(
Instruction &
I) {
return false; }
3734 template <
typename Derived>
class OpSplitter {
3766 BaseAlign(BaseAlign),
DL(
DL) {
3787 return static_cast<Derived *
>(
this)->emitFunc(
3791 if (
ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
3792 unsigned OldSize = Indices.
size();
3794 for (
unsigned Idx = 0,
Size = ATy->getNumElements();
Idx !=
Size;
3796 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
3799 emitSplitOps(ATy->getElementType(), Agg,
Name +
"." +
Twine(
Idx));
3806 if (
StructType *STy = dyn_cast<StructType>(Ty)) {
3807 unsigned OldSize = Indices.
size();
3809 for (
unsigned Idx = 0,
Size = STy->getNumElements();
Idx !=
Size;
3811 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
3825 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
3847 IRB.CreateInBoundsGEP(
BaseTy,
Ptr, GEPIndices,
Name +
".gep");
3849 IRB.CreateAlignedLoad(Ty,
GEP, Alignment,
Name +
".load");
3852 DL.getIndexSizeInBits(
Ptr->getType()->getPointerAddressSpace()), 0);
3855 Load->setAAMetadata(
3861 Agg = IRB.CreateInsertValue(Agg, Load, Indices,
Name +
".insert");
3866 void recordFakeUses(
LoadInst &LI) {
3868 if (
auto *
II = dyn_cast<IntrinsicInst>(
U.getUser()))
3869 if (
II->getIntrinsicID() == Intrinsic::fake_use)
3875 void emitFakeUses() {
3877 IRB.SetInsertPoint(
I);
3878 for (
auto *V : Components)
3879 IRB.CreateIntrinsic(Intrinsic::fake_use, {}, {
V});
3880 I->eraseFromParent();
3894 Splitter.recordFakeUses(LI);
3897 Splitter.emitFakeUses();
3904 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
3910 AATags(AATags), AggStore(AggStore) {}
3921 Value *ExtractValue =
3922 IRB.CreateExtractValue(Agg, Indices,
Name +
".extract");
3923 Value *InBoundsGEP =
3924 IRB.CreateInBoundsGEP(
BaseTy,
Ptr, GEPIndices,
Name +
".gep");
3926 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
3929 DL.getIndexSizeInBits(
Ptr->getType()->getPointerAddressSpace()), 0);
3941 if (
auto *OldAI = dyn_cast<AllocaInst>(
Base)) {
3943 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
3945 SizeInBits, AggStore, Store,
3946 Store->getPointerOperand(),
Store->getValueOperand(),
3951 "AT: unexpected debug.assign linked to store through "
3959 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
3962 if (
V->getType()->isSingleValueType())
3967 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
3969 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
3974 SI.eraseFromParent();
3997 if (
auto *SI = dyn_cast<SelectInst>(
Op)) {
4008 if (!isa<ConstantInt>(
Op))
4016 dbgs() <<
" original: " << *Sel <<
"\n";
4017 dbgs() <<
" " << GEPI <<
"\n";);
4019 auto GetNewOps = [&](
Value *SelOp) {
4029 Value *True = Sel->getTrueValue();
4030 Value *False = Sel->getFalseValue();
4034 IRB.SetInsertPoint(&GEPI);
4038 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4039 True->
getName() +
".sroa.gep", NW);
4042 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4043 False->
getName() +
".sroa.gep", NW);
4045 Value *NSel = IRB.CreateSelect(Sel->getCondition(), NTrue, NFalse,
4046 Sel->getName() +
".sroa.sel");
4047 Visited.
erase(&GEPI);
4052 enqueueUsers(*NSelI);
4055 dbgs() <<
" " << *NFalse <<
"\n";
4056 dbgs() <<
" " << *NSel <<
"\n";);
4070 auto IsInvalidPointerOperand = [](
Value *
V) {
4071 if (!isa<Instruction>(V))
4073 if (
auto *AI = dyn_cast<AllocaInst>(V))
4074 return !AI->isStaticAlloca();
4078 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4087 if (
auto *SI = dyn_cast<PHINode>(
Op)) {
4093 [](
Value *V) { return isa<ConstantInt>(V); }))
4098 if (!isa<ConstantInt>(
Op))
4106 dbgs() <<
" original: " << *
Phi <<
"\n";
4107 dbgs() <<
" " << GEPI <<
"\n";);
4109 auto GetNewOps = [&](
Value *PhiOp) {
4119 IRB.SetInsertPoint(Phi);
4121 Phi->getName() +
".sroa.phi");
4127 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4136 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4142 Visited.
erase(&GEPI);
4146 enqueueUsers(*NewPhi);
4152 dbgs() <<
"\n " << *NewPhi <<
'\n');
4158 if (unfoldGEPSelect(GEPI))
4161 if (unfoldGEPPhi(GEPI))
4168 bool visitPHINode(
PHINode &PN) {
4190 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4194 if (
ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
4195 InnerTy = ArrTy->getElementType();
4196 }
else if (
StructType *STy = dyn_cast<StructType>(Ty)) {
4199 InnerTy = STy->getElementType(Index);
4204 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4205 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4226 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4228 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4229 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4232 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty)) {
4235 if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
4236 ElementTy = AT->getElementType();
4237 TyNumElements = AT->getNumElements();
4241 auto *VT = cast<FixedVectorType>(Ty);
4242 ElementTy = VT->getElementType();
4243 TyNumElements = VT->getNumElements();
4245 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4247 if (NumSkippedElements >= TyNumElements)
4249 Offset -= NumSkippedElements * ElementSize;
4261 if (
Size == ElementSize)
4265 if (NumElements * ElementSize !=
Size)
4267 return ArrayType::get(ElementTy, NumElements);
4289 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4290 if (
Offset >= ElementSize)
4301 if (
Size == ElementSize)
4308 if (Index == EndIndex)
4318 assert(Index < EndIndex);
4357bool SROA::presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS) {
4371 struct SplitOffsets {
4373 std::vector<uint64_t> Splits;
4390 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
4391 for (
auto &
P : AS.partitions()) {
4392 for (Slice &S :
P) {
4393 Instruction *
I = cast<Instruction>(S.getUse()->getUser());
4394 if (!S.isSplittable() || S.endOffset() <=
P.endOffset()) {
4398 if (
auto *LI = dyn_cast<LoadInst>(
I))
4399 UnsplittableLoads.
insert(LI);
4400 else if (
auto *SI = dyn_cast<StoreInst>(
I))
4401 if (
auto *LI = dyn_cast<LoadInst>(
SI->getValueOperand()))
4402 UnsplittableLoads.
insert(LI);
4405 assert(
P.endOffset() > S.beginOffset() &&
4406 "Empty or backwards partition!");
4409 if (
auto *LI = dyn_cast<LoadInst>(
I)) {
4415 auto IsLoadSimplyStored = [](
LoadInst *LI) {
4417 auto *
SI = dyn_cast<StoreInst>(LU);
4418 if (!SI || !
SI->isSimple())
4423 if (!IsLoadSimplyStored(LI)) {
4424 UnsplittableLoads.
insert(LI);
4429 }
else if (
auto *SI = dyn_cast<StoreInst>(
I)) {
4430 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
4433 auto *StoredLoad = dyn_cast<LoadInst>(
SI->getValueOperand());
4434 if (!StoredLoad || !StoredLoad->isSimple())
4436 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
4446 auto &
Offsets = SplitOffsetsMap[
I];
4448 "Should not have splits the first time we see an instruction!");
4450 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
4455 for (Slice *S :
P.splitSliceTails()) {
4456 auto SplitOffsetsMapI =
4457 SplitOffsetsMap.
find(cast<Instruction>(S->getUse()->getUser()));
4458 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
4460 auto &
Offsets = SplitOffsetsMapI->second;
4464 "Cannot have an empty set of splits on the second partition!");
4466 P.beginOffset() -
Offsets.S->beginOffset() &&
4467 "Previous split does not end where this one begins!");
4471 if (S->endOffset() >
P.endOffset())
4483 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4486 if (UnsplittableLoads.
count(LI))
4489 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
4490 if (LoadOffsetsI == SplitOffsetsMap.
end())
4492 auto &LoadOffsets = LoadOffsetsI->second;
4495 auto &StoreOffsets = SplitOffsetsMap[
SI];
4500 if (LoadOffsets.Splits == StoreOffsets.Splits)
4504 <<
" " << *LI <<
"\n"
4505 <<
" " << *SI <<
"\n");
4511 UnsplittableLoads.
insert(LI);
4519 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4520 return UnsplittableLoads.
count(LI);
4525 return UnsplittableLoads.
count(LI);
4535 IRBuilderTy IRB(&AI);
4553 std::vector<LoadInst *> SplitLoads;
4558 auto &
Offsets = SplitOffsetsMap[LI];
4559 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
4561 "Load must have type size equal to store size");
4563 "Load must be >= slice size");
4566 assert(BaseOffset + SliceSize > BaseOffset &&
4567 "Cannot represent alloca access size using 64-bit integers!");
4570 IRB.SetInsertPoint(LI);
4580 LoadInst *PLoad = IRB.CreateAlignedLoad(
4583 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4584 PartPtrTy,
BasePtr->getName() +
"."),
4587 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
4588 LLVMContext::MD_access_group});
4592 SplitLoads.push_back(PLoad);
4596 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4600 <<
", " << NewSlices.
back().endOffset()
4601 <<
"): " << *PLoad <<
"\n");
4616 bool DeferredStores =
false;
4619 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
4620 DeferredStores =
true;
4626 Value *StoreBasePtr =
SI->getPointerOperand();
4627 IRB.SetInsertPoint(SI);
4630 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
4635 auto *PartPtrTy =
SI->getPointerOperandType();
4637 auto AS =
SI->getPointerAddressSpace();
4638 StoreInst *PStore = IRB.CreateAlignedStore(
4641 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4642 PartPtrTy, StoreBasePtr->
getName() +
"."),
4645 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
4646 LLVMContext::MD_access_group,
4647 LLVMContext::MD_DIAssignID});
4652 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
4659 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(StoreBasePtr)) {
4660 ResplitPromotableAllocas.
insert(OtherAI);
4661 Worklist.insert(OtherAI);
4662 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
4664 Worklist.insert(OtherAI);
4668 DeadInsts.push_back(SI);
4673 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
4676 DeadInsts.push_back(LI);
4686 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4690 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
4694 "Slice size should always match load size exactly!");
4696 assert(BaseOffset + StoreSize > BaseOffset &&
4697 "Cannot represent alloca access size using 64-bit integers!");
4700 Instruction *StoreBasePtr = cast<Instruction>(
SI->getPointerOperand());
4705 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
4706 std::vector<LoadInst *> *SplitLoads =
nullptr;
4707 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
4708 SplitLoads = &SplitLoadsMapI->second;
4710 "Too few split loads for the number of splits in the store!");
4720 auto *StorePartPtrTy =
SI->getPointerOperandType();
4725 PLoad = (*SplitLoads)[
Idx];
4727 IRB.SetInsertPoint(LI);
4729 PLoad = IRB.CreateAlignedLoad(
4732 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4733 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
4736 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
4737 LLVMContext::MD_access_group});
4741 IRB.SetInsertPoint(SI);
4742 auto AS =
SI->getPointerAddressSpace();
4743 StoreInst *PStore = IRB.CreateAlignedStore(
4746 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4747 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
4750 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
4751 LLVMContext::MD_access_group});
4755 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4759 <<
", " << NewSlices.
back().endOffset()
4760 <<
"): " << *PStore <<
"\n");
4781 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(LoadBasePtr)) {
4782 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
4783 ResplitPromotableAllocas.
insert(OtherAI);
4784 Worklist.insert(OtherAI);
4785 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
4787 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
4788 Worklist.insert(OtherAI);
4803 DeadInsts.push_back(LI);
4805 DeadInsts.push_back(SI);
4814 AS.insert(NewSlices);
4818 for (
auto I = AS.begin(), E = AS.end();
I != E; ++
I)
4824 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
4844 Type *SliceTy =
nullptr;
4847 std::pair<Type *, IntegerType *> CommonUseTy =
4850 if (CommonUseTy.first)
4851 if (
DL.getTypeAllocSize(CommonUseTy.first).getFixedValue() >=
P.size()) {
4852 SliceTy = CommonUseTy.first;
4853 SliceVecTy = dyn_cast<VectorType>(SliceTy);
4858 P.beginOffset(),
P.size()))
4859 SliceTy = TypePartitionTy;
4862 if (!SliceTy && CommonUseTy.second)
4863 if (
DL.getTypeAllocSize(CommonUseTy.second).getFixedValue() >=
P.size()) {
4864 SliceTy = CommonUseTy.second;
4865 SliceVecTy = dyn_cast<VectorType>(SliceTy);
4867 if ((!SliceTy || (SliceTy->
isArrayTy() &&
4869 DL.isLegalInteger(
P.size() * 8)) {
4877 P.beginOffset(),
P.size())) {
4878 VectorType *TypePartitionVecTy = dyn_cast<VectorType>(TypePartitionTy);
4879 if (TypePartitionVecTy &&
4881 SliceTy = TypePartitionTy;
4886 assert(
DL.getTypeAllocSize(SliceTy).getFixedValue() >=
P.size());
4912 const bool IsUnconstrained = Alignment <=
DL.getABITypeAlign(SliceTy);
4915 IsUnconstrained ?
DL.getPrefTypeAlign(SliceTy) : Alignment,
4923 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
4924 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
4929 unsigned PPWOldSize = PostPromotionWorklist.size();
4930 unsigned NumUses = 0;
4934 AllocaSliceRewriter
Rewriter(
DL, AS, *
this, AI, *NewAI,
P.beginOffset(),
4935 P.endOffset(), IsIntegerPromotable, VecTy,
4936 PHIUsers, SelectUsers);
4937 bool Promotable =
true;
4938 for (Slice *S :
P.splitSliceTails()) {
4942 for (Slice &S :
P) {
4947 NumAllocaPartitionUses += NumUses;
4948 MaxUsesPerAllocaPartition.updateMax(NumUses);
4956 SelectUsers.
clear();
4961 NewSelectsToRewrite;
4964 std::optional<RewriteableMemOps> Ops =
4969 SelectUsers.clear();
4970 NewSelectsToRewrite.
clear();
4973 NewSelectsToRewrite.
emplace_back(std::make_pair(Sel, *Ops));
4977 for (
Use *U : AS.getDeadUsesIfPromotable()) {
4978 auto *OldInst = dyn_cast<Instruction>(
U->get());
4982 DeadInsts.push_back(OldInst);
4984 if (PHIUsers.empty() && SelectUsers.empty()) {
4986 PromotableAllocas.insert(NewAI);
4991 for (
PHINode *PHIUser : PHIUsers)
4992 SpeculatablePHIs.insert(PHIUser);
4993 SelectsToRewrite.reserve(SelectsToRewrite.size() +
4994 NewSelectsToRewrite.
size());
4996 std::make_move_iterator(NewSelectsToRewrite.
begin()),
4997 std::make_move_iterator(NewSelectsToRewrite.
end())))
4998 SelectsToRewrite.insert(std::move(KV));
4999 Worklist.insert(NewAI);
5003 while (PostPromotionWorklist.size() > PPWOldSize)
5004 PostPromotionWorklist.pop_back();
5014 Worklist.insert(NewAI);
5024 if (
const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
5025 return DAI->getAddress();
5026 return cast<DbgDeclareInst>(DVI)->getAddress();
5034 if (
const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
5035 return DAI->isKillAddress();
5036 return cast<DbgDeclareInst>(DVI)->isKillLocation();
5040 if (DVR->
getType() == DbgVariableRecord::LocationType::Assign)
5046 if (
const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
5047 return DAI->getAddressExpression();
5048 return cast<DbgDeclareInst>(DVI)->getExpression();
5052 if (DVR->
getType() == DbgVariableRecord::LocationType::Assign)
5084 int64_t BitExtractOffset) {
5086 bool HasFragment =
false;
5087 bool HasBitExtract =
false;
5096 HasBitExtract =
true;
5097 int64_t ExtractOffsetInBits =
Op.getArg(0);
5098 int64_t ExtractSizeInBits =
Op.getArg(1);
5107 assert(BitExtractOffset <= 0);
5108 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5114 if (AdjustedOffset < 0)
5118 Ops.
push_back(std::max<int64_t>(0, AdjustedOffset));
5122 Op.appendToVector(Ops);
5127 if (HasFragment && HasBitExtract)
5130 if (!HasBitExtract) {
5135 return DIExpression::get(Expr->
getContext(), Ops);
5148 std::optional<DIExpression::FragmentInfo> NewFragment,
5149 int64_t BitExtractAdjustment) {
5152 BitExtractAdjustment);
5156 DIB.insertDeclare(NewAddr, Orig->
getVariable(), NewAddrExpr,
5171 std::optional<DIExpression::FragmentInfo> NewFragment,
5172 int64_t BitExtractAdjustment) {
5181 BitExtractAdjustment);
5182 if (!NewFragmentExpr)
5186 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5194 LLVM_DEBUG(
dbgs() <<
"Created new assign intrinsic: " << *NewAssign <<
"\n");
5209 std::optional<DIExpression::FragmentInfo> NewFragment,
5210 int64_t BitExtractAdjustment) {
5220 BitExtractAdjustment);
5221 if (!NewFragmentExpr)
5227 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5240 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5246 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5254 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
5260bool SROA::splitAlloca(
AllocaInst &AI, AllocaSlices &AS) {
5261 if (AS.begin() == AS.end())
5264 unsigned NumPartitions = 0;
5265 bool Changed =
false;
5269 Changed |= presplitLoadsAndStores(AI, AS);
5277 bool IsSorted =
true;
5281 const uint64_t MaxBitVectorSize = 1024;
5282 if (AllocaSize <= MaxBitVectorSize) {
5287 for (
unsigned O = S.beginOffset() + 1;
5288 O < S.endOffset() && O < AllocaSize; O++)
5289 SplittableOffset.reset(O);
5291 for (Slice &S : AS) {
5292 if (!S.isSplittable())
5295 if ((S.beginOffset() > AllocaSize || SplittableOffset[S.beginOffset()]) &&
5296 (S.endOffset() > AllocaSize || SplittableOffset[S.endOffset()]))
5299 if (isa<LoadInst>(S.getUse()->getUser()) ||
5300 isa<StoreInst>(S.getUse()->getUser())) {
5301 S.makeUnsplittable();
5308 for (Slice &S : AS) {
5309 if (!S.isSplittable())
5312 if (S.beginOffset() == 0 && S.endOffset() >= AllocaSize)
5315 if (isa<LoadInst>(S.getUse()->getUser()) ||
5316 isa<StoreInst>(S.getUse()->getUser())) {
5317 S.makeUnsplittable();
5338 for (
auto &
P : AS.partitions()) {
5339 if (
AllocaInst *NewAI = rewritePartition(AI, AS,
P)) {
5346 uint64_t Size = std::min(AllocaSize,
P.size() * SizeOfByte);
5348 Fragment(NewAI,
P.beginOffset() * SizeOfByte,
Size));
5354 NumAllocaPartitions += NumPartitions;
5355 MaxPartitionsPerAlloca.updateMax(NumPartitions);
5369 int64_t CurrentExprOffsetInBytes = 0;
5372 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
5376 int64_t ExtractOffsetInBits = 0;
5380 ExtractOffsetInBits =
Op.getArg(0);
5386 for (
auto Fragment : Fragments) {
5387 int64_t OffsetFromLocationInBits;
5388 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
5393 DL, &AI, Fragment.Offset, Fragment.Size, DbgPtr,
5394 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
5395 NewDbgFragment, OffsetFromLocationInBits))
5401 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
5406 if (!NewDbgFragment)
5411 int64_t OffestFromNewAllocaInBits =
5412 OffsetFromLocationInBits - ExtractOffsetInBits;
5415 int64_t BitExtractOffset =
5416 std::min<int64_t>(0, OffestFromNewAllocaInBits);
5421 OffestFromNewAllocaInBits =
5422 std::max(int64_t(0), OffestFromNewAllocaInBits);
5429 if (OffestFromNewAllocaInBits > 0) {
5430 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
5437 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
5438 return LHS->getVariable() ==
RHS->getVariable() &&
5439 LHS->getDebugLoc()->getInlinedAt() ==
5440 RHS->getDebugLoc()->getInlinedAt();
5443 OldDII->eraseFromParent();
5449 NewDbgFragment, BitExtractOffset);
5465void SROA::clobberUse(
Use &U) {
5473 if (
Instruction *OldI = dyn_cast<Instruction>(OldV))
5475 DeadInsts.push_back(OldI);
5486 return !isa<StoreInst>(
I) && !isa<AllocaInst>(
I);
5497bool SROA::propagateStoredValuesToLoads(
AllocaInst &AI, AllocaSlices &AS) {
5502 auto PartitionBegin = AS.begin();
5503 auto PartitionEnd = PartitionBegin;
5504 uint64_t BeginOffset = PartitionBegin->beginOffset();
5505 uint64_t EndOffset = PartitionBegin->endOffset();
5506 while (PartitionBegin != AS.end()) {
5507 bool AllSameAndValid =
true;
5509 Type *PartitionType =
nullptr;
5510 while (PartitionEnd != AS.end() &&
5511 (PartitionEnd->beginOffset() < EndOffset ||
5512 PartitionEnd->endOffset() <= EndOffset)) {
5513 if (AllSameAndValid) {
5514 AllSameAndValid &= PartitionEnd->beginOffset() == BeginOffset &&
5515 PartitionEnd->endOffset() == EndOffset;
5517 cast<Instruction>(PartitionEnd->getUse()->getUser());
5518 if (
auto *LI = dyn_cast<LoadInst>(
User)) {
5521 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
5522 AllSameAndValid =
false;
5523 PartitionType = UserTy;
5525 }
else if (
auto *SI = dyn_cast<StoreInst>(
User)) {
5526 Type *UserTy =
SI->getValueOperand()->getType();
5527 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
5528 AllSameAndValid =
false;
5529 PartitionType = UserTy;
5532 AllSameAndValid =
false;
5535 EndOffset = std::max(EndOffset, PartitionEnd->endOffset());
5541 if (AllSameAndValid && !Insts.
empty()) {
5542 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
5543 << EndOffset <<
")\n");
5548 Promoter.run(Insts);
5552 PartitionBegin = PartitionEnd;
5553 if (PartitionBegin == AS.end())
5555 BeginOffset = PartitionBegin->beginOffset();
5556 EndOffset = PartitionBegin->endOffset();
5566std::pair<
bool ,
bool >
5568 bool Changed =
false;
5569 bool CFGChanged =
false;
5572 ++NumAllocasAnalyzed;
5578 return {Changed, CFGChanged};
5586 Size.getFixedValue() == 0)
5587 return {Changed, CFGChanged};
5591 IRBuilderTy IRB(&AI);
5592 AggLoadStoreRewriter AggRewriter(
DL, IRB);
5593 Changed |= AggRewriter.rewrite(AI);
5596 AllocaSlices AS(
DL, AI);
5599 return {Changed, CFGChanged};
5601 if (AS.isEscapedReadOnly()) {
5602 Changed |= propagateStoredValuesToLoads(AI, AS);
5603 return {Changed, CFGChanged};
5609 for (
Use &DeadOp : DeadUser->operands())
5616 DeadInsts.push_back(DeadUser);
5619 for (
Use *DeadOp : AS.getDeadOperands()) {
5620 clobberUse(*DeadOp);
5625 if (AS.begin() == AS.end())
5626 return {Changed, CFGChanged};
5628 Changed |= splitAlloca(AI, AS);
5631 while (!SpeculatablePHIs.empty())
5635 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
5636 while (!RemainingSelectsToRewrite.empty()) {
5637 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
5642 return {Changed, CFGChanged};
5654bool SROA::deleteDeadInstructions(
5656 bool Changed =
false;
5657 while (!DeadInsts.empty()) {
5658 Instruction *
I = dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val());
5667 DeletedAllocas.
insert(AI);
5669 OldDII->eraseFromParent();
5671 OldDII->eraseFromParent();
5677 for (
Use &Operand :
I->operands())
5678 if (
Instruction *U = dyn_cast<Instruction>(Operand)) {
5682 DeadInsts.push_back(U);
5686 I->eraseFromParent();
5697 if (PromotableAllocas.empty())
5704 NumPromoted += PromotableAllocas.size();
5705 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
5708 PromotableAllocas.clear();
5712std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
5722 PromotableAllocas.insert(AI);
5724 Worklist.insert(AI);
5728 bool Changed =
false;
5729 bool CFGChanged =
false;
5735 while (!Worklist.empty()) {
5736 auto [IterationChanged, IterationCFGChanged] =
5737 runOnAlloca(*Worklist.pop_back_val());
5738 Changed |= IterationChanged;
5739 CFGChanged |= IterationCFGChanged;
5741 Changed |= deleteDeadInstructions(DeletedAllocas);
5745 if (!DeletedAllocas.
empty()) {
5746 Worklist.set_subtract(DeletedAllocas);
5747 PostPromotionWorklist.set_subtract(DeletedAllocas);
5748 PromotableAllocas.set_subtract(DeletedAllocas);
5749 DeletedAllocas.
clear();
5753 Changed |= promoteAllocas(
F);
5755 Worklist = PostPromotionWorklist;
5756 PostPromotionWorklist.clear();
5757 }
while (!Worklist.empty());
5759 assert((!CFGChanged || Changed) &&
"Can not only modify the CFG.");
5761 "Should not have modified the CFG when told to preserve it.");
5764 for (
auto &BB :
F) {
5769 return {Changed, CFGChanged};
5776 auto [Changed, CFGChanged] =
5790 OS, MapClassName2PassName);
5791 OS << (
PreserveCFG == SROAOptions::PreserveCFG ?
"<preserve-cfg>"
5812 if (skipFunction(
F))
5815 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
5817 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
5831 StringRef getPassName()
const override {
return "SROA"; }
5836char SROALegacyPass::ID = 0;
5844 "Scalar Replacement Of Aggregates",
false,
false)
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
#define LLVM_ATTRIBUTE_UNUSED
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PointerIntPair class.
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
Remove Loads Into Fake Uses
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, uint64_t OldAllocaOffsetInBits, uint64_t SliceSizeInBits, Instruction *OldInst, Instruction *Inst, Value *Dest, Value *Value, const DataLayout &DL)
Find linked dbg.assign and generate a new one with the correct FragmentInfo.
static Align getAdjustedAlignment(Instruction *I, uint64_t Offset)
Compute the adjusted alignment for a load or store from an offset.
static cl::opt< bool > SROASkipMem2Reg("sroa-skip-mem2reg", cl::init(false), cl::Hidden)
Disable running mem2reg during SROA in order to test or debug SROA.
DbgVariableRecord * UnwrapDbgInstPtr(DbgInstPtr P, DbgVariableRecord *Unused)
Helpers for handling new and old debug info modes in migrateDebugInfo.
static std::pair< Type *, IntegerType * > findCommonType(AllocaSlices::const_iterator B, AllocaSlices::const_iterator E, uint64_t EndOffset)
Walk the range of a partitioning looking for a common type to cover this sequence of slices.
static Type * stripAggregateTypeWrapping(const DataLayout &DL, Type *Ty)
Strip aggregate type wrapping.
static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy)
Test whether we can convert a value from the old to the new type.
static DebugVariable getAggregateVariable(DbgVariableIntrinsic *DVI)
static VectorType * createAndCheckVectorTypesForPromotion(SetVector< Type * > &OtherTys, ArrayRef< VectorType * > CandidateTysCopy, function_ref< void(Type *)> CheckCandidateType, Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool &HaveCommonEltTy, Type *&CommonEltTy, bool &HaveVecPtrTy, bool &HaveCommonVecPtrTy, VectorType *&CommonVecPtrTy)
static FragCalcResult calculateFragment(DILocalVariable *Variable, uint64_t NewStorageSliceOffsetInBits, uint64_t NewStorageSliceSizeInBits, std::optional< DIExpression::FragmentInfo > StorageFragment, std::optional< DIExpression::FragmentInfo > CurrentFragment, DIExpression::FragmentInfo &Target)
const Value * getAddress(const DbgVariableIntrinsic *DVI)
static DIExpression * createOrReplaceFragment(const DIExpression *Expr, DIExpression::FragmentInfo Frag, int64_t BitExtractOffset)
Create or replace an existing fragment in a DIExpression with Frag.
static Value * insertInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *Old, Value *V, uint64_t Offset, const Twine &Name)
static Value * getAdjustedPtr(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, APInt Offset, Type *PointerTy, const Twine &NamePrefix)
Compute an adjusted pointer from Ptr by Offset bytes where the resulting pointer has PointerTy.
static bool isIntegerWideningViableForSlice(const Slice &S, uint64_t AllocBeginOffset, Type *AllocaTy, const DataLayout &DL, bool &WholeAllocaOp)
Test whether a slice of an alloca is valid for integer widening.
Scalar Replacement Of Aggregates
static Value * extractVector(IRBuilderTy &IRB, Value *V, unsigned BeginIndex, unsigned EndIndex, const Twine &Name)
static Value * foldPHINodeOrSelectInst(Instruction &I)
A helper that folds a PHI node or a select.
static bool rewriteSelectInstMemOps(SelectInst &SI, const RewriteableMemOps &Ops, IRBuilderTy &IRB, DomTreeUpdater *DTU)
static void rewriteMemOpOfSelect(SelectInst &SI, T &I, SelectHandSpeculativity Spec, DomTreeUpdater &DTU)
static Value * foldSelectInst(SelectInst &SI)
static bool checkVectorTypeForPromotion(Partition &P, VectorType *VTy, const DataLayout &DL)
Test whether a vector type is viable for promotion.
static Value * insertVector(IRBuilderTy &IRB, Value *Old, Value *V, unsigned BeginIndex, const Twine &Name)
static bool isIntegerWideningViable(Partition &P, Type *AllocaTy, const DataLayout &DL)
Test whether the given alloca partition's integer operations can be widened to promotable ones.
static void speculatePHINodeLoads(IRBuilderTy &IRB, PHINode &PN)
bool isKillAddress(const DbgVariableIntrinsic *DVI)
static bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
static Value * extractInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *V, IntegerType *Ty, uint64_t Offset, const Twine &Name)
static bool isVectorPromotionViableForSlice(Partition &P, const Slice &S, VectorType *Ty, uint64_t ElementSize, const DataLayout &DL)
Test whether the given slice use can be promoted to a vector.
static void insertNewDbgInst(DIBuilder &DIB, DbgDeclareInst *Orig, AllocaInst *NewAddr, DIExpression *NewAddrExpr, Instruction *BeforeInst, std::optional< DIExpression::FragmentInfo > NewFragment, int64_t BitExtractAdjustment)
Insert a new dbg.declare.
const DIExpression * getAddressExpression(const DbgVariableIntrinsic *DVI)
static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, IRBuilderTy &IRB)
static Type * getTypePartition(const DataLayout &DL, Type *Ty, uint64_t Offset, uint64_t Size)
Try to find a partition of the aggregate type passed in for a given offset and size.
static SelectHandSpeculativity isSafeLoadOfSelectToSpeculate(LoadInst &LI, SelectInst &SI, bool PreserveCFG)
static Value * convertValue(const DataLayout &DL, IRBuilderTy &IRB, Value *V, Type *NewTy)
Generic routine to convert an SSA value to a value of a different type.
static VectorType * isVectorPromotionViable(Partition &P, const DataLayout &DL)
Test whether the given alloca partitioning and range of slices can be promoted to a vector.
static VectorType * checkVectorTypesForPromotion(Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool HaveCommonEltTy, Type *CommonEltTy, bool HaveVecPtrTy, bool HaveCommonVecPtrTy, VectorType *CommonVecPtrTy)
Test whether any vector type in CandidateTys is viable for promotion.
This file provides the interface for LLVM's Scalar Replacement of Aggregates pass.
This file implements a set that has insertion order iteration characteristics.
This file implements the SmallBitVector class.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Virtual Register Rewriter
Builder for the alloca slices.
SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
An iterator over partitions of the alloca's slices.
bool operator==(const partition_iterator &RHS) const
friend class AllocaSlices
partition_iterator & operator++()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This class represents a no-op cast from one type to another.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool doesNotCapture(unsigned OpNo) const
Determine whether this data operand is not captured.
bool onlyReadsMemory(unsigned OpNo) const
bool isDataOperand(const Use *U) const
This class represents a function call, abstracting a target machine's calling convention.
ConstantFolder - Create constants with minimum, target independent, folding.
This is the shared class of boolean and integer constants.
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
DbgInstPtr insertDbgAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *SrcVar, DIExpression *ValExpr, Value *Addr, DIExpression *AddrExpr, const DILocation *DL)
Insert a new llvm.dbg.assign intrinsic call.
iterator_range< expr_op_iterator > expr_ops() const
DbgVariableFragmentInfo FragmentInfo
bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static bool calculateFragmentIntersect(const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits, int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag, std::optional< DIExpression::FragmentInfo > &Result, int64_t &OffsetFromLocationInBits)
Computes a fragment, bit-extract operation if needed, and new constant offset to describe a part of a...
static std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
bool typeSizeEqualsStoreSize(Type *Ty) const
Returns true if no extra padding bits are needed when storing the specified type.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
This represents the llvm.dbg.assign instruction.
This represents the llvm.dbg.declare instruction.
DebugLoc getDebugLoc() const
Value * getValue(unsigned OpIdx=0) const
This is the common base class for debug info intrinsics for variables.
DILocalVariable * getVariable() const
DIExpression * getExpression() const
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LocationType getType() const
bool isKillAddress() const
Check whether this kills the address component.
bool isKillLocation() const
Value * getValue(unsigned OpIdx=0) const
static DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
static DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
Value * getAddress() const
DIExpression * getExpression() const
void setKillAddress()
Kill the address component.
DILocalVariable * getVariable() const
bool isDbgDeclare() const
static DbgVariableRecord * createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, DIExpression *Expression, Value *Address, DIExpression *AddressExpression, const DILocation *DI)
DIExpression * getAddressExpression() const
This class is used to track local variable information.
DILocation * getInlinedAt() const
Identifies a unique instance of a variable.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
Represents flags for the getelementptr instruction/expression.
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * getPointerOperand()
iterator_range< op_iterator > indices()
Type * getSourceElementType() const
GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
Legacy wrapper pass to provide the GlobalsAAResult object.
This provides the default implementation of the IRBuilder 'InsertHelper' method that is called whenev...
virtual void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.memcpy/memmove intrinsics.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
PointerIntPair - This class implements a pair of a pointer and small integer.
void setPointer(PointerTy PtrVal) &
void setInt(IntType IntVal) &
PointerTy getPointer() const
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
A base class for visitors over the uses of a pointer value.
void visitCallBase(CallBase &CB)
void visitGetElementPtrInst(GetElementPtrInst &GEPI)
void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC)
void visitBitCastInst(BitCastInst &BC)
void visitIntrinsicInst(IntrinsicInst &II)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
SROAPass(SROAOptions PreserveCFG)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
Helper class for SSA formation on a set of values defined in multiple blocks.
This class represents the LLVM 'select' instruction.
const Value * getFalseValue() const
const Value * getTrueValue() const
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void clear()
Completely clear the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setAlignment(Align Align)
Value * getValueOperand()
static unsigned getPointerOperandIndex()
Value * getPointerOperand()
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
static constexpr size_t npos
size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getSizeInBytes() const
unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
TypeSize getElementOffset(unsigned Idx) const
TypeSize getSizeInBits() const
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
element_iterator element_end() const
element_iterator element_begin() const
Type * getElementType(unsigned N) const
Type::subtype_iterator element_iterator
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static IntegerType * getInt8Ty(LLVMContext &C)
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr) const
Accumulate the constant offset this value has compared to a base pointer.
bool hasOneUse() const
Return true if there is exactly one use of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
iterator_range< user_iterator > users()
static void dropDroppableUse(Use &U)
Remove the droppable use U.
void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
void setAborted(Instruction *I)
Mark the visit as aborted.
void setEscapedAndAborted(Instruction *I)
Mark the pointer as escaped, and the visit as aborted.
void setEscapedReadOnly(Instruction *I)
Mark the pointer as escaped into a readonly-nocapture call.
APInt Offset
The constant offset of the use if that is known.
void enqueueUsers(Value &I)
Enqueue the users of this instruction in the visit worklist.
bool IsOffsetKnown
True if we have a known constant offset for the use currently being visited.
PtrInfo PI
The info collected about the pointer being visited thus far.
Use * U
The use currently being visited.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
friend const_iterator begin(StringRef path, Style style)
Get begin iterator over path.
friend const_iterator end(StringRef path)
Get end iterator over path.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
AssignmentMarkerRange getAssignmentMarkers(DIAssignID *ID)
Return a range of dbg.assign intrinsics which use \ID as an operand.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_extract_bits_zext
Only used in LLVM metadata.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_sext
Only used in LLVM metadata.
NodeAddr< PhiNode * > Phi
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
bool RemoveRedundantDbgInstrs(BasicBlock *BB)
Try to remove redundant dbg.value instructions from given basic block.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
TinyPtrVector< DbgDeclareInst * > findDbgDeclares(Value *V)
Finds dbg.declare intrinsics declaring local variables as living in the memory that 'V' points to.
void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
bool isAssumeLikeIntrinsic(const Instruction *I)
Return true if it is an intrinsic that cannot be speculated but also cannot trap.
auto successors(const MachineBasicBlock *BB)
bool operator!=(uint64_t V1, const APInt &V2)
void copyMetadataForLoad(LoadInst &Dest, const LoadInst &Source)
Copy the metadata from the source instruction to the destination (the replacement for the source inst...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::optional< RegOrConstant > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
auto unique(Range &&R, Predicate P)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const DataLayout &DL, Instruction *ScanFrom, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)
Return true if we know that executing a load from this value cannot trap.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
TinyPtrVector< DbgVariableRecord * > findDVRValues(Value *V)
As above, for DVRValues.
void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
void initializeSROALegacyPassPass(PassRegistry &)
bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
As above, for DVRDeclares.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
FunctionPass * createSROAPass(bool PreserveCFG=true)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes shift(size_t Offset) const
Create a new AAMDNode that describes this AAMDNode after applying a constant offset to the start of t...
AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Describes an element of a Bitfield.
Holds functions to get, set or test bitfields.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A CRTP mix-in to automatically provide informational APIs needed for passes.
A MapVector that performs no allocations if smaller than a certain size.