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");
128class AllocaSliceRewriter;
132class SelectHandSpeculativity {
133 unsigned char Storage = 0;
137 SelectHandSpeculativity() =
default;
138 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
139 bool isSpeculatable(
bool isTrueVal)
const;
140 bool areAllSpeculatable()
const;
141 bool areAnySpeculatable()
const;
142 bool areNoneSpeculatable()
const;
144 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
145 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
147static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
149using PossiblySpeculatableLoad =
152using RewriteableMemOp =
153 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
175 LLVMContext *
const C;
176 DomTreeUpdater *
const DTU;
177 AssumptionCache *
const AC;
178 const bool PreserveCFG;
179 const bool AggregateToVector;
188 SmallSetVector<AllocaInst *, 16> Worklist;
203 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
206 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
207 SmallPtrSet<AllocaInst *, 16>, 16>
215 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
222 SmallSetVector<PHINode *, 8> PHIsWithStoreToRewrite;
226 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
242 static std::optional<RewriteableMemOps>
243 isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG);
246 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
248 : C(C), DTU(DTU), AC(AC),
249 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
250 AggregateToVector(
Options.AggregateToVector) {}
253 std::pair<
bool ,
bool > runSROA(
Function &
F);
256 friend class AllocaSliceRewriter;
258 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
259 std::pair<AllocaInst *, uint64_t>
260 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
261 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
262 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
263 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
264 void clobberUse(Use &U);
265 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
266 bool promoteAllocas();
280enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
284 uint64_t NewStorageSliceOffsetInBits,
286 std::optional<DIExpression::FragmentInfo> StorageFragment,
287 std::optional<DIExpression::FragmentInfo> CurrentFragment,
291 if (StorageFragment) {
293 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
295 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
297 Target.SizeInBits = NewStorageSliceSizeInBits;
298 Target.OffsetInBits = NewStorageSliceOffsetInBits;
304 if (!CurrentFragment) {
305 if (
auto Size = Variable->getSizeInBits()) {
308 if (
Target == CurrentFragment)
315 if (!CurrentFragment || *CurrentFragment ==
Target)
321 if (
Target.startInBits() < CurrentFragment->startInBits() ||
322 Target.endInBits() > CurrentFragment->endInBits())
361 if (DVRAssignMarkerRange.empty())
367 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
369 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
381 DVR->getExpression()->getFragmentInfo();
394 auto *Expr = DbgAssign->getExpression();
395 bool SetKillLocation =
false;
398 std::optional<DIExpression::FragmentInfo> BaseFragment;
401 if (R == BaseFragments.
end())
403 BaseFragment = R->second;
405 std::optional<DIExpression::FragmentInfo> CurrentFragment =
406 Expr->getFragmentInfo();
409 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
410 BaseFragment, CurrentFragment, NewFragment);
414 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
415 if (CurrentFragment) {
420 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
433 SetKillLocation =
true;
441 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
448 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
452 NewAssign = DbgAssign;
471 Value && (DbgAssign->hasArgList() ||
472 !DbgAssign->getExpression()->isSingleLocationExpression());
489 if (NewAssign != DbgAssign) {
490 NewAssign->
moveBefore(DbgAssign->getIterator());
493 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
496 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
506 Twine getNameWithPrefix(
const Twine &Name)
const {
511 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
513 void InsertHelper(Instruction *
I,
const Twine &Name,
538 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
544 : BeginOffset(BeginOffset), EndOffset(EndOffset),
545 UseAndIsSplittable(
U, IsSplittable) {}
547 uint64_t beginOffset()
const {
return BeginOffset; }
548 uint64_t endOffset()
const {
return EndOffset; }
550 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
551 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
553 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
555 bool isDead()
const {
return getUse() ==
nullptr; }
556 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
565 if (beginOffset() <
RHS.beginOffset())
567 if (beginOffset() >
RHS.beginOffset())
569 if (isSplittable() !=
RHS.isSplittable())
570 return !isSplittable();
571 if (endOffset() >
RHS.endOffset())
578 return LHS.beginOffset() < RHSOffset;
581 return LHSOffset <
RHS.beginOffset();
585 return isSplittable() ==
RHS.isSplittable() &&
586 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
601 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
607 bool isEscaped()
const {
return PointerEscapingInstr; }
608 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
613 using range = iterator_range<iterator>;
615 iterator
begin() {
return Slices.begin(); }
616 iterator
end() {
return Slices.end(); }
619 using const_range = iterator_range<const_iterator>;
621 const_iterator
begin()
const {
return Slices.begin(); }
622 const_iterator
end()
const {
return Slices.end(); }
626 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
634 int OldSize = Slices.size();
635 Slices.append(NewSlices.
begin(), NewSlices.
end());
636 auto SliceI = Slices.begin() + OldSize;
637 std::stable_sort(SliceI, Slices.end());
638 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
647 ArrayRef<Instruction *> getDeadUsers()
const {
return DeadUsers; }
651 return DeadUseIfPromotable;
662#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
663 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
664 void printSlice(raw_ostream &OS, const_iterator
I,
665 StringRef Indent =
" ")
const;
666 void printUse(raw_ostream &OS, const_iterator
I,
667 StringRef Indent =
" ")
const;
668 void print(raw_ostream &OS)
const;
669 void dump(const_iterator
I)
const;
674 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
677 friend class AllocaSlices::SliceBuilder;
679#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
707 SmallVector<Instruction *, 8> DeadUsers;
734 friend class AllocaSlices;
735 friend class AllocaSlices::partition_iterator;
737 using iterator = AllocaSlices::iterator;
741 uint64_t BeginOffset = 0, EndOffset = 0;
751 Partition(iterator SI) : SI(SI), SJ(SI) {}
757 uint64_t beginOffset()
const {
return BeginOffset; }
762 uint64_t endOffset()
const {
return EndOffset; }
768 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
769 return EndOffset - BeginOffset;
774 bool empty()
const {
return SI == SJ; }
785 iterator
begin()
const {
return SI; }
786 iterator
end()
const {
return SJ; }
818 AllocaSlices::iterator SE;
822 uint64_t MaxSplitSliceEndOffset = 0;
826 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
838 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
839 "Cannot advance past the end of the slices!");
842 if (!
P.SplitTails.empty()) {
843 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
845 P.SplitTails.clear();
846 MaxSplitSliceEndOffset = 0;
852 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
855 return S->endOffset() == MaxSplitSliceEndOffset;
857 "Could not find the current max split slice offset!");
860 return S->endOffset() <= MaxSplitSliceEndOffset;
862 "Max split slice end offset is not actually the max!");
869 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
879 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
880 P.SplitTails.push_back(&S);
881 MaxSplitSliceEndOffset =
882 std::max(S.endOffset(), MaxSplitSliceEndOffset);
890 P.BeginOffset = P.EndOffset;
891 P.EndOffset = MaxSplitSliceEndOffset;
898 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
899 !P.SI->isSplittable()) {
900 P.BeginOffset = P.EndOffset;
901 P.EndOffset = P.SI->beginOffset();
911 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
912 P.EndOffset = P.SI->endOffset();
917 if (!P.SI->isSplittable()) {
920 assert(P.BeginOffset == P.SI->beginOffset());
924 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
925 if (!P.SJ->isSplittable())
926 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
938 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
941 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
942 P.SJ->isSplittable()) {
943 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
950 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
951 assert(!P.SJ->isSplittable());
952 P.EndOffset = P.SJ->beginOffset();
959 "End iterators don't match between compared partition iterators!");
966 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
967 assert(P.SJ == RHS.P.SJ &&
968 "Same set of slices formed two different sized partitions!");
969 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
970 "Same slice position with differently sized non-empty split "
993 return make_range(partition_iterator(begin(), end()),
994 partition_iterator(end(), end()));
1002 return SI.getOperand(1 + CI->isZero());
1003 if (
SI.getOperand(1) ==
SI.getOperand(2))
1004 return SI.getOperand(1);
1013 return PN->hasConstantValue();
1028 const uint64_t AllocSize;
1044 if (VisitedDeadInsts.
insert(&
I).second)
1049 bool IsSplittable =
false) {
1055 <<
" which has zero size or starts outside of the "
1056 << AllocSize <<
" byte alloca:\n"
1057 <<
" alloca: " << AS.AI <<
"\n"
1058 <<
" use: " <<
I <<
"\n");
1059 return markAsDead(
I);
1071 assert(AllocSize >= BeginOffset);
1072 if (
Size > AllocSize - BeginOffset) {
1074 <<
Offset <<
" to remain within the " << AllocSize
1075 <<
" byte alloca:\n"
1076 <<
" alloca: " << AS.AI <<
"\n"
1077 <<
" use: " <<
I <<
"\n");
1078 EndOffset = AllocSize;
1081 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1084 void visitBitCastInst(BitCastInst &BC) {
1086 return markAsDead(BC);
1088 return Base::visitBitCastInst(BC);
1091 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1093 return markAsDead(ASC);
1095 return Base::visitAddrSpaceCastInst(ASC);
1098 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1100 return markAsDead(GEPI);
1102 return Base::visitGetElementPtrInst(GEPI);
1105 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1116 void visitLoadInst(LoadInst &LI) {
1118 "All simple FCA loads should have been pre-split");
1123 return PI.setEscapedReadOnly(&LI);
1126 if (
Size.isScalable()) {
1129 return PI.setAborted(&LI);
1138 void visitStoreInst(StoreInst &SI) {
1139 Value *ValOp =
SI.getValueOperand();
1141 return PI.setEscapedAndAborted(&SI);
1143 return PI.setAborted(&SI);
1145 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1147 unsigned VScale =
SI.getFunction()->getVScaleValue();
1149 return PI.setAborted(&SI);
1165 <<
Offset <<
" which extends past the end of the "
1166 << AllocSize <<
" byte alloca:\n"
1167 <<
" alloca: " << AS.AI <<
"\n"
1168 <<
" use: " << SI <<
"\n");
1169 return markAsDead(SI);
1173 "All simple FCA stores should have been pre-split");
1177 void visitMemSetInst(MemSetInst &
II) {
1178 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1181 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1183 return markAsDead(
II);
1186 return PI.setAborted(&
II);
1190 : AllocSize -
Offset.getLimitedValue(),
1194 void visitMemTransferInst(MemTransferInst &
II) {
1198 return markAsDead(
II);
1202 if (VisitedDeadInsts.
count(&
II))
1206 return PI.setAborted(&
II);
1213 if (
Offset.uge(AllocSize)) {
1214 auto MTPI = MemTransferSliceMap.
find(&
II);
1215 if (MTPI != MemTransferSliceMap.
end())
1216 AS.Slices[MTPI->second].kill();
1217 return markAsDead(
II);
1225 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1227 if (!
II.isVolatile())
1228 return markAsDead(
II);
1236 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1237 std::tie(MTPI, Inserted) =
1238 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1239 unsigned PrevIdx = MTPI->second;
1241 Slice &PrevP = AS.Slices[PrevIdx];
1245 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1247 return markAsDead(
II);
1252 PrevP.makeUnsplittable();
1259 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1260 "Map index doesn't point back to a slice with this user.");
1266 void visitIntrinsicInst(IntrinsicInst &
II) {
1267 if (
II.isDroppable()) {
1268 AS.DeadUseIfPromotable.push_back(U);
1273 return PI.setAborted(&
II);
1275 if (
II.isLifetimeStartOrEnd()) {
1276 insertUse(
II,
Offset, AllocSize,
true);
1280 Base::visitIntrinsicInst(
II);
1288 SmallPtrSet<Instruction *, 4> Visited;
1298 std::tie(UsedI,
I) =
Uses.pop_back_val();
1301 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1313 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1323 if (!
GEP->hasAllZeroIndices())
1330 for (User *U :
I->users())
1333 }
while (!
Uses.empty());
1338 void visitPHINodeOrSelectInst(Instruction &
I) {
1341 return markAsDead(
I);
1347 return PI.setAborted(&
I);
1365 AS.DeadOperands.push_back(U);
1371 return PI.setAborted(&
I);
1377 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1378 return PI.setAborted(UnsafeI);
1387 if (
Offset.uge(AllocSize)) {
1388 AS.DeadOperands.push_back(U);
1395 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1397 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1400 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1402 void visitCallBase(CallBase &CB) {
1408 PI.setEscapedReadOnly(&CB);
1412 Base::visitCallBase(CB);
1416AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1418#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1421 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1423 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1424 if (PtrI.isEscaped() || PtrI.isAborted()) {
1427 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1428 : PtrI.getAbortingInst();
1429 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1432 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1434 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1441#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1443void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1444 StringRef Indent)
const {
1445 printSlice(OS,
I, Indent);
1447 printUse(OS,
I, Indent);
1450void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1451 StringRef Indent)
const {
1452 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1453 <<
" slice #" << (
I -
begin())
1454 << (
I->isSplittable() ?
" (splittable)" :
"");
1457void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1458 StringRef Indent)
const {
1459 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1462void AllocaSlices::print(raw_ostream &OS)
const {
1463 if (PointerEscapingInstr) {
1464 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1465 <<
" A pointer to this alloca escaped by:\n"
1466 <<
" " << *PointerEscapingInstr <<
"\n";
1470 if (PointerEscapingInstrReadOnly)
1471 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1473 OS <<
"Slices of alloca: " << AI <<
"\n";
1494 for (
User *U :
I.users()) {
1495 Type *UserTy =
nullptr;
1501 UserTy =
Store->getValueOperand()->getType();
1503 if (!UserTy || (Ty && Ty != UserTy))
1513static std::pair<Type *, IntegerType *>
1517 bool TyIsCommon =
true;
1522 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1523 Use *U =
I->getUse();
1526 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1529 Type *UserTy =
nullptr;
1533 UserTy =
SI->getValueOperand()->getType();
1544 if (UserITy->getBitWidth() % 8 != 0 ||
1545 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1550 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1556 if (!UserTy || (Ty && Ty != UserTy))
1562 return {TyIsCommon ? Ty :
nullptr, ITy};
1592 Type *LoadType =
nullptr;
1605 if (LoadType != LI->
getType())
1614 if (BBI->mayWriteToMemory())
1617 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1624 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1667 if (!
SI ||
SI->getPointerOperand() != &PN)
1670 if (
SI->isVolatile())
1678 Value *StoredValue =
SI->getValueOperand();
1684 if (!SeenPreds.
insert(Pred).second)
1717 IRB.SetInsertPoint(&PN);
1719 PN.
getName() +
".sroa.speculated");
1749 IRB.SetInsertPoint(TI);
1752 LoadTy, InVal, Alignment,
1753 (PN.
getName() +
".sroa.speculate.load." + Pred->getName()));
1754 ++NumLoadsSpeculated;
1756 Load->setAAMetadata(AATags);
1758 InjectedLoads[Pred] =
Load;
1770 <<
" " <<
SI <<
"\n");
1778 if (!SeenPreds.
insert(Pred).second)
1788 bool CFGChanged =
false;
1790 for (
auto [Pred, InVal] : IncomingValues) {
1792 if (Pred->getTerminator()->getNumSuccessors() != 1) {
1794 assert(StoreBB &&
"store edge was not checked for splitting");
1801 ++NumStoresPredicated;
1805 SI.eraseFromParent();
1810SelectHandSpeculativity &
1811SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1819bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1824bool SelectHandSpeculativity::areAllSpeculatable()
const {
1825 return isSpeculatable(
true) &&
1826 isSpeculatable(
false);
1829bool SelectHandSpeculativity::areAnySpeculatable()
const {
1830 return isSpeculatable(
true) ||
1831 isSpeculatable(
false);
1833bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1834 return !areAnySpeculatable();
1837static SelectHandSpeculativity
1840 SelectHandSpeculativity
Spec;
1846 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1847 else if (PreserveCFG)
1853std::optional<RewriteableMemOps>
1854SROA::isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG) {
1855 RewriteableMemOps
Ops;
1857 for (User *U :
SI.users()) {
1862 if (
Store->isVolatile() || PreserveCFG)
1875 PossiblySpeculatableLoad
Load(LI);
1885 SelectHandSpeculativity Spec =
1887 if (PreserveCFG && !Spec.areAllSpeculatable())
1901 Value *TV =
SI.getTrueValue();
1902 Value *FV =
SI.getFalseValue();
1907 IRB.SetInsertPoint(&LI);
1911 LI.
getName() +
".sroa.speculate.load.true");
1914 LI.
getName() +
".sroa.speculate.load.false");
1915 NumLoadsSpeculated += 2;
1927 Value *V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1928 LI.
getName() +
".sroa.speculated", &
SI);
1934template <
typename T>
1936 SelectHandSpeculativity
Spec,
1943 if (
Spec.areNoneSpeculatable())
1945 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1948 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1950 if (
Spec.isSpeculatable(
true))
1956 Tail->setName(Head->
getName() +
".cont");
1961 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1962 int SuccIdx = IsThen ? 0 : 1;
1963 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
1964 auto &CondMemOp =
cast<T>(*
I.clone());
1965 if (NewMemOpBB != Head) {
1966 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1968 ++NumLoadsPredicated;
1970 ++NumStoresPredicated;
1972 CondMemOp.dropUBImplyingAttrsAndMetadata();
1973 ++NumLoadsSpeculated;
1975 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
1976 Value *Ptr =
SI.getOperand(1 + SuccIdx);
1977 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
1979 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1987 I.replaceAllUsesWith(PN);
1992 SelectHandSpeculativity
Spec,
2003 const RewriteableMemOps &
Ops,
2005 bool CFGChanged =
false;
2008 for (
const RewriteableMemOp &
Op :
Ops) {
2009 SelectHandSpeculativity
Spec;
2011 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
2014 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
2015 I = PSL.getPointer();
2016 Spec = PSL.getInt();
2018 if (
Spec.areAllSpeculatable()) {
2021 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
2025 I->eraseFromParent();
2030 SI.eraseFromParent();
2038 const Twine &NamePrefix) {
2040 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
2041 NamePrefix +
"sroa_idx");
2042 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
2043 NamePrefix +
"sroa_cast");
2058 unsigned VScale = 0) {
2068 "We can't have the same bitwidth for different int types");
2072 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
2073 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
2100 if (NewSize != OldSize)
2116 return OldAS == NewAS ||
2117 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2118 !
DL.isNonIntegralAddressSpace(NewAS) &&
2119 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2125 return !
DL.isNonIntegralPointerType(NewTy);
2129 if (!
DL.isNonIntegralPointerType(OldTy))
2152 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2153 uint64_t BeginIndex = BeginOffset / ElementSize;
2154 if (BeginIndex * ElementSize != BeginOffset ||
2157 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2158 uint64_t EndIndex = EndOffset / ElementSize;
2159 if (EndIndex * ElementSize != EndOffset ||
2163 assert(EndIndex > BeginIndex &&
"Empty vector!");
2164 uint64_t NumElements = EndIndex - BeginIndex;
2165 Type *SliceTy = (NumElements == 1)
2166 ? Ty->getElementType()
2172 Use *U = S.getUse();
2175 if (
MI->isVolatile())
2177 if (!S.isSplittable())
2185 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2192 if (LTy->isStructTy())
2194 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2195 assert(LTy->isIntegerTy());
2201 if (
SI->isVolatile())
2203 Type *STy =
SI->getValueOperand()->getType();
2207 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2227 bool HaveCommonEltTy,
Type *CommonEltTy,
2228 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2229 VectorType *CommonVecPtrTy,
unsigned VScale) {
2231 if (CandidateTys.
empty())
2238 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2242 if (!HaveCommonEltTy && HaveVecPtrTy) {
2244 CandidateTys.
clear();
2246 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2249 if (!VTy->getElementType()->isIntegerTy())
2251 VTy->getContext(), VTy->getScalarSizeInBits())));
2258 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2259 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2260 "Cannot have vector types of different sizes!");
2261 assert(RHSTy->getElementType()->isIntegerTy() &&
2262 "All non-integer types eliminated!");
2263 assert(LHSTy->getElementType()->isIntegerTy() &&
2264 "All non-integer types eliminated!");
2270 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2271 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2272 "Cannot have vector types of different sizes!");
2273 assert(RHSTy->getElementType()->isIntegerTy() &&
2274 "All non-integer types eliminated!");
2275 assert(LHSTy->getElementType()->isIntegerTy() &&
2276 "All non-integer types eliminated!");
2280 llvm::sort(CandidateTys, RankVectorTypesComp);
2281 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2282 CandidateTys.end());
2288 assert(VTy->getElementType() == CommonEltTy &&
2289 "Unaccounted for element type!");
2290 assert(VTy == CandidateTys[0] &&
2291 "Different vector types with the same element type!");
2294 CandidateTys.resize(1);
2301 std::numeric_limits<unsigned short>::max();
2307 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2311 if (ElementSize % 8)
2313 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2314 "vector size not a multiple of element size?");
2317 for (
const Slice &S :
P)
2321 for (
const Slice *S :
P.splitSliceTails())
2327 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2334 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2335 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2337 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2340 for (
Type *Ty : OtherTys) {
2343 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2346 for (
VectorType *
const VTy : CandidateTysCopy) {
2348 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2349 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2350 unsigned ElementSize =
2351 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2355 CheckCandidateType(NewVTy);
2361 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2362 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2381 Type *CommonEltTy =
nullptr;
2383 bool HaveVecPtrTy =
false;
2384 bool HaveCommonEltTy =
true;
2385 bool HaveCommonVecPtrTy =
true;
2386 auto CheckCandidateType = [&](
Type *Ty) {
2389 if (!CandidateTys.
empty()) {
2391 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2392 DL.getTypeSizeInBits(V).getFixedValue()) {
2393 CandidateTys.
clear();
2398 Type *EltTy = VTy->getElementType();
2401 CommonEltTy = EltTy;
2402 else if (CommonEltTy != EltTy)
2403 HaveCommonEltTy =
false;
2406 HaveVecPtrTy =
true;
2407 if (!CommonVecPtrTy)
2408 CommonVecPtrTy = VTy;
2409 else if (CommonVecPtrTy != VTy)
2410 HaveCommonVecPtrTy =
false;
2416 for (
const Slice &S :
P) {
2421 Ty =
SI->getValueOperand()->getType();
2425 auto CandTy = Ty->getScalarType();
2426 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2427 S.endOffset() !=
P.endOffset())) {
2434 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2435 CheckCandidateType(Ty);
2440 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2441 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2442 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2445 CandidateTys.
clear();
2447 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2448 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2449 CommonVecPtrTy, VScale);
2460 bool &WholeAllocaOp) {
2463 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2464 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2466 Use *U = S.getUse();
2473 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2491 if (S.beginOffset() < AllocBeginOffset)
2497 WholeAllocaOp =
true;
2499 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2501 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2508 Type *ValueTy =
SI->getValueOperand()->getType();
2509 if (
SI->isVolatile())
2512 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2517 if (S.beginOffset() < AllocBeginOffset)
2523 WholeAllocaOp =
true;
2525 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2527 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2536 if (!S.isSplittable())
2553 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2559 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2577 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2579 for (
const Slice &S :
P)
2584 for (
const Slice *S :
P.splitSliceTails())
2589 return WholeAllocaOp;
2594 const Twine &Name) {
2598 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2599 "Element extends past full value");
2601 if (
DL.isBigEndian())
2602 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2603 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2605 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2608 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2609 "Cannot extract to a larger integer!");
2611 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2621 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2622 "Cannot insert a larger integer!");
2625 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2629 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2630 "Element store outside of alloca store");
2632 if (
DL.isBigEndian())
2633 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2634 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2636 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2640 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2641 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2642 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2644 V = IRB.CreateOr(Old, V, Name +
".insert");
2651 unsigned EndIndex,
const Twine &Name) {
2653 unsigned NumElements = EndIndex - BeginIndex;
2654 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2656 if (NumElements == VecTy->getNumElements())
2659 if (NumElements == 1) {
2660 V = IRB.CreateExtractElement(V, BeginIndex, Name +
".extract");
2666 V = IRB.CreateShuffleVector(V, Mask, Name +
".extract");
2672 unsigned BeginIndex,
const Twine &Name) {
2674 assert(VecTy &&
"Can only insert a vector into a vector");
2679 V = IRB.CreateInsertElement(Old, V, BeginIndex, Name +
".insert");
2687 assert(NumSubElements <= NumElements &&
"Too many elements!");
2688 if (NumSubElements == NumElements) {
2689 assert(V->getType() == VecTy &&
"Vector type mismatch");
2692 unsigned EndIndex = BeginIndex + NumSubElements;
2699 Mask.reserve(NumElements);
2700 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2701 if (Idx >= BeginIndex && Idx < EndIndex)
2702 Mask.push_back(Idx - BeginIndex);
2705 V = IRB.CreateShuffleVector(V, Mask, Name +
".expand");
2709 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2710 if (Idx >= BeginIndex && Idx < EndIndex)
2711 Mask.push_back(Idx);
2713 Mask.push_back(Idx + NumElements);
2714 V = IRB.CreateShuffleVector(V, Old, Mask, Name +
"blend");
2753 const char *DebugName) {
2754 Type *EltType = VecType->getElementType();
2755 if (EltType != NewAIEltTy) {
2757 unsigned TotalBits =
2758 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2759 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2762 V = Builder.CreateBitCast(V, NewVecType);
2763 VecType = NewVecType;
2764 LLVM_DEBUG(
dbgs() <<
" bitcast " << DebugName <<
": " << *V <<
"\n");
2768 BitcastIfNeeded(V0, VecType0,
"V0");
2769 BitcastIfNeeded(
V1, VecType1,
"V1");
2771 unsigned NumElts0 = VecType0->getNumElements();
2772 unsigned NumElts1 = VecType1->getNumElements();
2776 if (NumElts0 == NumElts1) {
2777 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2778 ShuffleMask.push_back(i);
2782 unsigned SmallSize = std::min(NumElts0, NumElts1);
2783 unsigned LargeSize = std::max(NumElts0, NumElts1);
2784 bool IsV0Smaller = NumElts0 < NumElts1;
2785 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2787 for (
unsigned i = 0; i < SmallSize; ++i)
2789 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2791 ExtendedVec = Builder.CreateShuffleVector(
2793 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2794 for (
unsigned i = 0; i < NumElts0; ++i)
2795 ShuffleMask.push_back(i);
2796 for (
unsigned i = 0; i < NumElts1; ++i)
2797 ShuffleMask.push_back(LargeSize + i);
2800 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2811class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2813 friend class InstVisitor<AllocaSliceRewriter, bool>;
2815 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2817 const DataLayout &
DL;
2820 AllocaInst &OldAI, &NewAI;
2821 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2850 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2853 bool IsSplittable =
false;
2854 bool IsSplit =
false;
2855 Use *OldUse =
nullptr;
2859 SmallSetVector<PHINode *, 8> &PHIUsers;
2860 SmallSetVector<SelectInst *, 8> &SelectUsers;
2868 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2872 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2873 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2877 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2878 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2880 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2881 VectorType *PromotableVecTy,
2882 SmallSetVector<PHINode *, 8> &PHIUsers,
2883 SmallSetVector<SelectInst *, 8> &SelectUsers)
2884 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2885 NewAllocaBeginOffset(NewAllocaBeginOffset),
2886 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2887 IntTy(IsIntegerPromotable
2890 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2892 VecTy(PromotableVecTy),
2893 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2894 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2896 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2899 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2900 "Only multiple-of-8 sized vector elements are viable");
2903 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2906 bool visit(AllocaSlices::const_iterator
I) {
2907 bool CanSROA =
true;
2908 BeginOffset =
I->beginOffset();
2909 EndOffset =
I->endOffset();
2910 IsSplittable =
I->isSplittable();
2912 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2913 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2918 assert(BeginOffset < NewAllocaEndOffset);
2919 assert(EndOffset > NewAllocaBeginOffset);
2920 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2921 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2923 SliceSize = NewEndOffset - NewBeginOffset;
2924 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2925 <<
") NewBegin:(" << NewBeginOffset <<
", "
2926 << NewEndOffset <<
") NewAllocaBegin:("
2927 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2929 assert(IsSplit || NewBeginOffset == BeginOffset);
2930 OldUse =
I->getUse();
2934 IRB.SetInsertPoint(OldUserI);
2935 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2937 if (!IRB.getContext().shouldDiscardValueNames())
2938 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2939 Twine(BeginOffset) +
".");
3001 std::optional<SmallVector<Value *, 4>>
3002 rewriteTreeStructuredMerge(Partition &
P) {
3004 if (
P.splitSliceTails().size() > 0)
3005 return std::nullopt;
3014 :
Store(
SI), BeginOffset(Begin), EndOffset(End), StoredValue(Val) {}
3024 LoadInst *FullLoad =
nullptr;
3025 StoreInst *InitStore =
nullptr;
3029 Type *AllocatedEltTy =
3033 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
3040 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
3042 return FixedVecTy &&
3043 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
3044 !FixedVecTy->getElementType()->isPointerTy();
3047 for (Slice &S :
P) {
3051 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
3052 S.endOffset() == NewAllocaEndOffset);
3056 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
3057 return std::nullopt;
3062 return std::nullopt;
3066 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
3078 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
3079 SI->getValueOperand()->getType()))
3080 return std::nullopt;
3082 unsigned NumElts = StVecTy->getNumElements();
3083 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
3084 if (NumElts * EltSize % AllocatedEltTySize != 0)
3085 return std::nullopt;
3090 return std::nullopt;
3093 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
3094 SI->getValueOperand());
3099 return std::nullopt;
3106 if (StoreInfos.
size() < 2)
3107 return std::nullopt;
3115 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3116 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3117 if (!IsRMWPattern && !IsStoresOnlyPattern)
3118 return std::nullopt;
3122 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3123 for (
auto &Info : StoreInfos)
3124 if (
Info.Store->getParent() != StoreBB)
3125 return std::nullopt;
3127 SmallVector<Value *, 4> DeletedValues;
3134 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3137 while (Vals.
size() > 1) {
3138 SmallVector<Value *, 8>
Next;
3139 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3145 if (Vals.
size() % 2 == 1)
3147 Vals = std::move(
Next);
3156 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3158 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3159 Merged->getType(), &NewAI, getSliceAlign(),
3161 LoadToReplace->
getName() +
".sroa.new.load");
3163 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3168 if (IsStoresOnlyPattern) {
3171 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3172 return A.BeginOffset <
B.BeginOffset;
3177 uint64_t Expected = NewAllocaBeginOffset;
3178 for (
auto &Info : StoreInfos) {
3179 if (
Info.BeginOffset != Expected)
3180 return std::nullopt;
3181 Expected =
Info.EndOffset;
3184 if (Expected != NewAllocaEndOffset)
3185 return std::nullopt;
3195 if (LoadBB == StoreBB) {
3196 for (
auto &Info : StoreInfos)
3197 if (!
Info.Store->comesBefore(FullLoad))
3198 return std::nullopt;
3202 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3203 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3204 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3205 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3206 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3207 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3220 SmallVector<Value *, 8> Vals;
3221 for (
const auto &Info : StoreInfos) {
3226 Value *Merged = TreeMerge(Vals, Builder);
3227 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3230 ReplaceFullLoad(FullLoad, Merged);
3231 return DeletedValues;
3239 return std::nullopt;
3240 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3241 return I.Load->getParent() != StoreBB;
3243 return std::nullopt;
3259 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3260 for (
const auto &L : LoadInfos)
3261 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3262 for (
const auto &S : StoreInfos)
3263 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3265 return A.Inst->comesBefore(
B.Inst);
3273 return std::nullopt;
3279 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3280 !
Accesses.back().Inst->comesBefore(FullLoad))
3281 return std::nullopt;
3292 using SliceRange = std::pair<uint64_t, uint64_t>;
3296 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3300 uint64_t Expected = NewAllocaBeginOffset;
3301 for (
auto &
Range : SortedRanges) {
3302 if (
Range.first != Expected)
3303 return std::nullopt;
3304 Expected =
Range.second;
3306 if (Expected != NewAllocaEndOffset)
3307 return std::nullopt;
3310 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3311 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3313 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3314 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3315 for (
auto &
Range : SortedRanges)
3326 if (InitVec->
getType() != NewAllocaTy)
3327 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3328 DenseMap<SliceRange, Value *> SliceValues;
3329 for (
auto &
Range : SortedRanges) {
3330 unsigned BeginIdx = getIndex(
Range.first);
3331 unsigned EndIdx = getIndex(
Range.second);
3332 SliceValues[
Range] = IRB.CreateShuffleVector(
3348 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3351 if (
V->getType() != Acc.Inst->getType()) {
3353 V = IRB.CreateBitCast(V, Acc.Inst->getType());
3355 Acc.Inst->replaceAllUsesWith(V);
3372 SmallVector<Value *, 8> Vals;
3373 for (
auto &
Range : SortedRanges)
3375 Value *Merged = TreeMerge(Vals, Builder);
3376 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3381 ReplaceFullLoad(FullLoad, Merged);
3383 return DeletedValues;
3391 bool visitInstruction(Instruction &
I) {
3399 assert(IsSplit || BeginOffset == NewBeginOffset);
3402 StringRef OldName = OldPtr->
getName();
3404 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3406 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3411 OldName = OldName.
substr(IndexEnd + 1);
3415 OldName = OldName.
substr(OffsetEnd + 1);
3419 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3431 Align getSliceAlign() {
3433 NewBeginOffset - NewAllocaBeginOffset);
3437 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3439 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3440 uint32_t
Index = RelOffset / ElementSize;
3441 assert(Index * ElementSize == RelOffset);
3445 void deleteIfTriviallyDead(
Value *V) {
3448 Pass.DeadInsts.push_back(
I);
3451 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3452 unsigned BeginIndex = getIndex(NewBeginOffset);
3453 unsigned EndIndex = getIndex(NewEndOffset);
3454 assert(EndIndex > BeginIndex &&
"Empty vector!");
3457 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3459 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3460 LLVMContext::MD_access_group});
3464 Value *rewriteIntegerLoad(LoadInst &LI) {
3465 assert(IntTy &&
"We cannot insert an integer to the alloca");
3468 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3469 V = IRB.CreateBitPreservingCastChain(
DL, V, IntTy);
3470 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3472 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3473 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3482 "Can only handle an extract for an overly wide load");
3484 V = IRB.CreateZExt(V, LI.
getType());
3488 bool visitLoadInst(LoadInst &LI) {
3497 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3499 bool IsPtrAdjusted =
false;
3502 V = rewriteVectorizedLoadInst(LI);
3504 V = rewriteIntegerLoad(LI);
3505 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3506 NewEndOffset == NewAllocaEndOffset &&
3509 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3512 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3513 LoadInst *NewLI = IRB.CreateAlignedLoad(
3514 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3515 if (LI.isVolatile())
3516 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3517 if (NewLI->isAtomic())
3518 NewLI->setAlignment(LI.getAlign());
3523 copyMetadataForLoad(*NewLI, LI);
3527 NewLI->setAAMetadata(AATags.adjustForAccess(
3528 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3536 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3537 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3538 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3539 V = IRB.CreateZExt(V, TITy,
"load.ext");
3540 if (DL.isBigEndian())
3541 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3545 Type *LTy = IRB.getPtrTy(AS);
3547 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3552 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3556 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3557 LLVMContext::MD_access_group});
3560 IsPtrAdjusted =
true;
3562 V = IRB.CreateBitPreservingCastChain(
DL, V, TargetTy);
3567 "Only integer type loads and stores are split");
3568 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3569 "Split load isn't smaller than original load");
3571 "Non-byte-multiple bit width");
3577 LIIt.setHeadBit(
true);
3578 IRB.SetInsertPoint(LI.
getParent(), LIIt);
3583 Value *Placeholder =
3589 Placeholder->replaceAllUsesWith(&LI);
3590 Placeholder->deleteValue();
3595 Pass.DeadInsts.push_back(&LI);
3596 deleteIfTriviallyDead(OldOp);
3601 bool rewriteVectorizedStoreInst(
Value *V, StoreInst &SI,
Value *OldOp,
3606 if (
V->getType() != VecTy) {
3607 unsigned BeginIndex = getIndex(NewBeginOffset);
3608 unsigned EndIndex = getIndex(NewEndOffset);
3609 assert(EndIndex > BeginIndex &&
"Empty vector!");
3610 unsigned NumElements = EndIndex - BeginIndex;
3612 "Too many elements!");
3613 Type *SliceTy = (NumElements == 1)
3615 : FixedVectorType::
get(ElementTy, NumElements);
3616 if (
V->getType() != SliceTy)
3617 V = IRB.CreateBitPreservingCastChain(
DL, V, SliceTy);
3621 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3624 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3625 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3626 LLVMContext::MD_access_group});
3630 Pass.DeadInsts.push_back(&SI);
3639 bool rewriteIntegerStore(
Value *V, StoreInst &SI, AAMDNodes AATags) {
3640 assert(IntTy &&
"We cannot extract an integer from the alloca");
3642 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3644 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3646 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3647 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3651 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3652 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3653 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3654 LLVMContext::MD_access_group});
3661 Store->getValueOperand(),
DL);
3663 Pass.DeadInsts.push_back(&SI);
3668 bool visitStoreInst(StoreInst &SI) {
3670 Value *OldOp =
SI.getOperand(1);
3673 AAMDNodes AATags =
SI.getAAMetadata();
3678 if (
V->getType()->isPointerTy())
3680 Pass.PostPromotionWorklist.insert(AI);
3682 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3685 assert(
V->getType()->isIntegerTy() &&
3686 "Only integer type loads and stores are split");
3687 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3688 "Non-byte-multiple bit width");
3689 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3695 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3696 if (IntTy &&
V->getType()->isIntegerTy())
3697 return rewriteIntegerStore(V, SI, AATags);
3700 if (NewBeginOffset == NewAllocaBeginOffset &&
3701 NewEndOffset == NewAllocaEndOffset &&
3703 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3705 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3708 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3710 unsigned AS =
SI.getPointerAddressSpace();
3711 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3713 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3715 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3716 LLVMContext::MD_access_group});
3720 if (
SI.isVolatile())
3729 Pass.DeadInsts.push_back(&SI);
3730 deleteIfTriviallyDead(OldOp);
3748 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3756 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3766 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3771 bool visitMemSetInst(MemSetInst &
II) {
3775 AAMDNodes AATags =
II.getAAMetadata();
3781 assert(NewBeginOffset == BeginOffset);
3782 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3783 II.setDestAlignment(getSliceAlign());
3788 "AT: Unexpected link to non-const GEP");
3789 deleteIfTriviallyDead(OldPtr);
3794 Pass.DeadInsts.push_back(&
II);
3798 const bool CanContinue = [&]() {
3801 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3806 if (Len > std::numeric_limits<unsigned>::max())
3808 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3811 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3817 Type *SizeTy =
II.getLength()->getType();
3818 unsigned Sz = NewEndOffset - NewBeginOffset;
3821 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3822 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3828 New,
New->getRawDest(),
nullptr,
DL);
3843 assert(ElementTy == ScalarTy);
3845 unsigned BeginIndex = getIndex(NewBeginOffset);
3846 unsigned EndIndex = getIndex(NewEndOffset);
3847 assert(EndIndex > BeginIndex &&
"Empty vector!");
3848 unsigned NumElements = EndIndex - BeginIndex;
3850 "Too many elements!");
3853 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3854 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3855 if (NumElements > 1)
3858 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3867 V = getIntegerSplat(
II.getValue(),
Size);
3869 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3870 NewEndOffset != NewAllocaEndOffset)) {
3871 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3873 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3877 assert(
V->getType() == IntTy &&
3878 "Wrong type for an alloca wide integer!");
3880 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3883 assert(NewBeginOffset == NewAllocaBeginOffset);
3884 assert(NewEndOffset == NewAllocaEndOffset);
3886 V = getIntegerSplat(
II.getValue(),
3887 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3892 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3895 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3897 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3898 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3899 LLVMContext::MD_access_group});
3905 New,
New->getPointerOperand(), V,
DL);
3908 return !
II.isVolatile();
3911 bool visitMemTransferInst(MemTransferInst &
II) {
3917 AAMDNodes AATags =
II.getAAMetadata();
3919 bool IsDest = &
II.getRawDestUse() == OldUse;
3920 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3921 (!IsDest &&
II.getRawSource() == OldPtr));
3923 Align SliceAlign = getSliceAlign();
3931 if (!IsSplittable) {
3932 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3937 DbgAssign->getAddress() ==
II.getDest())
3938 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3940 II.setDest(AdjustedPtr);
3941 II.setDestAlignment(SliceAlign);
3943 II.setSource(AdjustedPtr);
3944 II.setSourceAlignment(SliceAlign);
3948 deleteIfTriviallyDead(OldPtr);
3961 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3962 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
3963 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
3969 if (EmitMemCpy && &OldAI == &NewAI) {
3971 assert(NewBeginOffset == BeginOffset);
3974 if (NewEndOffset != EndOffset)
3975 II.setLength(NewEndOffset - NewBeginOffset);
3979 Pass.DeadInsts.push_back(&
II);
3983 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3984 if (AllocaInst *AI =
3986 assert(AI != &OldAI && AI != &NewAI &&
3987 "Splittable transfers cannot reach the same alloca on both ends.");
3988 Pass.Worklist.insert(AI);
3995 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3996 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3998 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
4000 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
4008 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4009 Type *SizeTy =
II.getLength()->getType();
4010 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
4012 Value *DestPtr, *SrcPtr;
4013 MaybeAlign DestAlign, SrcAlign;
4017 DestAlign = SliceAlign;
4019 SrcAlign = OtherAlign;
4022 DestAlign = OtherAlign;
4024 SrcAlign = SliceAlign;
4026 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
4029 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
4034 &
II, New, DestPtr,
nullptr,
DL);
4039 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
4045 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
4046 NewEndOffset == NewAllocaEndOffset;
4048 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
4049 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
4050 unsigned NumElements = EndIndex - BeginIndex;
4051 IntegerType *SubIntTy =
4052 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
4057 if (VecTy && !IsWholeAlloca) {
4058 if (NumElements == 1)
4059 OtherTy = VecTy->getElementType();
4062 }
else if (IntTy && !IsWholeAlloca) {
4065 OtherTy = NewAllocaTy;
4070 MaybeAlign SrcAlign = OtherAlign;
4071 MaybeAlign DstAlign = SliceAlign;
4079 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
4083 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
4087 if (VecTy && !IsWholeAlloca && !IsDest) {
4089 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4091 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
4093 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4094 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
4098 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
4099 II.isVolatile(),
"copyload");
4100 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4101 LLVMContext::MD_access_group});
4108 if (VecTy && !IsWholeAlloca && IsDest) {
4109 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4112 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4113 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4115 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4118 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4122 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4123 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4124 LLVMContext::MD_access_group});
4127 Src->getType(),
DL));
4142 return !
II.isVolatile();
4145 bool visitIntrinsicInst(IntrinsicInst &
II) {
4146 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4147 "Unexpected intrinsic!");
4151 Pass.DeadInsts.push_back(&
II);
4153 if (
II.isDroppable()) {
4154 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4160 assert(
II.getArgOperand(0) == OldPtr);
4164 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4165 New = IRB.CreateLifetimeStart(Ptr);
4167 New = IRB.CreateLifetimeEnd(Ptr);
4175 void fixLoadStoreAlign(Instruction &Root) {
4179 SmallPtrSet<Instruction *, 4> Visited;
4180 SmallVector<Instruction *, 4>
Uses;
4182 Uses.push_back(&Root);
4191 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4198 for (User *U :
I->users())
4201 }
while (!
Uses.empty());
4204 bool visitPHINode(PHINode &PN) {
4206 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4207 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4213 IRBuilderBase::InsertPointGuard Guard(IRB);
4216 OldPtr->
getParent()->getFirstInsertionPt());
4218 IRB.SetInsertPoint(OldPtr);
4219 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4221 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4226 deleteIfTriviallyDead(OldPtr);
4229 fixLoadStoreAlign(PN);
4238 bool visitSelectInst(SelectInst &SI) {
4240 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4241 "Pointer isn't an operand!");
4242 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4243 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4245 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4247 if (
SI.getOperand(1) == OldPtr)
4248 SI.setOperand(1, NewPtr);
4249 if (
SI.getOperand(2) == OldPtr)
4250 SI.setOperand(2, NewPtr);
4253 deleteIfTriviallyDead(OldPtr);
4256 fixLoadStoreAlign(SI);
4271class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4273 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4279 SmallPtrSet<User *, 8> Visited;
4286 const DataLayout &
DL;
4291 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4292 :
DL(
DL), IRB(IRB) {}
4296 bool rewrite(Instruction &
I) {
4300 while (!
Queue.empty()) {
4301 U =
Queue.pop_back_val();
4310 void enqueueUsers(Instruction &
I) {
4311 for (Use &U :
I.uses())
4312 if (Visited.
insert(
U.getUser()).second)
4313 Queue.push_back(&U);
4317 bool visitInstruction(Instruction &
I) {
return false; }
4320 template <
typename Derived>
class OpSplitter {
4327 SmallVector<unsigned, 4> Indices;
4331 SmallVector<Value *, 4> GEPIndices;
4345 const DataLayout &
DL;
4349 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4350 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4351 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4352 BaseAlign(BaseAlign),
DL(
DL) {
4353 IRB.SetInsertPoint(InsertionPoint);
4370 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4372 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4373 return static_cast<Derived *
>(
this)->emitFunc(
4378 unsigned OldSize = Indices.
size();
4380 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4382 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4384 GEPIndices.
push_back(IRB.getInt32(Idx));
4385 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4393 unsigned OldSize = Indices.
size();
4395 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4397 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4399 GEPIndices.
push_back(IRB.getInt32(Idx));
4400 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4411 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4415 SmallVector<Value *, 4> Components;
4420 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4421 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4423 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4429 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4433 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4435 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4441 Load->setAAMetadata(
4447 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4452 void recordFakeUses(LoadInst &LI) {
4453 for (Use &U : LI.
uses())
4455 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4461 void emitFakeUses() {
4462 for (Instruction *
I : FakeUses) {
4463 IRB.SetInsertPoint(
I);
4464 for (
auto *V : Components)
4465 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4466 I->eraseFromParent();
4471 bool visitLoadInst(LoadInst &LI) {
4480 Splitter.recordFakeUses(LI);
4483 Splitter.emitFakeUses();
4490 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4491 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4492 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4493 const DataLayout &
DL, IRBuilderTy &IRB)
4494 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4496 AATags(AATags), AggStore(AggStore) {}
4498 StoreInst *AggStore;
4501 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4507 Value *ExtractValue =
4508 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4509 Value *InBoundsGEP =
4510 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4512 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4529 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4531 SizeInBits, AggStore,
Store,
4532 Store->getPointerOperand(),
Store->getValueOperand(),
4536 "AT: unexpected debug.assign linked to store through "
4543 bool visitStoreInst(StoreInst &SI) {
4544 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4547 if (
V->getType()->isSingleValueType())
4552 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4554 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4559 SI.eraseFromParent();
4563 bool visitBitCastInst(BitCastInst &BC) {
4568 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4578 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4597 if (!ZI->getSrcTy()->isIntegerTy(1))
4610 dbgs() <<
" original: " << *Sel <<
"\n";
4611 dbgs() <<
" " << GEPI <<
"\n";);
4613 auto GetNewOps = [&](
Value *SelOp) {
4626 Cond =
SI->getCondition();
4627 True =
SI->getTrueValue();
4628 False =
SI->getFalseValue();
4631 Cond = Sel->getOperand(0);
4632 True = ConstantInt::get(Sel->getType(), 1);
4633 False = ConstantInt::get(Sel->getType(), 0);
4638 IRB.SetInsertPoint(&GEPI);
4642 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4643 True->
getName() +
".sroa.gep", NW);
4646 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4647 False->
getName() +
".sroa.gep", NW);
4649 Value *NSel = MDFrom
4650 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4651 Sel->getName() +
".sroa.sel", MDFrom)
4652 : IRB.CreateSelectWithUnknownProfile(
4654 Sel->getName() +
".sroa.sel");
4655 Visited.
erase(&GEPI);
4660 enqueueUsers(*NSelI);
4663 dbgs() <<
" " << *NFalse <<
"\n";
4664 dbgs() <<
" " << *NSel <<
"\n";);
4673 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4678 auto IsInvalidPointerOperand = [](
Value *
V) {
4682 return !AI->isStaticAlloca();
4686 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4701 [](
Value *V) { return isa<ConstantInt>(V); }))
4714 dbgs() <<
" original: " << *
Phi <<
"\n";
4715 dbgs() <<
" " << GEPI <<
"\n";);
4717 auto GetNewOps = [&](
Value *PhiOp) {
4727 IRB.SetInsertPoint(Phi);
4728 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4729 Phi->getName() +
".sroa.phi");
4735 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4744 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4750 Visited.
erase(&GEPI);
4754 enqueueUsers(*NewPhi);
4760 dbgs() <<
"\n " << *NewPhi <<
'\n');
4765 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4766 if (unfoldGEPSelect(GEPI))
4769 if (unfoldGEPPhi(GEPI))
4776 bool visitPHINode(PHINode &PN) {
4781 bool visitSelectInst(SelectInst &SI) {
4795 if (Ty->isSingleValueType())
4798 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4803 InnerTy = ArrTy->getElementType();
4807 InnerTy = STy->getElementType(Index);
4812 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4813 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4834 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4836 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4837 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4844 ElementTy = AT->getElementType();
4845 TyNumElements = AT->getNumElements();
4850 ElementTy = VT->getElementType();
4851 TyNumElements = VT->getNumElements();
4853 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4855 if (NumSkippedElements >= TyNumElements)
4857 Offset -= NumSkippedElements * ElementSize;
4869 if (
Size == ElementSize)
4873 if (NumElements * ElementSize !=
Size)
4897 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4898 if (
Offset >= ElementSize)
4909 if (
Size == ElementSize)
4916 if (Index == EndIndex)
4926 assert(Index < EndIndex);
4965bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
4979 struct SplitOffsets {
4981 std::vector<uint64_t> Splits;
4983 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
4996 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
4998 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
4999 for (
auto &
P : AS.partitions()) {
5000 for (Slice &S :
P) {
5002 if (!S.isSplittable() || S.endOffset() <=
P.endOffset()) {
5007 UnsplittableLoads.
insert(LI);
5010 UnsplittableLoads.
insert(LI);
5013 assert(
P.endOffset() > S.beginOffset() &&
5014 "Empty or backwards partition!");
5023 auto IsLoadSimplyStored = [](LoadInst *LI) {
5024 for (User *LU : LI->
users()) {
5026 if (!SI || !
SI->isSimple())
5031 if (!IsLoadSimplyStored(LI)) {
5032 UnsplittableLoads.
insert(LI);
5038 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
5042 if (!StoredLoad || !StoredLoad->isSimple())
5044 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
5054 auto &
Offsets = SplitOffsetsMap[
I];
5056 "Should not have splits the first time we see an instruction!");
5058 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
5063 for (Slice *S :
P.splitSliceTails()) {
5064 auto SplitOffsetsMapI =
5066 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
5068 auto &
Offsets = SplitOffsetsMapI->second;
5072 "Cannot have an empty set of splits on the second partition!");
5074 P.beginOffset() -
Offsets.S->beginOffset() &&
5075 "Previous split does not end where this one begins!");
5079 if (S->endOffset() >
P.endOffset())
5088 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5094 if (UnsplittableLoads.
count(LI))
5097 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5098 if (LoadOffsetsI == SplitOffsetsMap.
end())
5100 auto &LoadOffsets = LoadOffsetsI->second;
5103 auto &StoreOffsets = SplitOffsetsMap[
SI];
5108 if (LoadOffsets.Splits == StoreOffsets.Splits)
5112 <<
" " << *LI <<
"\n"
5113 <<
" " << *SI <<
"\n");
5119 UnsplittableLoads.
insert(LI);
5128 return UnsplittableLoads.
count(LI);
5133 return UnsplittableLoads.
count(LI);
5143 IRBuilderTy IRB(&AI);
5150 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5160 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5161 std::vector<LoadInst *> SplitLoads;
5162 const DataLayout &
DL = AI.getDataLayout();
5163 for (LoadInst *LI : Loads) {
5166 auto &
Offsets = SplitOffsetsMap[LI];
5167 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5169 "Load must have type size equal to store size");
5171 "Load must be >= slice size");
5174 assert(BaseOffset + SliceSize > BaseOffset &&
5175 "Cannot represent alloca access size using 64-bit integers!");
5178 IRB.SetInsertPoint(LI);
5185 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5188 LoadInst *PLoad = IRB.CreateAlignedLoad(
5191 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5192 PartPtrTy,
BasePtr->getName() +
"."),
5195 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5196 LLVMContext::MD_access_group});
5200 SplitLoads.push_back(PLoad);
5204 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5208 <<
", " << NewSlices.
back().endOffset()
5209 <<
"): " << *PLoad <<
"\n");
5216 PartOffset =
Offsets.Splits[Idx];
5218 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : SliceSize) - PartOffset;
5224 bool DeferredStores =
false;
5225 for (User *LU : LI->
users()) {
5227 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5228 DeferredStores =
true;
5234 Value *StoreBasePtr =
SI->getPointerOperand();
5235 IRB.SetInsertPoint(SI);
5236 AAMDNodes AATags =
SI->getAAMetadata();
5238 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5240 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5241 LoadInst *PLoad = SplitLoads[Idx];
5243 auto *PartPtrTy =
SI->getPointerOperandType();
5245 auto AS =
SI->getPointerAddressSpace();
5246 StoreInst *PStore = IRB.CreateAlignedStore(
5249 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5250 PartPtrTy, StoreBasePtr->
getName() +
"."),
5253 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5254 LLVMContext::MD_access_group,
5255 LLVMContext::MD_DIAssignID});
5260 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5268 ResplitPromotableAllocas.
insert(OtherAI);
5269 Worklist.insert(OtherAI);
5272 Worklist.insert(OtherAI);
5276 DeadInsts.push_back(SI);
5281 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5284 DeadInsts.push_back(LI);
5293 for (StoreInst *SI : Stores) {
5298 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5302 "Slice size should always match load size exactly!");
5304 assert(BaseOffset + StoreSize > BaseOffset &&
5305 "Cannot represent alloca access size using 64-bit integers!");
5313 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5314 std::vector<LoadInst *> *SplitLoads =
nullptr;
5315 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5316 SplitLoads = &SplitLoadsMapI->second;
5318 "Too few split loads for the number of splits in the store!");
5326 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5328 auto *StorePartPtrTy =
SI->getPointerOperandType();
5333 PLoad = (*SplitLoads)[Idx];
5335 IRB.SetInsertPoint(LI);
5337 PLoad = IRB.CreateAlignedLoad(
5340 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5341 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5344 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5345 LLVMContext::MD_access_group});
5349 IRB.SetInsertPoint(SI);
5350 auto AS =
SI->getPointerAddressSpace();
5351 StoreInst *PStore = IRB.CreateAlignedStore(
5354 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5355 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5358 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5359 LLVMContext::MD_access_group});
5363 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5367 <<
", " << NewSlices.
back().endOffset()
5368 <<
"): " << *PStore <<
"\n");
5378 PartOffset =
Offsets.Splits[Idx];
5380 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : StoreSize) - PartOffset;
5390 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5391 ResplitPromotableAllocas.
insert(OtherAI);
5392 Worklist.insert(OtherAI);
5395 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5396 Worklist.insert(OtherAI);
5411 DeadInsts.push_back(LI);
5413 DeadInsts.push_back(SI);
5422 AS.insert(NewSlices);
5426 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5432 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5469 bool IsIntegralPointerTy =
5470 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5472 !IsIntegralPointerTy)
5479 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5483 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5484 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5487 if (StructSize != VectorSize)
5490 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5493 auto *U = S.getUse();
5497 User *Usr = U->getUser();
5504 for (
const Slice &S :
P)
5505 if (!IsIgnorableOrMemIntrinsicSlice(S))
5508 for (
const Slice *S :
P.splitSliceTails())
5509 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5526static std::tuple<Type *, bool, VectorType *>
5530 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5532 dbgs() <<
"selectPartitionType path=" << Path
5537 dbgs() <<
"<unnamed>";
5538 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5539 <<
") size=" <<
P.size();
5541 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5543 dbgs() <<
" chosen=" << *SelectedTy;
5545 dbgs() <<
" vec=" << *SelectedVecTy;
5546 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5564 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5565 VecTy->getElementCount().getFixedValue() > 1) {
5566 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5567 return {VecTy,
false, VecTy};
5572 auto [CommonUseTy, LargestIntTy] =
5575 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5581 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5582 return {VecTy,
false, VecTy};
5585 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5586 return {CommonUseTy, IntWiden,
nullptr};
5593 P.beginOffset(),
P.size())) {
5597 if (TypePartitionTy->isArrayTy() &&
5598 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5599 DL.isLegalInteger(
P.size() * 8))
5603 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5604 return {TypePartitionTy,
true,
nullptr};
5607 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5608 return {VecTy,
false, VecTy};
5613 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5615 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5616 return {LargestIntTy,
true,
nullptr};
5621 if (AggregateToVector) {
5624 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5625 return {VTy,
false,
nullptr};
5631 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5632 return {TypePartitionTy,
false,
nullptr};
5637 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5638 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5639 return {LargestIntTy,
false,
nullptr};
5643 if (
DL.isLegalInteger(
P.size() * 8)) {
5645 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5646 return {IntTy,
false,
nullptr};
5651 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5652 return {ArrayTy,
false,
nullptr};
5665std::pair<AllocaInst *, uint64_t>
5666SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5667 const DataLayout &
DL = AI.getDataLayout();
5669 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5679 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5688 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5689 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5697 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5698 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5703 unsigned PPWOldSize = PostPromotionWorklist.size();
5704 unsigned NumUses = 0;
5705 SmallSetVector<PHINode *, 8> PHIUsers;
5706 SmallSetVector<SelectInst *, 8> SelectUsers;
5709 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5710 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5711 bool Promotable =
true;
5713 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5714 NumUses += DeletedValues->
size() + 1;
5715 for (
Value *V : *DeletedValues)
5716 DeadInsts.push_back(V);
5718 for (Slice *S :
P.splitSliceTails()) {
5722 for (Slice &S :
P) {
5728 NumAllocaPartitionUses += NumUses;
5729 MaxUsesPerAllocaPartition.updateMax(NumUses);
5735 for (PHINode *
PHI : PHIUsers) {
5746 SelectUsers.
clear();
5751 NewSelectsToRewrite;
5753 for (SelectInst *Sel : SelectUsers) {
5754 std::optional<RewriteableMemOps>
Ops =
5755 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5764 for (Use *U : AS.getDeadUsesIfPromotable()) {
5766 Value::dropDroppableUse(*U);
5769 DeadInsts.push_back(OldInst);
5771 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5772 SelectUsers.empty()) {
5774 PromotableAllocas.insert(NewAI);
5779 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5780 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5781 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5782 NewSelectsToRewrite.
size());
5784 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5785 std::make_move_iterator(NewSelectsToRewrite.
end())))
5786 SelectsToRewrite.insert(std::move(KV));
5787 Worklist.insert(NewAI);
5791 while (PostPromotionWorklist.size() > PPWOldSize)
5792 PostPromotionWorklist.pop_back();
5797 return {
nullptr, 0};
5802 Worklist.insert(NewAI);
5805 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5849 int64_t BitExtractOffset) {
5851 bool HasFragment =
false;
5852 bool HasBitExtract =
false;
5860 HasBitExtract =
true;
5861 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5862 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5871 assert(BitExtractOffset <= 0);
5872 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5878 if (AdjustedOffset < 0)
5881 Ops.push_back(
Op.getOp());
5882 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5883 Ops.push_back(ExtractSizeInBits);
5886 Op.appendToVector(
Ops);
5891 if (HasFragment && HasBitExtract)
5894 if (!HasBitExtract) {
5913 std::optional<DIExpression::FragmentInfo> NewFragment,
5914 int64_t BitExtractAdjustment) {
5924 BitExtractAdjustment);
5925 if (!NewFragmentExpr)
5931 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5944 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5950 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5958 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
5964bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
5965 if (AS.begin() == AS.end())
5968 unsigned NumPartitions = 0;
5970 const DataLayout &
DL = AI.getModule()->getDataLayout();
5973 Changed |= presplitLoadsAndStores(AI, AS);
5981 bool IsSorted =
true;
5983 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
5991 SparseBitVector<> SplittableOffset;
5993 for (Slice &S : AS) {
5995 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
5997 if (S.beginOffset() >= CurEnd) {
5998 SplittableOffset.
set(S.beginOffset());
6001 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6002 SplittableOffset.
reset(CurEnd);
6004 CurBegin = S.beginOffset();
6008 if (S.endOffset() > CurEnd) {
6009 CurEnd = S.endOffset();
6010 SplittableOffset.
set(CurEnd);
6015 for (Slice &S : AS) {
6016 if (!S.isSplittable())
6019 if ((S.beginOffset() > AllocaSize ||
6020 SplittableOffset.
test(S.beginOffset())) &&
6021 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6026 S.makeUnsplittable();
6046 for (
auto &
P : AS.partitions()) {
6047 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6051 uint64_t SizeOfByte = 8;
6053 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6054 Fragments.push_back(
6055 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6061 NumAllocaPartitions += NumPartitions;
6062 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6066 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6071 const Value *DbgPtr = DbgVariable->getAddress();
6073 DbgVariable->getFragmentOrEntireVariable();
6076 int64_t CurrentExprOffsetInBytes = 0;
6077 SmallVector<uint64_t> PostOffsetOps;
6079 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6083 int64_t ExtractOffsetInBits = 0;
6086 ExtractOffsetInBits = Extract.getOffsetInBits();
6091 DIBuilder DIB(*AI.getModule(),
false);
6093 int64_t OffsetFromLocationInBits;
6094 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6100 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6101 NewDbgFragment, OffsetFromLocationInBits))
6107 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6112 if (!NewDbgFragment)
6113 NewDbgFragment = DbgVariable->getFragment();
6117 int64_t OffestFromNewAllocaInBits =
6118 OffsetFromLocationInBits - ExtractOffsetInBits;
6121 int64_t BitExtractOffset =
6122 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6127 OffestFromNewAllocaInBits =
6128 std::max(int64_t(0), OffestFromNewAllocaInBits);
6134 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6135 if (OffestFromNewAllocaInBits > 0) {
6136 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6142 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6143 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6144 return LHS->getVariable() ==
RHS->getVariable() &&
6145 LHS->getDebugLoc()->getInlinedAt() ==
6146 RHS->getDebugLoc()->getInlinedAt();
6148 if (SameVariableFragment(OldDII, DbgVariable))
6149 OldDII->eraseFromParent();
6154 NewDbgFragment, BitExtractOffset);
6168void SROA::clobberUse(Use &U) {
6178 DeadInsts.push_back(OldI);
6200bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6205 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6206 bool AllSameAndValid =
true;
6207 Type *PartitionType =
nullptr;
6208 SmallVector<Instruction *> Insts;
6212 auto Flush = [&]() {
6213 if (AllSameAndValid && !Insts.
empty()) {
6214 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6215 << EndOffset <<
")\n");
6217 SSAUpdater
SSA(&NewPHIs);
6219 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6220 Promoter.run(Insts);
6222 AllSameAndValid =
true;
6223 PartitionType =
nullptr;
6227 for (Slice &S : AS) {
6231 dbgs() <<
"Ignoring slice: ";
6232 AS.print(
dbgs(), &S);
6236 if (S.beginOffset() >= EndOffset) {
6238 BeginOffset = S.beginOffset();
6239 EndOffset = S.endOffset();
6240 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6241 if (AllSameAndValid) {
6243 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6244 << EndOffset <<
")";
6245 AS.print(
dbgs(), &S);
6247 AllSameAndValid =
false;
6249 EndOffset = std::max(EndOffset, S.endOffset());
6256 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6257 AllSameAndValid =
false;
6258 PartitionType = UserTy;
6261 Type *UserTy =
SI->getValueOperand()->getType();
6262 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6263 AllSameAndValid =
false;
6264 PartitionType = UserTy;
6267 AllSameAndValid =
false;
6280std::pair<
bool ,
bool >
6281SROA::runOnAlloca(AllocaInst &AI) {
6283 bool CFGChanged =
false;
6286 ++NumAllocasAnalyzed;
6289 if (AI.use_empty()) {
6290 AI.eraseFromParent();
6294 const DataLayout &
DL = AI.getDataLayout();
6297 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6298 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6303 IRBuilderTy IRB(&AI);
6304 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6305 Changed |= AggRewriter.rewrite(AI);
6308 AllocaSlices AS(
DL, AI);
6313 if (AS.isEscapedReadOnly()) {
6314 Changed |= propagateStoredValuesToLoads(AI, AS);
6319 for (Instruction *DeadUser : AS.getDeadUsers()) {
6321 for (Use &DeadOp : DeadUser->operands())
6328 DeadInsts.push_back(DeadUser);
6331 for (Use *DeadOp : AS.getDeadOperands()) {
6332 clobberUse(*DeadOp);
6337 if (AS.begin() == AS.end())
6340 Changed |= splitAlloca(AI, AS);
6343 while (!SpeculatablePHIs.empty())
6347 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6348 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6349 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6355 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6356 while (!RemainingSelectsToRewrite.empty()) {
6357 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6374bool SROA::deleteDeadInstructions(
6375 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6377 while (!DeadInsts.empty()) {
6387 DeletedAllocas.
insert(AI);
6389 OldDII->eraseFromParent();
6395 for (Use &Operand :
I->operands())
6400 DeadInsts.push_back(U);
6404 I->eraseFromParent();
6414bool SROA::promoteAllocas() {
6415 if (PromotableAllocas.empty())
6422 NumPromoted += PromotableAllocas.size();
6423 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6426 PromotableAllocas.clear();
6430std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6433 const DataLayout &
DL =
F.getDataLayout();
6438 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6440 PromotableAllocas.insert(AI);
6442 Worklist.insert(AI);
6447 bool CFGChanged =
false;
6450 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6453 while (!Worklist.empty()) {
6454 auto [IterationChanged, IterationCFGChanged] =
6455 runOnAlloca(*Worklist.pop_back_val());
6457 CFGChanged |= IterationCFGChanged;
6459 Changed |= deleteDeadInstructions(DeletedAllocas);
6463 if (!DeletedAllocas.
empty()) {
6464 Worklist.set_subtract(DeletedAllocas);
6465 PostPromotionWorklist.set_subtract(DeletedAllocas);
6466 PromotableAllocas.set_subtract(DeletedAllocas);
6467 DeletedAllocas.
clear();
6473 Worklist = PostPromotionWorklist;
6474 PostPromotionWorklist.clear();
6475 }
while (!Worklist.empty());
6477 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6478 assert((!CFGChanged || !PreserveCFG) &&
6479 "Should not have modified the CFG when told to preserve it.");
6482 for (
auto &BB :
F) {
6495 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6507 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6508 OS, MapClassName2PassName);
6512 if (Options.AggregateToVector)
6513 OS <<
";aggregate-to-vector";
6534 if (skipFunction(
F))
6537 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6539 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6545 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6552 StringRef getPassName()
const override {
return "SROA"; }
6557char SROALegacyPass::ID = 0;
6562 AggregateToVector));
6566 "Scalar Replacement Of Aggregates",
false,
false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DXIL Forward Handle Accesses
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
This file implements a map that provides insertion order iteration.
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PointerIntPair class.
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, uint64_t OldAllocaOffsetInBits, uint64_t SliceSizeInBits, Instruction *OldInst, Instruction *Inst, Value *Dest, Value *Value, const DataLayout &DL)
Find linked dbg.assign and generate a new one with the correct FragmentInfo.
static VectorType * isVectorPromotionViable(Partition &P, const DataLayout &DL, unsigned VScale)
Test whether the given alloca partitioning and range of slices can be promoted to a vector.
static Align getAdjustedAlignment(Instruction *I, uint64_t Offset)
Compute the adjusted alignment for a load or store from an offset.
static VectorType * checkVectorTypesForPromotion(Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool HaveCommonEltTy, Type *CommonEltTy, bool HaveVecPtrTy, bool HaveCommonVecPtrTy, VectorType *CommonVecPtrTy, unsigned VScale)
Test whether any vector type in CandidateTys is viable for promotion.
static std::pair< Type *, IntegerType * > findCommonType(AllocaSlices::const_iterator B, AllocaSlices::const_iterator E, uint64_t EndOffset)
Walk the range of a partitioning looking for a common type to cover this sequence of slices.
static Type * stripAggregateTypeWrapping(const DataLayout &DL, Type *Ty)
Strip aggregate type wrapping.
static FragCalcResult calculateFragment(DILocalVariable *Variable, uint64_t NewStorageSliceOffsetInBits, uint64_t NewStorageSliceSizeInBits, std::optional< DIExpression::FragmentInfo > StorageFragment, std::optional< DIExpression::FragmentInfo > CurrentFragment, DIExpression::FragmentInfo &Target)
static DIExpression * createOrReplaceFragment(const DIExpression *Expr, DIExpression::FragmentInfo Frag, int64_t BitExtractOffset)
Create or replace an existing fragment in a DIExpression with Frag.
static Value * insertInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *Old, Value *V, uint64_t Offset, const Twine &Name)
static bool isVectorPromotionViableForSlice(Partition &P, const Slice &S, VectorType *Ty, uint64_t ElementSize, const DataLayout &DL, unsigned VScale)
Test whether the given slice use can be promoted to a vector.
static Value * getAdjustedPtr(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, APInt Offset, Type *PointerTy, const Twine &NamePrefix)
Compute an adjusted pointer from Ptr by Offset bytes where the resulting pointer has PointerTy.
static bool isIntegerWideningViableForSlice(const Slice &S, uint64_t AllocBeginOffset, Type *AllocaTy, const DataLayout &DL, bool &WholeAllocaOp)
Test whether a slice of an alloca is valid for integer widening.
static 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 void rewriteMemOpOfSelect(SelectInst &SI, T &I, SelectHandSpeculativity Spec, DomTreeUpdater &DTU)
static Value * foldSelectInst(SelectInst &SI)
bool isKillAddress(const DbgVariableRecord *DVR)
static Value * insertVector(IRBuilderTy &IRB, Value *Old, Value *V, unsigned BeginIndex, const Twine &Name)
static bool isIntegerWideningViable(Partition &P, Type *AllocaTy, const DataLayout &DL)
Test whether the given alloca partition's integer operations can be widened to promotable ones.
static void speculatePHINodeLoads(IRBuilderTy &IRB, PHINode &PN)
static VectorType * createAndCheckVectorTypesForPromotion(SetVector< Type * > &OtherTys, ArrayRef< VectorType * > CandidateTysCopy, function_ref< void(Type *)> CheckCandidateType, Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool &HaveCommonEltTy, Type *&CommonEltTy, bool &HaveVecPtrTy, bool &HaveCommonVecPtrTy, VectorType *&CommonVecPtrTy, unsigned VScale)
static DebugVariable getAggregateVariable(DbgVariableRecord *DVR)
static std::tuple< Type *, bool, VectorType * > selectPartitionType(Partition &P, const DataLayout &DL, AllocaInst &AI, LLVMContext &C, bool AggregateToVector)
Select a partition type for an alloca partition.
static bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
static FixedVectorType * tryCanonicalizeStructToVector(StructType *STy, Partition &P, const DataLayout &DL)
Try to canonicalize a homogeneous struct partition to a vector type.
static Value * extractInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *V, IntegerType *Ty, uint64_t Offset, const Twine &Name)
static void insertNewDbgInst(DIBuilder &DIB, DbgVariableRecord *Orig, AllocaInst *NewAddr, DIExpression *NewAddrExpr, Instruction *BeforeInst, std::optional< DIExpression::FragmentInfo > NewFragment, int64_t BitExtractAdjustment)
Insert a new DbgRecord.
static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, IRBuilderTy &IRB)
static Value * mergeTwoVectors(Value *V0, Value *V1, const DataLayout &DL, Type *NewAIEltTy, IRBuilder<> &Builder)
This function takes two vector values and combines them into a single vector by concatenating their e...
const DIExpression * getAddressExpression(const DbgVariableRecord *DVR)
static Type * getTypePartition(const DataLayout &DL, Type *Ty, uint64_t Offset, uint64_t Size)
Try to find a partition of the aggregate type passed in for a given offset and size.
static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy, unsigned VScale=0)
Test whether we can convert a value from the old to the new type.
static SelectHandSpeculativity isSafeLoadOfSelectToSpeculate(LoadInst &LI, SelectInst &SI, bool PreserveCFG)
static 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.
Virtual Register Rewriter
Builder for the alloca slices.
SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
An iterator over partitions of the alloca's slices.
bool operator==(const partition_iterator &RHS) const
friend class AllocaSlices
partition_iterator & operator++()
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
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.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
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...
virtual void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
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.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
LLVM_ABI void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static VectorType * getWithSizeAndScalar(VectorType *SizeTy, Type *EltTy)
This static method attempts to construct a VectorType with the same size-in-bits as SizeTy but with a...
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
unsigned getNumElements(Type *Ty)
This is an optimization pass for GlobalISel generic memory operations.
static cl::opt< bool > SROASkipMem2Reg("sroa-skip-mem2reg", cl::init(false), cl::Hidden)
Disable running mem2reg during SROA in order to test or debug SROA.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
LLVM_ABI bool RemoveRedundantDbgInstrs(BasicBlock *BB)
Try to remove redundant dbg.value instructions from given basic block.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
LLVM_ABI bool isAssumeLikeIntrinsic(const Instruction *I)
Return true if it is an intrinsic that cannot be speculated but also cannot trap.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI std::optional< RegOrConstant > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
auto unique(Range &&R, Predicate P)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
bool capturesFullProvenance(CaptureComponents CC)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void initializeSROALegacyPassPass(PassRegistry &)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRValues(Value *V)
As above, for DVRValues.
LLVM_ABI void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI 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.
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes shift(size_t Offset) const
Create a new AAMDNode that describes this AAMDNode after applying a constant offset to the start of t...
LLVM_ABI AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Describes an element of a Bitfield.
static Bitfield::Type get(StorageType Packed)
Unpacks the field from the Packed value.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.