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");
128class AllocaSliceRewriter;
132class SelectHandSpeculativity {
133 unsigned char Storage = 0;
137 SelectHandSpeculativity() =
default;
138 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
139 bool isSpeculatable(
bool isTrueVal)
const;
140 bool areAllSpeculatable()
const;
141 bool areAnySpeculatable()
const;
142 bool areNoneSpeculatable()
const;
144 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
145 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
147static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
149using PossiblySpeculatableLoad =
152using RewriteableMemOp =
153 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
175 LLVMContext *
const C;
176 DomTreeUpdater *
const DTU;
177 AssumptionCache *
const AC;
178 const bool PreserveCFG;
179 const bool AggregateToVector;
188 SmallSetVector<AllocaInst *, 16> Worklist;
203 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
206 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
207 SmallPtrSet<AllocaInst *, 16>, 16>
215 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
219 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
235 static std::optional<RewriteableMemOps>
236 isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG);
239 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
241 : C(C), DTU(DTU), AC(AC),
242 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
243 AggregateToVector(
Options.AggregateToVector) {}
246 std::pair<
bool ,
bool > runSROA(
Function &
F);
249 friend class AllocaSliceRewriter;
251 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
252 std::pair<AllocaInst *, uint64_t>
253 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
254 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
255 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
256 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
257 void clobberUse(Use &U);
258 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
259 bool promoteAllocas();
273enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
277 uint64_t NewStorageSliceOffsetInBits,
279 std::optional<DIExpression::FragmentInfo> StorageFragment,
280 std::optional<DIExpression::FragmentInfo> CurrentFragment,
284 if (StorageFragment) {
286 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
288 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
290 Target.SizeInBits = NewStorageSliceSizeInBits;
291 Target.OffsetInBits = NewStorageSliceOffsetInBits;
297 if (!CurrentFragment) {
298 if (
auto Size = Variable->getSizeInBits()) {
301 if (
Target == CurrentFragment)
308 if (!CurrentFragment || *CurrentFragment ==
Target)
314 if (
Target.startInBits() < CurrentFragment->startInBits() ||
315 Target.endInBits() > CurrentFragment->endInBits())
354 if (DVRAssignMarkerRange.empty())
360 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
362 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
374 DVR->getExpression()->getFragmentInfo();
387 auto *Expr = DbgAssign->getExpression();
388 bool SetKillLocation =
false;
391 std::optional<DIExpression::FragmentInfo> BaseFragment;
394 if (R == BaseFragments.
end())
396 BaseFragment = R->second;
398 std::optional<DIExpression::FragmentInfo> CurrentFragment =
399 Expr->getFragmentInfo();
402 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
403 BaseFragment, CurrentFragment, NewFragment);
407 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
408 if (CurrentFragment) {
413 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
426 SetKillLocation =
true;
434 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
441 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
445 NewAssign = DbgAssign;
464 Value && (DbgAssign->hasArgList() ||
465 !DbgAssign->getExpression()->isSingleLocationExpression());
482 if (NewAssign != DbgAssign) {
483 NewAssign->
moveBefore(DbgAssign->getIterator());
486 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
489 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
499 Twine getNameWithPrefix(
const Twine &Name)
const {
504 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
506 void InsertHelper(Instruction *
I,
const Twine &Name,
531 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
537 : BeginOffset(BeginOffset), EndOffset(EndOffset),
538 UseAndIsSplittable(
U, IsSplittable) {}
540 uint64_t beginOffset()
const {
return BeginOffset; }
541 uint64_t endOffset()
const {
return EndOffset; }
543 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
544 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
546 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
548 bool isDead()
const {
return getUse() ==
nullptr; }
549 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
558 if (beginOffset() <
RHS.beginOffset())
560 if (beginOffset() >
RHS.beginOffset())
562 if (isSplittable() !=
RHS.isSplittable())
563 return !isSplittable();
564 if (endOffset() >
RHS.endOffset())
571 return LHS.beginOffset() < RHSOffset;
574 return LHSOffset <
RHS.beginOffset();
578 return isSplittable() ==
RHS.isSplittable() &&
579 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
594 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
600 bool isEscaped()
const {
return PointerEscapingInstr; }
601 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
606 using range = iterator_range<iterator>;
608 iterator
begin() {
return Slices.begin(); }
609 iterator
end() {
return Slices.end(); }
612 using const_range = iterator_range<const_iterator>;
614 const_iterator
begin()
const {
return Slices.begin(); }
615 const_iterator
end()
const {
return Slices.end(); }
619 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
627 int OldSize = Slices.size();
628 Slices.append(NewSlices.
begin(), NewSlices.
end());
629 auto SliceI = Slices.begin() + OldSize;
630 std::stable_sort(SliceI, Slices.end());
631 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
644 return DeadUseIfPromotable;
655#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
656 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
657 void printSlice(raw_ostream &OS, const_iterator
I,
658 StringRef Indent =
" ")
const;
659 void printUse(raw_ostream &OS, const_iterator
I,
660 StringRef Indent =
" ")
const;
661 void print(raw_ostream &OS)
const;
662 void dump(const_iterator
I)
const;
667 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
670 friend class AllocaSlices::SliceBuilder;
672#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
700 SmallVector<Instruction *, 8> DeadUsers;
727 friend class AllocaSlices;
728 friend class AllocaSlices::partition_iterator;
730 using iterator = AllocaSlices::iterator;
734 uint64_t BeginOffset = 0, EndOffset = 0;
744 Partition(iterator SI) : SI(SI), SJ(SI) {}
750 uint64_t beginOffset()
const {
return BeginOffset; }
755 uint64_t endOffset()
const {
return EndOffset; }
761 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
762 return EndOffset - BeginOffset;
767 bool empty()
const {
return SI == SJ; }
778 iterator
begin()
const {
return SI; }
779 iterator
end()
const {
return SJ; }
811 AllocaSlices::iterator SE;
815 uint64_t MaxSplitSliceEndOffset = 0;
819 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
831 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
832 "Cannot advance past the end of the slices!");
835 if (!
P.SplitTails.empty()) {
836 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
838 P.SplitTails.clear();
839 MaxSplitSliceEndOffset = 0;
845 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
848 return S->endOffset() == MaxSplitSliceEndOffset;
850 "Could not find the current max split slice offset!");
853 return S->endOffset() <= MaxSplitSliceEndOffset;
855 "Max split slice end offset is not actually the max!");
862 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
872 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
873 P.SplitTails.push_back(&S);
874 MaxSplitSliceEndOffset =
875 std::max(S.endOffset(), MaxSplitSliceEndOffset);
883 P.BeginOffset = P.EndOffset;
884 P.EndOffset = MaxSplitSliceEndOffset;
891 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
892 !P.SI->isSplittable()) {
893 P.BeginOffset = P.EndOffset;
894 P.EndOffset = P.SI->beginOffset();
904 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
905 P.EndOffset = P.SI->endOffset();
910 if (!P.SI->isSplittable()) {
913 assert(P.BeginOffset == P.SI->beginOffset());
917 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
918 if (!P.SJ->isSplittable())
919 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
931 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
934 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
935 P.SJ->isSplittable()) {
936 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
943 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
944 assert(!P.SJ->isSplittable());
945 P.EndOffset = P.SJ->beginOffset();
952 "End iterators don't match between compared partition iterators!");
959 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
960 assert(P.SJ == RHS.P.SJ &&
961 "Same set of slices formed two different sized partitions!");
962 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
963 "Same slice position with differently sized non-empty split "
986 return make_range(partition_iterator(begin(), end()),
987 partition_iterator(end(), end()));
995 return SI.getOperand(1 + CI->isZero());
996 if (
SI.getOperand(1) ==
SI.getOperand(2))
997 return SI.getOperand(1);
1006 return PN->hasConstantValue();
1021 const uint64_t AllocSize;
1037 if (VisitedDeadInsts.
insert(&
I).second)
1042 bool IsSplittable =
false) {
1048 <<
" which has zero size or starts outside of the "
1049 << AllocSize <<
" byte alloca:\n"
1050 <<
" alloca: " << AS.AI <<
"\n"
1051 <<
" use: " <<
I <<
"\n");
1052 return markAsDead(
I);
1064 assert(AllocSize >= BeginOffset);
1065 if (
Size > AllocSize - BeginOffset) {
1067 <<
Offset <<
" to remain within the " << AllocSize
1068 <<
" byte alloca:\n"
1069 <<
" alloca: " << AS.AI <<
"\n"
1070 <<
" use: " <<
I <<
"\n");
1071 EndOffset = AllocSize;
1074 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1077 void visitBitCastInst(BitCastInst &BC) {
1079 return markAsDead(BC);
1081 return Base::visitBitCastInst(BC);
1084 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1086 return markAsDead(ASC);
1088 return Base::visitAddrSpaceCastInst(ASC);
1091 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1093 return markAsDead(GEPI);
1095 return Base::visitGetElementPtrInst(GEPI);
1098 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1109 void visitLoadInst(LoadInst &LI) {
1111 "All simple FCA loads should have been pre-split");
1116 return PI.setEscapedReadOnly(&LI);
1119 if (
Size.isScalable()) {
1122 return PI.setAborted(&LI);
1131 void visitStoreInst(StoreInst &SI) {
1132 Value *ValOp =
SI.getValueOperand();
1134 return PI.setEscapedAndAborted(&SI);
1136 return PI.setAborted(&SI);
1138 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1140 unsigned VScale =
SI.getFunction()->getVScaleValue();
1142 return PI.setAborted(&SI);
1158 <<
Offset <<
" which extends past the end of the "
1159 << AllocSize <<
" byte alloca:\n"
1160 <<
" alloca: " << AS.AI <<
"\n"
1161 <<
" use: " << SI <<
"\n");
1162 return markAsDead(SI);
1166 "All simple FCA stores should have been pre-split");
1170 void visitMemSetInst(MemSetInst &
II) {
1171 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1174 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1176 return markAsDead(
II);
1179 return PI.setAborted(&
II);
1183 : AllocSize -
Offset.getLimitedValue(),
1187 void visitMemTransferInst(MemTransferInst &
II) {
1191 return markAsDead(
II);
1195 if (VisitedDeadInsts.
count(&
II))
1199 return PI.setAborted(&
II);
1206 if (
Offset.uge(AllocSize)) {
1207 auto MTPI = MemTransferSliceMap.
find(&
II);
1208 if (MTPI != MemTransferSliceMap.
end())
1209 AS.Slices[MTPI->second].kill();
1210 return markAsDead(
II);
1218 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1220 if (!
II.isVolatile())
1221 return markAsDead(
II);
1229 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1230 std::tie(MTPI, Inserted) =
1231 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1232 unsigned PrevIdx = MTPI->second;
1234 Slice &PrevP = AS.Slices[PrevIdx];
1238 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1240 return markAsDead(
II);
1245 PrevP.makeUnsplittable();
1252 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1253 "Map index doesn't point back to a slice with this user.");
1259 void visitIntrinsicInst(IntrinsicInst &
II) {
1260 if (
II.isDroppable()) {
1261 AS.DeadUseIfPromotable.push_back(U);
1266 return PI.setAborted(&
II);
1268 if (
II.isLifetimeStartOrEnd()) {
1269 insertUse(
II,
Offset, AllocSize,
true);
1273 Base::visitIntrinsicInst(
II);
1281 SmallPtrSet<Instruction *, 4> Visited;
1291 std::tie(UsedI,
I) =
Uses.pop_back_val();
1294 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1306 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1316 if (!
GEP->hasAllZeroIndices())
1323 for (User *U :
I->users())
1326 }
while (!
Uses.empty());
1331 void visitPHINodeOrSelectInst(Instruction &
I) {
1334 return markAsDead(
I);
1340 return PI.setAborted(&
I);
1358 AS.DeadOperands.push_back(U);
1364 return PI.setAborted(&
I);
1370 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1371 return PI.setAborted(UnsafeI);
1380 if (
Offset.uge(AllocSize)) {
1381 AS.DeadOperands.push_back(U);
1388 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1390 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1393 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1395 void visitCallBase(CallBase &CB) {
1401 PI.setEscapedReadOnly(&CB);
1405 Base::visitCallBase(CB);
1409AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1411#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1414 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1416 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1417 if (PtrI.isEscaped() || PtrI.isAborted()) {
1420 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1421 : PtrI.getAbortingInst();
1422 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1425 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1427 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1434#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1436void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1437 StringRef Indent)
const {
1438 printSlice(OS,
I, Indent);
1440 printUse(OS,
I, Indent);
1443void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1444 StringRef Indent)
const {
1445 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1446 <<
" slice #" << (
I -
begin())
1447 << (
I->isSplittable() ?
" (splittable)" :
"");
1450void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1451 StringRef Indent)
const {
1452 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1455void AllocaSlices::print(raw_ostream &OS)
const {
1456 if (PointerEscapingInstr) {
1457 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1458 <<
" A pointer to this alloca escaped by:\n"
1459 <<
" " << *PointerEscapingInstr <<
"\n";
1463 if (PointerEscapingInstrReadOnly)
1464 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1466 OS <<
"Slices of alloca: " << AI <<
"\n";
1487 for (
User *U :
I.users()) {
1488 Type *UserTy =
nullptr;
1494 UserTy =
Store->getValueOperand()->getType();
1496 if (!UserTy || (Ty && Ty != UserTy))
1506static std::pair<Type *, IntegerType *>
1510 bool TyIsCommon =
true;
1515 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1516 Use *U =
I->getUse();
1519 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1522 Type *UserTy =
nullptr;
1526 UserTy =
SI->getValueOperand()->getType();
1537 if (UserITy->getBitWidth() % 8 != 0 ||
1538 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1543 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1549 if (!UserTy || (Ty && Ty != UserTy))
1555 return {TyIsCommon ? Ty :
nullptr, ITy};
1586 Type *LoadType =
nullptr;
1599 if (LoadType != LI->
getType())
1608 if (BBI->mayWriteToMemory())
1611 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1618 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1656 IRB.SetInsertPoint(&PN);
1658 PN.
getName() +
".sroa.speculated");
1688 IRB.SetInsertPoint(TI);
1691 LoadTy, InVal, Alignment,
1692 (PN.
getName() +
".sroa.speculate.load." + Pred->getName()));
1693 ++NumLoadsSpeculated;
1695 Load->setAAMetadata(AATags);
1697 InjectedLoads[Pred] =
Load;
1704SelectHandSpeculativity &
1705SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1713bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1718bool SelectHandSpeculativity::areAllSpeculatable()
const {
1719 return isSpeculatable(
true) &&
1720 isSpeculatable(
false);
1723bool SelectHandSpeculativity::areAnySpeculatable()
const {
1724 return isSpeculatable(
true) ||
1725 isSpeculatable(
false);
1727bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1728 return !areAnySpeculatable();
1731static SelectHandSpeculativity
1734 SelectHandSpeculativity
Spec;
1740 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1741 else if (PreserveCFG)
1747std::optional<RewriteableMemOps>
1748SROA::isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG) {
1749 RewriteableMemOps
Ops;
1751 for (User *U :
SI.users()) {
1756 if (
Store->isVolatile() || PreserveCFG)
1769 PossiblySpeculatableLoad
Load(LI);
1779 SelectHandSpeculativity Spec =
1781 if (PreserveCFG && !Spec.areAllSpeculatable())
1795 Value *TV =
SI.getTrueValue();
1796 Value *FV =
SI.getFalseValue();
1801 IRB.SetInsertPoint(&LI);
1805 LI.
getName() +
".sroa.speculate.load.true");
1808 LI.
getName() +
".sroa.speculate.load.false");
1809 NumLoadsSpeculated += 2;
1821 Value *V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1822 LI.
getName() +
".sroa.speculated", &
SI);
1828template <
typename T>
1830 SelectHandSpeculativity
Spec,
1837 if (
Spec.areNoneSpeculatable())
1839 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1842 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1844 if (
Spec.isSpeculatable(
true))
1850 Tail->setName(Head->
getName() +
".cont");
1855 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1856 int SuccIdx = IsThen ? 0 : 1;
1857 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
1858 auto &CondMemOp =
cast<T>(*
I.clone());
1859 if (NewMemOpBB != Head) {
1860 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1862 ++NumLoadsPredicated;
1864 ++NumStoresPredicated;
1866 CondMemOp.dropUBImplyingAttrsAndMetadata();
1867 ++NumLoadsSpeculated;
1869 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
1870 Value *Ptr =
SI.getOperand(1 + SuccIdx);
1871 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
1873 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1881 I.replaceAllUsesWith(PN);
1886 SelectHandSpeculativity
Spec,
1897 const RewriteableMemOps &
Ops,
1899 bool CFGChanged =
false;
1902 for (
const RewriteableMemOp &
Op :
Ops) {
1903 SelectHandSpeculativity
Spec;
1905 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
1908 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
1909 I = PSL.getPointer();
1910 Spec = PSL.getInt();
1912 if (
Spec.areAllSpeculatable()) {
1915 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
1919 I->eraseFromParent();
1924 SI.eraseFromParent();
1932 const Twine &NamePrefix) {
1934 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
1935 NamePrefix +
"sroa_idx");
1936 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
1937 NamePrefix +
"sroa_cast");
1952 unsigned VScale = 0) {
1962 "We can't have the same bitwidth for different int types");
1966 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
1967 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
1994 if (NewSize != OldSize)
2010 return OldAS == NewAS ||
2011 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2012 !
DL.isNonIntegralAddressSpace(NewAS) &&
2013 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2019 return !
DL.isNonIntegralPointerType(NewTy);
2023 if (!
DL.isNonIntegralPointerType(OldTy))
2046 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2047 uint64_t BeginIndex = BeginOffset / ElementSize;
2048 if (BeginIndex * ElementSize != BeginOffset ||
2051 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2052 uint64_t EndIndex = EndOffset / ElementSize;
2053 if (EndIndex * ElementSize != EndOffset ||
2057 assert(EndIndex > BeginIndex &&
"Empty vector!");
2058 uint64_t NumElements = EndIndex - BeginIndex;
2059 Type *SliceTy = (NumElements == 1)
2060 ? Ty->getElementType()
2066 Use *U = S.getUse();
2069 if (
MI->isVolatile())
2071 if (!S.isSplittable())
2079 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2086 if (LTy->isStructTy())
2088 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2089 assert(LTy->isIntegerTy());
2095 if (
SI->isVolatile())
2097 Type *STy =
SI->getValueOperand()->getType();
2101 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2121 bool HaveCommonEltTy,
Type *CommonEltTy,
2122 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2123 VectorType *CommonVecPtrTy,
unsigned VScale) {
2125 if (CandidateTys.
empty())
2132 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2136 if (!HaveCommonEltTy && HaveVecPtrTy) {
2138 CandidateTys.
clear();
2140 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2143 if (!VTy->getElementType()->isIntegerTy())
2145 VTy->getContext(), VTy->getScalarSizeInBits())));
2152 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2153 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2154 "Cannot have vector types of different sizes!");
2155 assert(RHSTy->getElementType()->isIntegerTy() &&
2156 "All non-integer types eliminated!");
2157 assert(LHSTy->getElementType()->isIntegerTy() &&
2158 "All non-integer types eliminated!");
2164 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2165 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2166 "Cannot have vector types of different sizes!");
2167 assert(RHSTy->getElementType()->isIntegerTy() &&
2168 "All non-integer types eliminated!");
2169 assert(LHSTy->getElementType()->isIntegerTy() &&
2170 "All non-integer types eliminated!");
2174 llvm::sort(CandidateTys, RankVectorTypesComp);
2175 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2176 CandidateTys.end());
2182 assert(VTy->getElementType() == CommonEltTy &&
2183 "Unaccounted for element type!");
2184 assert(VTy == CandidateTys[0] &&
2185 "Different vector types with the same element type!");
2188 CandidateTys.resize(1);
2195 std::numeric_limits<unsigned short>::max();
2201 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2205 if (ElementSize % 8)
2207 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2208 "vector size not a multiple of element size?");
2211 for (
const Slice &S :
P)
2215 for (
const Slice *S :
P.splitSliceTails())
2221 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2228 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2229 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2231 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2234 for (
Type *Ty : OtherTys) {
2237 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2240 for (
VectorType *
const VTy : CandidateTysCopy) {
2242 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2243 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2244 unsigned ElementSize =
2245 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2249 CheckCandidateType(NewVTy);
2255 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2256 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2275 Type *CommonEltTy =
nullptr;
2277 bool HaveVecPtrTy =
false;
2278 bool HaveCommonEltTy =
true;
2279 bool HaveCommonVecPtrTy =
true;
2280 auto CheckCandidateType = [&](
Type *Ty) {
2283 if (!CandidateTys.
empty()) {
2285 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2286 DL.getTypeSizeInBits(V).getFixedValue()) {
2287 CandidateTys.
clear();
2292 Type *EltTy = VTy->getElementType();
2295 CommonEltTy = EltTy;
2296 else if (CommonEltTy != EltTy)
2297 HaveCommonEltTy =
false;
2300 HaveVecPtrTy =
true;
2301 if (!CommonVecPtrTy)
2302 CommonVecPtrTy = VTy;
2303 else if (CommonVecPtrTy != VTy)
2304 HaveCommonVecPtrTy =
false;
2310 for (
const Slice &S :
P) {
2315 Ty =
SI->getValueOperand()->getType();
2319 auto CandTy = Ty->getScalarType();
2320 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2321 S.endOffset() !=
P.endOffset())) {
2328 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2329 CheckCandidateType(Ty);
2334 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2335 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2336 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2339 CandidateTys.
clear();
2341 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2342 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2343 CommonVecPtrTy, VScale);
2354 bool &WholeAllocaOp) {
2357 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2358 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2360 Use *U = S.getUse();
2367 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2385 if (S.beginOffset() < AllocBeginOffset)
2391 WholeAllocaOp =
true;
2393 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2395 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2402 Type *ValueTy =
SI->getValueOperand()->getType();
2403 if (
SI->isVolatile())
2406 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2411 if (S.beginOffset() < AllocBeginOffset)
2417 WholeAllocaOp =
true;
2419 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2421 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2430 if (!S.isSplittable())
2447 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2453 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2471 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2473 for (
const Slice &S :
P)
2478 for (
const Slice *S :
P.splitSliceTails())
2483 return WholeAllocaOp;
2488 const Twine &Name) {
2492 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2493 "Element extends past full value");
2495 if (
DL.isBigEndian())
2496 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2497 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2499 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2502 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2503 "Cannot extract to a larger integer!");
2505 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2515 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2516 "Cannot insert a larger integer!");
2519 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2523 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2524 "Element store outside of alloca store");
2526 if (
DL.isBigEndian())
2527 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2528 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2530 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2534 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2535 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2536 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2538 V = IRB.CreateOr(Old, V, Name +
".insert");
2545 unsigned EndIndex,
const Twine &Name) {
2547 unsigned NumElements = EndIndex - BeginIndex;
2548 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2550 if (NumElements == VecTy->getNumElements())
2553 if (NumElements == 1) {
2554 V = IRB.CreateExtractElement(V, BeginIndex, Name +
".extract");
2560 V = IRB.CreateShuffleVector(V, Mask, Name +
".extract");
2566 unsigned BeginIndex,
const Twine &Name) {
2568 assert(VecTy &&
"Can only insert a vector into a vector");
2573 V = IRB.CreateInsertElement(Old, V, BeginIndex, Name +
".insert");
2581 assert(NumSubElements <= NumElements &&
"Too many elements!");
2582 if (NumSubElements == NumElements) {
2583 assert(V->getType() == VecTy &&
"Vector type mismatch");
2586 unsigned EndIndex = BeginIndex + NumSubElements;
2593 Mask.reserve(NumElements);
2594 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2595 if (Idx >= BeginIndex && Idx < EndIndex)
2596 Mask.push_back(Idx - BeginIndex);
2599 V = IRB.CreateShuffleVector(V, Mask, Name +
".expand");
2603 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2604 if (Idx >= BeginIndex && Idx < EndIndex)
2605 Mask.push_back(Idx);
2607 Mask.push_back(Idx + NumElements);
2608 V = IRB.CreateShuffleVector(V, Old, Mask, Name +
"blend");
2647 const char *DebugName) {
2648 Type *EltType = VecType->getElementType();
2649 if (EltType != NewAIEltTy) {
2651 unsigned TotalBits =
2652 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2653 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2656 V = Builder.CreateBitCast(V, NewVecType);
2657 VecType = NewVecType;
2658 LLVM_DEBUG(
dbgs() <<
" bitcast " << DebugName <<
": " << *V <<
"\n");
2662 BitcastIfNeeded(V0, VecType0,
"V0");
2663 BitcastIfNeeded(
V1, VecType1,
"V1");
2665 unsigned NumElts0 = VecType0->getNumElements();
2666 unsigned NumElts1 = VecType1->getNumElements();
2670 if (NumElts0 == NumElts1) {
2671 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2672 ShuffleMask.push_back(i);
2676 unsigned SmallSize = std::min(NumElts0, NumElts1);
2677 unsigned LargeSize = std::max(NumElts0, NumElts1);
2678 bool IsV0Smaller = NumElts0 < NumElts1;
2679 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2681 for (
unsigned i = 0; i < SmallSize; ++i)
2683 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2685 ExtendedVec = Builder.CreateShuffleVector(
2687 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2688 for (
unsigned i = 0; i < NumElts0; ++i)
2689 ShuffleMask.push_back(i);
2690 for (
unsigned i = 0; i < NumElts1; ++i)
2691 ShuffleMask.push_back(LargeSize + i);
2694 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2705class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2707 friend class InstVisitor<AllocaSliceRewriter, bool>;
2709 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2711 const DataLayout &
DL;
2714 AllocaInst &OldAI, &NewAI;
2715 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2744 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2747 bool IsSplittable =
false;
2748 bool IsSplit =
false;
2749 Use *OldUse =
nullptr;
2753 SmallSetVector<PHINode *, 8> &PHIUsers;
2754 SmallSetVector<SelectInst *, 8> &SelectUsers;
2762 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2766 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2767 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2771 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2772 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2774 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2775 VectorType *PromotableVecTy,
2776 SmallSetVector<PHINode *, 8> &PHIUsers,
2777 SmallSetVector<SelectInst *, 8> &SelectUsers)
2778 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2779 NewAllocaBeginOffset(NewAllocaBeginOffset),
2780 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2781 IntTy(IsIntegerPromotable
2784 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2786 VecTy(PromotableVecTy),
2787 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2788 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2790 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2793 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2794 "Only multiple-of-8 sized vector elements are viable");
2797 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2800 bool visit(AllocaSlices::const_iterator
I) {
2801 bool CanSROA =
true;
2802 BeginOffset =
I->beginOffset();
2803 EndOffset =
I->endOffset();
2804 IsSplittable =
I->isSplittable();
2806 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2807 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2812 assert(BeginOffset < NewAllocaEndOffset);
2813 assert(EndOffset > NewAllocaBeginOffset);
2814 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2815 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2817 SliceSize = NewEndOffset - NewBeginOffset;
2818 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2819 <<
") NewBegin:(" << NewBeginOffset <<
", "
2820 << NewEndOffset <<
") NewAllocaBegin:("
2821 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2823 assert(IsSplit || NewBeginOffset == BeginOffset);
2824 OldUse =
I->getUse();
2828 IRB.SetInsertPoint(OldUserI);
2829 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2831 if (!IRB.getContext().shouldDiscardValueNames())
2832 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2833 Twine(BeginOffset) +
".");
2895 std::optional<SmallVector<Value *, 4>>
2896 rewriteTreeStructuredMerge(Partition &
P) {
2898 if (
P.splitSliceTails().size() > 0)
2899 return std::nullopt;
2908 :
Store(
SI), BeginOffset(Begin), EndOffset(End), StoredValue(Val) {}
2918 LoadInst *FullLoad =
nullptr;
2919 StoreInst *InitStore =
nullptr;
2923 Type *AllocatedEltTy =
2927 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
2934 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
2936 return FixedVecTy &&
2937 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
2938 !FixedVecTy->getElementType()->isPointerTy();
2941 for (Slice &S :
P) {
2945 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
2946 S.endOffset() == NewAllocaEndOffset);
2950 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
2951 return std::nullopt;
2956 return std::nullopt;
2960 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
2972 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
2973 SI->getValueOperand()->getType()))
2974 return std::nullopt;
2976 unsigned NumElts = StVecTy->getNumElements();
2977 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
2978 if (NumElts * EltSize % AllocatedEltTySize != 0)
2979 return std::nullopt;
2984 return std::nullopt;
2987 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
2988 SI->getValueOperand());
2993 return std::nullopt;
3000 if (StoreInfos.
size() < 2)
3001 return std::nullopt;
3009 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3010 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3011 if (!IsRMWPattern && !IsStoresOnlyPattern)
3012 return std::nullopt;
3016 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3017 for (
auto &Info : StoreInfos)
3018 if (
Info.Store->getParent() != StoreBB)
3019 return std::nullopt;
3021 SmallVector<Value *, 4> DeletedValues;
3028 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3031 while (Vals.
size() > 1) {
3032 SmallVector<Value *, 8>
Next;
3033 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3039 if (Vals.
size() % 2 == 1)
3041 Vals = std::move(
Next);
3050 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3052 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3053 Merged->getType(), &NewAI, getSliceAlign(),
3055 LoadToReplace->
getName() +
".sroa.new.load");
3057 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3062 if (IsStoresOnlyPattern) {
3065 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3066 return A.BeginOffset <
B.BeginOffset;
3071 uint64_t Expected = NewAllocaBeginOffset;
3072 for (
auto &Info : StoreInfos) {
3073 if (
Info.BeginOffset != Expected)
3074 return std::nullopt;
3075 Expected =
Info.EndOffset;
3078 if (Expected != NewAllocaEndOffset)
3079 return std::nullopt;
3089 if (LoadBB == StoreBB) {
3090 for (
auto &Info : StoreInfos)
3091 if (!
Info.Store->comesBefore(FullLoad))
3092 return std::nullopt;
3096 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3097 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3098 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3099 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3100 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3101 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3114 SmallVector<Value *, 8> Vals;
3115 for (
const auto &Info : StoreInfos) {
3120 Value *Merged = TreeMerge(Vals, Builder);
3121 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3124 ReplaceFullLoad(FullLoad, Merged);
3125 return DeletedValues;
3133 return std::nullopt;
3134 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3135 return I.Load->getParent() != StoreBB;
3137 return std::nullopt;
3153 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3154 for (
const auto &L : LoadInfos)
3155 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3156 for (
const auto &S : StoreInfos)
3157 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3159 return A.Inst->comesBefore(
B.Inst);
3167 return std::nullopt;
3173 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3174 !
Accesses.back().Inst->comesBefore(FullLoad))
3175 return std::nullopt;
3186 using SliceRange = std::pair<uint64_t, uint64_t>;
3190 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3194 uint64_t Expected = NewAllocaBeginOffset;
3195 for (
auto &
Range : SortedRanges) {
3196 if (
Range.first != Expected)
3197 return std::nullopt;
3198 Expected =
Range.second;
3200 if (Expected != NewAllocaEndOffset)
3201 return std::nullopt;
3204 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3205 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3207 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3208 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3209 for (
auto &
Range : SortedRanges)
3220 if (InitVec->
getType() != NewAllocaTy)
3221 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3222 DenseMap<SliceRange, Value *> SliceValues;
3223 for (
auto &
Range : SortedRanges) {
3224 unsigned BeginIdx = getIndex(
Range.first);
3225 unsigned EndIdx = getIndex(
Range.second);
3226 SliceValues[
Range] = IRB.CreateShuffleVector(
3242 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3245 if (
V->getType() != Acc.Inst->getType()) {
3247 V = IRB.CreateBitCast(V, Acc.Inst->getType());
3249 Acc.Inst->replaceAllUsesWith(V);
3266 SmallVector<Value *, 8> Vals;
3267 for (
auto &
Range : SortedRanges)
3269 Value *Merged = TreeMerge(Vals, Builder);
3270 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3275 ReplaceFullLoad(FullLoad, Merged);
3277 return DeletedValues;
3285 bool visitInstruction(Instruction &
I) {
3293 assert(IsSplit || BeginOffset == NewBeginOffset);
3296 StringRef OldName = OldPtr->
getName();
3298 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3300 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3305 OldName = OldName.
substr(IndexEnd + 1);
3309 OldName = OldName.
substr(OffsetEnd + 1);
3313 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3325 Align getSliceAlign() {
3327 NewBeginOffset - NewAllocaBeginOffset);
3331 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3333 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3334 uint32_t
Index = RelOffset / ElementSize;
3335 assert(Index * ElementSize == RelOffset);
3339 void deleteIfTriviallyDead(
Value *V) {
3342 Pass.DeadInsts.push_back(
I);
3345 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3346 unsigned BeginIndex = getIndex(NewBeginOffset);
3347 unsigned EndIndex = getIndex(NewEndOffset);
3348 assert(EndIndex > BeginIndex &&
"Empty vector!");
3351 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3353 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3354 LLVMContext::MD_access_group});
3358 Value *rewriteIntegerLoad(LoadInst &LI) {
3359 assert(IntTy &&
"We cannot insert an integer to the alloca");
3362 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3363 V = IRB.CreateBitPreservingCastChain(
DL, V, IntTy);
3364 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3366 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3367 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3376 "Can only handle an extract for an overly wide load");
3378 V = IRB.CreateZExt(V, LI.
getType());
3382 bool visitLoadInst(LoadInst &LI) {
3391 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3393 bool IsPtrAdjusted =
false;
3396 V = rewriteVectorizedLoadInst(LI);
3398 V = rewriteIntegerLoad(LI);
3399 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3400 NewEndOffset == NewAllocaEndOffset &&
3403 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3406 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3407 LoadInst *NewLI = IRB.CreateAlignedLoad(
3408 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3409 if (LI.isVolatile())
3410 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3411 if (NewLI->isAtomic())
3412 NewLI->setAlignment(LI.getAlign());
3417 copyMetadataForLoad(*NewLI, LI);
3421 NewLI->setAAMetadata(AATags.adjustForAccess(
3422 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3430 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3431 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3432 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3433 V = IRB.CreateZExt(V, TITy,
"load.ext");
3434 if (DL.isBigEndian())
3435 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3439 Type *LTy = IRB.getPtrTy(AS);
3441 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3446 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3450 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3451 LLVMContext::MD_access_group});
3454 IsPtrAdjusted =
true;
3456 V = IRB.CreateBitPreservingCastChain(
DL, V, TargetTy);
3461 "Only integer type loads and stores are split");
3462 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3463 "Split load isn't smaller than original load");
3465 "Non-byte-multiple bit width");
3471 LIIt.setHeadBit(
true);
3472 IRB.SetInsertPoint(LI.
getParent(), LIIt);
3477 Value *Placeholder =
3483 Placeholder->replaceAllUsesWith(&LI);
3484 Placeholder->deleteValue();
3489 Pass.DeadInsts.push_back(&LI);
3490 deleteIfTriviallyDead(OldOp);
3495 bool rewriteVectorizedStoreInst(
Value *V, StoreInst &SI,
Value *OldOp,
3500 if (
V->getType() != VecTy) {
3501 unsigned BeginIndex = getIndex(NewBeginOffset);
3502 unsigned EndIndex = getIndex(NewEndOffset);
3503 assert(EndIndex > BeginIndex &&
"Empty vector!");
3504 unsigned NumElements = EndIndex - BeginIndex;
3506 "Too many elements!");
3507 Type *SliceTy = (NumElements == 1)
3509 : FixedVectorType::
get(ElementTy, NumElements);
3510 if (
V->getType() != SliceTy)
3511 V = IRB.CreateBitPreservingCastChain(
DL, V, SliceTy);
3515 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3518 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3519 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3520 LLVMContext::MD_access_group});
3524 Pass.DeadInsts.push_back(&SI);
3533 bool rewriteIntegerStore(
Value *V, StoreInst &SI, AAMDNodes AATags) {
3534 assert(IntTy &&
"We cannot extract an integer from the alloca");
3536 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3538 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3540 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3541 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3545 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3546 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3547 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3548 LLVMContext::MD_access_group});
3555 Store->getValueOperand(),
DL);
3557 Pass.DeadInsts.push_back(&SI);
3562 bool visitStoreInst(StoreInst &SI) {
3564 Value *OldOp =
SI.getOperand(1);
3567 AAMDNodes AATags =
SI.getAAMetadata();
3572 if (
V->getType()->isPointerTy())
3574 Pass.PostPromotionWorklist.insert(AI);
3576 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3579 assert(
V->getType()->isIntegerTy() &&
3580 "Only integer type loads and stores are split");
3581 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3582 "Non-byte-multiple bit width");
3583 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3589 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3590 if (IntTy &&
V->getType()->isIntegerTy())
3591 return rewriteIntegerStore(V, SI, AATags);
3594 if (NewBeginOffset == NewAllocaBeginOffset &&
3595 NewEndOffset == NewAllocaEndOffset &&
3597 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3599 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3602 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3604 unsigned AS =
SI.getPointerAddressSpace();
3605 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3607 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3609 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3610 LLVMContext::MD_access_group});
3614 if (
SI.isVolatile())
3623 Pass.DeadInsts.push_back(&SI);
3624 deleteIfTriviallyDead(OldOp);
3642 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3650 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3660 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3665 bool visitMemSetInst(MemSetInst &
II) {
3669 AAMDNodes AATags =
II.getAAMetadata();
3675 assert(NewBeginOffset == BeginOffset);
3676 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3677 II.setDestAlignment(getSliceAlign());
3682 "AT: Unexpected link to non-const GEP");
3683 deleteIfTriviallyDead(OldPtr);
3688 Pass.DeadInsts.push_back(&
II);
3692 const bool CanContinue = [&]() {
3695 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3700 if (Len > std::numeric_limits<unsigned>::max())
3702 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3705 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3711 Type *SizeTy =
II.getLength()->getType();
3712 unsigned Sz = NewEndOffset - NewBeginOffset;
3715 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3716 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3722 New,
New->getRawDest(),
nullptr,
DL);
3737 assert(ElementTy == ScalarTy);
3739 unsigned BeginIndex = getIndex(NewBeginOffset);
3740 unsigned EndIndex = getIndex(NewEndOffset);
3741 assert(EndIndex > BeginIndex &&
"Empty vector!");
3742 unsigned NumElements = EndIndex - BeginIndex;
3744 "Too many elements!");
3747 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3748 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3749 if (NumElements > 1)
3752 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3761 V = getIntegerSplat(
II.getValue(),
Size);
3763 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3764 NewEndOffset != NewAllocaEndOffset)) {
3765 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3767 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3771 assert(
V->getType() == IntTy &&
3772 "Wrong type for an alloca wide integer!");
3774 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3777 assert(NewBeginOffset == NewAllocaBeginOffset);
3778 assert(NewEndOffset == NewAllocaEndOffset);
3780 V = getIntegerSplat(
II.getValue(),
3781 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3786 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3789 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3791 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3792 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3793 LLVMContext::MD_access_group});
3799 New,
New->getPointerOperand(), V,
DL);
3802 return !
II.isVolatile();
3805 bool visitMemTransferInst(MemTransferInst &
II) {
3811 AAMDNodes AATags =
II.getAAMetadata();
3813 bool IsDest = &
II.getRawDestUse() == OldUse;
3814 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3815 (!IsDest &&
II.getRawSource() == OldPtr));
3817 Align SliceAlign = getSliceAlign();
3825 if (!IsSplittable) {
3826 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3831 DbgAssign->getAddress() ==
II.getDest())
3832 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3834 II.setDest(AdjustedPtr);
3835 II.setDestAlignment(SliceAlign);
3837 II.setSource(AdjustedPtr);
3838 II.setSourceAlignment(SliceAlign);
3842 deleteIfTriviallyDead(OldPtr);
3855 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3856 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
3857 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
3863 if (EmitMemCpy && &OldAI == &NewAI) {
3865 assert(NewBeginOffset == BeginOffset);
3868 if (NewEndOffset != EndOffset)
3869 II.setLength(NewEndOffset - NewBeginOffset);
3873 Pass.DeadInsts.push_back(&
II);
3877 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3878 if (AllocaInst *AI =
3880 assert(AI != &OldAI && AI != &NewAI &&
3881 "Splittable transfers cannot reach the same alloca on both ends.");
3882 Pass.Worklist.insert(AI);
3889 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3890 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3892 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
3894 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
3902 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3903 Type *SizeTy =
II.getLength()->getType();
3904 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
3906 Value *DestPtr, *SrcPtr;
3907 MaybeAlign DestAlign, SrcAlign;
3911 DestAlign = SliceAlign;
3913 SrcAlign = OtherAlign;
3916 DestAlign = OtherAlign;
3918 SrcAlign = SliceAlign;
3920 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
3923 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
3928 &
II, New, DestPtr,
nullptr,
DL);
3933 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
3939 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
3940 NewEndOffset == NewAllocaEndOffset;
3942 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
3943 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
3944 unsigned NumElements = EndIndex - BeginIndex;
3945 IntegerType *SubIntTy =
3946 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
3951 if (VecTy && !IsWholeAlloca) {
3952 if (NumElements == 1)
3953 OtherTy = VecTy->getElementType();
3956 }
else if (IntTy && !IsWholeAlloca) {
3959 OtherTy = NewAllocaTy;
3964 MaybeAlign SrcAlign = OtherAlign;
3965 MaybeAlign DstAlign = SliceAlign;
3973 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3977 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
3981 if (VecTy && !IsWholeAlloca && !IsDest) {
3983 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3985 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
3987 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3988 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
3992 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
3993 II.isVolatile(),
"copyload");
3994 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3995 LLVMContext::MD_access_group});
4002 if (VecTy && !IsWholeAlloca && IsDest) {
4003 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4006 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4007 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4009 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4012 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4016 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4017 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4018 LLVMContext::MD_access_group});
4021 Src->getType(),
DL));
4036 return !
II.isVolatile();
4039 bool visitIntrinsicInst(IntrinsicInst &
II) {
4040 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4041 "Unexpected intrinsic!");
4045 Pass.DeadInsts.push_back(&
II);
4047 if (
II.isDroppable()) {
4048 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4054 assert(
II.getArgOperand(0) == OldPtr);
4058 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4059 New = IRB.CreateLifetimeStart(Ptr);
4061 New = IRB.CreateLifetimeEnd(Ptr);
4069 void fixLoadStoreAlign(Instruction &Root) {
4073 SmallPtrSet<Instruction *, 4> Visited;
4074 SmallVector<Instruction *, 4>
Uses;
4076 Uses.push_back(&Root);
4085 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4092 for (User *U :
I->users())
4095 }
while (!
Uses.empty());
4098 bool visitPHINode(PHINode &PN) {
4100 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4101 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4107 IRBuilderBase::InsertPointGuard Guard(IRB);
4110 OldPtr->
getParent()->getFirstInsertionPt());
4112 IRB.SetInsertPoint(OldPtr);
4113 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4115 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4120 deleteIfTriviallyDead(OldPtr);
4123 fixLoadStoreAlign(PN);
4132 bool visitSelectInst(SelectInst &SI) {
4134 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4135 "Pointer isn't an operand!");
4136 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4137 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4139 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4141 if (
SI.getOperand(1) == OldPtr)
4142 SI.setOperand(1, NewPtr);
4143 if (
SI.getOperand(2) == OldPtr)
4144 SI.setOperand(2, NewPtr);
4147 deleteIfTriviallyDead(OldPtr);
4150 fixLoadStoreAlign(SI);
4165class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4167 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4173 SmallPtrSet<User *, 8> Visited;
4180 const DataLayout &
DL;
4185 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4186 :
DL(
DL), IRB(IRB) {}
4190 bool rewrite(Instruction &
I) {
4194 while (!
Queue.empty()) {
4195 U =
Queue.pop_back_val();
4204 void enqueueUsers(Instruction &
I) {
4205 for (Use &U :
I.uses())
4206 if (Visited.
insert(
U.getUser()).second)
4207 Queue.push_back(&U);
4211 bool visitInstruction(Instruction &
I) {
return false; }
4214 template <
typename Derived>
class OpSplitter {
4221 SmallVector<unsigned, 4> Indices;
4225 SmallVector<Value *, 4> GEPIndices;
4239 const DataLayout &
DL;
4243 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4244 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4245 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4246 BaseAlign(BaseAlign),
DL(
DL) {
4247 IRB.SetInsertPoint(InsertionPoint);
4264 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4266 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4267 return static_cast<Derived *
>(
this)->emitFunc(
4272 unsigned OldSize = Indices.
size();
4274 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4276 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4278 GEPIndices.
push_back(IRB.getInt32(Idx));
4279 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4287 unsigned OldSize = Indices.
size();
4289 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4291 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4293 GEPIndices.
push_back(IRB.getInt32(Idx));
4294 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4305 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4309 SmallVector<Value *, 4> Components;
4314 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4315 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4317 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4323 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4327 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4329 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4335 Load->setAAMetadata(
4341 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4346 void recordFakeUses(LoadInst &LI) {
4347 for (Use &U : LI.
uses())
4349 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4355 void emitFakeUses() {
4356 for (Instruction *
I : FakeUses) {
4357 IRB.SetInsertPoint(
I);
4358 for (
auto *V : Components)
4359 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4360 I->eraseFromParent();
4365 bool visitLoadInst(LoadInst &LI) {
4374 Splitter.recordFakeUses(LI);
4377 Splitter.emitFakeUses();
4384 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4385 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4386 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4387 const DataLayout &
DL, IRBuilderTy &IRB)
4388 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4390 AATags(AATags), AggStore(AggStore) {}
4392 StoreInst *AggStore;
4395 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4401 Value *ExtractValue =
4402 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4403 Value *InBoundsGEP =
4404 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4406 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4423 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4425 SizeInBits, AggStore,
Store,
4426 Store->getPointerOperand(),
Store->getValueOperand(),
4430 "AT: unexpected debug.assign linked to store through "
4437 bool visitStoreInst(StoreInst &SI) {
4438 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4441 if (
V->getType()->isSingleValueType())
4446 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4448 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4453 SI.eraseFromParent();
4457 bool visitBitCastInst(BitCastInst &BC) {
4462 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4472 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4491 if (!ZI->getSrcTy()->isIntegerTy(1))
4504 dbgs() <<
" original: " << *Sel <<
"\n";
4505 dbgs() <<
" " << GEPI <<
"\n";);
4507 auto GetNewOps = [&](
Value *SelOp) {
4520 Cond =
SI->getCondition();
4521 True =
SI->getTrueValue();
4522 False =
SI->getFalseValue();
4525 Cond = Sel->getOperand(0);
4526 True = ConstantInt::get(Sel->getType(), 1);
4527 False = ConstantInt::get(Sel->getType(), 0);
4532 IRB.SetInsertPoint(&GEPI);
4536 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4537 True->
getName() +
".sroa.gep", NW);
4540 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4541 False->
getName() +
".sroa.gep", NW);
4543 Value *NSel = MDFrom
4544 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4545 Sel->getName() +
".sroa.sel", MDFrom)
4546 : IRB.CreateSelectWithUnknownProfile(
4548 Sel->getName() +
".sroa.sel");
4549 Visited.
erase(&GEPI);
4554 enqueueUsers(*NSelI);
4557 dbgs() <<
" " << *NFalse <<
"\n";
4558 dbgs() <<
" " << *NSel <<
"\n";);
4567 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4572 auto IsInvalidPointerOperand = [](
Value *
V) {
4576 return !AI->isStaticAlloca();
4580 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4595 [](
Value *V) { return isa<ConstantInt>(V); }))
4608 dbgs() <<
" original: " << *
Phi <<
"\n";
4609 dbgs() <<
" " << GEPI <<
"\n";);
4611 auto GetNewOps = [&](
Value *PhiOp) {
4621 IRB.SetInsertPoint(Phi);
4622 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4623 Phi->getName() +
".sroa.phi");
4629 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4638 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4644 Visited.
erase(&GEPI);
4648 enqueueUsers(*NewPhi);
4654 dbgs() <<
"\n " << *NewPhi <<
'\n');
4659 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4660 if (unfoldGEPSelect(GEPI))
4663 if (unfoldGEPPhi(GEPI))
4670 bool visitPHINode(PHINode &PN) {
4675 bool visitSelectInst(SelectInst &SI) {
4689 if (Ty->isSingleValueType())
4692 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4697 InnerTy = ArrTy->getElementType();
4701 InnerTy = STy->getElementType(Index);
4706 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4707 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4728 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4730 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4731 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4738 ElementTy = AT->getElementType();
4739 TyNumElements = AT->getNumElements();
4744 ElementTy = VT->getElementType();
4745 TyNumElements = VT->getNumElements();
4747 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4749 if (NumSkippedElements >= TyNumElements)
4751 Offset -= NumSkippedElements * ElementSize;
4763 if (
Size == ElementSize)
4767 if (NumElements * ElementSize !=
Size)
4791 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4792 if (
Offset >= ElementSize)
4803 if (
Size == ElementSize)
4810 if (Index == EndIndex)
4820 assert(Index < EndIndex);
4859bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
4873 struct SplitOffsets {
4875 std::vector<uint64_t> Splits;
4877 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
4890 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
4892 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
4893 for (
auto &
P : AS.partitions()) {
4894 for (Slice &S :
P) {
4896 if (!S.isSplittable() || S.endOffset() <=
P.endOffset()) {
4901 UnsplittableLoads.
insert(LI);
4904 UnsplittableLoads.
insert(LI);
4907 assert(
P.endOffset() > S.beginOffset() &&
4908 "Empty or backwards partition!");
4917 auto IsLoadSimplyStored = [](LoadInst *LI) {
4918 for (User *LU : LI->
users()) {
4920 if (!SI || !
SI->isSimple())
4925 if (!IsLoadSimplyStored(LI)) {
4926 UnsplittableLoads.
insert(LI);
4932 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
4936 if (!StoredLoad || !StoredLoad->isSimple())
4938 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
4948 auto &
Offsets = SplitOffsetsMap[
I];
4950 "Should not have splits the first time we see an instruction!");
4952 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
4957 for (Slice *S :
P.splitSliceTails()) {
4958 auto SplitOffsetsMapI =
4960 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
4962 auto &
Offsets = SplitOffsetsMapI->second;
4966 "Cannot have an empty set of splits on the second partition!");
4968 P.beginOffset() -
Offsets.S->beginOffset() &&
4969 "Previous split does not end where this one begins!");
4973 if (S->endOffset() >
P.endOffset())
4982 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
4988 if (UnsplittableLoads.
count(LI))
4991 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
4992 if (LoadOffsetsI == SplitOffsetsMap.
end())
4994 auto &LoadOffsets = LoadOffsetsI->second;
4997 auto &StoreOffsets = SplitOffsetsMap[
SI];
5002 if (LoadOffsets.Splits == StoreOffsets.Splits)
5006 <<
" " << *LI <<
"\n"
5007 <<
" " << *SI <<
"\n");
5013 UnsplittableLoads.
insert(LI);
5022 return UnsplittableLoads.
count(LI);
5027 return UnsplittableLoads.
count(LI);
5037 IRBuilderTy IRB(&AI);
5044 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5054 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5055 std::vector<LoadInst *> SplitLoads;
5056 const DataLayout &
DL = AI.getDataLayout();
5057 for (LoadInst *LI : Loads) {
5060 auto &
Offsets = SplitOffsetsMap[LI];
5061 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5063 "Load must have type size equal to store size");
5065 "Load must be >= slice size");
5068 assert(BaseOffset + SliceSize > BaseOffset &&
5069 "Cannot represent alloca access size using 64-bit integers!");
5072 IRB.SetInsertPoint(LI);
5079 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5082 LoadInst *PLoad = IRB.CreateAlignedLoad(
5085 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5086 PartPtrTy,
BasePtr->getName() +
"."),
5089 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5090 LLVMContext::MD_access_group});
5094 SplitLoads.push_back(PLoad);
5098 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5102 <<
", " << NewSlices.
back().endOffset()
5103 <<
"): " << *PLoad <<
"\n");
5110 PartOffset =
Offsets.Splits[Idx];
5112 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : SliceSize) - PartOffset;
5118 bool DeferredStores =
false;
5119 for (User *LU : LI->
users()) {
5121 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5122 DeferredStores =
true;
5128 Value *StoreBasePtr =
SI->getPointerOperand();
5129 IRB.SetInsertPoint(SI);
5130 AAMDNodes AATags =
SI->getAAMetadata();
5132 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5134 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5135 LoadInst *PLoad = SplitLoads[Idx];
5137 auto *PartPtrTy =
SI->getPointerOperandType();
5139 auto AS =
SI->getPointerAddressSpace();
5140 StoreInst *PStore = IRB.CreateAlignedStore(
5143 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5144 PartPtrTy, StoreBasePtr->
getName() +
"."),
5147 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5148 LLVMContext::MD_access_group,
5149 LLVMContext::MD_DIAssignID});
5154 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5162 ResplitPromotableAllocas.
insert(OtherAI);
5163 Worklist.insert(OtherAI);
5166 Worklist.insert(OtherAI);
5170 DeadInsts.push_back(SI);
5175 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5178 DeadInsts.push_back(LI);
5187 for (StoreInst *SI : Stores) {
5192 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5196 "Slice size should always match load size exactly!");
5198 assert(BaseOffset + StoreSize > BaseOffset &&
5199 "Cannot represent alloca access size using 64-bit integers!");
5207 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5208 std::vector<LoadInst *> *SplitLoads =
nullptr;
5209 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5210 SplitLoads = &SplitLoadsMapI->second;
5212 "Too few split loads for the number of splits in the store!");
5220 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5222 auto *StorePartPtrTy =
SI->getPointerOperandType();
5227 PLoad = (*SplitLoads)[Idx];
5229 IRB.SetInsertPoint(LI);
5231 PLoad = IRB.CreateAlignedLoad(
5234 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5235 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5238 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5239 LLVMContext::MD_access_group});
5243 IRB.SetInsertPoint(SI);
5244 auto AS =
SI->getPointerAddressSpace();
5245 StoreInst *PStore = IRB.CreateAlignedStore(
5248 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5249 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5252 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5253 LLVMContext::MD_access_group});
5257 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5261 <<
", " << NewSlices.
back().endOffset()
5262 <<
"): " << *PStore <<
"\n");
5272 PartOffset =
Offsets.Splits[Idx];
5274 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : StoreSize) - PartOffset;
5284 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5285 ResplitPromotableAllocas.
insert(OtherAI);
5286 Worklist.insert(OtherAI);
5289 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5290 Worklist.insert(OtherAI);
5305 DeadInsts.push_back(LI);
5307 DeadInsts.push_back(SI);
5316 AS.insert(NewSlices);
5320 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5326 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5363 bool IsIntegralPointerTy =
5364 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5366 !IsIntegralPointerTy)
5373 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5377 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5378 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5381 if (StructSize != VectorSize)
5384 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5387 auto *U = S.getUse();
5391 User *Usr = U->getUser();
5398 for (
const Slice &S :
P)
5399 if (!IsIgnorableOrMemIntrinsicSlice(S))
5402 for (
const Slice *S :
P.splitSliceTails())
5403 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5420static std::tuple<Type *, bool, VectorType *>
5424 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5426 dbgs() <<
"selectPartitionType path=" << Path
5431 dbgs() <<
"<unnamed>";
5432 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5433 <<
") size=" <<
P.size();
5435 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5437 dbgs() <<
" chosen=" << *SelectedTy;
5439 dbgs() <<
" vec=" << *SelectedVecTy;
5440 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5458 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5459 VecTy->getElementCount().getFixedValue() > 1) {
5460 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5461 return {VecTy,
false, VecTy};
5466 auto [CommonUseTy, LargestIntTy] =
5469 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5475 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5476 return {VecTy,
false, VecTy};
5479 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5480 return {CommonUseTy, IntWiden,
nullptr};
5487 P.beginOffset(),
P.size())) {
5491 if (TypePartitionTy->isArrayTy() &&
5492 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5493 DL.isLegalInteger(
P.size() * 8))
5497 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5498 return {TypePartitionTy,
true,
nullptr};
5501 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5502 return {VecTy,
false, VecTy};
5507 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5509 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5510 return {LargestIntTy,
true,
nullptr};
5515 if (AggregateToVector) {
5518 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5519 return {VTy,
false,
nullptr};
5525 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5526 return {TypePartitionTy,
false,
nullptr};
5531 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5532 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5533 return {LargestIntTy,
false,
nullptr};
5537 if (
DL.isLegalInteger(
P.size() * 8)) {
5539 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5540 return {IntTy,
false,
nullptr};
5545 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5546 return {ArrayTy,
false,
nullptr};
5559std::pair<AllocaInst *, uint64_t>
5560SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5561 const DataLayout &
DL = AI.getDataLayout();
5563 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5573 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5583 const bool IsUnconstrained =
Alignment <=
DL.getABITypeAlign(PartitionTy);
5584 NewAI =
new AllocaInst(
5585 PartitionTy, AI.getAddressSpace(),
nullptr,
5586 IsUnconstrained ?
DL.getPrefTypeAlign(PartitionTy) : Alignment,
5587 AI.
getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5594 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5595 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5600 unsigned PPWOldSize = PostPromotionWorklist.size();
5601 unsigned NumUses = 0;
5602 SmallSetVector<PHINode *, 8> PHIUsers;
5603 SmallSetVector<SelectInst *, 8> SelectUsers;
5606 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5607 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5608 bool Promotable =
true;
5610 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5611 NumUses += DeletedValues->
size() + 1;
5612 for (
Value *V : *DeletedValues)
5613 DeadInsts.push_back(V);
5615 for (Slice *S :
P.splitSliceTails()) {
5619 for (Slice &S :
P) {
5625 NumAllocaPartitionUses += NumUses;
5626 MaxUsesPerAllocaPartition.updateMax(NumUses);
5630 for (PHINode *
PHI : PHIUsers)
5634 SelectUsers.
clear();
5639 NewSelectsToRewrite;
5641 for (SelectInst *Sel : SelectUsers) {
5642 std::optional<RewriteableMemOps>
Ops =
5643 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5647 SelectUsers.clear();
5648 NewSelectsToRewrite.
clear();
5655 for (Use *U : AS.getDeadUsesIfPromotable()) {
5657 Value::dropDroppableUse(*U);
5660 DeadInsts.push_back(OldInst);
5662 if (PHIUsers.empty() && SelectUsers.empty()) {
5664 PromotableAllocas.insert(NewAI);
5669 SpeculatablePHIs.insert_range(PHIUsers);
5670 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5671 NewSelectsToRewrite.
size());
5673 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5674 std::make_move_iterator(NewSelectsToRewrite.
end())))
5675 SelectsToRewrite.insert(std::move(KV));
5676 Worklist.insert(NewAI);
5680 while (PostPromotionWorklist.size() > PPWOldSize)
5681 PostPromotionWorklist.pop_back();
5686 return {
nullptr, 0};
5691 Worklist.insert(NewAI);
5694 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5738 int64_t BitExtractOffset) {
5740 bool HasFragment =
false;
5741 bool HasBitExtract =
false;
5749 HasBitExtract =
true;
5750 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5751 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5760 assert(BitExtractOffset <= 0);
5761 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5767 if (AdjustedOffset < 0)
5770 Ops.push_back(
Op.getOp());
5771 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5772 Ops.push_back(ExtractSizeInBits);
5775 Op.appendToVector(
Ops);
5780 if (HasFragment && HasBitExtract)
5783 if (!HasBitExtract) {
5802 std::optional<DIExpression::FragmentInfo> NewFragment,
5803 int64_t BitExtractAdjustment) {
5813 BitExtractAdjustment);
5814 if (!NewFragmentExpr)
5820 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5833 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5839 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5847 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
5853bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
5854 if (AS.begin() == AS.end())
5857 unsigned NumPartitions = 0;
5859 const DataLayout &
DL = AI.getModule()->getDataLayout();
5862 Changed |= presplitLoadsAndStores(AI, AS);
5870 bool IsSorted =
true;
5872 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
5873 const uint64_t MaxBitVectorSize = 1024;
5874 if (AllocaSize <= MaxBitVectorSize) {
5877 SmallBitVector SplittableOffset(AllocaSize + 1,
true);
5879 for (
unsigned O = S.beginOffset() + 1;
5880 O < S.endOffset() && O < AllocaSize; O++)
5881 SplittableOffset.reset(O);
5883 for (Slice &S : AS) {
5884 if (!S.isSplittable())
5887 if ((S.beginOffset() > AllocaSize || SplittableOffset[S.beginOffset()]) &&
5888 (S.endOffset() > AllocaSize || SplittableOffset[S.endOffset()]))
5893 S.makeUnsplittable();
5900 for (Slice &S : AS) {
5901 if (!S.isSplittable())
5904 if (S.beginOffset() == 0 && S.endOffset() >= AllocaSize)
5909 S.makeUnsplittable();
5930 for (
auto &
P : AS.partitions()) {
5931 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
5935 uint64_t SizeOfByte = 8;
5937 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
5938 Fragments.push_back(
5939 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
5945 NumAllocaPartitions += NumPartitions;
5946 MaxPartitionsPerAlloca.updateMax(NumPartitions);
5950 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
5955 const Value *DbgPtr = DbgVariable->getAddress();
5957 DbgVariable->getFragmentOrEntireVariable();
5960 int64_t CurrentExprOffsetInBytes = 0;
5961 SmallVector<uint64_t> PostOffsetOps;
5963 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
5967 int64_t ExtractOffsetInBits = 0;
5970 ExtractOffsetInBits = Extract.getOffsetInBits();
5975 DIBuilder DIB(*AI.getModule(),
false);
5977 int64_t OffsetFromLocationInBits;
5978 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
5984 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
5985 NewDbgFragment, OffsetFromLocationInBits))
5991 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
5996 if (!NewDbgFragment)
5997 NewDbgFragment = DbgVariable->getFragment();
6001 int64_t OffestFromNewAllocaInBits =
6002 OffsetFromLocationInBits - ExtractOffsetInBits;
6005 int64_t BitExtractOffset =
6006 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6011 OffestFromNewAllocaInBits =
6012 std::max(int64_t(0), OffestFromNewAllocaInBits);
6018 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6019 if (OffestFromNewAllocaInBits > 0) {
6020 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6026 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6027 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6028 return LHS->getVariable() ==
RHS->getVariable() &&
6029 LHS->getDebugLoc()->getInlinedAt() ==
6030 RHS->getDebugLoc()->getInlinedAt();
6032 if (SameVariableFragment(OldDII, DbgVariable))
6033 OldDII->eraseFromParent();
6038 NewDbgFragment, BitExtractOffset);
6052void SROA::clobberUse(Use &U) {
6062 DeadInsts.push_back(OldI);
6084bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6089 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6090 bool AllSameAndValid =
true;
6091 Type *PartitionType =
nullptr;
6092 SmallVector<Instruction *> Insts;
6096 auto Flush = [&]() {
6097 if (AllSameAndValid && !Insts.
empty()) {
6098 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6099 << EndOffset <<
")\n");
6101 SSAUpdater
SSA(&NewPHIs);
6103 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6104 Promoter.run(Insts);
6106 AllSameAndValid =
true;
6107 PartitionType =
nullptr;
6111 for (Slice &S : AS) {
6115 dbgs() <<
"Ignoring slice: ";
6116 AS.print(
dbgs(), &S);
6120 if (S.beginOffset() >= EndOffset) {
6122 BeginOffset = S.beginOffset();
6123 EndOffset = S.endOffset();
6124 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6125 if (AllSameAndValid) {
6127 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6128 << EndOffset <<
")";
6129 AS.print(
dbgs(), &S);
6131 AllSameAndValid =
false;
6133 EndOffset = std::max(EndOffset, S.endOffset());
6140 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6141 AllSameAndValid =
false;
6142 PartitionType = UserTy;
6145 Type *UserTy =
SI->getValueOperand()->getType();
6146 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6147 AllSameAndValid =
false;
6148 PartitionType = UserTy;
6151 AllSameAndValid =
false;
6164std::pair<
bool ,
bool >
6165SROA::runOnAlloca(AllocaInst &AI) {
6167 bool CFGChanged =
false;
6170 ++NumAllocasAnalyzed;
6173 if (AI.use_empty()) {
6174 AI.eraseFromParent();
6178 const DataLayout &
DL = AI.getDataLayout();
6181 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6182 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6187 IRBuilderTy IRB(&AI);
6188 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6189 Changed |= AggRewriter.rewrite(AI);
6192 AllocaSlices AS(
DL, AI);
6197 if (AS.isEscapedReadOnly()) {
6198 Changed |= propagateStoredValuesToLoads(AI, AS);
6203 for (Instruction *DeadUser : AS.getDeadUsers()) {
6205 for (Use &DeadOp : DeadUser->operands())
6212 DeadInsts.push_back(DeadUser);
6215 for (Use *DeadOp : AS.getDeadOperands()) {
6216 clobberUse(*DeadOp);
6221 if (AS.begin() == AS.end())
6224 Changed |= splitAlloca(AI, AS);
6227 while (!SpeculatablePHIs.empty())
6231 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6232 while (!RemainingSelectsToRewrite.empty()) {
6233 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6250bool SROA::deleteDeadInstructions(
6251 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6253 while (!DeadInsts.empty()) {
6263 DeletedAllocas.
insert(AI);
6265 OldDII->eraseFromParent();
6271 for (Use &Operand :
I->operands())
6276 DeadInsts.push_back(U);
6280 I->eraseFromParent();
6290bool SROA::promoteAllocas() {
6291 if (PromotableAllocas.empty())
6298 NumPromoted += PromotableAllocas.size();
6299 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6302 PromotableAllocas.clear();
6306std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6309 const DataLayout &
DL =
F.getDataLayout();
6314 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6316 PromotableAllocas.insert(AI);
6318 Worklist.insert(AI);
6323 bool CFGChanged =
false;
6326 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6329 while (!Worklist.empty()) {
6330 auto [IterationChanged, IterationCFGChanged] =
6331 runOnAlloca(*Worklist.pop_back_val());
6333 CFGChanged |= IterationCFGChanged;
6335 Changed |= deleteDeadInstructions(DeletedAllocas);
6339 if (!DeletedAllocas.
empty()) {
6340 Worklist.set_subtract(DeletedAllocas);
6341 PostPromotionWorklist.set_subtract(DeletedAllocas);
6342 PromotableAllocas.set_subtract(DeletedAllocas);
6343 DeletedAllocas.
clear();
6349 Worklist = PostPromotionWorklist;
6350 PostPromotionWorklist.clear();
6351 }
while (!Worklist.empty());
6353 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6354 assert((!CFGChanged || !PreserveCFG) &&
6355 "Should not have modified the CFG when told to preserve it.");
6358 for (
auto &BB :
F) {
6371 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6383 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6384 OS, MapClassName2PassName);
6388 if (Options.AggregateToVector)
6389 OS <<
";aggregate-to-vector";
6410 if (skipFunction(
F))
6413 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6415 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6421 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6428 StringRef getPassName()
const override {
return "SROA"; }
6433char SROALegacyPass::ID = 0;
6438 AggregateToVector));
6442 "Scalar Replacement Of Aggregates",
false,
false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DXIL Forward Handle Accesses
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.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
This file implements a map that provides insertion order iteration.
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
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.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> 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 VectorType * isVectorPromotionViable(Partition &P, const DataLayout &DL, unsigned VScale)
Test whether the given alloca partitioning and range of slices can be promoted to a vector.
static Align getAdjustedAlignment(Instruction *I, uint64_t Offset)
Compute the adjusted alignment for a load or store from an offset.
static VectorType * checkVectorTypesForPromotion(Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool HaveCommonEltTy, Type *CommonEltTy, bool HaveVecPtrTy, bool HaveCommonVecPtrTy, VectorType *CommonVecPtrTy, unsigned VScale)
Test whether any vector type in CandidateTys is viable for promotion.
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 FragCalcResult calculateFragment(DILocalVariable *Variable, uint64_t NewStorageSliceOffsetInBits, uint64_t NewStorageSliceSizeInBits, std::optional< DIExpression::FragmentInfo > StorageFragment, std::optional< DIExpression::FragmentInfo > CurrentFragment, DIExpression::FragmentInfo &Target)
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 bool isVectorPromotionViableForSlice(Partition &P, const Slice &S, VectorType *Ty, uint64_t ElementSize, const DataLayout &DL, unsigned VScale)
Test whether the given slice use can be promoted to a vector.
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.
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)
bool isKillAddress(const DbgVariableRecord *DVR)
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)
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, unsigned VScale)
static DebugVariable getAggregateVariable(DbgVariableRecord *DVR)
static std::tuple< Type *, bool, VectorType * > selectPartitionType(Partition &P, const DataLayout &DL, AllocaInst &AI, LLVMContext &C, bool AggregateToVector)
Select a partition type for an alloca partition.
static bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
static FixedVectorType * tryCanonicalizeStructToVector(StructType *STy, Partition &P, const DataLayout &DL)
Try to canonicalize a homogeneous struct partition to a vector type.
static Value * extractInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *V, IntegerType *Ty, uint64_t Offset, const Twine &Name)
static void insertNewDbgInst(DIBuilder &DIB, DbgVariableRecord *Orig, AllocaInst *NewAddr, DIExpression *NewAddrExpr, Instruction *BeforeInst, std::optional< DIExpression::FragmentInfo > NewFragment, int64_t BitExtractAdjustment)
Insert a new DbgRecord.
static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, IRBuilderTy &IRB)
static Value * mergeTwoVectors(Value *V0, Value *V1, const DataLayout &DL, Type *NewAIEltTy, IRBuilder<> &Builder)
This function takes two vector values and combines them into a single vector by concatenating their e...
const DIExpression * getAddressExpression(const DbgVariableRecord *DVR)
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 bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy, unsigned VScale=0)
Test whether we can convert a value from the old to the new type.
static SelectHandSpeculativity isSafeLoadOfSelectToSpeculate(LoadInst &LI, SelectInst &SI, bool PreserveCFG)
static Type * findCommonTypeThroughPHIOrSelect(Instruction &I)
Find a common load/store type used through a pointer PHI or select.
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.
an instruction to allocate memory on the stack
LLVM_ABI 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.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
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; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
LLVM_ABI CaptureInfo getCaptureInfo(unsigned OpNo) const
Return which pointer components this operand may capture.
bool onlyReadsMemory(unsigned OpNo) const
bool isDataOperand(const Use *U) const
This is the shared class of boolean and integer constants.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
LLVM_ABI DbgRecord * insertDbgAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *SrcVar, DIExpression *ValExpr, Value *Addr, DIExpression *AddrExpr, const DILocation *DL)
Insert a new dbg_assign record.
iterator_range< expr_op_iterator > expr_ops() const
DbgVariableFragmentInfo FragmentInfo
LLVM_ABI bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static LLVM_ABI 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 LLVM_ABI 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 LLVM_ABI 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 ...
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI void moveBefore(DbgRecord *MoveBefore)
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI void setKillAddress()
Kill the address component.
LLVM_ABI bool isKillLocation() const
LocationType getType() const
LLVM_ABI bool isKillAddress() const
Check whether this kills the address component.
LLVM_ABI void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
Value * getValue(unsigned OpIdx=0) const
static LLVM_ABI DbgVariableRecord * createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, DIExpression *Expression, Value *Address, DIExpression *AddressExpression, const DILocation *DI)
LLVM_ABI void setAssignId(DIAssignID *New)
DIExpression * getExpression() const
static LLVM_ABI DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
static LLVM_ABI DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
DILocalVariable * getVariable() const
LLVM_ABI void setKillLocation()
bool isDbgDeclare() const
void setAddress(Value *V)
DIExpression * getAddressExpression() const
LLVM_ABI DILocation * getInlinedAt() const
Identifies a unique instance of a variable.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
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.
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getVScaleValue() const
Return the value for vscale based on the vscale_range attribute or 0 when unknown.
const BasicBlock & getEntryBlock() const
LLVM_ABI 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.
Value * getPointerOperand()
iterator_range< op_iterator > indices()
Type * getSourceElementType() const
LLVM_ABI GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
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.
LLVM_ABI 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.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI 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.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI 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.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
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.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
This is the common base class for memset/memcpy/memmove.
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 LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerIntPair - This class implements a pair of a pointer and small integer.
static LLVM_ABI 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.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PtrUseVisitor(const DataLayout &DL)
LLVM_ABI SROAPass(SROAOptions Options)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Helper class for SSA formation on a set of values defined in multiple blocks.
This class represents the LLVM 'select' instruction.
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.
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.
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)
iterator erase(const_iterator CI)
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.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
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.
LLVM_ABI 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
LLVM_ABI 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 LLVM_ABI 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
ArrayRef< Type * > elements() const
element_iterator element_begin() const
unsigned getNumElements() const
Random access to the elements.
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...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI 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 LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
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.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
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.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI 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.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
LLVM_ABI void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static VectorType * getWithSizeAndScalar(VectorType *SizeTy, Type *EltTy)
This static method attempts to construct a VectorType with the same size-in-bits as SizeTy but with a...
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
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.
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.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
unsigned getNumElements(Type *Ty)
This is an optimization pass for GlobalISel generic memory operations.
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.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
LLVM_ABI 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.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
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.
LLVM_ABI 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...
LLVM_ABI bool isAssumeLikeIntrinsic(const Instruction *I)
Return true if it is an intrinsic that cannot be speculated but also cannot trap.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI 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)
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
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.
LLVM_ABI 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.
bool capturesFullProvenance(CaptureComponents CC)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI 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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void initializeSROALegacyPassPass(PassRegistry &)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRValues(Value *V)
As above, for DVRValues.
LLVM_ABI 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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI FunctionPass * createSROAPass(bool PreserveCFG=true, bool AggregateToVector=false)
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI 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 ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
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...
LLVM_ABI 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.
static Bitfield::Type get(StorageType Packed)
Unpacks the field from the Packed value.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.