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");
129class AllocaSliceRewriter;
133class SelectHandSpeculativity {
134 unsigned char Storage = 0;
138 SelectHandSpeculativity() =
default;
139 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
140 bool isSpeculatable(
bool isTrueVal)
const;
141 bool areAllSpeculatable()
const;
142 bool areAnySpeculatable()
const;
143 bool areNoneSpeculatable()
const;
145 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
146 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
148static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
150using PossiblySpeculatableLoad =
153using RewriteableMemOp =
154 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
176 LLVMContext *
const C;
177 DomTreeUpdater *
const DTU;
178 AssumptionCache *
const AC;
179 const bool PreserveCFG;
180 const bool AggregateToVector;
189 SmallSetVector<AllocaInst *, 16> Worklist;
204 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
207 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
208 SmallPtrSet<AllocaInst *, 16>, 16>
216 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
220 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
236 static std::optional<RewriteableMemOps>
237 isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG);
240 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
242 : C(C), DTU(DTU), AC(AC),
243 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
244 AggregateToVector(
Options.AggregateToVector) {}
247 std::pair<
bool ,
bool > runSROA(
Function &
F);
250 friend class AllocaSliceRewriter;
252 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
253 std::pair<AllocaInst *, uint64_t>
254 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
255 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
256 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
257 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
258 void clobberUse(Use &U);
259 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
260 bool promoteAllocas();
274enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
278 uint64_t NewStorageSliceOffsetInBits,
280 std::optional<DIExpression::FragmentInfo> StorageFragment,
281 std::optional<DIExpression::FragmentInfo> CurrentFragment,
285 if (StorageFragment) {
287 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
289 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
291 Target.SizeInBits = NewStorageSliceSizeInBits;
292 Target.OffsetInBits = NewStorageSliceOffsetInBits;
298 if (!CurrentFragment) {
299 if (
auto Size = Variable->getSizeInBits()) {
302 if (
Target == CurrentFragment)
309 if (!CurrentFragment || *CurrentFragment ==
Target)
315 if (
Target.startInBits() < CurrentFragment->startInBits() ||
316 Target.endInBits() > CurrentFragment->endInBits())
355 if (DVRAssignMarkerRange.empty())
361 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
363 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
375 DVR->getExpression()->getFragmentInfo();
388 auto *Expr = DbgAssign->getExpression();
389 bool SetKillLocation =
false;
392 std::optional<DIExpression::FragmentInfo> BaseFragment;
395 if (R == BaseFragments.
end())
397 BaseFragment = R->second;
399 std::optional<DIExpression::FragmentInfo> CurrentFragment =
400 Expr->getFragmentInfo();
403 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
404 BaseFragment, CurrentFragment, NewFragment);
408 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
409 if (CurrentFragment) {
414 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
427 SetKillLocation =
true;
435 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
442 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
446 NewAssign = DbgAssign;
465 Value && (DbgAssign->hasArgList() ||
466 !DbgAssign->getExpression()->isSingleLocationExpression());
483 if (NewAssign != DbgAssign) {
484 NewAssign->
moveBefore(DbgAssign->getIterator());
487 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
490 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
500 Twine getNameWithPrefix(
const Twine &Name)
const {
505 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
507 void InsertHelper(Instruction *
I,
const Twine &Name,
532 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
538 : BeginOffset(BeginOffset), EndOffset(EndOffset),
539 UseAndIsSplittable(
U, IsSplittable) {}
541 uint64_t beginOffset()
const {
return BeginOffset; }
542 uint64_t endOffset()
const {
return EndOffset; }
544 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
545 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
547 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
549 bool isDead()
const {
return getUse() ==
nullptr; }
550 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
559 if (beginOffset() <
RHS.beginOffset())
561 if (beginOffset() >
RHS.beginOffset())
563 if (isSplittable() !=
RHS.isSplittable())
564 return !isSplittable();
565 if (endOffset() >
RHS.endOffset())
572 return LHS.beginOffset() < RHSOffset;
575 return LHSOffset <
RHS.beginOffset();
579 return isSplittable() ==
RHS.isSplittable() &&
580 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
595 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
601 bool isEscaped()
const {
return PointerEscapingInstr; }
602 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
607 using range = iterator_range<iterator>;
609 iterator
begin() {
return Slices.begin(); }
610 iterator
end() {
return Slices.end(); }
613 using const_range = iterator_range<const_iterator>;
615 const_iterator
begin()
const {
return Slices.begin(); }
616 const_iterator
end()
const {
return Slices.end(); }
620 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
628 int OldSize = Slices.size();
629 Slices.append(NewSlices.
begin(), NewSlices.
end());
630 auto SliceI = Slices.begin() + OldSize;
631 std::stable_sort(SliceI, Slices.end());
632 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
645 return DeadUseIfPromotable;
656#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
657 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
658 void printSlice(raw_ostream &OS, const_iterator
I,
659 StringRef Indent =
" ")
const;
660 void printUse(raw_ostream &OS, const_iterator
I,
661 StringRef Indent =
" ")
const;
662 void print(raw_ostream &OS)
const;
663 void dump(const_iterator
I)
const;
668 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
671 friend class AllocaSlices::SliceBuilder;
673#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
701 SmallVector<Instruction *, 8> DeadUsers;
728 friend class AllocaSlices;
729 friend class AllocaSlices::partition_iterator;
731 using iterator = AllocaSlices::iterator;
735 uint64_t BeginOffset = 0, EndOffset = 0;
745 Partition(iterator SI) : SI(SI), SJ(SI) {}
751 uint64_t beginOffset()
const {
return BeginOffset; }
756 uint64_t endOffset()
const {
return EndOffset; }
762 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
763 return EndOffset - BeginOffset;
768 bool empty()
const {
return SI == SJ; }
779 iterator
begin()
const {
return SI; }
780 iterator
end()
const {
return SJ; }
812 AllocaSlices::iterator SE;
816 uint64_t MaxSplitSliceEndOffset = 0;
820 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
832 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
833 "Cannot advance past the end of the slices!");
836 if (!
P.SplitTails.empty()) {
837 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
839 P.SplitTails.clear();
840 MaxSplitSliceEndOffset = 0;
846 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
849 return S->endOffset() == MaxSplitSliceEndOffset;
851 "Could not find the current max split slice offset!");
854 return S->endOffset() <= MaxSplitSliceEndOffset;
856 "Max split slice end offset is not actually the max!");
863 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
873 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
874 P.SplitTails.push_back(&S);
875 MaxSplitSliceEndOffset =
876 std::max(S.endOffset(), MaxSplitSliceEndOffset);
884 P.BeginOffset = P.EndOffset;
885 P.EndOffset = MaxSplitSliceEndOffset;
892 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
893 !P.SI->isSplittable()) {
894 P.BeginOffset = P.EndOffset;
895 P.EndOffset = P.SI->beginOffset();
905 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
906 P.EndOffset = P.SI->endOffset();
911 if (!P.SI->isSplittable()) {
914 assert(P.BeginOffset == P.SI->beginOffset());
918 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
919 if (!P.SJ->isSplittable())
920 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
932 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
935 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
936 P.SJ->isSplittable()) {
937 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
944 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
945 assert(!P.SJ->isSplittable());
946 P.EndOffset = P.SJ->beginOffset();
953 "End iterators don't match between compared partition iterators!");
960 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
961 assert(P.SJ == RHS.P.SJ &&
962 "Same set of slices formed two different sized partitions!");
963 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
964 "Same slice position with differently sized non-empty split "
987 return make_range(partition_iterator(begin(), end()),
988 partition_iterator(end(), end()));
996 return SI.getOperand(1 + CI->isZero());
997 if (
SI.getOperand(1) ==
SI.getOperand(2))
998 return SI.getOperand(1);
1007 return PN->hasConstantValue();
1022 const uint64_t AllocSize;
1038 if (VisitedDeadInsts.
insert(&
I).second)
1043 bool IsSplittable =
false) {
1049 <<
" which has zero size or starts outside of the "
1050 << AllocSize <<
" byte alloca:\n"
1051 <<
" alloca: " << AS.AI <<
"\n"
1052 <<
" use: " <<
I <<
"\n");
1053 return markAsDead(
I);
1065 assert(AllocSize >= BeginOffset);
1066 if (
Size > AllocSize - BeginOffset) {
1068 <<
Offset <<
" to remain within the " << AllocSize
1069 <<
" byte alloca:\n"
1070 <<
" alloca: " << AS.AI <<
"\n"
1071 <<
" use: " <<
I <<
"\n");
1072 EndOffset = AllocSize;
1075 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1078 void visitBitCastInst(BitCastInst &BC) {
1080 return markAsDead(BC);
1082 return Base::visitBitCastInst(BC);
1085 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1087 return markAsDead(ASC);
1089 return Base::visitAddrSpaceCastInst(ASC);
1092 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1094 return markAsDead(GEPI);
1096 return Base::visitGetElementPtrInst(GEPI);
1099 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1110 void visitLoadInst(LoadInst &LI) {
1112 "All simple FCA loads should have been pre-split");
1117 return PI.setEscapedReadOnly(&LI);
1120 if (
Size.isScalable()) {
1123 return PI.setAborted(&LI);
1132 void visitStoreInst(StoreInst &SI) {
1133 Value *ValOp =
SI.getValueOperand();
1135 return PI.setEscapedAndAborted(&SI);
1137 return PI.setAborted(&SI);
1139 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1141 unsigned VScale =
SI.getFunction()->getVScaleValue();
1143 return PI.setAborted(&SI);
1159 <<
Offset <<
" which extends past the end of the "
1160 << AllocSize <<
" byte alloca:\n"
1161 <<
" alloca: " << AS.AI <<
"\n"
1162 <<
" use: " << SI <<
"\n");
1163 return markAsDead(SI);
1167 "All simple FCA stores should have been pre-split");
1171 void visitMemSetInst(MemSetInst &
II) {
1172 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1175 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1177 return markAsDead(
II);
1180 return PI.setAborted(&
II);
1184 : AllocSize -
Offset.getLimitedValue(),
1188 void visitMemTransferInst(MemTransferInst &
II) {
1192 return markAsDead(
II);
1196 if (VisitedDeadInsts.
count(&
II))
1200 return PI.setAborted(&
II);
1207 if (
Offset.uge(AllocSize)) {
1208 auto MTPI = MemTransferSliceMap.
find(&
II);
1209 if (MTPI != MemTransferSliceMap.
end())
1210 AS.Slices[MTPI->second].kill();
1211 return markAsDead(
II);
1219 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1221 if (!
II.isVolatile())
1222 return markAsDead(
II);
1230 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1231 std::tie(MTPI, Inserted) =
1232 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1233 unsigned PrevIdx = MTPI->second;
1235 Slice &PrevP = AS.Slices[PrevIdx];
1239 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1241 return markAsDead(
II);
1246 PrevP.makeUnsplittable();
1253 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1254 "Map index doesn't point back to a slice with this user.");
1260 void visitIntrinsicInst(IntrinsicInst &
II) {
1261 if (
II.isDroppable()) {
1262 AS.DeadUseIfPromotable.push_back(U);
1267 return PI.setAborted(&
II);
1269 if (
II.isLifetimeStartOrEnd()) {
1270 insertUse(
II,
Offset, AllocSize,
true);
1274 Base::visitIntrinsicInst(
II);
1282 SmallPtrSet<Instruction *, 4> Visited;
1292 std::tie(UsedI,
I) =
Uses.pop_back_val();
1295 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1307 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1317 if (!
GEP->hasAllZeroIndices())
1324 for (User *U :
I->users())
1327 }
while (!
Uses.empty());
1332 void visitPHINodeOrSelectInst(Instruction &
I) {
1335 return markAsDead(
I);
1341 return PI.setAborted(&
I);
1359 AS.DeadOperands.push_back(U);
1365 return PI.setAborted(&
I);
1371 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1372 return PI.setAborted(UnsafeI);
1381 if (
Offset.uge(AllocSize)) {
1382 AS.DeadOperands.push_back(U);
1389 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1391 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1394 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1396 void visitCallBase(CallBase &CB) {
1402 PI.setEscapedReadOnly(&CB);
1406 Base::visitCallBase(CB);
1410AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1412#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1415 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1417 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1418 if (PtrI.isEscaped() || PtrI.isAborted()) {
1421 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1422 : PtrI.getAbortingInst();
1423 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1426 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1428 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1435#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1437void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1438 StringRef Indent)
const {
1439 printSlice(OS,
I, Indent);
1441 printUse(OS,
I, Indent);
1444void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1445 StringRef Indent)
const {
1446 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1447 <<
" slice #" << (
I -
begin())
1448 << (
I->isSplittable() ?
" (splittable)" :
"");
1451void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1452 StringRef Indent)
const {
1453 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1456void AllocaSlices::print(raw_ostream &OS)
const {
1457 if (PointerEscapingInstr) {
1458 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1459 <<
" A pointer to this alloca escaped by:\n"
1460 <<
" " << *PointerEscapingInstr <<
"\n";
1464 if (PointerEscapingInstrReadOnly)
1465 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1467 OS <<
"Slices of alloca: " << AI <<
"\n";
1488 for (
User *U :
I.users()) {
1489 Type *UserTy =
nullptr;
1495 UserTy =
Store->getValueOperand()->getType();
1497 if (!UserTy || (Ty && Ty != UserTy))
1507static std::pair<Type *, IntegerType *>
1511 bool TyIsCommon =
true;
1516 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1517 Use *U =
I->getUse();
1520 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1523 Type *UserTy =
nullptr;
1527 UserTy =
SI->getValueOperand()->getType();
1538 if (UserITy->getBitWidth() % 8 != 0 ||
1539 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1544 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1550 if (!UserTy || (Ty && Ty != UserTy))
1556 return {TyIsCommon ? Ty :
nullptr, ITy};
1587 Type *LoadType =
nullptr;
1600 if (LoadType != LI->
getType())
1609 if (BBI->mayWriteToMemory())
1612 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1619 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1657 IRB.SetInsertPoint(&PN);
1659 PN.
getName() +
".sroa.speculated");
1689 IRB.SetInsertPoint(TI);
1692 LoadTy, InVal, Alignment,
1693 (PN.
getName() +
".sroa.speculate.load." + Pred->getName()));
1694 ++NumLoadsSpeculated;
1696 Load->setAAMetadata(AATags);
1698 InjectedLoads[Pred] =
Load;
1705SelectHandSpeculativity &
1706SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1714bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1719bool SelectHandSpeculativity::areAllSpeculatable()
const {
1720 return isSpeculatable(
true) &&
1721 isSpeculatable(
false);
1724bool SelectHandSpeculativity::areAnySpeculatable()
const {
1725 return isSpeculatable(
true) ||
1726 isSpeculatable(
false);
1728bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1729 return !areAnySpeculatable();
1732static SelectHandSpeculativity
1735 SelectHandSpeculativity
Spec;
1741 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1742 else if (PreserveCFG)
1748std::optional<RewriteableMemOps>
1749SROA::isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG) {
1750 RewriteableMemOps
Ops;
1752 for (User *U :
SI.users()) {
1757 if (
Store->isVolatile() || PreserveCFG)
1770 PossiblySpeculatableLoad
Load(LI);
1780 SelectHandSpeculativity Spec =
1782 if (PreserveCFG && !Spec.areAllSpeculatable())
1796 Value *TV =
SI.getTrueValue();
1797 Value *FV =
SI.getFalseValue();
1802 IRB.SetInsertPoint(&LI);
1806 LI.
getName() +
".sroa.speculate.load.true");
1809 LI.
getName() +
".sroa.speculate.load.false");
1810 NumLoadsSpeculated += 2;
1822 Value *V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1823 LI.
getName() +
".sroa.speculated",
1830template <
typename T>
1832 SelectHandSpeculativity
Spec,
1839 if (
Spec.areNoneSpeculatable())
1841 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1844 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1846 if (
Spec.isSpeculatable(
true))
1852 Tail->setName(Head->
getName() +
".cont");
1857 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1858 int SuccIdx = IsThen ? 0 : 1;
1859 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
1860 auto &CondMemOp =
cast<T>(*
I.clone());
1861 if (NewMemOpBB != Head) {
1862 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1864 ++NumLoadsPredicated;
1866 ++NumStoresPredicated;
1868 CondMemOp.dropUBImplyingAttrsAndMetadata();
1869 ++NumLoadsSpeculated;
1871 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
1872 Value *Ptr =
SI.getOperand(1 + SuccIdx);
1873 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
1875 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1883 I.replaceAllUsesWith(PN);
1888 SelectHandSpeculativity
Spec,
1899 const RewriteableMemOps &
Ops,
1901 bool CFGChanged =
false;
1904 for (
const RewriteableMemOp &
Op :
Ops) {
1905 SelectHandSpeculativity
Spec;
1907 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
1910 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
1911 I = PSL.getPointer();
1912 Spec = PSL.getInt();
1914 if (
Spec.areAllSpeculatable()) {
1917 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
1921 I->eraseFromParent();
1926 SI.eraseFromParent();
1934 const Twine &NamePrefix) {
1936 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
1937 NamePrefix +
"sroa_idx");
1938 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
1939 NamePrefix +
"sroa_cast");
1954 unsigned VScale = 0) {
1964 "We can't have the same bitwidth for different int types");
1968 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
1969 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
1996 if (NewSize != OldSize)
2012 return OldAS == NewAS ||
2013 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2014 !
DL.isNonIntegralAddressSpace(NewAS) &&
2015 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2021 return !
DL.isNonIntegralPointerType(NewTy);
2025 if (!
DL.isNonIntegralPointerType(OldTy))
2048 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2049 uint64_t BeginIndex = BeginOffset / ElementSize;
2050 if (BeginIndex * ElementSize != BeginOffset ||
2053 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2054 uint64_t EndIndex = EndOffset / ElementSize;
2055 if (EndIndex * ElementSize != EndOffset ||
2059 assert(EndIndex > BeginIndex &&
"Empty vector!");
2060 uint64_t NumElements = EndIndex - BeginIndex;
2061 Type *SliceTy = (NumElements == 1)
2062 ? Ty->getElementType()
2068 Use *U = S.getUse();
2071 if (
MI->isVolatile())
2073 if (!S.isSplittable())
2081 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2088 if (LTy->isStructTy())
2090 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2091 assert(LTy->isIntegerTy());
2097 if (
SI->isVolatile())
2099 Type *STy =
SI->getValueOperand()->getType();
2103 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2123 bool HaveCommonEltTy,
Type *CommonEltTy,
2124 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2125 VectorType *CommonVecPtrTy,
unsigned VScale) {
2127 if (CandidateTys.
empty())
2134 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2138 if (!HaveCommonEltTy && HaveVecPtrTy) {
2140 CandidateTys.
clear();
2142 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2145 if (!VTy->getElementType()->isIntegerTy())
2147 VTy->getContext(), VTy->getScalarSizeInBits())));
2154 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2155 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2156 "Cannot have vector types of different sizes!");
2157 assert(RHSTy->getElementType()->isIntegerTy() &&
2158 "All non-integer types eliminated!");
2159 assert(LHSTy->getElementType()->isIntegerTy() &&
2160 "All non-integer types eliminated!");
2166 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2167 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2168 "Cannot have vector types of different sizes!");
2169 assert(RHSTy->getElementType()->isIntegerTy() &&
2170 "All non-integer types eliminated!");
2171 assert(LHSTy->getElementType()->isIntegerTy() &&
2172 "All non-integer types eliminated!");
2176 llvm::sort(CandidateTys, RankVectorTypesComp);
2177 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2178 CandidateTys.end());
2184 assert(VTy->getElementType() == CommonEltTy &&
2185 "Unaccounted for element type!");
2186 assert(VTy == CandidateTys[0] &&
2187 "Different vector types with the same element type!");
2190 CandidateTys.resize(1);
2197 std::numeric_limits<unsigned short>::max();
2203 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2207 if (ElementSize % 8)
2209 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2210 "vector size not a multiple of element size?");
2213 for (
const Slice &S :
P)
2217 for (
const Slice *S :
P.splitSliceTails())
2223 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2230 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2231 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2233 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2236 for (
Type *Ty : OtherTys) {
2239 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2242 for (
VectorType *
const VTy : CandidateTysCopy) {
2244 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2245 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2246 unsigned ElementSize =
2247 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2251 CheckCandidateType(NewVTy);
2257 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2258 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2277 Type *CommonEltTy =
nullptr;
2279 bool HaveVecPtrTy =
false;
2280 bool HaveCommonEltTy =
true;
2281 bool HaveCommonVecPtrTy =
true;
2282 auto CheckCandidateType = [&](
Type *Ty) {
2285 if (!CandidateTys.
empty()) {
2287 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2288 DL.getTypeSizeInBits(V).getFixedValue()) {
2289 CandidateTys.
clear();
2294 Type *EltTy = VTy->getElementType();
2297 CommonEltTy = EltTy;
2298 else if (CommonEltTy != EltTy)
2299 HaveCommonEltTy =
false;
2302 HaveVecPtrTy =
true;
2303 if (!CommonVecPtrTy)
2304 CommonVecPtrTy = VTy;
2305 else if (CommonVecPtrTy != VTy)
2306 HaveCommonVecPtrTy =
false;
2312 for (
const Slice &S :
P) {
2317 Ty =
SI->getValueOperand()->getType();
2321 auto CandTy = Ty->getScalarType();
2322 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2323 S.endOffset() !=
P.endOffset())) {
2330 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2331 CheckCandidateType(Ty);
2336 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2337 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2338 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2341 CandidateTys.
clear();
2343 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2344 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2345 CommonVecPtrTy, VScale);
2356 bool &WholeAllocaOp) {
2359 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2360 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2362 Use *U = S.getUse();
2369 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2387 if (S.beginOffset() < AllocBeginOffset)
2393 WholeAllocaOp =
true;
2395 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2397 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2404 Type *ValueTy =
SI->getValueOperand()->getType();
2405 if (
SI->isVolatile())
2408 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2413 if (S.beginOffset() < AllocBeginOffset)
2419 WholeAllocaOp =
true;
2421 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2423 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2432 if (!S.isSplittable())
2449 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2455 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2473 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2475 for (
const Slice &S :
P)
2480 for (
const Slice *S :
P.splitSliceTails())
2485 return WholeAllocaOp;
2490 const Twine &Name) {
2494 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2495 "Element extends past full value");
2497 if (
DL.isBigEndian())
2498 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2499 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2501 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2504 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2505 "Cannot extract to a larger integer!");
2507 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2517 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2518 "Cannot insert a larger integer!");
2521 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2525 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2526 "Element store outside of alloca store");
2528 if (
DL.isBigEndian())
2529 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2530 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2532 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2536 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2537 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2538 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2540 V = IRB.CreateOr(Old, V, Name +
".insert");
2547 unsigned EndIndex,
const Twine &Name) {
2549 unsigned NumElements = EndIndex - BeginIndex;
2550 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2552 if (NumElements == VecTy->getNumElements())
2555 if (NumElements == 1) {
2556 V = IRB.CreateExtractElement(V, BeginIndex, Name +
".extract");
2562 V = IRB.CreateShuffleVector(V, Mask, Name +
".extract");
2568 unsigned BeginIndex,
const Twine &Name) {
2570 assert(VecTy &&
"Can only insert a vector into a vector");
2575 V = IRB.CreateInsertElement(Old, V, BeginIndex, Name +
".insert");
2583 assert(NumSubElements <= NumElements &&
"Too many elements!");
2584 if (NumSubElements == NumElements) {
2585 assert(V->getType() == VecTy &&
"Vector type mismatch");
2588 unsigned EndIndex = BeginIndex + NumSubElements;
2595 Mask.reserve(NumElements);
2596 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2597 if (Idx >= BeginIndex && Idx < EndIndex)
2598 Mask.push_back(Idx - BeginIndex);
2601 V = IRB.CreateShuffleVector(V, Mask, Name +
".expand");
2605 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2606 if (Idx >= BeginIndex && Idx < EndIndex)
2607 Mask.push_back(Idx);
2609 Mask.push_back(Idx + NumElements);
2610 V = IRB.CreateShuffleVector(V, Old, Mask, Name +
"blend");
2649 const char *DebugName) {
2650 Type *EltType = VecType->getElementType();
2651 if (EltType != NewAIEltTy) {
2653 unsigned TotalBits =
2654 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2655 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2658 V = Builder.CreateBitCast(V, NewVecType);
2659 VecType = NewVecType;
2660 LLVM_DEBUG(
dbgs() <<
" bitcast " << DebugName <<
": " << *V <<
"\n");
2664 BitcastIfNeeded(V0, VecType0,
"V0");
2665 BitcastIfNeeded(
V1, VecType1,
"V1");
2667 unsigned NumElts0 = VecType0->getNumElements();
2668 unsigned NumElts1 = VecType1->getNumElements();
2672 if (NumElts0 == NumElts1) {
2673 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2674 ShuffleMask.push_back(i);
2678 unsigned SmallSize = std::min(NumElts0, NumElts1);
2679 unsigned LargeSize = std::max(NumElts0, NumElts1);
2680 bool IsV0Smaller = NumElts0 < NumElts1;
2681 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2683 for (
unsigned i = 0; i < SmallSize; ++i)
2685 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2687 ExtendedVec = Builder.CreateShuffleVector(
2689 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2690 for (
unsigned i = 0; i < NumElts0; ++i)
2691 ShuffleMask.push_back(i);
2692 for (
unsigned i = 0; i < NumElts1; ++i)
2693 ShuffleMask.push_back(LargeSize + i);
2696 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2707class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2709 friend class InstVisitor<AllocaSliceRewriter, bool>;
2711 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2713 const DataLayout &
DL;
2716 AllocaInst &OldAI, &NewAI;
2717 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2746 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2749 bool IsSplittable =
false;
2750 bool IsSplit =
false;
2751 Use *OldUse =
nullptr;
2755 SmallSetVector<PHINode *, 8> &PHIUsers;
2756 SmallSetVector<SelectInst *, 8> &SelectUsers;
2764 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2768 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2769 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2773 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2774 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2776 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2777 VectorType *PromotableVecTy,
2778 SmallSetVector<PHINode *, 8> &PHIUsers,
2779 SmallSetVector<SelectInst *, 8> &SelectUsers)
2780 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2781 NewAllocaBeginOffset(NewAllocaBeginOffset),
2782 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2783 IntTy(IsIntegerPromotable
2786 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2788 VecTy(PromotableVecTy),
2789 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2790 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2792 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2795 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2796 "Only multiple-of-8 sized vector elements are viable");
2799 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2802 bool visit(AllocaSlices::const_iterator
I) {
2803 bool CanSROA =
true;
2804 BeginOffset =
I->beginOffset();
2805 EndOffset =
I->endOffset();
2806 IsSplittable =
I->isSplittable();
2808 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2809 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2814 assert(BeginOffset < NewAllocaEndOffset);
2815 assert(EndOffset > NewAllocaBeginOffset);
2816 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2817 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2819 SliceSize = NewEndOffset - NewBeginOffset;
2820 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2821 <<
") NewBegin:(" << NewBeginOffset <<
", "
2822 << NewEndOffset <<
") NewAllocaBegin:("
2823 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2825 assert(IsSplit || NewBeginOffset == BeginOffset);
2826 OldUse =
I->getUse();
2830 IRB.SetInsertPoint(OldUserI);
2831 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2833 if (!IRB.getContext().shouldDiscardValueNames())
2834 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2835 Twine(BeginOffset) +
".");
2897 std::optional<SmallVector<Value *, 4>>
2898 rewriteTreeStructuredMerge(Partition &
P) {
2900 if (
P.splitSliceTails().size() > 0)
2901 return std::nullopt;
2910 :
Store(
SI), BeginOffset(Begin), EndOffset(End), StoredValue(Val) {}
2920 LoadInst *FullLoad =
nullptr;
2921 StoreInst *InitStore =
nullptr;
2925 Type *AllocatedEltTy =
2929 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
2936 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
2938 return FixedVecTy &&
2939 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
2940 !FixedVecTy->getElementType()->isPointerTy();
2943 for (Slice &S :
P) {
2947 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
2948 S.endOffset() == NewAllocaEndOffset);
2952 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
2953 return std::nullopt;
2958 return std::nullopt;
2962 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
2974 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
2975 SI->getValueOperand()->getType()))
2976 return std::nullopt;
2978 unsigned NumElts = StVecTy->getNumElements();
2979 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
2980 if (NumElts * EltSize % AllocatedEltTySize != 0)
2981 return std::nullopt;
2986 return std::nullopt;
2989 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
2990 SI->getValueOperand());
2995 return std::nullopt;
3002 if (StoreInfos.
size() < 2)
3003 return std::nullopt;
3011 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3012 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3013 if (!IsRMWPattern && !IsStoresOnlyPattern)
3014 return std::nullopt;
3018 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3019 for (
auto &Info : StoreInfos)
3020 if (
Info.Store->getParent() != StoreBB)
3021 return std::nullopt;
3023 SmallVector<Value *, 4> DeletedValues;
3030 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3033 while (Vals.
size() > 1) {
3034 SmallVector<Value *, 8>
Next;
3035 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3041 if (Vals.
size() % 2 == 1)
3043 Vals = std::move(
Next);
3052 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3054 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3055 Merged->getType(), &NewAI, getSliceAlign(),
3057 LoadToReplace->
getName() +
".sroa.new.load");
3059 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3064 if (IsStoresOnlyPattern) {
3067 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3068 return A.BeginOffset <
B.BeginOffset;
3073 uint64_t Expected = NewAllocaBeginOffset;
3074 for (
auto &Info : StoreInfos) {
3075 if (
Info.BeginOffset != Expected)
3076 return std::nullopt;
3077 Expected =
Info.EndOffset;
3080 if (Expected != NewAllocaEndOffset)
3081 return std::nullopt;
3091 if (LoadBB == StoreBB) {
3092 for (
auto &Info : StoreInfos)
3093 if (!
Info.Store->comesBefore(FullLoad))
3094 return std::nullopt;
3098 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3099 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3100 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3101 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3102 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3103 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3116 SmallVector<Value *, 8> Vals;
3117 for (
const auto &Info : StoreInfos) {
3122 Value *Merged = TreeMerge(Vals, Builder);
3123 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3126 ReplaceFullLoad(FullLoad, Merged);
3127 return DeletedValues;
3135 return std::nullopt;
3136 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3137 return I.Load->getParent() != StoreBB;
3139 return std::nullopt;
3155 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3156 for (
const auto &L : LoadInfos)
3157 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3158 for (
const auto &S : StoreInfos)
3159 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3161 return A.Inst->comesBefore(
B.Inst);
3169 return std::nullopt;
3175 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3176 !
Accesses.back().Inst->comesBefore(FullLoad))
3177 return std::nullopt;
3188 using SliceRange = std::pair<uint64_t, uint64_t>;
3192 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3196 uint64_t Expected = NewAllocaBeginOffset;
3197 for (
auto &
Range : SortedRanges) {
3198 if (
Range.first != Expected)
3199 return std::nullopt;
3200 Expected =
Range.second;
3202 if (Expected != NewAllocaEndOffset)
3203 return std::nullopt;
3206 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3207 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3209 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3210 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3211 for (
auto &
Range : SortedRanges)
3222 if (InitVec->
getType() != NewAllocaTy)
3223 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3224 DenseMap<SliceRange, Value *> SliceValues;
3225 for (
auto &
Range : SortedRanges) {
3226 unsigned BeginIdx = getIndex(
Range.first);
3227 unsigned EndIdx = getIndex(
Range.second);
3228 SliceValues[
Range] = IRB.CreateShuffleVector(
3244 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3247 if (
V->getType() != Acc.Inst->getType()) {
3249 V = IRB.CreateBitCast(V, Acc.Inst->getType());
3251 Acc.Inst->replaceAllUsesWith(V);
3268 SmallVector<Value *, 8> Vals;
3269 for (
auto &
Range : SortedRanges)
3271 Value *Merged = TreeMerge(Vals, Builder);
3272 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3277 ReplaceFullLoad(FullLoad, Merged);
3279 return DeletedValues;
3287 bool visitInstruction(Instruction &
I) {
3295 assert(IsSplit || BeginOffset == NewBeginOffset);
3298 StringRef OldName = OldPtr->
getName();
3300 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3302 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3307 OldName = OldName.
substr(IndexEnd + 1);
3311 OldName = OldName.
substr(OffsetEnd + 1);
3315 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3327 Align getSliceAlign() {
3329 NewBeginOffset - NewAllocaBeginOffset);
3333 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3335 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3336 uint32_t
Index = RelOffset / ElementSize;
3337 assert(Index * ElementSize == RelOffset);
3341 void deleteIfTriviallyDead(
Value *V) {
3344 Pass.DeadInsts.push_back(
I);
3347 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3348 unsigned BeginIndex = getIndex(NewBeginOffset);
3349 unsigned EndIndex = getIndex(NewEndOffset);
3350 assert(EndIndex > BeginIndex &&
"Empty vector!");
3353 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3355 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3356 LLVMContext::MD_access_group});
3360 Value *rewriteIntegerLoad(LoadInst &LI) {
3361 assert(IntTy &&
"We cannot insert an integer to the alloca");
3364 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3365 V = IRB.CreateBitPreservingCastChain(
DL, V, IntTy);
3366 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3368 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3369 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3378 "Can only handle an extract for an overly wide load");
3380 V = IRB.CreateZExt(V, LI.
getType());
3384 bool visitLoadInst(LoadInst &LI) {
3393 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3395 bool IsPtrAdjusted =
false;
3398 V = rewriteVectorizedLoadInst(LI);
3400 V = rewriteIntegerLoad(LI);
3401 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3402 NewEndOffset == NewAllocaEndOffset &&
3405 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3408 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3409 LoadInst *NewLI = IRB.CreateAlignedLoad(
3410 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3411 if (LI.isVolatile())
3412 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3413 if (NewLI->isAtomic())
3414 NewLI->setAlignment(LI.getAlign());
3419 copyMetadataForLoad(*NewLI, LI);
3423 NewLI->setAAMetadata(AATags.adjustForAccess(
3424 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3432 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3433 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3434 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3435 V = IRB.CreateZExt(V, TITy,
"load.ext");
3436 if (DL.isBigEndian())
3437 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3441 Type *LTy = IRB.getPtrTy(AS);
3443 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3448 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3452 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3453 LLVMContext::MD_access_group});
3456 IsPtrAdjusted =
true;
3458 V = IRB.CreateBitPreservingCastChain(
DL, V, TargetTy);
3463 "Only integer type loads and stores are split");
3464 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3465 "Split load isn't smaller than original load");
3467 "Non-byte-multiple bit width");
3473 LIIt.setHeadBit(
true);
3474 IRB.SetInsertPoint(LI.
getParent(), LIIt);
3479 Value *Placeholder =
3485 Placeholder->replaceAllUsesWith(&LI);
3486 Placeholder->deleteValue();
3491 Pass.DeadInsts.push_back(&LI);
3492 deleteIfTriviallyDead(OldOp);
3497 bool rewriteVectorizedStoreInst(
Value *V, StoreInst &SI,
Value *OldOp,
3502 if (
V->getType() != VecTy) {
3503 unsigned BeginIndex = getIndex(NewBeginOffset);
3504 unsigned EndIndex = getIndex(NewEndOffset);
3505 assert(EndIndex > BeginIndex &&
"Empty vector!");
3506 unsigned NumElements = EndIndex - BeginIndex;
3508 "Too many elements!");
3509 Type *SliceTy = (NumElements == 1)
3511 : FixedVectorType::
get(ElementTy, NumElements);
3512 if (
V->getType() != SliceTy)
3513 V = IRB.CreateBitPreservingCastChain(
DL, V, SliceTy);
3517 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3520 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3521 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3522 LLVMContext::MD_access_group});
3526 Pass.DeadInsts.push_back(&SI);
3535 bool rewriteIntegerStore(
Value *V, StoreInst &SI, AAMDNodes AATags) {
3536 assert(IntTy &&
"We cannot extract an integer from the alloca");
3538 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3540 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3542 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3543 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3547 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3548 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3549 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3550 LLVMContext::MD_access_group});
3557 Store->getValueOperand(),
DL);
3559 Pass.DeadInsts.push_back(&SI);
3564 bool visitStoreInst(StoreInst &SI) {
3566 Value *OldOp =
SI.getOperand(1);
3569 AAMDNodes AATags =
SI.getAAMetadata();
3574 if (
V->getType()->isPointerTy())
3576 Pass.PostPromotionWorklist.insert(AI);
3578 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3581 assert(
V->getType()->isIntegerTy() &&
3582 "Only integer type loads and stores are split");
3583 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3584 "Non-byte-multiple bit width");
3585 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3591 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3592 if (IntTy &&
V->getType()->isIntegerTy())
3593 return rewriteIntegerStore(V, SI, AATags);
3596 if (NewBeginOffset == NewAllocaBeginOffset &&
3597 NewEndOffset == NewAllocaEndOffset &&
3599 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3601 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3604 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3606 unsigned AS =
SI.getPointerAddressSpace();
3607 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3609 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3611 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3612 LLVMContext::MD_access_group});
3616 if (
SI.isVolatile())
3625 Pass.DeadInsts.push_back(&SI);
3626 deleteIfTriviallyDead(OldOp);
3644 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3652 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3662 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3667 bool visitMemSetInst(MemSetInst &
II) {
3671 AAMDNodes AATags =
II.getAAMetadata();
3677 assert(NewBeginOffset == BeginOffset);
3678 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3679 II.setDestAlignment(getSliceAlign());
3684 "AT: Unexpected link to non-const GEP");
3685 deleteIfTriviallyDead(OldPtr);
3690 Pass.DeadInsts.push_back(&
II);
3694 const bool CanContinue = [&]() {
3697 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3702 if (Len > std::numeric_limits<unsigned>::max())
3704 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3707 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3713 Type *SizeTy =
II.getLength()->getType();
3714 unsigned Sz = NewEndOffset - NewBeginOffset;
3717 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3718 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3724 New,
New->getRawDest(),
nullptr,
DL);
3739 assert(ElementTy == ScalarTy);
3741 unsigned BeginIndex = getIndex(NewBeginOffset);
3742 unsigned EndIndex = getIndex(NewEndOffset);
3743 assert(EndIndex > BeginIndex &&
"Empty vector!");
3744 unsigned NumElements = EndIndex - BeginIndex;
3746 "Too many elements!");
3749 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3750 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3751 if (NumElements > 1)
3754 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3763 V = getIntegerSplat(
II.getValue(),
Size);
3765 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3766 NewEndOffset != NewAllocaEndOffset)) {
3767 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3769 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3773 assert(
V->getType() == IntTy &&
3774 "Wrong type for an alloca wide integer!");
3776 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3779 assert(NewBeginOffset == NewAllocaBeginOffset);
3780 assert(NewEndOffset == NewAllocaEndOffset);
3782 V = getIntegerSplat(
II.getValue(),
3783 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3788 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3791 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3793 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3794 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3795 LLVMContext::MD_access_group});
3801 New,
New->getPointerOperand(), V,
DL);
3804 return !
II.isVolatile();
3807 bool visitMemTransferInst(MemTransferInst &
II) {
3813 AAMDNodes AATags =
II.getAAMetadata();
3815 bool IsDest = &
II.getRawDestUse() == OldUse;
3816 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3817 (!IsDest &&
II.getRawSource() == OldPtr));
3819 Align SliceAlign = getSliceAlign();
3827 if (!IsSplittable) {
3828 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3833 DbgAssign->getAddress() ==
II.getDest())
3834 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3836 II.setDest(AdjustedPtr);
3837 II.setDestAlignment(SliceAlign);
3839 II.setSource(AdjustedPtr);
3840 II.setSourceAlignment(SliceAlign);
3844 deleteIfTriviallyDead(OldPtr);
3857 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3858 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
3859 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
3865 if (EmitMemCpy && &OldAI == &NewAI) {
3867 assert(NewBeginOffset == BeginOffset);
3870 if (NewEndOffset != EndOffset)
3871 II.setLength(NewEndOffset - NewBeginOffset);
3875 Pass.DeadInsts.push_back(&
II);
3879 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3880 if (AllocaInst *AI =
3882 assert(AI != &OldAI && AI != &NewAI &&
3883 "Splittable transfers cannot reach the same alloca on both ends.");
3884 Pass.Worklist.insert(AI);
3891 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3892 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3894 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
3896 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
3904 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3905 Type *SizeTy =
II.getLength()->getType();
3906 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
3908 Value *DestPtr, *SrcPtr;
3909 MaybeAlign DestAlign, SrcAlign;
3913 DestAlign = SliceAlign;
3915 SrcAlign = OtherAlign;
3918 DestAlign = OtherAlign;
3920 SrcAlign = SliceAlign;
3922 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
3925 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
3930 &
II, New, DestPtr,
nullptr,
DL);
3935 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
3941 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
3942 NewEndOffset == NewAllocaEndOffset;
3944 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
3945 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
3946 unsigned NumElements = EndIndex - BeginIndex;
3947 IntegerType *SubIntTy =
3948 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
3953 if (VecTy && !IsWholeAlloca) {
3954 if (NumElements == 1)
3955 OtherTy = VecTy->getElementType();
3958 }
else if (IntTy && !IsWholeAlloca) {
3961 OtherTy = NewAllocaTy;
3966 MaybeAlign SrcAlign = OtherAlign;
3967 MaybeAlign DstAlign = SliceAlign;
3975 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3979 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
3983 if (VecTy && !IsWholeAlloca && !IsDest) {
3985 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3987 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
3989 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3990 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
3994 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
3995 II.isVolatile(),
"copyload");
3996 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3997 LLVMContext::MD_access_group});
4004 if (VecTy && !IsWholeAlloca && IsDest) {
4005 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4008 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4009 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4011 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4014 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4018 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4019 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4020 LLVMContext::MD_access_group});
4023 Src->getType(),
DL));
4038 return !
II.isVolatile();
4041 bool visitIntrinsicInst(IntrinsicInst &
II) {
4042 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4043 "Unexpected intrinsic!");
4047 Pass.DeadInsts.push_back(&
II);
4049 if (
II.isDroppable()) {
4050 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4056 assert(
II.getArgOperand(0) == OldPtr);
4060 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4061 New = IRB.CreateLifetimeStart(Ptr);
4063 New = IRB.CreateLifetimeEnd(Ptr);
4071 void fixLoadStoreAlign(Instruction &Root) {
4075 SmallPtrSet<Instruction *, 4> Visited;
4076 SmallVector<Instruction *, 4>
Uses;
4078 Uses.push_back(&Root);
4087 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4094 for (User *U :
I->users())
4097 }
while (!
Uses.empty());
4100 bool visitPHINode(PHINode &PN) {
4102 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4103 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4109 IRBuilderBase::InsertPointGuard Guard(IRB);
4112 OldPtr->
getParent()->getFirstInsertionPt());
4114 IRB.SetInsertPoint(OldPtr);
4115 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4117 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4122 deleteIfTriviallyDead(OldPtr);
4125 fixLoadStoreAlign(PN);
4134 bool visitSelectInst(SelectInst &SI) {
4136 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4137 "Pointer isn't an operand!");
4138 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4139 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4141 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4143 if (
SI.getOperand(1) == OldPtr)
4144 SI.setOperand(1, NewPtr);
4145 if (
SI.getOperand(2) == OldPtr)
4146 SI.setOperand(2, NewPtr);
4149 deleteIfTriviallyDead(OldPtr);
4152 fixLoadStoreAlign(SI);
4167class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4169 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4175 SmallPtrSet<User *, 8> Visited;
4182 const DataLayout &
DL;
4187 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4188 :
DL(
DL), IRB(IRB) {}
4192 bool rewrite(Instruction &
I) {
4196 while (!
Queue.empty()) {
4197 U =
Queue.pop_back_val();
4206 void enqueueUsers(Instruction &
I) {
4207 for (Use &U :
I.uses())
4208 if (Visited.
insert(
U.getUser()).second)
4209 Queue.push_back(&U);
4213 bool visitInstruction(Instruction &
I) {
return false; }
4216 template <
typename Derived>
class OpSplitter {
4223 SmallVector<unsigned, 4> Indices;
4227 SmallVector<Value *, 4> GEPIndices;
4241 const DataLayout &
DL;
4245 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4246 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4247 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4248 BaseAlign(BaseAlign),
DL(
DL) {
4249 IRB.SetInsertPoint(InsertionPoint);
4266 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4268 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4269 return static_cast<Derived *
>(
this)->emitFunc(
4274 unsigned OldSize = Indices.
size();
4276 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4278 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4280 GEPIndices.
push_back(IRB.getInt32(Idx));
4281 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4289 unsigned OldSize = Indices.
size();
4291 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4293 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4295 GEPIndices.
push_back(IRB.getInt32(Idx));
4296 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4307 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4311 SmallVector<Value *, 4> Components;
4316 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4317 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4319 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4325 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4329 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4331 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4337 Load->setAAMetadata(
4343 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4348 void recordFakeUses(LoadInst &LI) {
4349 for (Use &U : LI.
uses())
4351 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4357 void emitFakeUses() {
4358 for (Instruction *
I : FakeUses) {
4359 IRB.SetInsertPoint(
I);
4360 for (
auto *V : Components)
4361 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4362 I->eraseFromParent();
4367 bool visitLoadInst(LoadInst &LI) {
4376 Splitter.recordFakeUses(LI);
4379 Splitter.emitFakeUses();
4386 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4387 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4388 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4389 const DataLayout &
DL, IRBuilderTy &IRB)
4390 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4392 AATags(AATags), AggStore(AggStore) {}
4394 StoreInst *AggStore;
4397 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4403 Value *ExtractValue =
4404 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4405 Value *InBoundsGEP =
4406 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4408 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4425 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4427 SizeInBits, AggStore,
Store,
4428 Store->getPointerOperand(),
Store->getValueOperand(),
4432 "AT: unexpected debug.assign linked to store through "
4439 bool visitStoreInst(StoreInst &SI) {
4440 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4443 if (
V->getType()->isSingleValueType())
4448 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4450 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4455 SI.eraseFromParent();
4459 bool visitBitCastInst(BitCastInst &BC) {
4464 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4474 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4493 if (!ZI->getSrcTy()->isIntegerTy(1))
4506 dbgs() <<
" original: " << *Sel <<
"\n";
4507 dbgs() <<
" " << GEPI <<
"\n";);
4509 auto GetNewOps = [&](
Value *SelOp) {
4522 Cond =
SI->getCondition();
4523 True =
SI->getTrueValue();
4524 False =
SI->getFalseValue();
4528 Cond = Sel->getOperand(0);
4529 True = ConstantInt::get(Sel->getType(), 1);
4530 False = ConstantInt::get(Sel->getType(), 0);
4535 IRB.SetInsertPoint(&GEPI);
4539 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4540 True->
getName() +
".sroa.gep", NW);
4543 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4544 False->
getName() +
".sroa.gep", NW);
4546 Value *NSel = MDFrom
4547 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4548 Sel->getName() +
".sroa.sel", MDFrom)
4549 : IRB.CreateSelectWithUnknownProfile(
4551 Sel->getName() +
".sroa.sel");
4552 Visited.
erase(&GEPI);
4557 enqueueUsers(*NSelI);
4560 dbgs() <<
" " << *NFalse <<
"\n";
4561 dbgs() <<
" " << *NSel <<
"\n";);
4570 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4575 auto IsInvalidPointerOperand = [](
Value *
V) {
4579 return !AI->isStaticAlloca();
4583 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4598 [](
Value *V) { return isa<ConstantInt>(V); }))
4611 dbgs() <<
" original: " << *
Phi <<
"\n";
4612 dbgs() <<
" " << GEPI <<
"\n";);
4614 auto GetNewOps = [&](
Value *PhiOp) {
4624 IRB.SetInsertPoint(Phi);
4625 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4626 Phi->getName() +
".sroa.phi");
4632 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4641 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4647 Visited.
erase(&GEPI);
4651 enqueueUsers(*NewPhi);
4657 dbgs() <<
"\n " << *NewPhi <<
'\n');
4662 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4663 if (unfoldGEPSelect(GEPI))
4666 if (unfoldGEPPhi(GEPI))
4673 bool visitPHINode(PHINode &PN) {
4678 bool visitSelectInst(SelectInst &SI) {
4692 if (Ty->isSingleValueType())
4695 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4700 InnerTy = ArrTy->getElementType();
4704 InnerTy = STy->getElementType(Index);
4709 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4710 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4731 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4733 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4734 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4741 ElementTy = AT->getElementType();
4742 TyNumElements = AT->getNumElements();
4747 ElementTy = VT->getElementType();
4748 TyNumElements = VT->getNumElements();
4750 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4752 if (NumSkippedElements >= TyNumElements)
4754 Offset -= NumSkippedElements * ElementSize;
4766 if (
Size == ElementSize)
4770 if (NumElements * ElementSize !=
Size)
4794 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4795 if (
Offset >= ElementSize)
4806 if (
Size == ElementSize)
4813 if (Index == EndIndex)
4823 assert(Index < EndIndex);
4862bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
4876 struct SplitOffsets {
4878 std::vector<uint64_t> Splits;
4880 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
4893 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
4895 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
4896 for (
auto &
P : AS.partitions()) {
4897 for (Slice &S :
P) {
4899 if (!S.isSplittable() || S.endOffset() <=
P.endOffset()) {
4904 UnsplittableLoads.
insert(LI);
4907 UnsplittableLoads.
insert(LI);
4910 assert(
P.endOffset() > S.beginOffset() &&
4911 "Empty or backwards partition!");
4920 auto IsLoadSimplyStored = [](LoadInst *LI) {
4921 for (User *LU : LI->
users()) {
4923 if (!SI || !
SI->isSimple())
4928 if (!IsLoadSimplyStored(LI)) {
4929 UnsplittableLoads.
insert(LI);
4935 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
4939 if (!StoredLoad || !StoredLoad->isSimple())
4941 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
4951 auto &
Offsets = SplitOffsetsMap[
I];
4953 "Should not have splits the first time we see an instruction!");
4955 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
4960 for (Slice *S :
P.splitSliceTails()) {
4961 auto SplitOffsetsMapI =
4963 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
4965 auto &
Offsets = SplitOffsetsMapI->second;
4969 "Cannot have an empty set of splits on the second partition!");
4971 P.beginOffset() -
Offsets.S->beginOffset() &&
4972 "Previous split does not end where this one begins!");
4976 if (S->endOffset() >
P.endOffset())
4985 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
4991 if (UnsplittableLoads.
count(LI))
4994 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
4995 if (LoadOffsetsI == SplitOffsetsMap.
end())
4997 auto &LoadOffsets = LoadOffsetsI->second;
5000 auto &StoreOffsets = SplitOffsetsMap[
SI];
5005 if (LoadOffsets.Splits == StoreOffsets.Splits)
5009 <<
" " << *LI <<
"\n"
5010 <<
" " << *SI <<
"\n");
5016 UnsplittableLoads.
insert(LI);
5025 return UnsplittableLoads.
count(LI);
5030 return UnsplittableLoads.
count(LI);
5040 IRBuilderTy IRB(&AI);
5047 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5057 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5058 std::vector<LoadInst *> SplitLoads;
5059 const DataLayout &
DL = AI.getDataLayout();
5060 for (LoadInst *LI : Loads) {
5063 auto &
Offsets = SplitOffsetsMap[LI];
5064 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5066 "Load must have type size equal to store size");
5068 "Load must be >= slice size");
5071 assert(BaseOffset + SliceSize > BaseOffset &&
5072 "Cannot represent alloca access size using 64-bit integers!");
5075 IRB.SetInsertPoint(LI);
5082 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5085 LoadInst *PLoad = IRB.CreateAlignedLoad(
5088 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5089 PartPtrTy,
BasePtr->getName() +
"."),
5092 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5093 LLVMContext::MD_access_group});
5097 SplitLoads.push_back(PLoad);
5101 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5105 <<
", " << NewSlices.
back().endOffset()
5106 <<
"): " << *PLoad <<
"\n");
5113 PartOffset =
Offsets.Splits[Idx];
5115 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : SliceSize) - PartOffset;
5121 bool DeferredStores =
false;
5122 for (User *LU : LI->
users()) {
5124 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5125 DeferredStores =
true;
5131 Value *StoreBasePtr =
SI->getPointerOperand();
5132 IRB.SetInsertPoint(SI);
5133 AAMDNodes AATags =
SI->getAAMetadata();
5135 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5137 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5138 LoadInst *PLoad = SplitLoads[Idx];
5140 auto *PartPtrTy =
SI->getPointerOperandType();
5142 auto AS =
SI->getPointerAddressSpace();
5143 StoreInst *PStore = IRB.CreateAlignedStore(
5146 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5147 PartPtrTy, StoreBasePtr->
getName() +
"."),
5150 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5151 LLVMContext::MD_access_group,
5152 LLVMContext::MD_DIAssignID});
5157 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5165 ResplitPromotableAllocas.
insert(OtherAI);
5166 Worklist.insert(OtherAI);
5169 Worklist.insert(OtherAI);
5173 DeadInsts.push_back(SI);
5178 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5181 DeadInsts.push_back(LI);
5190 for (StoreInst *SI : Stores) {
5195 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5199 "Slice size should always match load size exactly!");
5201 assert(BaseOffset + StoreSize > BaseOffset &&
5202 "Cannot represent alloca access size using 64-bit integers!");
5210 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5211 std::vector<LoadInst *> *SplitLoads =
nullptr;
5212 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5213 SplitLoads = &SplitLoadsMapI->second;
5215 "Too few split loads for the number of splits in the store!");
5223 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5225 auto *StorePartPtrTy =
SI->getPointerOperandType();
5230 PLoad = (*SplitLoads)[Idx];
5232 IRB.SetInsertPoint(LI);
5234 PLoad = IRB.CreateAlignedLoad(
5237 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5238 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5241 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5242 LLVMContext::MD_access_group});
5246 IRB.SetInsertPoint(SI);
5247 auto AS =
SI->getPointerAddressSpace();
5248 StoreInst *PStore = IRB.CreateAlignedStore(
5251 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5252 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5255 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5256 LLVMContext::MD_access_group});
5260 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5264 <<
", " << NewSlices.
back().endOffset()
5265 <<
"): " << *PStore <<
"\n");
5275 PartOffset =
Offsets.Splits[Idx];
5277 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : StoreSize) - PartOffset;
5287 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5288 ResplitPromotableAllocas.
insert(OtherAI);
5289 Worklist.insert(OtherAI);
5292 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5293 Worklist.insert(OtherAI);
5308 DeadInsts.push_back(LI);
5310 DeadInsts.push_back(SI);
5319 AS.insert(NewSlices);
5323 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5329 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5366 bool IsIntegralPointerTy =
5367 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5369 !IsIntegralPointerTy)
5376 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5380 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5381 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5384 if (StructSize != VectorSize)
5387 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5390 auto *U = S.getUse();
5394 User *Usr = U->getUser();
5401 for (
const Slice &S :
P)
5402 if (!IsIgnorableOrMemIntrinsicSlice(S))
5405 for (
const Slice *S :
P.splitSliceTails())
5406 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5423static std::tuple<Type *, bool, VectorType *>
5427 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5429 dbgs() <<
"selectPartitionType path=" << Path
5434 dbgs() <<
"<unnamed>";
5435 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5436 <<
") size=" <<
P.size();
5438 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5440 dbgs() <<
" chosen=" << *SelectedTy;
5442 dbgs() <<
" vec=" << *SelectedVecTy;
5443 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5461 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5462 VecTy->getElementCount().getFixedValue() > 1) {
5463 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5464 return {VecTy,
false, VecTy};
5469 auto [CommonUseTy, LargestIntTy] =
5472 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5478 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5479 return {VecTy,
false, VecTy};
5482 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5483 return {CommonUseTy, IntWiden,
nullptr};
5490 P.beginOffset(),
P.size())) {
5494 if (TypePartitionTy->isArrayTy() &&
5495 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5496 DL.isLegalInteger(
P.size() * 8))
5500 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5501 return {TypePartitionTy,
true,
nullptr};
5504 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5505 return {VecTy,
false, VecTy};
5510 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5512 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5513 return {LargestIntTy,
true,
nullptr};
5518 if (AggregateToVector) {
5521 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5522 return {VTy,
false,
nullptr};
5528 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5529 return {TypePartitionTy,
false,
nullptr};
5534 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5535 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5536 return {LargestIntTy,
false,
nullptr};
5540 if (
DL.isLegalInteger(
P.size() * 8)) {
5542 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5543 return {IntTy,
false,
nullptr};
5548 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5549 return {ArrayTy,
false,
nullptr};
5562std::pair<AllocaInst *, uint64_t>
5563SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5564 const DataLayout &
DL = AI.getDataLayout();
5566 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5576 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5586 const bool IsUnconstrained =
Alignment <=
DL.getABITypeAlign(PartitionTy);
5587 NewAI =
new AllocaInst(
5588 PartitionTy, AI.getAddressSpace(),
nullptr,
5589 IsUnconstrained ?
DL.getPrefTypeAlign(PartitionTy) : Alignment,
5590 AI.
getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5597 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5598 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5603 unsigned PPWOldSize = PostPromotionWorklist.size();
5604 unsigned NumUses = 0;
5605 SmallSetVector<PHINode *, 8> PHIUsers;
5606 SmallSetVector<SelectInst *, 8> SelectUsers;
5609 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5610 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5611 bool Promotable =
true;
5613 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5614 NumUses += DeletedValues->
size() + 1;
5615 for (
Value *V : *DeletedValues)
5616 DeadInsts.push_back(V);
5618 for (Slice *S :
P.splitSliceTails()) {
5622 for (Slice &S :
P) {
5628 NumAllocaPartitionUses += NumUses;
5629 MaxUsesPerAllocaPartition.updateMax(NumUses);
5633 for (PHINode *
PHI : PHIUsers)
5637 SelectUsers.
clear();
5642 NewSelectsToRewrite;
5644 for (SelectInst *Sel : SelectUsers) {
5645 std::optional<RewriteableMemOps>
Ops =
5646 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5650 SelectUsers.clear();
5651 NewSelectsToRewrite.
clear();
5658 for (Use *U : AS.getDeadUsesIfPromotable()) {
5660 Value::dropDroppableUse(*U);
5663 DeadInsts.push_back(OldInst);
5665 if (PHIUsers.empty() && SelectUsers.empty()) {
5667 PromotableAllocas.insert(NewAI);
5672 SpeculatablePHIs.insert_range(PHIUsers);
5673 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5674 NewSelectsToRewrite.
size());
5676 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5677 std::make_move_iterator(NewSelectsToRewrite.
end())))
5678 SelectsToRewrite.insert(std::move(KV));
5679 Worklist.insert(NewAI);
5683 while (PostPromotionWorklist.size() > PPWOldSize)
5684 PostPromotionWorklist.pop_back();
5689 return {
nullptr, 0};
5694 Worklist.insert(NewAI);
5697 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5741 int64_t BitExtractOffset) {
5743 bool HasFragment =
false;
5744 bool HasBitExtract =
false;
5752 HasBitExtract =
true;
5753 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5754 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5763 assert(BitExtractOffset <= 0);
5764 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5770 if (AdjustedOffset < 0)
5773 Ops.push_back(
Op.getOp());
5774 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5775 Ops.push_back(ExtractSizeInBits);
5778 Op.appendToVector(
Ops);
5783 if (HasFragment && HasBitExtract)
5786 if (!HasBitExtract) {
5805 std::optional<DIExpression::FragmentInfo> NewFragment,
5806 int64_t BitExtractAdjustment) {
5816 BitExtractAdjustment);
5817 if (!NewFragmentExpr)
5823 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5836 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5842 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5850 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
5856bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
5857 if (AS.begin() == AS.end())
5860 unsigned NumPartitions = 0;
5862 const DataLayout &
DL = AI.getModule()->getDataLayout();
5865 Changed |= presplitLoadsAndStores(AI, AS);
5873 bool IsSorted =
true;
5875 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
5876 const uint64_t MaxBitVectorSize = 1024;
5877 if (AllocaSize <= MaxBitVectorSize) {
5880 SmallBitVector SplittableOffset(AllocaSize + 1,
true);
5882 for (
unsigned O = S.beginOffset() + 1;
5883 O < S.endOffset() && O < AllocaSize; O++)
5884 SplittableOffset.reset(O);
5886 for (Slice &S : AS) {
5887 if (!S.isSplittable())
5890 if ((S.beginOffset() > AllocaSize || SplittableOffset[S.beginOffset()]) &&
5891 (S.endOffset() > AllocaSize || SplittableOffset[S.endOffset()]))
5896 S.makeUnsplittable();
5903 for (Slice &S : AS) {
5904 if (!S.isSplittable())
5907 if (S.beginOffset() == 0 && S.endOffset() >= AllocaSize)
5912 S.makeUnsplittable();
5933 for (
auto &
P : AS.partitions()) {
5934 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
5938 uint64_t SizeOfByte = 8;
5940 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
5941 Fragments.push_back(
5942 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
5948 NumAllocaPartitions += NumPartitions;
5949 MaxPartitionsPerAlloca.updateMax(NumPartitions);
5953 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
5958 const Value *DbgPtr = DbgVariable->getAddress();
5960 DbgVariable->getFragmentOrEntireVariable();
5963 int64_t CurrentExprOffsetInBytes = 0;
5964 SmallVector<uint64_t> PostOffsetOps;
5966 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
5970 int64_t ExtractOffsetInBits = 0;
5973 ExtractOffsetInBits = Extract.getOffsetInBits();
5978 DIBuilder DIB(*AI.getModule(),
false);
5979 for (
auto Fragment : Fragments) {
5980 int64_t OffsetFromLocationInBits;
5981 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
5986 DL, &AI, Fragment.Offset, Fragment.Size, DbgPtr,
5987 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
5988 NewDbgFragment, OffsetFromLocationInBits))
5994 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
5999 if (!NewDbgFragment)
6000 NewDbgFragment = DbgVariable->getFragment();
6004 int64_t OffestFromNewAllocaInBits =
6005 OffsetFromLocationInBits - ExtractOffsetInBits;
6008 int64_t BitExtractOffset =
6009 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6014 OffestFromNewAllocaInBits =
6015 std::max(int64_t(0), OffestFromNewAllocaInBits);
6021 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6022 if (OffestFromNewAllocaInBits > 0) {
6023 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6029 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6030 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6031 return LHS->getVariable() ==
RHS->getVariable() &&
6032 LHS->getDebugLoc()->getInlinedAt() ==
6033 RHS->getDebugLoc()->getInlinedAt();
6035 if (SameVariableFragment(OldDII, DbgVariable))
6036 OldDII->eraseFromParent();
6041 NewDbgFragment, BitExtractOffset);
6055void SROA::clobberUse(Use &U) {
6065 DeadInsts.push_back(OldI);
6087bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6092 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6093 bool AllSameAndValid =
true;
6094 Type *PartitionType =
nullptr;
6095 SmallVector<Instruction *> Insts;
6099 auto Flush = [&]() {
6100 if (AllSameAndValid && !Insts.
empty()) {
6101 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6102 << EndOffset <<
")\n");
6104 SSAUpdater
SSA(&NewPHIs);
6106 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6107 Promoter.run(Insts);
6109 AllSameAndValid =
true;
6110 PartitionType =
nullptr;
6114 for (Slice &S : AS) {
6118 dbgs() <<
"Ignoring slice: ";
6119 AS.print(
dbgs(), &S);
6123 if (S.beginOffset() >= EndOffset) {
6125 BeginOffset = S.beginOffset();
6126 EndOffset = S.endOffset();
6127 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6128 if (AllSameAndValid) {
6130 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6131 << EndOffset <<
")";
6132 AS.print(
dbgs(), &S);
6134 AllSameAndValid =
false;
6136 EndOffset = std::max(EndOffset, S.endOffset());
6143 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6144 AllSameAndValid =
false;
6145 PartitionType = UserTy;
6148 Type *UserTy =
SI->getValueOperand()->getType();
6149 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6150 AllSameAndValid =
false;
6151 PartitionType = UserTy;
6154 AllSameAndValid =
false;
6167std::pair<
bool ,
bool >
6168SROA::runOnAlloca(AllocaInst &AI) {
6170 bool CFGChanged =
false;
6173 ++NumAllocasAnalyzed;
6176 if (AI.use_empty()) {
6177 AI.eraseFromParent();
6181 const DataLayout &
DL = AI.getDataLayout();
6184 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6185 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6190 IRBuilderTy IRB(&AI);
6191 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6192 Changed |= AggRewriter.rewrite(AI);
6195 AllocaSlices AS(
DL, AI);
6200 if (AS.isEscapedReadOnly()) {
6201 Changed |= propagateStoredValuesToLoads(AI, AS);
6206 for (Instruction *DeadUser : AS.getDeadUsers()) {
6208 for (Use &DeadOp : DeadUser->operands())
6215 DeadInsts.push_back(DeadUser);
6218 for (Use *DeadOp : AS.getDeadOperands()) {
6219 clobberUse(*DeadOp);
6224 if (AS.begin() == AS.end())
6227 Changed |= splitAlloca(AI, AS);
6230 while (!SpeculatablePHIs.empty())
6234 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6235 while (!RemainingSelectsToRewrite.empty()) {
6236 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6253bool SROA::deleteDeadInstructions(
6254 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6256 while (!DeadInsts.empty()) {
6266 DeletedAllocas.
insert(AI);
6268 OldDII->eraseFromParent();
6274 for (Use &Operand :
I->operands())
6279 DeadInsts.push_back(U);
6283 I->eraseFromParent();
6293bool SROA::promoteAllocas() {
6294 if (PromotableAllocas.empty())
6301 NumPromoted += PromotableAllocas.size();
6302 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6305 PromotableAllocas.clear();
6309std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6312 const DataLayout &
DL =
F.getDataLayout();
6317 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6319 PromotableAllocas.insert(AI);
6321 Worklist.insert(AI);
6326 bool CFGChanged =
false;
6329 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6332 while (!Worklist.empty()) {
6333 auto [IterationChanged, IterationCFGChanged] =
6334 runOnAlloca(*Worklist.pop_back_val());
6336 CFGChanged |= IterationCFGChanged;
6338 Changed |= deleteDeadInstructions(DeletedAllocas);
6342 if (!DeletedAllocas.
empty()) {
6343 Worklist.set_subtract(DeletedAllocas);
6344 PostPromotionWorklist.set_subtract(DeletedAllocas);
6345 PromotableAllocas.set_subtract(DeletedAllocas);
6346 DeletedAllocas.
clear();
6352 Worklist = PostPromotionWorklist;
6353 PostPromotionWorklist.clear();
6354 }
while (!Worklist.empty());
6356 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6357 assert((!CFGChanged || !PreserveCFG) &&
6358 "Should not have modified the CFG when told to preserve it.");
6361 for (
auto &BB :
F) {
6374 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6386 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6387 OS, MapClassName2PassName);
6391 if (Options.AggregateToVector)
6392 OS <<
";aggregate-to-vector";
6413 if (skipFunction(
F))
6416 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6418 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6424 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6431 StringRef getPassName()
const override {
return "SROA"; }
6436char SROALegacyPass::ID = 0;
6441 AggregateToVector));
6445 "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()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
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...
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
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.
user_iterator user_begin()
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.
iterator_range< user_iterator > users()
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.
LLVM_ABI cl::opt< bool > ProfcheckDisableMetadataFixes
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.