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 stores to allow promotion");
118STATISTIC(NumVectorized,
"Number of vectorized aggregates");
122class AllocaSliceRewriter;
127class SelectHandSpeculativity {
128 unsigned char Storage = 0;
132 SelectHandSpeculativity() =
default;
133 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
134 bool isSpeculatable(
bool isTrueVal)
const;
135 bool areAllSpeculatable()
const;
136 bool areAnySpeculatable()
const;
137 bool areNoneSpeculatable()
const;
139 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
140 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
142static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
144using PossiblySpeculatableLoad =
147using RewriteableMemOp =
148 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
150using InstructionSliceMap =
172 LLVMContext *
const C;
173 DomTreeUpdater *
const DTU;
174 AssumptionCache *
const AC;
175 const bool PreserveCFG;
176 const bool AggregateToVector;
185 SmallSetVector<AllocaInst *, 16> Worklist;
200 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
203 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
204 SmallPtrSet<AllocaInst *, 16>, 16>
212 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
219 SmallSetVector<PHINode *, 8> PHIsWithStoreToRewrite;
223 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
268 static std::optional<RewriteableMemOps>
269 isSafeSelectToSpeculateOrPredicate(SelectInst &SI,
bool PreserveCFG);
272 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
274 : C(C), DTU(DTU), AC(AC),
275 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
276 AggregateToVector(
Options.AggregateToVector) {}
279 std::pair<
bool ,
bool > runSROA(
Function &
F);
282 friend class AllocaSliceRewriter;
284 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
285 std::pair<AllocaInst *, uint64_t>
286 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
287 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
288 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
289 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
290 void clobberUse(Use &U);
291 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
292 bool promoteAllocas();
306enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
310 uint64_t NewStorageSliceOffsetInBits,
312 std::optional<DIExpression::FragmentInfo> StorageFragment,
313 std::optional<DIExpression::FragmentInfo> CurrentFragment,
317 if (StorageFragment) {
319 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
321 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
323 Target.SizeInBits = NewStorageSliceSizeInBits;
324 Target.OffsetInBits = NewStorageSliceOffsetInBits;
330 if (!CurrentFragment) {
331 if (
auto Size = Variable->getSizeInBits()) {
334 if (
Target == CurrentFragment)
341 if (!CurrentFragment || *CurrentFragment ==
Target)
347 if (
Target.startInBits() < CurrentFragment->startInBits() ||
348 Target.endInBits() > CurrentFragment->endInBits())
387 if (DVRAssignMarkerRange.empty())
393 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
395 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
407 DVR->getExpression()->getFragmentInfo();
420 auto *Expr = DbgAssign->getExpression();
421 bool SetKillLocation =
false;
424 std::optional<DIExpression::FragmentInfo> BaseFragment;
427 if (R == BaseFragments.
end())
429 BaseFragment = R->second;
431 std::optional<DIExpression::FragmentInfo> CurrentFragment =
432 Expr->getFragmentInfo();
435 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
436 BaseFragment, CurrentFragment, NewFragment);
440 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
441 if (CurrentFragment) {
446 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
459 SetKillLocation =
true;
467 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
474 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
478 NewAssign = DbgAssign;
497 Value && (DbgAssign->hasArgList() ||
498 !DbgAssign->getExpression()->isSingleLocationExpression());
515 if (NewAssign != DbgAssign) {
516 NewAssign->
moveBefore(DbgAssign->getIterator());
519 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
522 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
532 Twine getNameWithPrefix(
const Twine &Name)
const {
537 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
539 void InsertHelper(Instruction *
I,
const Twine &Name,
564 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
570 : BeginOffset(BeginOffset), EndOffset(EndOffset),
571 UseAndIsSplittable(
U, IsSplittable) {}
573 uint64_t beginOffset()
const {
return BeginOffset; }
574 uint64_t endOffset()
const {
return EndOffset; }
576 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
577 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
579 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
581 bool isDead()
const {
return getUse() ==
nullptr; }
582 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
591 if (beginOffset() <
RHS.beginOffset())
593 if (beginOffset() >
RHS.beginOffset())
595 if (isSplittable() !=
RHS.isSplittable())
596 return !isSplittable();
597 if (endOffset() >
RHS.endOffset())
604 return LHS.beginOffset() < RHSOffset;
607 return LHSOffset <
RHS.beginOffset();
611 return isSplittable() ==
RHS.isSplittable() &&
612 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
627 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
633 bool isEscaped()
const {
return PointerEscapingInstr; }
634 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
639 using range = iterator_range<iterator>;
641 iterator
begin() {
return Slices.begin(); }
642 iterator
end() {
return Slices.end(); }
646 const_iterator
begin()
const {
return Slices.begin(); }
647 const_iterator
end()
const {
return Slices.end(); }
651 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
659 int OldSize = Slices.size();
660 Slices.append(NewSlices.
begin(), NewSlices.
end());
661 auto SliceI = Slices.begin() + OldSize;
662 std::stable_sort(SliceI, Slices.end());
663 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
672 ArrayRef<Instruction *> getDeadUsers()
const {
return DeadUsers; }
676 return DeadUseIfPromotable;
687#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
688 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
689 void printSlice(raw_ostream &OS, const_iterator
I,
690 StringRef Indent =
" ")
const;
691 void printUse(raw_ostream &OS, const_iterator
I,
692 StringRef Indent =
" ")
const;
693 void print(raw_ostream &OS)
const;
694 void dump(const_iterator
I)
const;
701 friend class AllocaSlices::SliceBuilder;
703#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
731 SmallVector<Instruction *, 8> DeadUsers;
758 friend class AllocaSlices;
759 friend class AllocaSlices::partition_iterator;
761 using iterator = AllocaSlices::iterator;
765 uint64_t BeginOffset = 0, EndOffset = 0;
775 Partition(iterator SI) : SI(SI), SJ(SI) {}
781 uint64_t beginOffset()
const {
return BeginOffset; }
786 uint64_t endOffset()
const {
return EndOffset; }
792 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
793 return EndOffset - BeginOffset;
798 bool empty()
const {
return SI == SJ; }
809 iterator
begin()
const {
return SI; }
810 iterator
end()
const {
return SJ; }
842 AllocaSlices::iterator SE;
846 uint64_t MaxSplitSliceEndOffset = 0;
850 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
862 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
863 "Cannot advance past the end of the slices!");
866 if (!
P.SplitTails.empty()) {
867 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
869 P.SplitTails.clear();
870 MaxSplitSliceEndOffset = 0;
876 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
879 return S->endOffset() == MaxSplitSliceEndOffset;
881 "Could not find the current max split slice offset!");
884 return S->endOffset() <= MaxSplitSliceEndOffset;
886 "Max split slice end offset is not actually the max!");
893 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
903 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
904 P.SplitTails.push_back(&S);
905 MaxSplitSliceEndOffset =
906 std::max(S.endOffset(), MaxSplitSliceEndOffset);
914 P.BeginOffset = P.EndOffset;
915 P.EndOffset = MaxSplitSliceEndOffset;
922 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
923 !P.SI->isSplittable()) {
924 P.BeginOffset = P.EndOffset;
925 P.EndOffset = P.SI->beginOffset();
935 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
936 P.EndOffset = P.SI->endOffset();
941 if (!P.SI->isSplittable()) {
944 assert(P.BeginOffset == P.SI->beginOffset());
948 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
949 if (!P.SJ->isSplittable())
950 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
962 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
965 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
966 P.SJ->isSplittable()) {
967 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
974 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
975 assert(!P.SJ->isSplittable());
976 P.EndOffset = P.SJ->beginOffset();
983 "End iterators don't match between compared partition iterators!");
990 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
991 assert(P.SJ == RHS.P.SJ &&
992 "Same set of slices formed two different sized partitions!");
993 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
994 "Same slice position with differently sized non-empty split "
1017 return make_range(partition_iterator(begin(), end()),
1018 partition_iterator(end(), end()));
1026 return SI.getOperand(1 + CI->isZero());
1027 if (
SI.getOperand(1) ==
SI.getOperand(2))
1028 return SI.getOperand(1);
1037 return PN->hasConstantValue();
1052 const uint64_t AllocSize;
1068 if (VisitedDeadInsts.
insert(&
I).second)
1073 bool IsSplittable =
false) {
1079 <<
" which has zero size or starts outside of the "
1080 << AllocSize <<
" byte alloca:\n"
1081 <<
" alloca: " << AS.AI <<
"\n"
1082 <<
" use: " <<
I <<
"\n");
1083 return markAsDead(
I);
1095 assert(AllocSize >= BeginOffset);
1096 if (
Size > AllocSize - BeginOffset) {
1098 <<
Offset <<
" to remain within the " << AllocSize
1099 <<
" byte alloca:\n"
1100 <<
" alloca: " << AS.AI <<
"\n"
1101 <<
" use: " <<
I <<
"\n");
1102 EndOffset = AllocSize;
1105 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1108 void visitBitCastInst(BitCastInst &BC) {
1110 return markAsDead(BC);
1112 return Base::visitBitCastInst(BC);
1115 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1117 return markAsDead(ASC);
1119 return Base::visitAddrSpaceCastInst(ASC);
1122 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1124 return markAsDead(GEPI);
1126 return Base::visitGetElementPtrInst(GEPI);
1129 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1140 void visitLoadInst(LoadInst &LI) {
1142 "All simple FCA loads should have been pre-split");
1147 return PI.setEscapedReadOnly(&LI);
1150 if (
Size.isScalable()) {
1153 return PI.setAborted(&LI);
1162 void visitStoreInst(StoreInst &SI) {
1163 Value *ValOp =
SI.getValueOperand();
1165 return PI.setEscapedAndAborted(&SI);
1167 return PI.setAborted(&SI);
1169 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1171 unsigned VScale =
SI.getFunction()->getVScaleValue();
1173 return PI.setAborted(&SI);
1189 <<
Offset <<
" which extends past the end of the "
1190 << AllocSize <<
" byte alloca:\n"
1191 <<
" alloca: " << AS.AI <<
"\n"
1192 <<
" use: " << SI <<
"\n");
1193 return markAsDead(SI);
1197 "All simple FCA stores should have been pre-split");
1201 void visitMemSetInst(MemSetInst &
II) {
1202 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1205 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1207 return markAsDead(
II);
1210 return PI.setAborted(&
II);
1214 : AllocSize -
Offset.getLimitedValue(),
1218 void visitMemTransferInst(MemTransferInst &
II) {
1222 return markAsDead(
II);
1226 if (VisitedDeadInsts.
count(&
II))
1230 return PI.setAborted(&
II);
1237 if (
Offset.uge(AllocSize)) {
1238 auto MTPI = MemTransferSliceMap.
find(&
II);
1239 if (MTPI != MemTransferSliceMap.
end())
1240 AS.Slices[MTPI->second].kill();
1241 return markAsDead(
II);
1249 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1251 if (!
II.isVolatile())
1252 return markAsDead(
II);
1260 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1261 std::tie(MTPI, Inserted) =
1262 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1263 unsigned PrevIdx = MTPI->second;
1265 Slice &PrevP = AS.Slices[PrevIdx];
1269 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1271 return markAsDead(
II);
1276 PrevP.makeUnsplittable();
1283 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1284 "Map index doesn't point back to a slice with this user.");
1290 void visitIntrinsicInst(IntrinsicInst &
II) {
1291 if (
II.isDroppable()) {
1292 AS.DeadUseIfPromotable.push_back(U);
1297 return PI.setAborted(&
II);
1299 if (
II.isLifetimeStartOrEnd()) {
1300 insertUse(
II,
Offset, AllocSize,
true);
1304 Base::visitIntrinsicInst(
II);
1312 SmallPtrSet<Instruction *, 4> Visited;
1322 std::tie(UsedI,
I) =
Uses.pop_back_val();
1325 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1337 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1347 if (!
GEP->hasAllZeroIndices())
1354 for (User *U :
I->users())
1357 }
while (!
Uses.empty());
1362 void visitPHINodeOrSelectInst(Instruction &
I) {
1365 return markAsDead(
I);
1371 return PI.setAborted(&
I);
1389 AS.DeadOperands.push_back(U);
1395 return PI.setAborted(&
I);
1401 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1402 return PI.setAborted(UnsafeI);
1411 if (
Offset.uge(AllocSize)) {
1412 AS.DeadOperands.push_back(U);
1419 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1421 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1424 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1426 void visitCallBase(CallBase &CB) {
1432 PI.setEscapedReadOnly(&CB);
1436 Base::visitCallBase(CB);
1440AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1442#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1445 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1447 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1448 if (PtrI.isEscaped() || PtrI.isAborted()) {
1451 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1452 : PtrI.getAbortingInst();
1453 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1456 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1458 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1465#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1467void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1468 StringRef Indent)
const {
1469 printSlice(OS,
I, Indent);
1471 printUse(OS,
I, Indent);
1474void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1475 StringRef Indent)
const {
1476 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1477 <<
" slice #" << (
I -
begin())
1478 << (
I->isSplittable() ?
" (splittable)" :
"");
1481void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1482 StringRef Indent)
const {
1483 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1486void AllocaSlices::print(raw_ostream &OS)
const {
1487 if (PointerEscapingInstr) {
1488 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1489 <<
" A pointer to this alloca escaped by:\n"
1490 <<
" " << *PointerEscapingInstr <<
"\n";
1494 if (PointerEscapingInstrReadOnly)
1495 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1497 OS <<
"Slices of alloca: " << AI <<
"\n";
1518 for (
User *U :
I.users()) {
1519 Type *UserTy =
nullptr;
1525 UserTy =
Store->getValueOperand()->getType();
1527 if (!UserTy || (Ty && Ty != UserTy))
1537static std::pair<Type *, IntegerType *>
1541 bool TyIsCommon =
true;
1546 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1547 Use *U =
I->getUse();
1550 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1553 Type *UserTy =
nullptr;
1557 UserTy =
SI->getValueOperand()->getType();
1568 if (UserITy->getBitWidth() % 8 != 0 ||
1569 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1574 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1580 if (!UserTy || (Ty && Ty != UserTy))
1586 return {TyIsCommon ? Ty :
nullptr, ITy};
1616 Type *LoadType =
nullptr;
1629 if (LoadType != LI->
getType())
1638 if (BBI->mayWriteToMemory())
1641 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1648 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1691 if (!
SI ||
SI->getPointerOperand() != &PN)
1694 if (
SI->isVolatile())
1702 Value *StoredValue =
SI->getValueOperand();
1741 IRB.SetInsertPoint(&PN);
1743 PN.
getName() +
".sroa.speculated");
1773 IRB.SetInsertPoint(TI);
1776 LoadTy, InVal, Alignment,
1777 (PN.
getName() +
".sroa.speculate.load." +
Pred->getName()));
1778 ++NumLoadsSpeculated;
1780 Load->setAAMetadata(AATags);
1794 <<
" " <<
SI <<
"\n");
1812 bool CFGChanged =
false;
1814 for (
auto [
Pred, InVal] : IncomingValues) {
1816 if (
Pred->getTerminator()->getNumSuccessors() != 1) {
1818 assert(StoreBB &&
"store edge was not checked for splitting");
1825 ++NumStoresPredicated;
1829 SI.eraseFromParent();
1834SelectHandSpeculativity &
1835SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1843bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1848bool SelectHandSpeculativity::areAllSpeculatable()
const {
1849 return isSpeculatable(
true) &&
1850 isSpeculatable(
false);
1853bool SelectHandSpeculativity::areAnySpeculatable()
const {
1854 return isSpeculatable(
true) ||
1855 isSpeculatable(
false);
1857bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1858 return !areAnySpeculatable();
1861static SelectHandSpeculativity
1864 SelectHandSpeculativity
Spec;
1870 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1871 else if (PreserveCFG)
1877std::optional<RewriteableMemOps>
1878SROA::isSafeSelectToSpeculateOrPredicate(SelectInst &SI,
bool PreserveCFG) {
1879 RewriteableMemOps
Ops;
1882 for (User *U :
SI.users()) {
1889 for (User *U :
Users) {
1892 if (
Store->isVolatile() || PreserveCFG)
1903 PossiblySpeculatableLoad
Load(LI);
1918 SelectHandSpeculativity Spec =
1920 if (PreserveCFG && !Spec.areAllSpeculatable())
1934 Value *TV =
SI.getTrueValue();
1935 Value *FV =
SI.getFalseValue();
1940 IRB.SetInsertPoint(&LI);
1944 LI.
getName() +
".sroa.speculate.cast.true");
1946 LI.
getName() +
".sroa.speculate.cast.false");
1950 LI.
getName() +
".sroa.speculate.load.true");
1953 LI.
getName() +
".sroa.speculate.load.false");
1954 NumLoadsSpeculated += 2;
1966 Value *
V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1967 LI.
getName() +
".sroa.speculated", &
SI);
1973template <
typename T>
1975 SelectHandSpeculativity
Spec, IRBuilderTy &IRB,
1982 if (
Spec.areNoneSpeculatable())
1984 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1987 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1989 if (
Spec.isSpeculatable(
true))
1995 Tail->setName(Head->
getName() +
".cont");
2000 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
2001 int SuccIdx = IsThen ? 0 : 1;
2002 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
2003 auto &CondMemOp =
cast<T>(*
I.clone());
2004 if (NewMemOpBB != Head) {
2005 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
2007 ++NumLoadsPredicated;
2009 ++NumStoresPredicated;
2011 CondMemOp.dropUBImplyingAttrsAndMetadata();
2012 ++NumLoadsSpeculated;
2014 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
2015 Value *Ptr =
SI.getOperand(1 + SuccIdx);
2018 IRB.SetInsertPoint(&CondMemOp);
2019 Ptr = IRB.CreateAddrSpaceCast(Ptr,
I.getPointerOperandType(),
2020 I.getName() + (IsThen ?
".then" :
".else") +
2022 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
2024 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
2032 I.replaceAllUsesWith(PN);
2037 SelectHandSpeculativity
Spec, IRBuilderTy &IRB,
2048 const RewriteableMemOps &
Ops,
2050 bool CFGChanged =
false;
2053 for (
const RewriteableMemOp &
Op :
Ops) {
2054 SelectHandSpeculativity
Spec;
2056 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
2059 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
2060 I = PSL.getPointer();
2061 Spec = PSL.getInt();
2063 if (
Spec.areAllSpeculatable()) {
2066 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
2070 I->eraseFromParent();
2075 SI.eraseFromParent();
2083 const Twine &NamePrefix) {
2085 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
2086 NamePrefix +
"sroa_idx");
2087 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
2088 NamePrefix +
"sroa_cast");
2103 unsigned VScale = 0) {
2113 "We can't have the same bitwidth for different int types");
2117 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
2118 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
2145 if (NewSize != OldSize)
2161 return OldAS == NewAS ||
2162 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2163 !
DL.isNonIntegralAddressSpace(NewAS) &&
2164 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2170 return !
DL.isNonIntegralPointerType(NewTy);
2174 if (!
DL.isNonIntegralPointerType(OldTy))
2197 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2198 uint64_t BeginIndex = BeginOffset / ElementSize;
2199 if (BeginIndex * ElementSize != BeginOffset ||
2202 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2203 uint64_t EndIndex = EndOffset / ElementSize;
2204 if (EndIndex * ElementSize != EndOffset ||
2208 assert(EndIndex > BeginIndex &&
"Empty vector!");
2209 uint64_t NumElements = EndIndex - BeginIndex;
2210 Type *SliceTy = (NumElements == 1)
2211 ? Ty->getElementType()
2217 Use *U = S.getUse();
2220 if (
MI->isVolatile())
2222 if (!S.isSplittable())
2230 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2237 if (LTy->isStructTy())
2239 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2240 assert(LTy->isIntegerTy());
2246 if (
SI->isVolatile())
2248 Type *STy =
SI->getValueOperand()->getType();
2252 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2272 bool HaveCommonEltTy,
Type *CommonEltTy,
2273 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2274 VectorType *CommonVecPtrTy,
unsigned VScale) {
2276 if (CandidateTys.
empty())
2283 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2287 if (!HaveCommonEltTy && HaveVecPtrTy) {
2289 CandidateTys.
clear();
2291 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2294 if (!VTy->getElementType()->isIntegerTy())
2296 VTy->getContext(), VTy->getScalarSizeInBits())));
2303 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2304 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2305 "Cannot have vector types of different sizes!");
2306 assert(RHSTy->getElementType()->isIntegerTy() &&
2307 "All non-integer types eliminated!");
2308 assert(LHSTy->getElementType()->isIntegerTy() &&
2309 "All non-integer types eliminated!");
2315 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2316 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2317 "Cannot have vector types of different sizes!");
2318 assert(RHSTy->getElementType()->isIntegerTy() &&
2319 "All non-integer types eliminated!");
2320 assert(LHSTy->getElementType()->isIntegerTy() &&
2321 "All non-integer types eliminated!");
2325 llvm::sort(CandidateTys, RankVectorTypesComp);
2326 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2327 CandidateTys.end());
2333 assert(VTy->getElementType() == CommonEltTy &&
2334 "Unaccounted for element type!");
2335 assert(VTy == CandidateTys[0] &&
2336 "Different vector types with the same element type!");
2339 CandidateTys.resize(1);
2346 std::numeric_limits<unsigned short>::max();
2352 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2356 if (ElementSize % 8)
2358 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2359 "vector size not a multiple of element size?");
2362 for (
const Slice &S :
P)
2366 for (
const Slice *S :
P.splitSliceTails())
2372 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2379 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2380 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2382 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2385 for (
Type *Ty : OtherTys) {
2388 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2391 for (
VectorType *
const VTy : CandidateTysCopy) {
2393 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2394 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2395 unsigned ElementSize =
2396 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2400 CheckCandidateType(NewVTy);
2406 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2407 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2426 Type *CommonEltTy =
nullptr;
2428 bool HaveVecPtrTy =
false;
2429 bool HaveCommonEltTy =
true;
2430 bool HaveCommonVecPtrTy =
true;
2431 auto CheckCandidateType = [&](
Type *Ty) {
2434 if (!CandidateTys.
empty()) {
2436 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2437 DL.getTypeSizeInBits(
V).getFixedValue()) {
2438 CandidateTys.
clear();
2443 Type *EltTy = VTy->getElementType();
2446 CommonEltTy = EltTy;
2447 else if (CommonEltTy != EltTy)
2448 HaveCommonEltTy =
false;
2451 HaveVecPtrTy =
true;
2452 if (!CommonVecPtrTy)
2453 CommonVecPtrTy = VTy;
2454 else if (CommonVecPtrTy != VTy)
2455 HaveCommonVecPtrTy =
false;
2461 for (
const Slice &S :
P) {
2466 Ty =
SI->getValueOperand()->getType();
2470 auto CandTy = Ty->getScalarType();
2471 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2472 S.endOffset() !=
P.endOffset())) {
2479 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2480 CheckCandidateType(Ty);
2485 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2486 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2487 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2490 CandidateTys.
clear();
2492 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2493 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2494 CommonVecPtrTy, VScale);
2505 bool &WholeAllocaOp) {
2508 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2509 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2511 Use *U = S.getUse();
2518 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2536 if (S.beginOffset() < AllocBeginOffset)
2542 WholeAllocaOp =
true;
2544 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2546 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2553 Type *ValueTy =
SI->getValueOperand()->getType();
2554 if (
SI->isVolatile())
2557 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2562 if (S.beginOffset() < AllocBeginOffset)
2568 WholeAllocaOp =
true;
2570 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2572 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2581 if (!S.isSplittable())
2598 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2604 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2622 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2624 for (
const Slice &S :
P)
2629 for (
const Slice *S :
P.splitSliceTails())
2634 return WholeAllocaOp;
2639 const Twine &Name) {
2643 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2644 "Element extends past full value");
2646 if (
DL.isBigEndian())
2647 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2648 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2650 V = IRB.CreateLShr(
V, ShAmt, Name +
".shift");
2653 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2654 "Cannot extract to a larger integer!");
2656 V = IRB.CreateTrunc(
V, Ty, Name +
".trunc");
2666 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2667 "Cannot insert a larger integer!");
2670 V = IRB.CreateZExt(
V, IntTy, Name +
".ext");
2674 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2675 "Element store outside of alloca store");
2677 if (
DL.isBigEndian())
2678 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2679 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2681 V = IRB.CreateShl(
V, ShAmt, Name +
".shift");
2685 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2686 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2687 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2689 V = IRB.CreateOr(Old,
V, Name +
".insert");
2696 unsigned EndIndex,
const Twine &Name) {
2698 unsigned NumElements = EndIndex - BeginIndex;
2699 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2701 if (NumElements == VecTy->getNumElements())
2704 if (NumElements == 1) {
2705 V = IRB.CreateExtractElement(
V, BeginIndex, Name +
".extract");
2711 V = IRB.CreateShuffleVector(
V, Mask, Name +
".extract");
2717 unsigned BeginIndex,
const Twine &Name) {
2719 assert(VecTy &&
"Can only insert a vector into a vector");
2724 V = IRB.CreateInsertElement(Old,
V, BeginIndex, Name +
".insert");
2732 assert(NumSubElements <= NumElements &&
"Too many elements!");
2733 if (NumSubElements == NumElements) {
2734 assert(
V->getType() == VecTy &&
"Vector type mismatch");
2737 unsigned EndIndex = BeginIndex + NumSubElements;
2744 Mask.reserve(NumElements);
2745 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2746 if (Idx >= BeginIndex && Idx < EndIndex)
2747 Mask.push_back(Idx - BeginIndex);
2750 V = IRB.CreateShuffleVector(
V, Mask, Name +
".expand");
2754 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2755 if (Idx >= BeginIndex && Idx < EndIndex)
2756 Mask.push_back(Idx);
2758 Mask.push_back(Idx + NumElements);
2759 V = IRB.CreateShuffleVector(
V, Old, Mask, Name +
"blend");
2798 const char *DebugName) {
2799 Type *EltType = VecType->getElementType();
2800 if (EltType != NewAIEltTy) {
2802 unsigned TotalBits =
2803 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2804 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2807 V = Builder.CreateBitCast(
V, NewVecType);
2808 VecType = NewVecType;
2813 BitcastIfNeeded(V0, VecType0,
"V0");
2814 BitcastIfNeeded(
V1, VecType1,
"V1");
2816 unsigned NumElts0 = VecType0->getNumElements();
2817 unsigned NumElts1 = VecType1->getNumElements();
2821 if (NumElts0 == NumElts1) {
2822 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2823 ShuffleMask.push_back(i);
2827 unsigned SmallSize = std::min(NumElts0, NumElts1);
2828 unsigned LargeSize = std::max(NumElts0, NumElts1);
2829 bool IsV0Smaller = NumElts0 < NumElts1;
2830 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2832 for (
unsigned i = 0; i < SmallSize; ++i)
2834 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2836 ExtendedVec = Builder.CreateShuffleVector(
2838 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2839 for (
unsigned i = 0; i < NumElts0; ++i)
2840 ShuffleMask.push_back(i);
2841 for (
unsigned i = 0; i < NumElts1; ++i)
2842 ShuffleMask.push_back(LargeSize + i);
2845 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2856class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2858 friend class InstVisitor<AllocaSliceRewriter, bool>;
2860 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2862 const DataLayout &
DL;
2865 AllocaInst &OldAI, &NewAI;
2866 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2895 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2898 bool IsSplittable =
false;
2899 bool IsSplit =
false;
2900 Use *OldUse =
nullptr;
2904 SmallSetVector<PHINode *, 8> &PHIUsers;
2905 SmallSetVector<SelectInst *, 8> &SelectUsers;
2913 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2917 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2918 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2922 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2923 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2925 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2926 VectorType *PromotableVecTy,
2927 SmallSetVector<PHINode *, 8> &PHIUsers,
2928 SmallSetVector<SelectInst *, 8> &SelectUsers)
2929 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2930 NewAllocaBeginOffset(NewAllocaBeginOffset),
2931 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2932 IntTy(IsIntegerPromotable
2935 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2937 VecTy(PromotableVecTy),
2938 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2939 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2941 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2942 IRB(*NewAI.getModule(), ConstantFolder()) {
2944 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2945 "Only multiple-of-8 sized vector elements are viable");
2948 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2951 bool visit(AllocaSlices::const_iterator
I) {
2952 bool CanSROA =
true;
2953 BeginOffset =
I->beginOffset();
2954 EndOffset =
I->endOffset();
2955 IsSplittable =
I->isSplittable();
2957 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2958 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2963 assert(BeginOffset < NewAllocaEndOffset);
2964 assert(EndOffset > NewAllocaBeginOffset);
2965 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2966 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2968 SliceSize = NewEndOffset - NewBeginOffset;
2969 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2970 <<
") NewBegin:(" << NewBeginOffset <<
", "
2971 << NewEndOffset <<
") NewAllocaBegin:("
2972 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2974 assert(IsSplit || NewBeginOffset == BeginOffset);
2975 OldUse =
I->getUse();
2979 IRB.SetInsertPoint(OldUserI);
2980 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2982 if (!IRB.getContext().shouldDiscardValueNames())
2983 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2984 Twine(BeginOffset) +
".");
3046 std::optional<SmallVector<Value *, 4>>
3047 rewriteTreeStructuredMerge(Partition &
P) {
3049 if (
P.splitSliceTails().size() > 0)
3050 return std::nullopt;
3059 :
Store(
SI), BeginOffset(Begin), EndOffset(
End), StoredValue(Val) {}
3069 LoadInst *FullLoad =
nullptr;
3070 StoreInst *InitStore =
nullptr;
3074 Type *AllocatedEltTy =
3078 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
3085 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
3087 return FixedVecTy &&
3088 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
3089 !FixedVecTy->getElementType()->isPointerTy();
3092 for (Slice &S :
P) {
3096 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
3097 S.endOffset() == NewAllocaEndOffset);
3101 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
3102 return std::nullopt;
3107 return std::nullopt;
3111 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
3123 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
3124 SI->getValueOperand()->getType()))
3125 return std::nullopt;
3127 unsigned NumElts = StVecTy->getNumElements();
3128 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
3129 if (NumElts * EltSize % AllocatedEltTySize != 0)
3130 return std::nullopt;
3135 return std::nullopt;
3138 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
3139 SI->getValueOperand());
3144 return std::nullopt;
3151 if (StoreInfos.
size() < 2)
3152 return std::nullopt;
3160 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3161 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3162 if (!IsRMWPattern && !IsStoresOnlyPattern)
3163 return std::nullopt;
3167 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3168 for (
auto &Info : StoreInfos)
3169 if (
Info.Store->getParent() != StoreBB)
3170 return std::nullopt;
3172 SmallVector<Value *, 4> DeletedValues;
3179 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3182 while (Vals.
size() > 1) {
3183 SmallVector<Value *, 8>
Next;
3184 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3190 if (Vals.
size() % 2 == 1)
3192 Vals = std::move(
Next);
3201 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3203 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3204 Merged->getType(), &NewAI, getSliceAlign(),
3206 LoadToReplace->
getName() +
".sroa.new.load");
3208 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3213 if (IsStoresOnlyPattern) {
3216 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3217 return A.BeginOffset <
B.BeginOffset;
3222 uint64_t Expected = NewAllocaBeginOffset;
3223 for (
auto &Info : StoreInfos) {
3224 if (
Info.BeginOffset != Expected)
3225 return std::nullopt;
3226 Expected =
Info.EndOffset;
3229 if (Expected != NewAllocaEndOffset)
3230 return std::nullopt;
3240 if (LoadBB == StoreBB) {
3241 for (
auto &Info : StoreInfos)
3242 if (!
Info.Store->comesBefore(FullLoad))
3243 return std::nullopt;
3247 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3248 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3249 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3250 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3251 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3252 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3265 SmallVector<Value *, 8> Vals;
3266 for (
const auto &Info : StoreInfos) {
3271 Value *Merged = TreeMerge(Vals, Builder);
3272 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3275 ReplaceFullLoad(FullLoad, Merged);
3276 return DeletedValues;
3284 return std::nullopt;
3285 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3286 return I.Load->getParent() != StoreBB;
3288 return std::nullopt;
3304 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3305 for (
const auto &L : LoadInfos)
3306 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3307 for (
const auto &S : StoreInfos)
3308 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3310 return A.Inst->comesBefore(
B.Inst);
3318 return std::nullopt;
3324 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3325 !
Accesses.back().Inst->comesBefore(FullLoad))
3326 return std::nullopt;
3337 using SliceRange = std::pair<uint64_t, uint64_t>;
3341 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3345 uint64_t Expected = NewAllocaBeginOffset;
3346 for (
auto &
Range : SortedRanges) {
3347 if (
Range.first != Expected)
3348 return std::nullopt;
3349 Expected =
Range.second;
3351 if (Expected != NewAllocaEndOffset)
3352 return std::nullopt;
3355 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3356 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3358 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3359 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3360 for (
auto &
Range : SortedRanges)
3371 if (InitVec->
getType() != NewAllocaTy)
3372 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3373 DenseMap<SliceRange, Value *> SliceValues;
3374 for (
auto &
Range : SortedRanges) {
3375 unsigned BeginIdx = getIndex(
Range.first);
3376 unsigned EndIdx = getIndex(
Range.second);
3377 SliceValues[
Range] = IRB.CreateShuffleVector(
3393 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3396 if (
V->getType() != Acc.Inst->getType()) {
3398 V = IRB.CreateBitCast(
V, Acc.Inst->getType());
3400 Acc.Inst->replaceAllUsesWith(
V);
3417 SmallVector<Value *, 8> Vals;
3418 for (
auto &
Range : SortedRanges)
3420 Value *Merged = TreeMerge(Vals, Builder);
3421 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3426 ReplaceFullLoad(FullLoad, Merged);
3428 return DeletedValues;
3436 bool visitInstruction(Instruction &
I) {
3444 assert(IsSplit || BeginOffset == NewBeginOffset);
3447 StringRef OldName = OldPtr->
getName();
3449 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3451 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3456 OldName = OldName.
substr(IndexEnd + 1);
3460 OldName = OldName.
substr(OffsetEnd + 1);
3464 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3469 Twine(OldName) +
".");
3477 Align getSliceAlign() {
3479 NewBeginOffset - NewAllocaBeginOffset);
3483 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3485 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3486 uint32_t
Index = RelOffset / ElementSize;
3487 assert(Index * ElementSize == RelOffset);
3491 void deleteIfTriviallyDead(
Value *
V) {
3494 Pass.DeadInsts.push_back(
I);
3497 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3498 unsigned BeginIndex = getIndex(NewBeginOffset);
3499 unsigned EndIndex = getIndex(NewEndOffset);
3500 assert(EndIndex > BeginIndex &&
"Empty vector!");
3503 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3505 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3506 LLVMContext::MD_access_group});
3510 Value *rewriteIntegerLoad(LoadInst &LI) {
3511 assert(IntTy &&
"We cannot insert an integer to the alloca");
3514 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3515 V = IRB.CreateBitPreservingCastChain(
DL,
V, IntTy);
3516 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3518 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3519 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3528 "Can only handle an extract for an overly wide load");
3534 bool visitLoadInst(LoadInst &LI) {
3543 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3545 bool IsPtrAdjusted =
false;
3548 V = rewriteVectorizedLoadInst(LI);
3550 V = rewriteIntegerLoad(LI);
3551 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3552 NewEndOffset == NewAllocaEndOffset &&
3555 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3558 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3559 LoadInst *NewLI = IRB.CreateAlignedLoad(
3560 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3561 if (LI.isVolatile())
3562 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3563 if (NewLI->isAtomic())
3564 NewLI->setAlignment(LI.getAlign());
3569 copyMetadataForLoad(*NewLI, LI);
3573 NewLI->setAAMetadata(AATags.adjustForAccess(
3574 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3582 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3583 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3584 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3585 V = IRB.CreateZExt(V, TITy,
"load.ext");
3586 if (DL.isBigEndian())
3587 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3591 Type *LTy = IRB.getPtrTy(AS);
3593 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3598 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3602 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3603 LLVMContext::MD_access_group});
3606 IsPtrAdjusted =
true;
3608 V = IRB.CreateBitPreservingCastChain(
DL,
V, TargetTy);
3613 "Only integer type loads and stores are split");
3614 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3615 "Split load isn't smaller than original load");
3617 "Non-byte-multiple bit width");
3623 LIIt.setHeadBit(
true);
3624 IRB.SetInsertPoint(LIIt);
3629 Value *Placeholder =
3635 Placeholder->replaceAllUsesWith(&LI);
3636 Placeholder->deleteValue();
3641 Pass.DeadInsts.push_back(&LI);
3642 deleteIfTriviallyDead(OldOp);
3647 bool rewriteVectorizedStoreInst(
Value *
V, StoreInst &SI,
Value *OldOp,
3652 if (
V->getType() != VecTy) {
3653 unsigned BeginIndex = getIndex(NewBeginOffset);
3654 unsigned EndIndex = getIndex(NewEndOffset);
3655 assert(EndIndex > BeginIndex &&
"Empty vector!");
3656 unsigned NumElements = EndIndex - BeginIndex;
3658 "Too many elements!");
3659 Type *SliceTy = (NumElements == 1)
3661 : FixedVectorType::
get(ElementTy, NumElements);
3662 if (
V->getType() != SliceTy)
3663 V = IRB.CreateBitPreservingCastChain(
DL,
V, SliceTy);
3667 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3670 StoreInst *
Store = IRB.CreateAlignedStore(
V, &NewAI, NewAI.
getAlign());
3671 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3672 LLVMContext::MD_access_group});
3676 Pass.DeadInsts.push_back(&SI);
3685 bool rewriteIntegerStore(
Value *
V, StoreInst &SI, AAMDNodes AATags) {
3686 assert(IntTy &&
"We cannot extract an integer from the alloca");
3688 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3690 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3692 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3693 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3697 V = IRB.CreateBitPreservingCastChain(
DL,
V, NewAllocaTy);
3698 StoreInst *
Store = IRB.CreateAlignedStore(
V, &NewAI, NewAI.
getAlign());
3699 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3700 LLVMContext::MD_access_group});
3707 Store->getValueOperand(),
DL);
3709 Pass.DeadInsts.push_back(&SI);
3714 bool visitStoreInst(StoreInst &SI) {
3716 Value *OldOp =
SI.getOperand(1);
3719 AAMDNodes AATags =
SI.getAAMetadata();
3724 if (
V->getType()->isPointerTy())
3726 Pass.PostPromotionWorklist.insert(AI);
3728 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3731 assert(
V->getType()->isIntegerTy() &&
3732 "Only integer type loads and stores are split");
3733 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3734 "Non-byte-multiple bit width");
3735 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3741 return rewriteVectorizedStoreInst(
V, SI, OldOp, AATags);
3742 if (IntTy &&
V->getType()->isIntegerTy())
3743 return rewriteIntegerStore(
V, SI, AATags);
3746 if (NewBeginOffset == NewAllocaBeginOffset &&
3747 NewEndOffset == NewAllocaEndOffset &&
3749 V = IRB.CreateBitPreservingCastChain(
DL,
V, NewAllocaTy);
3751 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3754 IRB.CreateAlignedStore(
V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3756 unsigned AS =
SI.getPointerAddressSpace();
3757 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3759 IRB.CreateAlignedStore(
V, NewPtr, getSliceAlign(),
SI.isVolatile());
3761 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3762 LLVMContext::MD_access_group});
3766 if (
SI.isVolatile())
3775 Pass.DeadInsts.push_back(&SI);
3776 deleteIfTriviallyDead(OldOp);
3794 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3802 IRB.CreateZExt(
V, SplatIntTy,
"zext"),
3812 V = IRB.CreateVectorSplat(NumElements,
V,
"vsplat");
3817 bool visitMemSetInst(MemSetInst &
II) {
3821 AAMDNodes AATags =
II.getAAMetadata();
3827 assert(NewBeginOffset == BeginOffset);
3828 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3829 II.setDestAlignment(getSliceAlign());
3834 "AT: Unexpected link to non-const GEP");
3835 deleteIfTriviallyDead(OldPtr);
3840 Pass.DeadInsts.push_back(&
II);
3844 const bool CanContinue = [&]() {
3847 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3852 if (Len > std::numeric_limits<unsigned>::max())
3854 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3857 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3863 Type *SizeTy =
II.getLength()->getType();
3864 unsigned Sz = NewEndOffset - NewBeginOffset;
3867 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3868 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3874 New,
New->getRawDest(),
nullptr,
DL);
3889 assert(ElementTy == ScalarTy);
3891 unsigned BeginIndex = getIndex(NewBeginOffset);
3892 unsigned EndIndex = getIndex(NewEndOffset);
3893 assert(EndIndex > BeginIndex &&
"Empty vector!");
3894 unsigned NumElements = EndIndex - BeginIndex;
3896 "Too many elements!");
3899 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3900 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3901 if (NumElements > 1)
3904 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3913 V = getIntegerSplat(
II.getValue(),
Size);
3915 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3916 NewEndOffset != NewAllocaEndOffset)) {
3917 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3919 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3923 assert(
V->getType() == IntTy &&
3924 "Wrong type for an alloca wide integer!");
3926 V = IRB.CreateBitPreservingCastChain(
DL,
V, NewAllocaTy);
3929 assert(NewBeginOffset == NewAllocaBeginOffset);
3930 assert(NewEndOffset == NewAllocaEndOffset);
3932 V = getIntegerSplat(
II.getValue(),
3933 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3938 V = IRB.CreateBitPreservingCastChain(
DL,
V, NewAllocaTy);
3941 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3943 IRB.CreateAlignedStore(
V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3944 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3945 LLVMContext::MD_access_group});
3951 New,
New->getPointerOperand(),
V,
DL);
3954 return !
II.isVolatile();
3957 bool visitMemTransferInst(MemTransferInst &
II) {
3963 AAMDNodes AATags =
II.getAAMetadata();
3965 bool IsDest = &
II.getRawDestUse() == OldUse;
3966 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3967 (!IsDest &&
II.getRawSource() == OldPtr));
3969 Align SliceAlign = getSliceAlign();
3977 if (!IsSplittable) {
3978 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3983 DbgAssign->getAddress() ==
II.getDest())
3984 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3986 II.setDest(AdjustedPtr);
3987 II.setDestAlignment(SliceAlign);
3989 II.setSource(AdjustedPtr);
3990 II.setSourceAlignment(SliceAlign);
3994 deleteIfTriviallyDead(OldPtr);
4007 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
4008 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
4009 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
4015 if (EmitMemCpy && &OldAI == &NewAI) {
4017 assert(NewBeginOffset == BeginOffset);
4020 if (NewEndOffset != EndOffset)
4021 II.setLength(NewEndOffset - NewBeginOffset);
4025 Pass.DeadInsts.push_back(&
II);
4029 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
4030 if (AllocaInst *AI =
4032 assert(AI != &OldAI && AI != &NewAI &&
4033 "Splittable transfers cannot reach the same alloca on both ends.");
4034 Pass.Worklist.insert(AI);
4041 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
4042 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
4044 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
4046 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
4054 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4055 Type *SizeTy =
II.getLength()->getType();
4056 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
4058 Value *DestPtr, *SrcPtr;
4059 MaybeAlign DestAlign, SrcAlign;
4063 DestAlign = SliceAlign;
4065 SrcAlign = OtherAlign;
4068 DestAlign = OtherAlign;
4070 SrcAlign = SliceAlign;
4072 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
4075 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
4080 &
II, New, DestPtr,
nullptr,
DL);
4085 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
4091 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
4092 NewEndOffset == NewAllocaEndOffset;
4094 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
4095 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
4096 unsigned NumElements = EndIndex - BeginIndex;
4097 IntegerType *SubIntTy =
4098 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
4103 if (VecTy && !IsWholeAlloca) {
4104 if (NumElements == 1)
4105 OtherTy = VecTy->getElementType();
4108 }
else if (IntTy && !IsWholeAlloca) {
4111 OtherTy = NewAllocaTy;
4116 MaybeAlign SrcAlign = OtherAlign;
4117 MaybeAlign DstAlign = SliceAlign;
4125 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
4129 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
4133 if (VecTy && !IsWholeAlloca && !IsDest) {
4135 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4137 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
4139 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4140 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
4144 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
4145 II.isVolatile(),
"copyload");
4146 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4147 LLVMContext::MD_access_group});
4154 if (VecTy && !IsWholeAlloca && IsDest) {
4155 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4158 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4159 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4161 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4164 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4168 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4169 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4170 LLVMContext::MD_access_group});
4173 Src->getType(),
DL));
4188 return !
II.isVolatile();
4191 bool visitIntrinsicInst(IntrinsicInst &
II) {
4192 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4193 "Unexpected intrinsic!");
4197 Pass.DeadInsts.push_back(&
II);
4199 if (
II.isDroppable()) {
4200 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4206 assert(
II.getArgOperand(0) == OldPtr);
4210 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4211 New = IRB.CreateLifetimeStart(Ptr);
4213 New = IRB.CreateLifetimeEnd(Ptr);
4221 void fixLoadStoreAlign(Instruction &Root) {
4225 SmallPtrSet<Instruction *, 4> Visited;
4226 SmallVector<Instruction *, 4>
Uses;
4228 Uses.push_back(&Root);
4237 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4244 for (User *U :
I->users())
4247 }
while (!
Uses.empty());
4250 bool visitPHINode(PHINode &PN) {
4252 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4253 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4259 IRBuilderBase::InsertPointGuard Guard(IRB);
4261 IRB.SetInsertPoint(OldPtr->
getParent()->getFirstInsertionPt());
4263 IRB.SetInsertPoint(OldPtr);
4264 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4266 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4271 deleteIfTriviallyDead(OldPtr);
4274 fixLoadStoreAlign(PN);
4283 bool visitSelectInst(SelectInst &SI) {
4285 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4286 "Pointer isn't an operand!");
4287 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4288 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4290 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4292 if (
SI.getOperand(1) == OldPtr)
4293 SI.setOperand(1, NewPtr);
4294 if (
SI.getOperand(2) == OldPtr)
4295 SI.setOperand(2, NewPtr);
4298 deleteIfTriviallyDead(OldPtr);
4301 fixLoadStoreAlign(SI);
4316class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4318 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4324 SmallPtrSet<User *, 8> Visited;
4331 const DataLayout &
DL;
4336 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4337 :
DL(
DL), IRB(IRB) {}
4341 bool rewrite(Instruction &
I) {
4345 while (!
Queue.empty()) {
4346 U =
Queue.pop_back_val();
4355 void enqueueUsers(Instruction &
I) {
4356 for (Use &U :
I.uses())
4357 if (Visited.
insert(
U.getUser()).second)
4358 Queue.push_back(&U);
4362 bool visitInstruction(Instruction &
I) {
return false; }
4365 template <
typename Derived>
class OpSplitter {
4372 SmallVector<unsigned, 4> Indices;
4376 SmallVector<Value *, 4> GEPIndices;
4390 const DataLayout &
DL;
4394 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4395 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4396 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4397 BaseAlign(BaseAlign),
DL(
DL) {
4398 IRB.SetInsertPoint(InsertionPoint);
4415 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4417 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4418 return static_cast<Derived *
>(
this)->emitFunc(
4423 unsigned OldSize = Indices.
size();
4425 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4427 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4429 GEPIndices.
push_back(IRB.getInt32(Idx));
4430 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4438 unsigned OldSize = Indices.
size();
4440 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4442 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4444 GEPIndices.
push_back(IRB.getInt32(Idx));
4445 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4456 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4460 SmallVector<Value *, 4> Components;
4465 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4466 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4468 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4474 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4478 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4480 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4486 Load->setAAMetadata(
4492 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4497 void recordFakeUses(LoadInst &LI) {
4498 for (Use &U : LI.
uses())
4500 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4506 void emitFakeUses() {
4507 for (Instruction *
I : FakeUses) {
4508 IRB.SetInsertPoint(
I);
4509 for (
auto *
V : Components)
4510 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4511 I->eraseFromParent();
4516 bool visitLoadInst(LoadInst &LI) {
4525 Splitter.recordFakeUses(LI);
4528 Splitter.emitFakeUses();
4535 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4536 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4537 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4538 const DataLayout &
DL, IRBuilderTy &IRB)
4539 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4541 AATags(AATags), AggStore(AggStore) {}
4543 StoreInst *AggStore;
4546 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4552 Value *ExtractValue =
4553 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4554 Value *InBoundsGEP =
4555 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4557 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4574 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4576 SizeInBits, AggStore,
Store,
4577 Store->getPointerOperand(),
Store->getValueOperand(),
4581 "AT: unexpected debug.assign linked to store through "
4588 bool visitStoreInst(StoreInst &SI) {
4589 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4592 if (
V->getType()->isSingleValueType())
4597 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4599 Splitter.emitSplitOps(
V->getType(),
V,
V->getName() +
".fca");
4604 SI.eraseFromParent();
4608 bool visitBitCastInst(BitCastInst &BC) {
4613 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4623 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4642 if (!ZI->getSrcTy()->isIntegerTy(1))
4655 dbgs() <<
" original: " << *Sel <<
"\n";
4656 dbgs() <<
" " << GEPI <<
"\n";);
4658 auto GetNewOps = [&](
Value *SelOp) {
4671 Cond =
SI->getCondition();
4672 True =
SI->getTrueValue();
4676 Cond = Sel->getOperand(0);
4677 True = ConstantInt::get(Sel->getType(), 1);
4678 False = ConstantInt::get(Sel->getType(), 0);
4683 IRB.SetInsertPoint(&GEPI);
4687 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4688 True->getName() +
".sroa.gep", NW);
4691 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4692 False->getName() +
".sroa.gep", NW);
4694 Value *NSel = MDFrom
4695 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4696 Sel->getName() +
".sroa.sel", MDFrom)
4697 : IRB.CreateSelectWithUnknownProfile(
4699 Sel->getName() +
".sroa.sel");
4700 Visited.
erase(&GEPI);
4705 enqueueUsers(*NSelI);
4708 dbgs() <<
" " << *NFalse <<
"\n";
4709 dbgs() <<
" " << *NSel <<
"\n";);
4718 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4723 auto IsInvalidPointerOperand = [](
Value *
V) {
4727 return !AI->isStaticAlloca();
4731 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4746 [](
Value *
V) { return isa<ConstantInt>(V); }))
4759 dbgs() <<
" original: " << *
Phi <<
"\n";
4760 dbgs() <<
" " << GEPI <<
"\n";);
4762 auto GetNewOps = [&](
Value *PhiOp) {
4772 IRB.SetInsertPoint(Phi);
4773 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4774 Phi->getName() +
".sroa.phi");
4780 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4789 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4795 Visited.
erase(&GEPI);
4799 enqueueUsers(*NewPhi);
4805 dbgs() <<
"\n " << *NewPhi <<
'\n');
4810 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4811 if (unfoldGEPSelect(GEPI))
4814 if (unfoldGEPPhi(GEPI))
4821 bool visitPHINode(PHINode &PN) {
4826 bool visitSelectInst(SelectInst &SI) {
4840 if (Ty->isSingleValueType())
4843 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4848 InnerTy = ArrTy->getElementType();
4852 InnerTy = STy->getElementType(Index);
4857 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4858 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4879 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4881 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4882 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4889 ElementTy = AT->getElementType();
4890 TyNumElements = AT->getNumElements();
4895 ElementTy = VT->getElementType();
4896 TyNumElements = VT->getNumElements();
4898 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4900 if (NumSkippedElements >= TyNumElements)
4902 Offset -= NumSkippedElements * ElementSize;
4914 if (
Size == ElementSize)
4918 if (NumElements * ElementSize !=
Size)
4942 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4943 if (
Offset >= ElementSize)
4954 if (
Size == ElementSize)
4961 if (Index == EndIndex)
4971 assert(Index < EndIndex);
4996 const std::vector<uint64_t> &Splits;
5003 std::vector<uint64_t> &Splits,
unsigned SliceSize)
5004 : IRB(IRB), DL(DL), Splits(Splits), SliceSize(SliceSize) {}
5014 Idx = IsEnd ?
SS.Splits.size() + 1 : 0;
5019 uint64_t NextOffset =
5020 Idx <
SS.Splits.size() ?
SS.Splits[
Idx] :
SS.SliceSize;
5036 Type *PartPtrTy = BasePtr->getType();
5038 LoadInst *PLoad = IRB.CreateAlignedLoad(
5042 PartPtrTy, BasePtr->getName() +
"."),
5045 PLoad->
copyMetadata(*SplitI, {LLVMContext::MD_mem_parallel_loop_access,
5046 LLVMContext::MD_access_group});
5052 Type *PartPtrTy = BasePtr->getType();
5054 StoreInst *PStore = IRB.CreateAlignedStore(
5058 PartPtrTy, BasePtr->getName() +
"."),
5061 PStore->
copyMetadata(*SplitI, {LLVMContext::MD_mem_parallel_loop_access,
5062 LLVMContext::MD_access_group,
5063 LLVMContext::MD_DIAssignID});
5073 unsigned PtrIdx = 0;
5077 PtrIdx =
SI->getPointerOperandIndex();
5084 &
I->getOperandUse(PtrIdx),
false);
5086 << S.endOffset() <<
"): " << *
I <<
"\n");
5097 InstructionSliceMap &SliceMap) {
5099 if (S.endOffset() - S.beginOffset() == 1)
5117 for (Slice *JS : SliceMap[J]) {
5118 if (S.beginOffset() > JS->beginOffset() &&
5119 S.beginOffset() < JS->endOffset())
5121 if (JS->beginOffset() > S.beginOffset() &&
5122 JS->beginOffset() < S.endOffset())
5153bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
5167 struct SplitOffsets {
5169 std::vector<uint64_t> Splits;
5171 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
5184 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
5186 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
5187 for (
auto &
P : AS.partitions()) {
5188 InstructionSliceMap SliceMap;
5189 for (Slice &S :
P) {
5192 for (Slice &S :
P) {
5194 bool ExtendsPastPartitionEnd = S.endOffset() >
P.endOffset();
5196 if (!S.isSplittable() || (!ExtendsPastPartitionEnd && !CopyOverlap)) {
5201 UnsplittableLoads.
insert(LI);
5204 UnsplittableLoads.
insert(LI);
5207 assert(
P.endOffset() > S.beginOffset() &&
5208 "Empty or backwards partition!");
5217 auto IsLoadSimplyStored = [](LoadInst *LI) {
5218 for (User *LU : LI->
users()) {
5220 if (!SI || !
SI->isSimple())
5225 if (!IsLoadSimplyStored(LI)) {
5226 UnsplittableLoads.
insert(LI);
5232 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
5236 if (!StoredLoad || !StoredLoad->isSimple())
5238 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
5248 auto &
Offsets = SplitOffsetsMap[
I];
5250 "Should not have splits the first time we see an instruction!");
5265 std::max(S.beginOffset(), CopyOverlap->beginOffset());
5266 uint64_t OverlapEnd = std::min(S.endOffset(), CopyOverlap->endOffset());
5267 uint64_t OverlapSize = OverlapEnd - OverlapStart;
5268 uint64_t SliceSize = S.endOffset() - S.beginOffset();
5269 uint64_t NonOverlapSize = SliceSize - OverlapSize;
5270 if (OverlapSize < NonOverlapSize) {
5275 Offsets.Splits.push_back(OverlapSize);
5276 Offsets.Splits.push_back(SliceSize - OverlapSize);
5277 }
else if (OverlapSize > NonOverlapSize) {
5280 for (
uint64_t Split = NonOverlapSize;
Split <= SliceSize / 2;
5281 Split += NonOverlapSize) {
5282 Offsets.Splits.push_back(Split);
5283 if (Split != SliceSize - Split) {
5284 Offsets.Splits.push_back(SliceSize - Split);
5292 Offsets.Splits.push_back(OverlapSize);
5295 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
5304 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5310 if (UnsplittableLoads.
count(LI))
5313 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5314 if (LoadOffsetsI == SplitOffsetsMap.
end())
5316 auto &LoadOffsets = LoadOffsetsI->second;
5319 auto &StoreOffsets = SplitOffsetsMap[
SI];
5324 if (LoadOffsets.Splits == StoreOffsets.Splits)
5328 <<
" " << *LI <<
"\n"
5329 <<
" " << *SI <<
"\n");
5335 UnsplittableLoads.
insert(LI);
5344 return UnsplittableLoads.
count(LI);
5349 return UnsplittableLoads.
count(LI);
5359 IRBuilderTy IRB(&AI);
5366 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5376 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5377 std::vector<LoadInst *> SplitLoads;
5378 const DataLayout &
DL = AI.getDataLayout();
5379 for (LoadInst *LI : Loads) {
5382 auto &
Offsets = SplitOffsetsMap[LI];
5383 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5385 "Load must have type size equal to store size");
5387 "Load must be >= slice size");
5390 assert(BaseOffset + SliceSize > BaseOffset &&
5391 "Cannot represent alloca access size using 64-bit integers!");
5394 IRB.SetInsertPoint(LI);
5398 SliceSplitter Splitter(IRB,
DL,
Offsets.Splits, SliceSize);
5399 for (
auto Part : Splitter) {
5400 LoadInst *PLoad = Splitter.createLoad(BasePtr, Part, LI);
5404 SplitLoads.push_back(PLoad);
5407 NewSlices.
push_back(Splitter.createSlice(PLoad, BaseOffset, Part));
5413 bool DeferredStores =
false;
5414 for (User *LU : LI->
users()) {
5416 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5417 DeferredStores =
true;
5423 Value *StoreBasePtr =
SI->getPointerOperand();
5424 IRB.SetInsertPoint(SI);
5426 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5428 for (
auto Part : Splitter) {
5429 LoadInst *PLoad = SplitLoads[Part.Idx];
5430 StoreInst *PStore = Splitter.createStore(PLoad, StoreBasePtr, Part, SI);
5441 ResplitPromotableAllocas.
insert(OtherAI);
5442 Worklist.insert(OtherAI);
5445 Worklist.insert(OtherAI);
5449 DeadInsts.push_back(SI);
5454 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5457 DeadInsts.push_back(LI);
5466 for (StoreInst *SI : Stores) {
5471 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5475 "Slice size should always match load size exactly!");
5477 assert(BaseOffset + StoreSize > BaseOffset &&
5478 "Cannot represent alloca access size using 64-bit integers!");
5486 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5487 std::vector<LoadInst *> *SplitLoads =
nullptr;
5488 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5489 SplitLoads = &SplitLoadsMapI->second;
5491 "Too few split loads for the number of splits in the store!");
5496 SliceSplitter Splitter(IRB,
DL,
Offsets.Splits, StoreSize);
5497 for (
auto Part : Splitter) {
5501 PLoad = (*SplitLoads)[Part.Idx];
5503 IRB.SetInsertPoint(LI);
5504 PLoad = Splitter.createLoad(LoadBasePtr, Part, LI);
5508 IRB.SetInsertPoint(SI);
5509 StoreInst *PStore = Splitter.createStore(PLoad, StoreBasePtr, Part, SI);
5512 NewSlices.
push_back(Splitter.createSlice(PStore, BaseOffset, Part));
5525 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5526 ResplitPromotableAllocas.
insert(OtherAI);
5527 Worklist.insert(OtherAI);
5530 assert(StrippedAI != &AI &&
"We can't re-split our own alloca!");
5531 Worklist.insert(StrippedAI);
5546 DeadInsts.push_back(LI);
5548 DeadInsts.push_back(SI);
5557 AS.insert(NewSlices);
5561 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5567 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5604 bool IsIntegralPointerTy =
5605 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5607 !IsIntegralPointerTy)
5614 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5618 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5619 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5622 if (StructSize != VectorSize)
5625 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5628 auto *U = S.getUse();
5632 for (
const Slice &S :
P)
5633 if (!IsIgnorableOrMemIntrinsicSlice(S))
5636 for (
const Slice *S :
P.splitSliceTails())
5637 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5654static std::tuple<Type *, bool, VectorType *>
5658 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5660 dbgs() <<
"selectPartitionType path=" << Path
5665 dbgs() <<
"<unnamed>";
5666 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5667 <<
") size=" <<
P.size();
5669 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5671 dbgs() <<
" chosen=" << *SelectedTy;
5673 dbgs() <<
" vec=" << *SelectedVecTy;
5674 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5692 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5693 VecTy->getElementCount().getFixedValue() > 1) {
5694 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5695 return {VecTy,
false, VecTy};
5700 auto [CommonUseTy, LargestIntTy] =
5703 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5709 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5710 return {VecTy,
false, VecTy};
5713 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5714 return {CommonUseTy, IntWiden,
nullptr};
5721 P.beginOffset(),
P.size())) {
5725 if (TypePartitionTy->isArrayTy() &&
5726 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5727 DL.isLegalInteger(
P.size() * 8))
5731 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5732 return {TypePartitionTy,
true,
nullptr};
5735 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5736 return {VecTy,
false, VecTy};
5741 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5743 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5744 return {LargestIntTy,
true,
nullptr};
5749 if (AggregateToVector) {
5752 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5753 return {VTy,
false,
nullptr};
5759 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5760 return {TypePartitionTy,
false,
nullptr};
5765 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5766 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5767 return {LargestIntTy,
false,
nullptr};
5771 if (
DL.isLegalInteger(
P.size() * 8)) {
5773 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5774 return {IntTy,
false,
nullptr};
5779 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5780 return {ArrayTy,
false,
nullptr};
5793std::pair<AllocaInst *, uint64_t>
5794SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5795 const DataLayout &
DL = AI.getDataLayout();
5797 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5807 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5816 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5817 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5825 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5826 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5831 unsigned PPWOldSize = PostPromotionWorklist.size();
5832 unsigned NumUses = 0;
5833 SmallSetVector<PHINode *, 8> PHIUsers;
5834 SmallSetVector<SelectInst *, 8> SelectUsers;
5837 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5838 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5839 bool Promotable =
true;
5841 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5842 NumUses += DeletedValues->
size() + 1;
5843 for (
Value *
V : *DeletedValues)
5844 DeadInsts.push_back(
V);
5846 for (Slice *S :
P.splitSliceTails()) {
5850 for (Slice &S :
P) {
5856 NumAllocaPartitionUses += NumUses;
5857 MaxUsesPerAllocaPartition.updateMax(NumUses);
5863 for (PHINode *
PHI : PHIUsers) {
5874 SelectUsers.
clear();
5879 NewSelectsToRewrite;
5881 for (SelectInst *Sel : SelectUsers) {
5882 std::optional<RewriteableMemOps>
Ops =
5883 isSafeSelectToSpeculateOrPredicate(*Sel, PreserveCFG);
5892 for (Use *U : AS.getDeadUsesIfPromotable()) {
5894 Value::dropDroppableUse(*U);
5897 DeadInsts.push_back(OldInst);
5899 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5900 SelectUsers.empty()) {
5902 PromotableAllocas.insert(NewAI);
5907 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5908 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5909 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5910 NewSelectsToRewrite.
size());
5912 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5913 std::make_move_iterator(NewSelectsToRewrite.
end())))
5914 SelectsToRewrite.insert(std::move(KV));
5915 Worklist.insert(NewAI);
5919 while (PostPromotionWorklist.size() > PPWOldSize)
5920 PostPromotionWorklist.pop_back();
5925 return {
nullptr, 0};
5930 Worklist.insert(NewAI);
5933 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5977 int64_t BitExtractOffset) {
5979 bool HasFragment =
false;
5980 bool HasBitExtract =
false;
5988 HasBitExtract =
true;
5989 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5990 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5999 assert(BitExtractOffset <= 0);
6000 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
6006 if (AdjustedOffset < 0)
6009 Ops.push_back(
Op.getOp());
6010 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
6011 Ops.push_back(ExtractSizeInBits);
6014 Op.appendToVector(
Ops);
6019 if (HasFragment && HasBitExtract)
6022 if (!HasBitExtract) {
6041 std::optional<DIExpression::FragmentInfo> NewFragment,
6042 int64_t BitExtractAdjustment) {
6052 BitExtractAdjustment);
6053 if (!NewFragmentExpr)
6059 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6072 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6078 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
6086 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
6092bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
6093 if (AS.begin() == AS.end())
6096 unsigned NumPartitions = 0;
6098 const DataLayout &
DL = AI.getDataLayout();
6101 Changed |= presplitLoadsAndStores(AI, AS);
6109 bool IsSorted =
true;
6111 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
6119 SparseBitVector<> SplittableOffset;
6121 for (Slice &S : AS) {
6123 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
6125 if (S.beginOffset() >= CurEnd) {
6126 SplittableOffset.
set(S.beginOffset());
6129 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6130 SplittableOffset.
reset(CurEnd);
6132 CurBegin = S.beginOffset();
6136 if (S.endOffset() > CurEnd) {
6137 CurEnd = S.endOffset();
6138 SplittableOffset.
set(CurEnd);
6143 for (Slice &S : AS) {
6144 if (!S.isSplittable())
6147 if ((S.beginOffset() > AllocaSize ||
6148 SplittableOffset.
test(S.beginOffset())) &&
6149 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6154 S.makeUnsplittable();
6174 for (
auto &
P : AS.partitions()) {
6175 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6179 uint64_t SizeOfByte = 8;
6181 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6182 Fragments.push_back(
6183 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6189 NumAllocaPartitions += NumPartitions;
6190 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6194 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6199 const Value *DbgPtr = DbgVariable->getAddress();
6201 DbgVariable->getFragmentOrEntireVariable();
6204 int64_t CurrentExprOffsetInBytes = 0;
6205 SmallVector<uint64_t> PostOffsetOps;
6207 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6211 int64_t ExtractOffsetInBits = 0;
6214 ExtractOffsetInBits = Extract.getOffsetInBits();
6219 DIBuilder DIB(*AI.getModule(),
false);
6221 int64_t OffsetFromLocationInBits;
6222 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6228 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6229 NewDbgFragment, OffsetFromLocationInBits))
6235 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6240 if (!NewDbgFragment)
6241 NewDbgFragment = DbgVariable->getFragment();
6245 int64_t OffestFromNewAllocaInBits =
6246 OffsetFromLocationInBits - ExtractOffsetInBits;
6249 int64_t BitExtractOffset =
6250 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6255 OffestFromNewAllocaInBits =
6256 std::max(int64_t(0), OffestFromNewAllocaInBits);
6262 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6263 if (OffestFromNewAllocaInBits > 0) {
6264 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6270 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6271 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6272 return LHS->getVariable() ==
RHS->getVariable() &&
6273 LHS->getDebugLoc()->getInlinedAt() ==
6274 RHS->getDebugLoc()->getInlinedAt();
6276 if (SameVariableFragment(OldDII, DbgVariable))
6277 OldDII->eraseFromParent();
6282 NewDbgFragment, BitExtractOffset);
6296void SROA::clobberUse(Use &U) {
6306 DeadInsts.push_back(OldI);
6328bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6333 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6334 bool AllSameAndValid =
true;
6335 Type *PartitionType =
nullptr;
6336 SmallVector<Instruction *> Insts;
6340 auto Flush = [&]() {
6341 if (AllSameAndValid && !Insts.
empty()) {
6342 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6343 << EndOffset <<
")\n");
6345 SSAUpdater
SSA(&NewPHIs);
6347 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6348 Promoter.run(Insts);
6350 AllSameAndValid =
true;
6351 PartitionType =
nullptr;
6355 for (Slice &S : AS) {
6359 dbgs() <<
"Ignoring slice: ";
6360 AS.print(
dbgs(), &S);
6364 if (S.beginOffset() >= EndOffset) {
6366 BeginOffset = S.beginOffset();
6367 EndOffset = S.endOffset();
6368 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6369 if (AllSameAndValid) {
6371 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6372 << EndOffset <<
")";
6373 AS.print(
dbgs(), &S);
6375 AllSameAndValid =
false;
6377 EndOffset = std::max(EndOffset, S.endOffset());
6384 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6385 AllSameAndValid =
false;
6386 PartitionType = UserTy;
6389 Type *UserTy =
SI->getValueOperand()->getType();
6390 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6391 AllSameAndValid =
false;
6392 PartitionType = UserTy;
6395 AllSameAndValid =
false;
6408std::pair<
bool ,
bool >
6409SROA::runOnAlloca(AllocaInst &AI) {
6411 bool CFGChanged =
false;
6414 ++NumAllocasAnalyzed;
6417 if (AI.use_empty()) {
6418 AI.eraseFromParent();
6422 const DataLayout &
DL = AI.getDataLayout();
6425 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6426 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6431 IRBuilderTy IRB(&AI);
6432 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6433 Changed |= AggRewriter.rewrite(AI);
6436 AllocaSlices AS(
DL, AI);
6441 if (AS.isEscapedReadOnly()) {
6442 Changed |= propagateStoredValuesToLoads(AI, AS);
6447 for (Instruction *DeadUser : AS.getDeadUsers()) {
6449 for (Use &DeadOp : DeadUser->operands())
6456 DeadInsts.push_back(DeadUser);
6459 for (Use *DeadOp : AS.getDeadOperands()) {
6460 clobberUse(*DeadOp);
6465 if (AS.begin() == AS.end())
6468 Changed |= splitAlloca(AI, AS);
6471 while (!SpeculatablePHIs.empty())
6475 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6476 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6477 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6483 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6484 while (!RemainingSelectsToRewrite.empty()) {
6485 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6502bool SROA::deleteDeadInstructions(
6503 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6505 while (!DeadInsts.empty()) {
6515 DeletedAllocas.
insert(AI);
6517 OldDII->eraseFromParent();
6523 for (Use &Operand :
I->operands())
6528 DeadInsts.push_back(U);
6532 I->eraseFromParent();
6542bool SROA::promoteAllocas() {
6543 if (PromotableAllocas.empty())
6550 NumPromoted += PromotableAllocas.size();
6551 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6554 PromotableAllocas.clear();
6558std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6561 const DataLayout &
DL =
F.getDataLayout();
6566 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6568 PromotableAllocas.insert(AI);
6570 Worklist.insert(AI);
6575 bool CFGChanged =
false;
6578 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6581 while (!Worklist.empty()) {
6582 auto [IterationChanged, IterationCFGChanged] =
6583 runOnAlloca(*Worklist.pop_back_val());
6585 CFGChanged |= IterationCFGChanged;
6587 Changed |= deleteDeadInstructions(DeletedAllocas);
6591 if (!DeletedAllocas.
empty()) {
6592 Worklist.set_subtract(DeletedAllocas);
6593 PostPromotionWorklist.set_subtract(DeletedAllocas);
6594 PromotableAllocas.set_subtract(DeletedAllocas);
6595 DeletedAllocas.
clear();
6601 Worklist = PostPromotionWorklist;
6602 PostPromotionWorklist.clear();
6603 }
while (!Worklist.empty());
6605 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6606 assert((!CFGChanged || !PreserveCFG) &&
6607 "Should not have modified the CFG when told to preserve it.");
6610 for (
auto &BB :
F) {
6623 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6635 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6636 OS, MapClassName2PassName);
6640 if (Options.AggregateToVector)
6641 OS <<
";aggregate-to-vector";
6662 if (skipFunction(
F))
6665 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6667 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6673 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6680 StringRef getPassName()
const override {
return "SROA"; }
6685char SROALegacyPass::ID = 0;
6690 AggregateToVector));
6694 "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.
iv Induction Variable Users
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(Mod->getContext(), 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.
SmallVector< MachineOperand, 4 > 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 void rewriteMemOpOfSelect(SelectInst &SI, T &I, SelectHandSpeculativity Spec, IRBuilderTy &IRB, DomTreeUpdater &DTU)
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 bool rewritePHINodeStore(PHINode &PN, StoreInst &SI, DomTreeUpdater &DTU, SmallSetVector< AllocaInst *, 16 > &Worklist)
Move a store through a pointer PHI onto each of the PHI's incoming edges.
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 Slice * findOverlappingCopySlice(Slice &S, InstructionSliceMap &SliceMap)
Try to find a slice in the map that partially overlaps with S, i.e.
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 StoreInst * getPHIStoreToRewrite(PHINode &PN, bool PreserveCFG, DominatorTree &DT)
Check whether a single store through PN can be moved onto each incoming edge.
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 defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the SparseBitVector 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.
virt reg 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++()
SliceSplitter(IRBuilderTy &IRB, const DataLayout &DL, std::vector< uint64_t > &Splits, unsigned SliceSize)
StoreInst * createStore(Value *StoreVal, Value *BasePtr, Iterator &It, Instruction *SplitI)
Slice createSlice(Instruction *I, uint64_t BaseOffset, Iterator &It)
LoadInst * createLoad(Value *BasePtr, Iterator &It, Instruction *SplitI)
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.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrPseudoProbe() const
Returns an iterator to the first instruction in this block that is not a PHINode or a pseudo operatio...
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI bool canSplitPredecessors() const
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.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
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.
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.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
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...
void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
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.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
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.
bool test(unsigned Idx) const
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.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
LLVM_ABI void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static VectorType * getWithSizeAndScalar(VectorType *SizeTy, Type *EltTy)
This static method attempts to construct a VectorType with the same size-in-bits as SizeTy but with a...
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
@ 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.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
LLVM_ABI bool RemoveRedundantDbgInstrs(BasicBlock *BB)
Try to remove redundant dbg.value instructions from given basic block.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
unsigned getLoadStoreAddressSpace(const Value *I)
A helper function that returns the address space of the pointer operand of load or store instruction.
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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
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.
const ScalarOptions & getScalarOptions(const LLVMContext &C)
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)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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 > >
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ, bool IgnoreFree=false)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI Align tryEnforceAlignment(Value *V, Align PrefAlign, const DataLayout &DL)
If the specified pointer points to an object that we control, try to modify the object's alignment to...
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.
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
LLVM_ABI std::optional< Register > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
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.
@ End
Run the machine verifier once, at the end of the pipeline.
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.
An iterator which iterates over the sub-slices that we want to split the slice into.
bool operator==(const Iterator &Other) const
const Iterator & operator*() const
uint64_t getOffset() const
Iterator(SliceSplitter &SS, bool IsEnd)
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.