102#define DEBUG_TYPE "sroa"
104STATISTIC(NumAllocasAnalyzed,
"Number of allocas analyzed for replacement");
105STATISTIC(NumAllocaPartitions,
"Number of alloca partitions formed");
106STATISTIC(MaxPartitionsPerAlloca,
"Maximum number of partitions per alloca");
107STATISTIC(NumAllocaPartitionUses,
"Number of alloca partition uses rewritten");
108STATISTIC(MaxUsesPerAllocaPartition,
"Maximum number of uses of a partition");
109STATISTIC(NumNewAllocas,
"Number of new, smaller allocas introduced");
110STATISTIC(NumPromoted,
"Number of allocas promoted to SSA values");
111STATISTIC(NumLoadsSpeculated,
"Number of loads speculated to allow promotion");
113 "Number of loads rewritten into predicated loads to allow promotion");
116 "Number of stores rewritten into predicated stores to allow promotion");
118STATISTIC(NumVectorized,
"Number of vectorized aggregates");
122class AllocaSliceRewriter;
127class SelectHandSpeculativity {
128 unsigned char Storage = 0;
132 SelectHandSpeculativity() =
default;
133 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
134 bool isSpeculatable(
bool isTrueVal)
const;
135 bool areAllSpeculatable()
const;
136 bool areAnySpeculatable()
const;
137 bool areNoneSpeculatable()
const;
139 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
140 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
142static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
144using PossiblySpeculatableLoad =
147using RewriteableMemOp =
148 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
150using InstructionSliceMap =
172 LLVMContext *
const C;
173 DomTreeUpdater *
const DTU;
174 AssumptionCache *
const AC;
175 const bool PreserveCFG;
176 const bool AggregateToVector;
185 SmallSetVector<AllocaInst *, 16> Worklist;
200 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
203 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
204 SmallPtrSet<AllocaInst *, 16>, 16>
212 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
219 SmallSetVector<PHINode *, 8> PHIsWithStoreToRewrite;
223 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
268 static std::optional<RewriteableMemOps>
269 isSafeSelectToSpeculateOrPredicate(SelectInst &SI,
bool PreserveCFG);
272 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
274 : C(C), DTU(DTU), AC(AC),
275 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
276 AggregateToVector(
Options.AggregateToVector) {}
279 std::pair<
bool ,
bool > runSROA(
Function &
F);
282 friend class AllocaSliceRewriter;
284 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
285 std::pair<AllocaInst *, uint64_t>
286 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
287 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
288 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
289 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
290 void clobberUse(Use &U);
291 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
292 bool promoteAllocas();
306enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
310 uint64_t NewStorageSliceOffsetInBits,
312 std::optional<DIExpression::FragmentInfo> StorageFragment,
313 std::optional<DIExpression::FragmentInfo> CurrentFragment,
317 if (StorageFragment) {
319 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
321 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
323 Target.SizeInBits = NewStorageSliceSizeInBits;
324 Target.OffsetInBits = NewStorageSliceOffsetInBits;
330 if (!CurrentFragment) {
331 if (
auto Size = Variable->getSizeInBits()) {
334 if (
Target == CurrentFragment)
341 if (!CurrentFragment || *CurrentFragment ==
Target)
347 if (
Target.startInBits() < CurrentFragment->startInBits() ||
348 Target.endInBits() > CurrentFragment->endInBits())
387 if (DVRAssignMarkerRange.empty())
393 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
395 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
407 DVR->getExpression()->getFragmentInfo();
420 auto *Expr = DbgAssign->getExpression();
421 bool SetKillLocation =
false;
424 std::optional<DIExpression::FragmentInfo> BaseFragment;
427 if (R == BaseFragments.
end())
429 BaseFragment = R->second;
431 std::optional<DIExpression::FragmentInfo> CurrentFragment =
432 Expr->getFragmentInfo();
435 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
436 BaseFragment, CurrentFragment, NewFragment);
440 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
441 if (CurrentFragment) {
446 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
459 SetKillLocation =
true;
467 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
474 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
478 NewAssign = DbgAssign;
497 Value && (DbgAssign->hasArgList() ||
498 !DbgAssign->getExpression()->isSingleLocationExpression());
515 if (NewAssign != DbgAssign) {
516 NewAssign->
moveBefore(DbgAssign->getIterator());
519 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
522 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
532 Twine getNameWithPrefix(
const Twine &Name)
const {
537 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
539 void InsertHelper(Instruction *
I,
const Twine &Name,
564 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
570 : BeginOffset(BeginOffset), EndOffset(EndOffset),
571 UseAndIsSplittable(
U, IsSplittable) {}
573 uint64_t beginOffset()
const {
return BeginOffset; }
574 uint64_t endOffset()
const {
return EndOffset; }
576 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
577 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
579 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
581 bool isDead()
const {
return getUse() ==
nullptr; }
582 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
591 if (beginOffset() <
RHS.beginOffset())
593 if (beginOffset() >
RHS.beginOffset())
595 if (isSplittable() !=
RHS.isSplittable())
596 return !isSplittable();
597 if (endOffset() >
RHS.endOffset())
604 return LHS.beginOffset() < RHSOffset;
607 return LHSOffset <
RHS.beginOffset();
611 return isSplittable() ==
RHS.isSplittable() &&
612 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
627 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
633 bool isEscaped()
const {
return PointerEscapingInstr; }
634 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
639 using range = iterator_range<iterator>;
641 iterator
begin() {
return Slices.begin(); }
642 iterator
end() {
return Slices.end(); }
645 using const_range = iterator_range<const_iterator>;
647 const_iterator
begin()
const {
return Slices.begin(); }
648 const_iterator
end()
const {
return Slices.end(); }
652 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
660 int OldSize = Slices.size();
661 Slices.append(NewSlices.
begin(), NewSlices.
end());
662 auto SliceI = Slices.begin() + OldSize;
663 std::stable_sort(SliceI, Slices.end());
664 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
673 ArrayRef<Instruction *> getDeadUsers()
const {
return DeadUsers; }
677 return DeadUseIfPromotable;
688#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
689 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
690 void printSlice(raw_ostream &OS, const_iterator
I,
691 StringRef Indent =
" ")
const;
692 void printUse(raw_ostream &OS, const_iterator
I,
693 StringRef Indent =
" ")
const;
694 void print(raw_ostream &OS)
const;
695 void dump(const_iterator
I)
const;
700 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
703 friend class AllocaSlices::SliceBuilder;
705#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
733 SmallVector<Instruction *, 8> DeadUsers;
760 friend class AllocaSlices;
761 friend class AllocaSlices::partition_iterator;
763 using iterator = AllocaSlices::iterator;
767 uint64_t BeginOffset = 0, EndOffset = 0;
777 Partition(iterator SI) : SI(SI), SJ(SI) {}
783 uint64_t beginOffset()
const {
return BeginOffset; }
788 uint64_t endOffset()
const {
return EndOffset; }
794 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
795 return EndOffset - BeginOffset;
800 bool empty()
const {
return SI == SJ; }
811 iterator
begin()
const {
return SI; }
812 iterator
end()
const {
return SJ; }
844 AllocaSlices::iterator SE;
848 uint64_t MaxSplitSliceEndOffset = 0;
852 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
864 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
865 "Cannot advance past the end of the slices!");
868 if (!
P.SplitTails.empty()) {
869 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
871 P.SplitTails.clear();
872 MaxSplitSliceEndOffset = 0;
878 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
881 return S->endOffset() == MaxSplitSliceEndOffset;
883 "Could not find the current max split slice offset!");
886 return S->endOffset() <= MaxSplitSliceEndOffset;
888 "Max split slice end offset is not actually the max!");
895 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
905 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
906 P.SplitTails.push_back(&S);
907 MaxSplitSliceEndOffset =
908 std::max(S.endOffset(), MaxSplitSliceEndOffset);
916 P.BeginOffset = P.EndOffset;
917 P.EndOffset = MaxSplitSliceEndOffset;
924 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
925 !P.SI->isSplittable()) {
926 P.BeginOffset = P.EndOffset;
927 P.EndOffset = P.SI->beginOffset();
937 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
938 P.EndOffset = P.SI->endOffset();
943 if (!P.SI->isSplittable()) {
946 assert(P.BeginOffset == P.SI->beginOffset());
950 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
951 if (!P.SJ->isSplittable())
952 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
964 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
967 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
968 P.SJ->isSplittable()) {
969 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
976 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
977 assert(!P.SJ->isSplittable());
978 P.EndOffset = P.SJ->beginOffset();
985 "End iterators don't match between compared partition iterators!");
992 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
993 assert(P.SJ == RHS.P.SJ &&
994 "Same set of slices formed two different sized partitions!");
995 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
996 "Same slice position with differently sized non-empty split "
1019 return make_range(partition_iterator(begin(), end()),
1020 partition_iterator(end(), end()));
1028 return SI.getOperand(1 + CI->isZero());
1029 if (
SI.getOperand(1) ==
SI.getOperand(2))
1030 return SI.getOperand(1);
1039 return PN->hasConstantValue();
1054 const uint64_t AllocSize;
1070 if (VisitedDeadInsts.
insert(&
I).second)
1075 bool IsSplittable =
false) {
1081 <<
" which has zero size or starts outside of the "
1082 << AllocSize <<
" byte alloca:\n"
1083 <<
" alloca: " << AS.AI <<
"\n"
1084 <<
" use: " <<
I <<
"\n");
1085 return markAsDead(
I);
1097 assert(AllocSize >= BeginOffset);
1098 if (
Size > AllocSize - BeginOffset) {
1100 <<
Offset <<
" to remain within the " << AllocSize
1101 <<
" byte alloca:\n"
1102 <<
" alloca: " << AS.AI <<
"\n"
1103 <<
" use: " <<
I <<
"\n");
1104 EndOffset = AllocSize;
1107 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1110 void visitBitCastInst(BitCastInst &BC) {
1112 return markAsDead(BC);
1114 return Base::visitBitCastInst(BC);
1117 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1119 return markAsDead(ASC);
1121 return Base::visitAddrSpaceCastInst(ASC);
1124 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1126 return markAsDead(GEPI);
1128 return Base::visitGetElementPtrInst(GEPI);
1131 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1142 void visitLoadInst(LoadInst &LI) {
1144 "All simple FCA loads should have been pre-split");
1149 return PI.setEscapedReadOnly(&LI);
1152 if (
Size.isScalable()) {
1155 return PI.setAborted(&LI);
1164 void visitStoreInst(StoreInst &SI) {
1165 Value *ValOp =
SI.getValueOperand();
1167 return PI.setEscapedAndAborted(&SI);
1169 return PI.setAborted(&SI);
1171 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1173 unsigned VScale =
SI.getFunction()->getVScaleValue();
1175 return PI.setAborted(&SI);
1191 <<
Offset <<
" which extends past the end of the "
1192 << AllocSize <<
" byte alloca:\n"
1193 <<
" alloca: " << AS.AI <<
"\n"
1194 <<
" use: " << SI <<
"\n");
1195 return markAsDead(SI);
1199 "All simple FCA stores should have been pre-split");
1203 void visitMemSetInst(MemSetInst &
II) {
1204 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1207 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1209 return markAsDead(
II);
1212 return PI.setAborted(&
II);
1216 : AllocSize -
Offset.getLimitedValue(),
1220 void visitMemTransferInst(MemTransferInst &
II) {
1224 return markAsDead(
II);
1228 if (VisitedDeadInsts.
count(&
II))
1232 return PI.setAborted(&
II);
1239 if (
Offset.uge(AllocSize)) {
1240 auto MTPI = MemTransferSliceMap.
find(&
II);
1241 if (MTPI != MemTransferSliceMap.
end())
1242 AS.Slices[MTPI->second].kill();
1243 return markAsDead(
II);
1251 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1253 if (!
II.isVolatile())
1254 return markAsDead(
II);
1262 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1263 std::tie(MTPI, Inserted) =
1264 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1265 unsigned PrevIdx = MTPI->second;
1267 Slice &PrevP = AS.Slices[PrevIdx];
1271 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1273 return markAsDead(
II);
1278 PrevP.makeUnsplittable();
1285 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1286 "Map index doesn't point back to a slice with this user.");
1292 void visitIntrinsicInst(IntrinsicInst &
II) {
1293 if (
II.isDroppable()) {
1294 AS.DeadUseIfPromotable.push_back(U);
1299 return PI.setAborted(&
II);
1301 if (
II.isLifetimeStartOrEnd()) {
1302 insertUse(
II,
Offset, AllocSize,
true);
1306 Base::visitIntrinsicInst(
II);
1314 SmallPtrSet<Instruction *, 4> Visited;
1324 std::tie(UsedI,
I) =
Uses.pop_back_val();
1327 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1339 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1349 if (!
GEP->hasAllZeroIndices())
1356 for (User *U :
I->users())
1359 }
while (!
Uses.empty());
1364 void visitPHINodeOrSelectInst(Instruction &
I) {
1367 return markAsDead(
I);
1373 return PI.setAborted(&
I);
1391 AS.DeadOperands.push_back(U);
1397 return PI.setAborted(&
I);
1403 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1404 return PI.setAborted(UnsafeI);
1413 if (
Offset.uge(AllocSize)) {
1414 AS.DeadOperands.push_back(U);
1421 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1423 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1426 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1428 void visitCallBase(CallBase &CB) {
1434 PI.setEscapedReadOnly(&CB);
1438 Base::visitCallBase(CB);
1442AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1444#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1447 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1449 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1450 if (PtrI.isEscaped() || PtrI.isAborted()) {
1453 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1454 : PtrI.getAbortingInst();
1455 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1458 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1460 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1467#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1469void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1470 StringRef Indent)
const {
1471 printSlice(OS,
I, Indent);
1473 printUse(OS,
I, Indent);
1476void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1477 StringRef Indent)
const {
1478 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1479 <<
" slice #" << (
I -
begin())
1480 << (
I->isSplittable() ?
" (splittable)" :
"");
1483void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1484 StringRef Indent)
const {
1485 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1488void AllocaSlices::print(raw_ostream &OS)
const {
1489 if (PointerEscapingInstr) {
1490 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1491 <<
" A pointer to this alloca escaped by:\n"
1492 <<
" " << *PointerEscapingInstr <<
"\n";
1496 if (PointerEscapingInstrReadOnly)
1497 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1499 OS <<
"Slices of alloca: " << AI <<
"\n";
1520 for (
User *U :
I.users()) {
1521 Type *UserTy =
nullptr;
1527 UserTy =
Store->getValueOperand()->getType();
1529 if (!UserTy || (Ty && Ty != UserTy))
1539static std::pair<Type *, IntegerType *>
1543 bool TyIsCommon =
true;
1548 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1549 Use *U =
I->getUse();
1552 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1555 Type *UserTy =
nullptr;
1559 UserTy =
SI->getValueOperand()->getType();
1570 if (UserITy->getBitWidth() % 8 != 0 ||
1571 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1576 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1582 if (!UserTy || (Ty && Ty != UserTy))
1588 return {TyIsCommon ? Ty :
nullptr, ITy};
1618 Type *LoadType =
nullptr;
1631 if (LoadType != LI->
getType())
1640 if (BBI->mayWriteToMemory())
1643 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1650 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1693 if (!
SI ||
SI->getPointerOperand() != &PN)
1696 if (
SI->isVolatile())
1704 Value *StoredValue =
SI->getValueOperand();
1710 if (!SeenPreds.
insert(Pred).second)
1743 IRB.SetInsertPoint(&PN);
1745 PN.
getName() +
".sroa.speculated");
1775 IRB.SetInsertPoint(TI);
1778 LoadTy, InVal, Alignment,
1779 (PN.
getName() +
".sroa.speculate.load." + Pred->getName()));
1780 ++NumLoadsSpeculated;
1782 Load->setAAMetadata(AATags);
1784 InjectedLoads[Pred] =
Load;
1796 <<
" " <<
SI <<
"\n");
1804 if (!SeenPreds.
insert(Pred).second)
1814 bool CFGChanged =
false;
1816 for (
auto [Pred, InVal] : IncomingValues) {
1818 if (Pred->getTerminator()->getNumSuccessors() != 1) {
1820 assert(StoreBB &&
"store edge was not checked for splitting");
1827 ++NumStoresPredicated;
1831 SI.eraseFromParent();
1836SelectHandSpeculativity &
1837SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1845bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1850bool SelectHandSpeculativity::areAllSpeculatable()
const {
1851 return isSpeculatable(
true) &&
1852 isSpeculatable(
false);
1855bool SelectHandSpeculativity::areAnySpeculatable()
const {
1856 return isSpeculatable(
true) ||
1857 isSpeculatable(
false);
1859bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1860 return !areAnySpeculatable();
1863static SelectHandSpeculativity
1866 SelectHandSpeculativity
Spec;
1872 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1873 else if (PreserveCFG)
1879std::optional<RewriteableMemOps>
1880SROA::isSafeSelectToSpeculateOrPredicate(SelectInst &SI,
bool PreserveCFG) {
1881 RewriteableMemOps
Ops;
1883 for (User *U :
SI.users()) {
1886 if (
Store->isVolatile() || PreserveCFG)
1897 PossiblySpeculatableLoad
Load(LI);
1912 SelectHandSpeculativity Spec =
1914 if (PreserveCFG && !Spec.areAllSpeculatable())
1928 Value *TV =
SI.getTrueValue();
1929 Value *FV =
SI.getFalseValue();
1934 IRB.SetInsertPoint(&LI);
1938 LI.
getName() +
".sroa.speculate.load.true");
1941 LI.
getName() +
".sroa.speculate.load.false");
1942 NumLoadsSpeculated += 2;
1954 Value *V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1955 LI.
getName() +
".sroa.speculated", &
SI);
1961template <
typename T>
1963 SelectHandSpeculativity
Spec,
1970 if (
Spec.areNoneSpeculatable())
1972 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1975 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1977 if (
Spec.isSpeculatable(
true))
1983 Tail->setName(Head->
getName() +
".cont");
1988 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1989 int SuccIdx = IsThen ? 0 : 1;
1990 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
1991 auto &CondMemOp =
cast<T>(*
I.clone());
1992 if (NewMemOpBB != Head) {
1993 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1995 ++NumLoadsPredicated;
1997 ++NumStoresPredicated;
1999 CondMemOp.dropUBImplyingAttrsAndMetadata();
2000 ++NumLoadsSpeculated;
2002 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
2003 Value *Ptr =
SI.getOperand(1 + SuccIdx);
2004 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
2006 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
2014 I.replaceAllUsesWith(PN);
2019 SelectHandSpeculativity
Spec,
2030 const RewriteableMemOps &
Ops,
2032 bool CFGChanged =
false;
2035 for (
const RewriteableMemOp &
Op :
Ops) {
2036 SelectHandSpeculativity
Spec;
2038 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
2041 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
2042 I = PSL.getPointer();
2043 Spec = PSL.getInt();
2045 if (
Spec.areAllSpeculatable()) {
2048 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
2052 I->eraseFromParent();
2057 SI.eraseFromParent();
2065 const Twine &NamePrefix) {
2067 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
2068 NamePrefix +
"sroa_idx");
2069 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
2070 NamePrefix +
"sroa_cast");
2085 unsigned VScale = 0) {
2095 "We can't have the same bitwidth for different int types");
2099 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
2100 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
2127 if (NewSize != OldSize)
2143 return OldAS == NewAS ||
2144 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2145 !
DL.isNonIntegralAddressSpace(NewAS) &&
2146 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2152 return !
DL.isNonIntegralPointerType(NewTy);
2156 if (!
DL.isNonIntegralPointerType(OldTy))
2179 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2180 uint64_t BeginIndex = BeginOffset / ElementSize;
2181 if (BeginIndex * ElementSize != BeginOffset ||
2184 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2185 uint64_t EndIndex = EndOffset / ElementSize;
2186 if (EndIndex * ElementSize != EndOffset ||
2190 assert(EndIndex > BeginIndex &&
"Empty vector!");
2191 uint64_t NumElements = EndIndex - BeginIndex;
2192 Type *SliceTy = (NumElements == 1)
2193 ? Ty->getElementType()
2199 Use *U = S.getUse();
2202 if (
MI->isVolatile())
2204 if (!S.isSplittable())
2212 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2219 if (LTy->isStructTy())
2221 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2222 assert(LTy->isIntegerTy());
2228 if (
SI->isVolatile())
2230 Type *STy =
SI->getValueOperand()->getType();
2234 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2254 bool HaveCommonEltTy,
Type *CommonEltTy,
2255 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2256 VectorType *CommonVecPtrTy,
unsigned VScale) {
2258 if (CandidateTys.
empty())
2265 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2269 if (!HaveCommonEltTy && HaveVecPtrTy) {
2271 CandidateTys.
clear();
2273 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2276 if (!VTy->getElementType()->isIntegerTy())
2278 VTy->getContext(), VTy->getScalarSizeInBits())));
2285 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2286 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2287 "Cannot have vector types of different sizes!");
2288 assert(RHSTy->getElementType()->isIntegerTy() &&
2289 "All non-integer types eliminated!");
2290 assert(LHSTy->getElementType()->isIntegerTy() &&
2291 "All non-integer types eliminated!");
2297 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2298 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2299 "Cannot have vector types of different sizes!");
2300 assert(RHSTy->getElementType()->isIntegerTy() &&
2301 "All non-integer types eliminated!");
2302 assert(LHSTy->getElementType()->isIntegerTy() &&
2303 "All non-integer types eliminated!");
2307 llvm::sort(CandidateTys, RankVectorTypesComp);
2308 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2309 CandidateTys.end());
2315 assert(VTy->getElementType() == CommonEltTy &&
2316 "Unaccounted for element type!");
2317 assert(VTy == CandidateTys[0] &&
2318 "Different vector types with the same element type!");
2321 CandidateTys.resize(1);
2328 std::numeric_limits<unsigned short>::max();
2334 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2338 if (ElementSize % 8)
2340 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2341 "vector size not a multiple of element size?");
2344 for (
const Slice &S :
P)
2348 for (
const Slice *S :
P.splitSliceTails())
2354 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2361 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2362 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2364 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2367 for (
Type *Ty : OtherTys) {
2370 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2373 for (
VectorType *
const VTy : CandidateTysCopy) {
2375 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2376 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2377 unsigned ElementSize =
2378 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2382 CheckCandidateType(NewVTy);
2388 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2389 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2408 Type *CommonEltTy =
nullptr;
2410 bool HaveVecPtrTy =
false;
2411 bool HaveCommonEltTy =
true;
2412 bool HaveCommonVecPtrTy =
true;
2413 auto CheckCandidateType = [&](
Type *Ty) {
2416 if (!CandidateTys.
empty()) {
2418 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2419 DL.getTypeSizeInBits(V).getFixedValue()) {
2420 CandidateTys.
clear();
2425 Type *EltTy = VTy->getElementType();
2428 CommonEltTy = EltTy;
2429 else if (CommonEltTy != EltTy)
2430 HaveCommonEltTy =
false;
2433 HaveVecPtrTy =
true;
2434 if (!CommonVecPtrTy)
2435 CommonVecPtrTy = VTy;
2436 else if (CommonVecPtrTy != VTy)
2437 HaveCommonVecPtrTy =
false;
2443 for (
const Slice &S :
P) {
2448 Ty =
SI->getValueOperand()->getType();
2452 auto CandTy = Ty->getScalarType();
2453 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2454 S.endOffset() !=
P.endOffset())) {
2461 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2462 CheckCandidateType(Ty);
2467 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2468 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2469 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2472 CandidateTys.
clear();
2474 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2475 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2476 CommonVecPtrTy, VScale);
2487 bool &WholeAllocaOp) {
2490 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2491 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2493 Use *U = S.getUse();
2500 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2518 if (S.beginOffset() < AllocBeginOffset)
2524 WholeAllocaOp =
true;
2526 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2528 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2535 Type *ValueTy =
SI->getValueOperand()->getType();
2536 if (
SI->isVolatile())
2539 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2544 if (S.beginOffset() < AllocBeginOffset)
2550 WholeAllocaOp =
true;
2552 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2554 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2563 if (!S.isSplittable())
2580 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2586 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2604 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2606 for (
const Slice &S :
P)
2611 for (
const Slice *S :
P.splitSliceTails())
2616 return WholeAllocaOp;
2621 const Twine &Name) {
2625 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2626 "Element extends past full value");
2628 if (
DL.isBigEndian())
2629 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2630 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2632 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2635 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2636 "Cannot extract to a larger integer!");
2638 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2648 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2649 "Cannot insert a larger integer!");
2652 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2656 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2657 "Element store outside of alloca store");
2659 if (
DL.isBigEndian())
2660 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2661 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2663 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2667 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2668 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2669 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2671 V = IRB.CreateOr(Old, V, Name +
".insert");
2678 unsigned EndIndex,
const Twine &Name) {
2680 unsigned NumElements = EndIndex - BeginIndex;
2681 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2683 if (NumElements == VecTy->getNumElements())
2686 if (NumElements == 1) {
2687 V = IRB.CreateExtractElement(V, BeginIndex, Name +
".extract");
2693 V = IRB.CreateShuffleVector(V, Mask, Name +
".extract");
2699 unsigned BeginIndex,
const Twine &Name) {
2701 assert(VecTy &&
"Can only insert a vector into a vector");
2706 V = IRB.CreateInsertElement(Old, V, BeginIndex, Name +
".insert");
2714 assert(NumSubElements <= NumElements &&
"Too many elements!");
2715 if (NumSubElements == NumElements) {
2716 assert(V->getType() == VecTy &&
"Vector type mismatch");
2719 unsigned EndIndex = BeginIndex + NumSubElements;
2726 Mask.reserve(NumElements);
2727 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2728 if (Idx >= BeginIndex && Idx < EndIndex)
2729 Mask.push_back(Idx - BeginIndex);
2732 V = IRB.CreateShuffleVector(V, Mask, Name +
".expand");
2736 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2737 if (Idx >= BeginIndex && Idx < EndIndex)
2738 Mask.push_back(Idx);
2740 Mask.push_back(Idx + NumElements);
2741 V = IRB.CreateShuffleVector(V, Old, Mask, Name +
"blend");
2780 const char *DebugName) {
2781 Type *EltType = VecType->getElementType();
2782 if (EltType != NewAIEltTy) {
2784 unsigned TotalBits =
2785 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2786 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2789 V = Builder.CreateBitCast(V, NewVecType);
2790 VecType = NewVecType;
2791 LLVM_DEBUG(
dbgs() <<
" bitcast " << DebugName <<
": " << *V <<
"\n");
2795 BitcastIfNeeded(V0, VecType0,
"V0");
2796 BitcastIfNeeded(
V1, VecType1,
"V1");
2798 unsigned NumElts0 = VecType0->getNumElements();
2799 unsigned NumElts1 = VecType1->getNumElements();
2803 if (NumElts0 == NumElts1) {
2804 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2805 ShuffleMask.push_back(i);
2809 unsigned SmallSize = std::min(NumElts0, NumElts1);
2810 unsigned LargeSize = std::max(NumElts0, NumElts1);
2811 bool IsV0Smaller = NumElts0 < NumElts1;
2812 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2814 for (
unsigned i = 0; i < SmallSize; ++i)
2816 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2818 ExtendedVec = Builder.CreateShuffleVector(
2820 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2821 for (
unsigned i = 0; i < NumElts0; ++i)
2822 ShuffleMask.push_back(i);
2823 for (
unsigned i = 0; i < NumElts1; ++i)
2824 ShuffleMask.push_back(LargeSize + i);
2827 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2838class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2840 friend class InstVisitor<AllocaSliceRewriter, bool>;
2842 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2844 const DataLayout &
DL;
2847 AllocaInst &OldAI, &NewAI;
2848 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2877 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2880 bool IsSplittable =
false;
2881 bool IsSplit =
false;
2882 Use *OldUse =
nullptr;
2886 SmallSetVector<PHINode *, 8> &PHIUsers;
2887 SmallSetVector<SelectInst *, 8> &SelectUsers;
2895 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2899 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2900 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2904 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2905 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2907 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2908 VectorType *PromotableVecTy,
2909 SmallSetVector<PHINode *, 8> &PHIUsers,
2910 SmallSetVector<SelectInst *, 8> &SelectUsers)
2911 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2912 NewAllocaBeginOffset(NewAllocaBeginOffset),
2913 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2914 IntTy(IsIntegerPromotable
2917 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2919 VecTy(PromotableVecTy),
2920 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2921 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2923 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2924 IRB(*NewAI.getModule(), ConstantFolder()) {
2926 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2927 "Only multiple-of-8 sized vector elements are viable");
2930 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2933 bool visit(AllocaSlices::const_iterator
I) {
2934 bool CanSROA =
true;
2935 BeginOffset =
I->beginOffset();
2936 EndOffset =
I->endOffset();
2937 IsSplittable =
I->isSplittable();
2939 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2940 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2945 assert(BeginOffset < NewAllocaEndOffset);
2946 assert(EndOffset > NewAllocaBeginOffset);
2947 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2948 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2950 SliceSize = NewEndOffset - NewBeginOffset;
2951 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2952 <<
") NewBegin:(" << NewBeginOffset <<
", "
2953 << NewEndOffset <<
") NewAllocaBegin:("
2954 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2956 assert(IsSplit || NewBeginOffset == BeginOffset);
2957 OldUse =
I->getUse();
2961 IRB.SetInsertPoint(OldUserI);
2962 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2964 if (!IRB.getContext().shouldDiscardValueNames())
2965 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2966 Twine(BeginOffset) +
".");
3028 std::optional<SmallVector<Value *, 4>>
3029 rewriteTreeStructuredMerge(Partition &
P) {
3031 if (
P.splitSliceTails().size() > 0)
3032 return std::nullopt;
3041 :
Store(
SI), BeginOffset(Begin), EndOffset(
End), StoredValue(Val) {}
3051 LoadInst *FullLoad =
nullptr;
3052 StoreInst *InitStore =
nullptr;
3056 Type *AllocatedEltTy =
3060 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
3067 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
3069 return FixedVecTy &&
3070 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
3071 !FixedVecTy->getElementType()->isPointerTy();
3074 for (Slice &S :
P) {
3078 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
3079 S.endOffset() == NewAllocaEndOffset);
3083 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
3084 return std::nullopt;
3089 return std::nullopt;
3093 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
3105 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
3106 SI->getValueOperand()->getType()))
3107 return std::nullopt;
3109 unsigned NumElts = StVecTy->getNumElements();
3110 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
3111 if (NumElts * EltSize % AllocatedEltTySize != 0)
3112 return std::nullopt;
3117 return std::nullopt;
3120 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
3121 SI->getValueOperand());
3126 return std::nullopt;
3133 if (StoreInfos.
size() < 2)
3134 return std::nullopt;
3142 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3143 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3144 if (!IsRMWPattern && !IsStoresOnlyPattern)
3145 return std::nullopt;
3149 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3150 for (
auto &Info : StoreInfos)
3151 if (
Info.Store->getParent() != StoreBB)
3152 return std::nullopt;
3154 SmallVector<Value *, 4> DeletedValues;
3161 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3164 while (Vals.
size() > 1) {
3165 SmallVector<Value *, 8>
Next;
3166 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3172 if (Vals.
size() % 2 == 1)
3174 Vals = std::move(
Next);
3183 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3185 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3186 Merged->getType(), &NewAI, getSliceAlign(),
3188 LoadToReplace->
getName() +
".sroa.new.load");
3190 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3195 if (IsStoresOnlyPattern) {
3198 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3199 return A.BeginOffset <
B.BeginOffset;
3204 uint64_t Expected = NewAllocaBeginOffset;
3205 for (
auto &Info : StoreInfos) {
3206 if (
Info.BeginOffset != Expected)
3207 return std::nullopt;
3208 Expected =
Info.EndOffset;
3211 if (Expected != NewAllocaEndOffset)
3212 return std::nullopt;
3222 if (LoadBB == StoreBB) {
3223 for (
auto &Info : StoreInfos)
3224 if (!
Info.Store->comesBefore(FullLoad))
3225 return std::nullopt;
3229 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3230 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3231 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3232 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3233 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3234 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3247 SmallVector<Value *, 8> Vals;
3248 for (
const auto &Info : StoreInfos) {
3253 Value *Merged = TreeMerge(Vals, Builder);
3254 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3257 ReplaceFullLoad(FullLoad, Merged);
3258 return DeletedValues;
3266 return std::nullopt;
3267 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3268 return I.Load->getParent() != StoreBB;
3270 return std::nullopt;
3286 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3287 for (
const auto &L : LoadInfos)
3288 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3289 for (
const auto &S : StoreInfos)
3290 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3292 return A.Inst->comesBefore(
B.Inst);
3300 return std::nullopt;
3306 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3307 !
Accesses.back().Inst->comesBefore(FullLoad))
3308 return std::nullopt;
3319 using SliceRange = std::pair<uint64_t, uint64_t>;
3323 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3327 uint64_t Expected = NewAllocaBeginOffset;
3328 for (
auto &
Range : SortedRanges) {
3329 if (
Range.first != Expected)
3330 return std::nullopt;
3331 Expected =
Range.second;
3333 if (Expected != NewAllocaEndOffset)
3334 return std::nullopt;
3337 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3338 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3340 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3341 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3342 for (
auto &
Range : SortedRanges)
3353 if (InitVec->
getType() != NewAllocaTy)
3354 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3355 DenseMap<SliceRange, Value *> SliceValues;
3356 for (
auto &
Range : SortedRanges) {
3357 unsigned BeginIdx = getIndex(
Range.first);
3358 unsigned EndIdx = getIndex(
Range.second);
3359 SliceValues[
Range] = IRB.CreateShuffleVector(
3375 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3378 if (
V->getType() != Acc.Inst->getType()) {
3380 V = IRB.CreateBitCast(V, Acc.Inst->getType());
3382 Acc.Inst->replaceAllUsesWith(V);
3399 SmallVector<Value *, 8> Vals;
3400 for (
auto &
Range : SortedRanges)
3402 Value *Merged = TreeMerge(Vals, Builder);
3403 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3408 ReplaceFullLoad(FullLoad, Merged);
3410 return DeletedValues;
3418 bool visitInstruction(Instruction &
I) {
3426 assert(IsSplit || BeginOffset == NewBeginOffset);
3429 StringRef OldName = OldPtr->
getName();
3431 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3433 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3438 OldName = OldName.
substr(IndexEnd + 1);
3442 OldName = OldName.
substr(OffsetEnd + 1);
3446 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3458 Align getSliceAlign() {
3460 NewBeginOffset - NewAllocaBeginOffset);
3464 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3466 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3467 uint32_t
Index = RelOffset / ElementSize;
3468 assert(Index * ElementSize == RelOffset);
3472 void deleteIfTriviallyDead(
Value *V) {
3475 Pass.DeadInsts.push_back(
I);
3478 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3479 unsigned BeginIndex = getIndex(NewBeginOffset);
3480 unsigned EndIndex = getIndex(NewEndOffset);
3481 assert(EndIndex > BeginIndex &&
"Empty vector!");
3484 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3486 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3487 LLVMContext::MD_access_group});
3491 Value *rewriteIntegerLoad(LoadInst &LI) {
3492 assert(IntTy &&
"We cannot insert an integer to the alloca");
3495 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3496 V = IRB.CreateBitPreservingCastChain(
DL, V, IntTy);
3497 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3499 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3500 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3509 "Can only handle an extract for an overly wide load");
3511 V = IRB.CreateZExt(V, LI.
getType());
3515 bool visitLoadInst(LoadInst &LI) {
3524 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3526 bool IsPtrAdjusted =
false;
3529 V = rewriteVectorizedLoadInst(LI);
3531 V = rewriteIntegerLoad(LI);
3532 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3533 NewEndOffset == NewAllocaEndOffset &&
3536 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3539 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3540 LoadInst *NewLI = IRB.CreateAlignedLoad(
3541 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3542 if (LI.isVolatile())
3543 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3544 if (NewLI->isAtomic())
3545 NewLI->setAlignment(LI.getAlign());
3550 copyMetadataForLoad(*NewLI, LI);
3554 NewLI->setAAMetadata(AATags.adjustForAccess(
3555 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3563 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3564 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3565 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3566 V = IRB.CreateZExt(V, TITy,
"load.ext");
3567 if (DL.isBigEndian())
3568 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3572 Type *LTy = IRB.getPtrTy(AS);
3574 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3579 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3583 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3584 LLVMContext::MD_access_group});
3587 IsPtrAdjusted =
true;
3589 V = IRB.CreateBitPreservingCastChain(
DL, V, TargetTy);
3594 "Only integer type loads and stores are split");
3595 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3596 "Split load isn't smaller than original load");
3598 "Non-byte-multiple bit width");
3604 LIIt.setHeadBit(
true);
3605 IRB.SetInsertPoint(LIIt);
3610 Value *Placeholder =
3616 Placeholder->replaceAllUsesWith(&LI);
3617 Placeholder->deleteValue();
3622 Pass.DeadInsts.push_back(&LI);
3623 deleteIfTriviallyDead(OldOp);
3628 bool rewriteVectorizedStoreInst(
Value *V, StoreInst &SI,
Value *OldOp,
3633 if (
V->getType() != VecTy) {
3634 unsigned BeginIndex = getIndex(NewBeginOffset);
3635 unsigned EndIndex = getIndex(NewEndOffset);
3636 assert(EndIndex > BeginIndex &&
"Empty vector!");
3637 unsigned NumElements = EndIndex - BeginIndex;
3639 "Too many elements!");
3640 Type *SliceTy = (NumElements == 1)
3642 : FixedVectorType::
get(ElementTy, NumElements);
3643 if (
V->getType() != SliceTy)
3644 V = IRB.CreateBitPreservingCastChain(
DL, V, SliceTy);
3648 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3651 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3652 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3653 LLVMContext::MD_access_group});
3657 Pass.DeadInsts.push_back(&SI);
3666 bool rewriteIntegerStore(
Value *V, StoreInst &SI, AAMDNodes AATags) {
3667 assert(IntTy &&
"We cannot extract an integer from the alloca");
3669 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3671 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3673 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3674 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3678 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3679 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3680 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3681 LLVMContext::MD_access_group});
3688 Store->getValueOperand(),
DL);
3690 Pass.DeadInsts.push_back(&SI);
3695 bool visitStoreInst(StoreInst &SI) {
3697 Value *OldOp =
SI.getOperand(1);
3700 AAMDNodes AATags =
SI.getAAMetadata();
3705 if (
V->getType()->isPointerTy())
3707 Pass.PostPromotionWorklist.insert(AI);
3709 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3712 assert(
V->getType()->isIntegerTy() &&
3713 "Only integer type loads and stores are split");
3714 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3715 "Non-byte-multiple bit width");
3716 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3722 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3723 if (IntTy &&
V->getType()->isIntegerTy())
3724 return rewriteIntegerStore(V, SI, AATags);
3727 if (NewBeginOffset == NewAllocaBeginOffset &&
3728 NewEndOffset == NewAllocaEndOffset &&
3730 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3732 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3735 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3737 unsigned AS =
SI.getPointerAddressSpace();
3738 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3740 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3742 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3743 LLVMContext::MD_access_group});
3747 if (
SI.isVolatile())
3756 Pass.DeadInsts.push_back(&SI);
3757 deleteIfTriviallyDead(OldOp);
3775 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3783 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3793 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3798 bool visitMemSetInst(MemSetInst &
II) {
3802 AAMDNodes AATags =
II.getAAMetadata();
3808 assert(NewBeginOffset == BeginOffset);
3809 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3810 II.setDestAlignment(getSliceAlign());
3815 "AT: Unexpected link to non-const GEP");
3816 deleteIfTriviallyDead(OldPtr);
3821 Pass.DeadInsts.push_back(&
II);
3825 const bool CanContinue = [&]() {
3828 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3833 if (Len > std::numeric_limits<unsigned>::max())
3835 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3838 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3844 Type *SizeTy =
II.getLength()->getType();
3845 unsigned Sz = NewEndOffset - NewBeginOffset;
3848 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3849 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3855 New,
New->getRawDest(),
nullptr,
DL);
3870 assert(ElementTy == ScalarTy);
3872 unsigned BeginIndex = getIndex(NewBeginOffset);
3873 unsigned EndIndex = getIndex(NewEndOffset);
3874 assert(EndIndex > BeginIndex &&
"Empty vector!");
3875 unsigned NumElements = EndIndex - BeginIndex;
3877 "Too many elements!");
3880 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3881 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3882 if (NumElements > 1)
3885 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3894 V = getIntegerSplat(
II.getValue(),
Size);
3896 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3897 NewEndOffset != NewAllocaEndOffset)) {
3898 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3900 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3904 assert(
V->getType() == IntTy &&
3905 "Wrong type for an alloca wide integer!");
3907 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3910 assert(NewBeginOffset == NewAllocaBeginOffset);
3911 assert(NewEndOffset == NewAllocaEndOffset);
3913 V = getIntegerSplat(
II.getValue(),
3914 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3919 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3922 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3924 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3925 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3926 LLVMContext::MD_access_group});
3932 New,
New->getPointerOperand(), V,
DL);
3935 return !
II.isVolatile();
3938 bool visitMemTransferInst(MemTransferInst &
II) {
3944 AAMDNodes AATags =
II.getAAMetadata();
3946 bool IsDest = &
II.getRawDestUse() == OldUse;
3947 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3948 (!IsDest &&
II.getRawSource() == OldPtr));
3950 Align SliceAlign = getSliceAlign();
3958 if (!IsSplittable) {
3959 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3964 DbgAssign->getAddress() ==
II.getDest())
3965 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3967 II.setDest(AdjustedPtr);
3968 II.setDestAlignment(SliceAlign);
3970 II.setSource(AdjustedPtr);
3971 II.setSourceAlignment(SliceAlign);
3975 deleteIfTriviallyDead(OldPtr);
3988 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3989 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
3990 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
3996 if (EmitMemCpy && &OldAI == &NewAI) {
3998 assert(NewBeginOffset == BeginOffset);
4001 if (NewEndOffset != EndOffset)
4002 II.setLength(NewEndOffset - NewBeginOffset);
4006 Pass.DeadInsts.push_back(&
II);
4010 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
4011 if (AllocaInst *AI =
4013 assert(AI != &OldAI && AI != &NewAI &&
4014 "Splittable transfers cannot reach the same alloca on both ends.");
4015 Pass.Worklist.insert(AI);
4022 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
4023 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
4025 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
4027 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
4035 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4036 Type *SizeTy =
II.getLength()->getType();
4037 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
4039 Value *DestPtr, *SrcPtr;
4040 MaybeAlign DestAlign, SrcAlign;
4044 DestAlign = SliceAlign;
4046 SrcAlign = OtherAlign;
4049 DestAlign = OtherAlign;
4051 SrcAlign = SliceAlign;
4053 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
4056 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
4061 &
II, New, DestPtr,
nullptr,
DL);
4066 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
4072 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
4073 NewEndOffset == NewAllocaEndOffset;
4075 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
4076 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
4077 unsigned NumElements = EndIndex - BeginIndex;
4078 IntegerType *SubIntTy =
4079 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
4084 if (VecTy && !IsWholeAlloca) {
4085 if (NumElements == 1)
4086 OtherTy = VecTy->getElementType();
4089 }
else if (IntTy && !IsWholeAlloca) {
4092 OtherTy = NewAllocaTy;
4097 MaybeAlign SrcAlign = OtherAlign;
4098 MaybeAlign DstAlign = SliceAlign;
4106 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
4110 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
4114 if (VecTy && !IsWholeAlloca && !IsDest) {
4116 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4118 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
4120 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4121 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
4125 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
4126 II.isVolatile(),
"copyload");
4127 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4128 LLVMContext::MD_access_group});
4135 if (VecTy && !IsWholeAlloca && IsDest) {
4136 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4139 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4140 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4142 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4145 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4149 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4150 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4151 LLVMContext::MD_access_group});
4154 Src->getType(),
DL));
4169 return !
II.isVolatile();
4172 bool visitIntrinsicInst(IntrinsicInst &
II) {
4173 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4174 "Unexpected intrinsic!");
4178 Pass.DeadInsts.push_back(&
II);
4180 if (
II.isDroppable()) {
4181 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4187 assert(
II.getArgOperand(0) == OldPtr);
4191 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4192 New = IRB.CreateLifetimeStart(Ptr);
4194 New = IRB.CreateLifetimeEnd(Ptr);
4202 void fixLoadStoreAlign(Instruction &Root) {
4206 SmallPtrSet<Instruction *, 4> Visited;
4207 SmallVector<Instruction *, 4>
Uses;
4209 Uses.push_back(&Root);
4218 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4225 for (User *U :
I->users())
4228 }
while (!
Uses.empty());
4231 bool visitPHINode(PHINode &PN) {
4233 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4234 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4240 IRBuilderBase::InsertPointGuard Guard(IRB);
4242 IRB.SetInsertPoint(OldPtr->
getParent()->getFirstInsertionPt());
4244 IRB.SetInsertPoint(OldPtr);
4245 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4247 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4252 deleteIfTriviallyDead(OldPtr);
4255 fixLoadStoreAlign(PN);
4264 bool visitSelectInst(SelectInst &SI) {
4266 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4267 "Pointer isn't an operand!");
4268 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4269 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4271 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4273 if (
SI.getOperand(1) == OldPtr)
4274 SI.setOperand(1, NewPtr);
4275 if (
SI.getOperand(2) == OldPtr)
4276 SI.setOperand(2, NewPtr);
4279 deleteIfTriviallyDead(OldPtr);
4282 fixLoadStoreAlign(SI);
4297class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4299 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4305 SmallPtrSet<User *, 8> Visited;
4312 const DataLayout &
DL;
4317 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4318 :
DL(
DL), IRB(IRB) {}
4322 bool rewrite(Instruction &
I) {
4326 while (!
Queue.empty()) {
4327 U =
Queue.pop_back_val();
4336 void enqueueUsers(Instruction &
I) {
4337 for (Use &U :
I.uses())
4338 if (Visited.
insert(
U.getUser()).second)
4339 Queue.push_back(&U);
4343 bool visitInstruction(Instruction &
I) {
return false; }
4346 template <
typename Derived>
class OpSplitter {
4353 SmallVector<unsigned, 4> Indices;
4357 SmallVector<Value *, 4> GEPIndices;
4371 const DataLayout &
DL;
4375 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4376 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4377 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4378 BaseAlign(BaseAlign),
DL(
DL) {
4379 IRB.SetInsertPoint(InsertionPoint);
4396 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4398 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4399 return static_cast<Derived *
>(
this)->emitFunc(
4404 unsigned OldSize = Indices.
size();
4406 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4408 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4410 GEPIndices.
push_back(IRB.getInt32(Idx));
4411 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4419 unsigned OldSize = Indices.
size();
4421 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4423 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4425 GEPIndices.
push_back(IRB.getInt32(Idx));
4426 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4437 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4441 SmallVector<Value *, 4> Components;
4446 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4447 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4449 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4455 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4459 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4461 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4467 Load->setAAMetadata(
4473 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4478 void recordFakeUses(LoadInst &LI) {
4479 for (Use &U : LI.
uses())
4481 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4487 void emitFakeUses() {
4488 for (Instruction *
I : FakeUses) {
4489 IRB.SetInsertPoint(
I);
4490 for (
auto *V : Components)
4491 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4492 I->eraseFromParent();
4497 bool visitLoadInst(LoadInst &LI) {
4506 Splitter.recordFakeUses(LI);
4509 Splitter.emitFakeUses();
4516 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4517 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4518 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4519 const DataLayout &
DL, IRBuilderTy &IRB)
4520 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4522 AATags(AATags), AggStore(AggStore) {}
4524 StoreInst *AggStore;
4527 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4533 Value *ExtractValue =
4534 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4535 Value *InBoundsGEP =
4536 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4538 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4555 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4557 SizeInBits, AggStore,
Store,
4558 Store->getPointerOperand(),
Store->getValueOperand(),
4562 "AT: unexpected debug.assign linked to store through "
4569 bool visitStoreInst(StoreInst &SI) {
4570 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4573 if (
V->getType()->isSingleValueType())
4578 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4580 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4585 SI.eraseFromParent();
4589 bool visitBitCastInst(BitCastInst &BC) {
4594 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4604 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4623 if (!ZI->getSrcTy()->isIntegerTy(1))
4636 dbgs() <<
" original: " << *Sel <<
"\n";
4637 dbgs() <<
" " << GEPI <<
"\n";);
4639 auto GetNewOps = [&](
Value *SelOp) {
4652 Cond =
SI->getCondition();
4653 True =
SI->getTrueValue();
4657 Cond = Sel->getOperand(0);
4658 True = ConstantInt::get(Sel->getType(), 1);
4659 False = ConstantInt::get(Sel->getType(), 0);
4664 IRB.SetInsertPoint(&GEPI);
4668 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4669 True->getName() +
".sroa.gep", NW);
4672 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4673 False->getName() +
".sroa.gep", NW);
4675 Value *NSel = MDFrom
4676 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4677 Sel->getName() +
".sroa.sel", MDFrom)
4678 : IRB.CreateSelectWithUnknownProfile(
4680 Sel->getName() +
".sroa.sel");
4681 Visited.
erase(&GEPI);
4686 enqueueUsers(*NSelI);
4689 dbgs() <<
" " << *NFalse <<
"\n";
4690 dbgs() <<
" " << *NSel <<
"\n";);
4699 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4704 auto IsInvalidPointerOperand = [](
Value *
V) {
4708 return !AI->isStaticAlloca();
4712 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4727 [](
Value *V) { return isa<ConstantInt>(V); }))
4740 dbgs() <<
" original: " << *
Phi <<
"\n";
4741 dbgs() <<
" " << GEPI <<
"\n";);
4743 auto GetNewOps = [&](
Value *PhiOp) {
4753 IRB.SetInsertPoint(Phi);
4754 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4755 Phi->getName() +
".sroa.phi");
4761 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4770 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4776 Visited.
erase(&GEPI);
4780 enqueueUsers(*NewPhi);
4786 dbgs() <<
"\n " << *NewPhi <<
'\n');
4791 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4792 if (unfoldGEPSelect(GEPI))
4795 if (unfoldGEPPhi(GEPI))
4802 bool visitPHINode(PHINode &PN) {
4807 bool visitSelectInst(SelectInst &SI) {
4821 if (Ty->isSingleValueType())
4824 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4829 InnerTy = ArrTy->getElementType();
4833 InnerTy = STy->getElementType(Index);
4838 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4839 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4860 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4862 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4863 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4870 ElementTy = AT->getElementType();
4871 TyNumElements = AT->getNumElements();
4876 ElementTy = VT->getElementType();
4877 TyNumElements = VT->getNumElements();
4879 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4881 if (NumSkippedElements >= TyNumElements)
4883 Offset -= NumSkippedElements * ElementSize;
4895 if (
Size == ElementSize)
4899 if (NumElements * ElementSize !=
Size)
4923 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4924 if (
Offset >= ElementSize)
4935 if (
Size == ElementSize)
4942 if (Index == EndIndex)
4952 assert(Index < EndIndex);
4972 InstructionSliceMap &SliceMap) {
4974 if (S.endOffset() - S.beginOffset() == 1)
4992 for (Slice *JS : SliceMap[J]) {
4993 if (S.beginOffset() > JS->beginOffset() &&
4994 S.beginOffset() < JS->endOffset())
4996 if (JS->beginOffset() > S.beginOffset() &&
4997 JS->beginOffset() < S.endOffset())
5028bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
5042 struct SplitOffsets {
5044 std::vector<uint64_t> Splits;
5046 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
5059 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
5061 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
5062 for (
auto &
P : AS.partitions()) {
5063 InstructionSliceMap SliceMap;
5064 for (Slice &S :
P) {
5067 for (Slice &S :
P) {
5069 bool ExtendsPastPartitionEnd = S.endOffset() >
P.endOffset();
5071 if (!S.isSplittable() || (!ExtendsPastPartitionEnd && !CopyOverlap)) {
5076 UnsplittableLoads.
insert(LI);
5079 UnsplittableLoads.
insert(LI);
5082 assert(
P.endOffset() > S.beginOffset() &&
5083 "Empty or backwards partition!");
5092 auto IsLoadSimplyStored = [](LoadInst *LI) {
5093 for (User *LU : LI->
users()) {
5095 if (!SI || !
SI->isSimple())
5100 if (!IsLoadSimplyStored(LI)) {
5101 UnsplittableLoads.
insert(LI);
5107 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
5111 if (!StoredLoad || !StoredLoad->isSimple())
5113 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
5123 auto &
Offsets = SplitOffsetsMap[
I];
5125 "Should not have splits the first time we see an instruction!");
5140 std::max(S.beginOffset(), CopyOverlap->beginOffset());
5141 uint64_t OverlapEnd = std::min(S.endOffset(), CopyOverlap->endOffset());
5142 uint64_t OverlapSize = OverlapEnd - OverlapStart;
5143 uint64_t SliceSize = S.endOffset() - S.beginOffset();
5144 uint64_t NonOverlapSize = SliceSize - OverlapSize;
5145 if (OverlapSize < NonOverlapSize) {
5150 Offsets.Splits.push_back(OverlapSize);
5151 Offsets.Splits.push_back(SliceSize - OverlapSize);
5152 }
else if (OverlapSize > NonOverlapSize) {
5155 for (
uint64_t Split = NonOverlapSize;
Split <= SliceSize / 2;
5156 Split += NonOverlapSize) {
5157 Offsets.Splits.push_back(Split);
5158 if (Split != SliceSize - Split) {
5159 Offsets.Splits.push_back(SliceSize - Split);
5167 Offsets.Splits.push_back(OverlapSize);
5170 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
5179 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5185 if (UnsplittableLoads.
count(LI))
5188 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5189 if (LoadOffsetsI == SplitOffsetsMap.
end())
5191 auto &LoadOffsets = LoadOffsetsI->second;
5194 auto &StoreOffsets = SplitOffsetsMap[
SI];
5199 if (LoadOffsets.Splits == StoreOffsets.Splits)
5203 <<
" " << *LI <<
"\n"
5204 <<
" " << *SI <<
"\n");
5210 UnsplittableLoads.
insert(LI);
5219 return UnsplittableLoads.
count(LI);
5224 return UnsplittableLoads.
count(LI);
5234 IRBuilderTy IRB(&AI);
5241 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5251 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5252 std::vector<LoadInst *> SplitLoads;
5253 const DataLayout &
DL = AI.getDataLayout();
5254 for (LoadInst *LI : Loads) {
5257 auto &
Offsets = SplitOffsetsMap[LI];
5258 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5260 "Load must have type size equal to store size");
5262 "Load must be >= slice size");
5265 assert(BaseOffset + SliceSize > BaseOffset &&
5266 "Cannot represent alloca access size using 64-bit integers!");
5269 IRB.SetInsertPoint(LI);
5276 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5279 LoadInst *PLoad = IRB.CreateAlignedLoad(
5282 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5283 PartPtrTy,
BasePtr->getName() +
"."),
5286 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5287 LLVMContext::MD_access_group});
5291 SplitLoads.push_back(PLoad);
5295 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5299 <<
", " << NewSlices.
back().endOffset()
5300 <<
"): " << *PLoad <<
"\n");
5315 bool DeferredStores =
false;
5316 for (User *LU : LI->
users()) {
5318 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5319 DeferredStores =
true;
5325 Value *StoreBasePtr =
SI->getPointerOperand();
5326 IRB.SetInsertPoint(SI);
5327 AAMDNodes AATags =
SI->getAAMetadata();
5329 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5331 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5332 LoadInst *PLoad = SplitLoads[
Idx];
5334 auto *PartPtrTy =
SI->getPointerOperandType();
5336 auto AS =
SI->getPointerAddressSpace();
5337 StoreInst *PStore = IRB.CreateAlignedStore(
5340 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5341 PartPtrTy, StoreBasePtr->
getName() +
"."),
5344 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5345 LLVMContext::MD_access_group,
5346 LLVMContext::MD_DIAssignID});
5351 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5359 ResplitPromotableAllocas.
insert(OtherAI);
5360 Worklist.insert(OtherAI);
5363 Worklist.insert(OtherAI);
5367 DeadInsts.push_back(SI);
5372 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5375 DeadInsts.push_back(LI);
5384 for (StoreInst *SI : Stores) {
5389 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5393 "Slice size should always match load size exactly!");
5395 assert(BaseOffset + StoreSize > BaseOffset &&
5396 "Cannot represent alloca access size using 64-bit integers!");
5404 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5405 std::vector<LoadInst *> *SplitLoads =
nullptr;
5406 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5407 SplitLoads = &SplitLoadsMapI->second;
5409 "Too few split loads for the number of splits in the store!");
5417 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5419 auto *StorePartPtrTy =
SI->getPointerOperandType();
5424 PLoad = (*SplitLoads)[
Idx];
5426 IRB.SetInsertPoint(LI);
5428 PLoad = IRB.CreateAlignedLoad(
5431 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5432 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5435 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5436 LLVMContext::MD_access_group});
5440 IRB.SetInsertPoint(SI);
5441 auto AS =
SI->getPointerAddressSpace();
5442 StoreInst *PStore = IRB.CreateAlignedStore(
5445 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5446 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5449 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5450 LLVMContext::MD_access_group});
5454 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5458 <<
", " << NewSlices.
back().endOffset()
5459 <<
"): " << *PStore <<
"\n");
5481 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5482 ResplitPromotableAllocas.
insert(OtherAI);
5483 Worklist.insert(OtherAI);
5486 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5487 Worklist.insert(OtherAI);
5502 DeadInsts.push_back(LI);
5504 DeadInsts.push_back(SI);
5513 AS.insert(NewSlices);
5517 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5523 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5560 bool IsIntegralPointerTy =
5561 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5563 !IsIntegralPointerTy)
5570 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5574 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5575 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5578 if (StructSize != VectorSize)
5581 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5584 auto *U = S.getUse();
5588 for (
const Slice &S :
P)
5589 if (!IsIgnorableOrMemIntrinsicSlice(S))
5592 for (
const Slice *S :
P.splitSliceTails())
5593 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5610static std::tuple<Type *, bool, VectorType *>
5614 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5616 dbgs() <<
"selectPartitionType path=" << Path
5621 dbgs() <<
"<unnamed>";
5622 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5623 <<
") size=" <<
P.size();
5625 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5627 dbgs() <<
" chosen=" << *SelectedTy;
5629 dbgs() <<
" vec=" << *SelectedVecTy;
5630 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5648 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5649 VecTy->getElementCount().getFixedValue() > 1) {
5650 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5651 return {VecTy,
false, VecTy};
5656 auto [CommonUseTy, LargestIntTy] =
5659 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5665 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5666 return {VecTy,
false, VecTy};
5669 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5670 return {CommonUseTy, IntWiden,
nullptr};
5677 P.beginOffset(),
P.size())) {
5681 if (TypePartitionTy->isArrayTy() &&
5682 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5683 DL.isLegalInteger(
P.size() * 8))
5687 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5688 return {TypePartitionTy,
true,
nullptr};
5691 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5692 return {VecTy,
false, VecTy};
5697 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5699 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5700 return {LargestIntTy,
true,
nullptr};
5705 if (AggregateToVector) {
5708 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5709 return {VTy,
false,
nullptr};
5715 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5716 return {TypePartitionTy,
false,
nullptr};
5721 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5722 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5723 return {LargestIntTy,
false,
nullptr};
5727 if (
DL.isLegalInteger(
P.size() * 8)) {
5729 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5730 return {IntTy,
false,
nullptr};
5735 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5736 return {ArrayTy,
false,
nullptr};
5749std::pair<AllocaInst *, uint64_t>
5750SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5751 const DataLayout &
DL = AI.getDataLayout();
5753 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5763 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5772 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5773 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5781 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5782 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5787 unsigned PPWOldSize = PostPromotionWorklist.size();
5788 unsigned NumUses = 0;
5789 SmallSetVector<PHINode *, 8> PHIUsers;
5790 SmallSetVector<SelectInst *, 8> SelectUsers;
5793 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5794 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5795 bool Promotable =
true;
5797 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5798 NumUses += DeletedValues->
size() + 1;
5799 for (
Value *V : *DeletedValues)
5800 DeadInsts.push_back(V);
5802 for (Slice *S :
P.splitSliceTails()) {
5806 for (Slice &S :
P) {
5812 NumAllocaPartitionUses += NumUses;
5813 MaxUsesPerAllocaPartition.updateMax(NumUses);
5819 for (PHINode *
PHI : PHIUsers) {
5830 SelectUsers.
clear();
5835 NewSelectsToRewrite;
5837 for (SelectInst *Sel : SelectUsers) {
5838 std::optional<RewriteableMemOps>
Ops =
5839 isSafeSelectToSpeculateOrPredicate(*Sel, PreserveCFG);
5848 for (Use *U : AS.getDeadUsesIfPromotable()) {
5850 Value::dropDroppableUse(*U);
5853 DeadInsts.push_back(OldInst);
5855 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5856 SelectUsers.empty()) {
5858 PromotableAllocas.insert(NewAI);
5863 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5864 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5865 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5866 NewSelectsToRewrite.
size());
5868 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5869 std::make_move_iterator(NewSelectsToRewrite.
end())))
5870 SelectsToRewrite.insert(std::move(KV));
5871 Worklist.insert(NewAI);
5875 while (PostPromotionWorklist.size() > PPWOldSize)
5876 PostPromotionWorklist.pop_back();
5881 return {
nullptr, 0};
5886 Worklist.insert(NewAI);
5889 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5933 int64_t BitExtractOffset) {
5935 bool HasFragment =
false;
5936 bool HasBitExtract =
false;
5944 HasBitExtract =
true;
5945 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5946 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5955 assert(BitExtractOffset <= 0);
5956 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5962 if (AdjustedOffset < 0)
5965 Ops.push_back(
Op.getOp());
5966 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5967 Ops.push_back(ExtractSizeInBits);
5970 Op.appendToVector(
Ops);
5975 if (HasFragment && HasBitExtract)
5978 if (!HasBitExtract) {
5997 std::optional<DIExpression::FragmentInfo> NewFragment,
5998 int64_t BitExtractAdjustment) {
6008 BitExtractAdjustment);
6009 if (!NewFragmentExpr)
6015 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6028 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6034 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
6042 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
6048bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
6049 if (AS.begin() == AS.end())
6052 unsigned NumPartitions = 0;
6054 const DataLayout &
DL = AI.getDataLayout();
6057 Changed |= presplitLoadsAndStores(AI, AS);
6065 bool IsSorted =
true;
6067 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
6075 SparseBitVector<> SplittableOffset;
6077 for (Slice &S : AS) {
6079 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
6081 if (S.beginOffset() >= CurEnd) {
6082 SplittableOffset.
set(S.beginOffset());
6085 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6086 SplittableOffset.
reset(CurEnd);
6088 CurBegin = S.beginOffset();
6092 if (S.endOffset() > CurEnd) {
6093 CurEnd = S.endOffset();
6094 SplittableOffset.
set(CurEnd);
6099 for (Slice &S : AS) {
6100 if (!S.isSplittable())
6103 if ((S.beginOffset() > AllocaSize ||
6104 SplittableOffset.
test(S.beginOffset())) &&
6105 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6110 S.makeUnsplittable();
6130 for (
auto &
P : AS.partitions()) {
6131 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6135 uint64_t SizeOfByte = 8;
6137 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6138 Fragments.push_back(
6139 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6145 NumAllocaPartitions += NumPartitions;
6146 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6150 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6155 const Value *DbgPtr = DbgVariable->getAddress();
6157 DbgVariable->getFragmentOrEntireVariable();
6160 int64_t CurrentExprOffsetInBytes = 0;
6161 SmallVector<uint64_t> PostOffsetOps;
6163 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6167 int64_t ExtractOffsetInBits = 0;
6170 ExtractOffsetInBits = Extract.getOffsetInBits();
6175 DIBuilder DIB(*AI.getModule(),
false);
6177 int64_t OffsetFromLocationInBits;
6178 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6184 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6185 NewDbgFragment, OffsetFromLocationInBits))
6191 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6196 if (!NewDbgFragment)
6197 NewDbgFragment = DbgVariable->getFragment();
6201 int64_t OffestFromNewAllocaInBits =
6202 OffsetFromLocationInBits - ExtractOffsetInBits;
6205 int64_t BitExtractOffset =
6206 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6211 OffestFromNewAllocaInBits =
6212 std::max(int64_t(0), OffestFromNewAllocaInBits);
6218 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6219 if (OffestFromNewAllocaInBits > 0) {
6220 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6226 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6227 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6228 return LHS->getVariable() ==
RHS->getVariable() &&
6229 LHS->getDebugLoc()->getInlinedAt() ==
6230 RHS->getDebugLoc()->getInlinedAt();
6232 if (SameVariableFragment(OldDII, DbgVariable))
6233 OldDII->eraseFromParent();
6238 NewDbgFragment, BitExtractOffset);
6252void SROA::clobberUse(Use &U) {
6262 DeadInsts.push_back(OldI);
6284bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6289 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6290 bool AllSameAndValid =
true;
6291 Type *PartitionType =
nullptr;
6292 SmallVector<Instruction *> Insts;
6296 auto Flush = [&]() {
6297 if (AllSameAndValid && !Insts.
empty()) {
6298 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6299 << EndOffset <<
")\n");
6301 SSAUpdater
SSA(&NewPHIs);
6303 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6304 Promoter.run(Insts);
6306 AllSameAndValid =
true;
6307 PartitionType =
nullptr;
6311 for (Slice &S : AS) {
6315 dbgs() <<
"Ignoring slice: ";
6316 AS.print(
dbgs(), &S);
6320 if (S.beginOffset() >= EndOffset) {
6322 BeginOffset = S.beginOffset();
6323 EndOffset = S.endOffset();
6324 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6325 if (AllSameAndValid) {
6327 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6328 << EndOffset <<
")";
6329 AS.print(
dbgs(), &S);
6331 AllSameAndValid =
false;
6333 EndOffset = std::max(EndOffset, S.endOffset());
6340 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6341 AllSameAndValid =
false;
6342 PartitionType = UserTy;
6345 Type *UserTy =
SI->getValueOperand()->getType();
6346 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6347 AllSameAndValid =
false;
6348 PartitionType = UserTy;
6351 AllSameAndValid =
false;
6364std::pair<
bool ,
bool >
6365SROA::runOnAlloca(AllocaInst &AI) {
6367 bool CFGChanged =
false;
6370 ++NumAllocasAnalyzed;
6373 if (AI.use_empty()) {
6374 AI.eraseFromParent();
6378 const DataLayout &
DL = AI.getDataLayout();
6381 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6382 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6387 IRBuilderTy IRB(&AI);
6388 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6389 Changed |= AggRewriter.rewrite(AI);
6392 AllocaSlices AS(
DL, AI);
6397 if (AS.isEscapedReadOnly()) {
6398 Changed |= propagateStoredValuesToLoads(AI, AS);
6403 for (Instruction *DeadUser : AS.getDeadUsers()) {
6405 for (Use &DeadOp : DeadUser->operands())
6412 DeadInsts.push_back(DeadUser);
6415 for (Use *DeadOp : AS.getDeadOperands()) {
6416 clobberUse(*DeadOp);
6421 if (AS.begin() == AS.end())
6424 Changed |= splitAlloca(AI, AS);
6427 while (!SpeculatablePHIs.empty())
6431 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6432 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6433 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6439 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6440 while (!RemainingSelectsToRewrite.empty()) {
6441 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6458bool SROA::deleteDeadInstructions(
6459 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6461 while (!DeadInsts.empty()) {
6471 DeletedAllocas.
insert(AI);
6473 OldDII->eraseFromParent();
6479 for (Use &Operand :
I->operands())
6484 DeadInsts.push_back(U);
6488 I->eraseFromParent();
6498bool SROA::promoteAllocas() {
6499 if (PromotableAllocas.empty())
6502 if (
C->getLibraryOptions().get<ScalarOptions>().sroa_skip_mem2reg) {
6506 NumPromoted += PromotableAllocas.size();
6507 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6510 PromotableAllocas.clear();
6514std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6517 const DataLayout &
DL =
F.getDataLayout();
6522 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6524 PromotableAllocas.insert(AI);
6526 Worklist.insert(AI);
6531 bool CFGChanged =
false;
6534 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6537 while (!Worklist.empty()) {
6538 auto [IterationChanged, IterationCFGChanged] =
6539 runOnAlloca(*Worklist.pop_back_val());
6541 CFGChanged |= IterationCFGChanged;
6543 Changed |= deleteDeadInstructions(DeletedAllocas);
6547 if (!DeletedAllocas.
empty()) {
6548 Worklist.set_subtract(DeletedAllocas);
6549 PostPromotionWorklist.set_subtract(DeletedAllocas);
6550 PromotableAllocas.set_subtract(DeletedAllocas);
6551 DeletedAllocas.
clear();
6557 Worklist = PostPromotionWorklist;
6558 PostPromotionWorklist.clear();
6559 }
while (!Worklist.empty());
6561 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6562 assert((!CFGChanged || !PreserveCFG) &&
6563 "Should not have modified the CFG when told to preserve it.");
6566 for (
auto &BB :
F) {
6579 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6591 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6592 OS, MapClassName2PassName);
6596 if (Options.AggregateToVector)
6597 OS <<
";aggregate-to-vector";
6618 if (skipFunction(
F))
6621 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6623 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6629 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6636 StringRef getPassName()
const override {
return "SROA"; }
6641char SROALegacyPass::ID = 0;
6646 AggregateToVector));
6650 "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(Mod->getContext(), Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PointerIntPair class.
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
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 Slice * findOverlappingCopySlice(Slice &S, InstructionSliceMap &SliceMap)
Try to find a slice in the map that partially overlaps with S, i.e.
static Value * foldSelectInst(SelectInst &SI)
bool isKillAddress(const DbgVariableRecord *DVR)
static Value * insertVector(IRBuilderTy &IRB, Value *Old, Value *V, unsigned BeginIndex, const Twine &Name)
static bool isIntegerWideningViable(Partition &P, Type *AllocaTy, const DataLayout &DL)
Test whether the given alloca partition's integer operations can be widened to promotable ones.
static void speculatePHINodeLoads(IRBuilderTy &IRB, PHINode &PN)
static VectorType * createAndCheckVectorTypesForPromotion(SetVector< Type * > &OtherTys, ArrayRef< VectorType * > CandidateTysCopy, function_ref< void(Type *)> CheckCandidateType, Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool &HaveCommonEltTy, Type *&CommonEltTy, bool &HaveVecPtrTy, bool &HaveCommonVecPtrTy, VectorType *&CommonVecPtrTy, unsigned VScale)
static DebugVariable getAggregateVariable(DbgVariableRecord *DVR)
static std::tuple< Type *, bool, VectorType * > selectPartitionType(Partition &P, const DataLayout &DL, AllocaInst &AI, LLVMContext &C, bool AggregateToVector)
Select a partition type for an alloca partition.
static bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
static FixedVectorType * tryCanonicalizeStructToVector(StructType *STy, Partition &P, const DataLayout &DL)
Try to canonicalize a homogeneous struct partition to a vector type.
static Value * extractInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *V, IntegerType *Ty, uint64_t Offset, const Twine &Name)
static void insertNewDbgInst(DIBuilder &DIB, DbgVariableRecord *Orig, AllocaInst *NewAddr, DIExpression *NewAddrExpr, Instruction *BeforeInst, std::optional< DIExpression::FragmentInfo > NewFragment, int64_t BitExtractAdjustment)
Insert a new DbgRecord.
static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, IRBuilderTy &IRB)
static Value * mergeTwoVectors(Value *V0, Value *V1, const DataLayout &DL, Type *NewAIEltTy, IRBuilder<> &Builder)
This function takes two vector values and combines them into a single vector by concatenating their e...
const DIExpression * getAddressExpression(const DbgVariableRecord *DVR)
static Type * getTypePartition(const DataLayout &DL, Type *Ty, uint64_t Offset, uint64_t Size)
Try to find a partition of the aggregate type passed in for a given offset and size.
static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy, unsigned VScale=0)
Test whether we can convert a value from the old to the new type.
static SelectHandSpeculativity isSafeLoadOfSelectToSpeculate(LoadInst &LI, SelectInst &SI, bool PreserveCFG)
static StoreInst * getPHIStoreToRewrite(PHINode &PN, bool PreserveCFG, DominatorTree &DT)
Check whether a single store through PN can be moved onto each incoming edge.
static Type * findCommonTypeThroughPHIOrSelect(Instruction &I)
Find a common load/store type used through a pointer PHI or select.
This file provides the interface for LLVM's Scalar Replacement of Aggregates pass.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the SparseBitVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
virt reg Virtual Register Rewriter
Builder for the alloca slices.
SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
An iterator over partitions of the alloca's slices.
bool operator==(const partition_iterator &RHS) const
friend class AllocaSlices
partition_iterator & operator++()
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrPseudoProbe() const
Returns an iterator to the first instruction in this block that is not a PHINode or a pseudo operatio...
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI bool canSplitPredecessors() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
LLVM_ABI CaptureInfo getCaptureInfo(unsigned OpNo) const
Return which pointer components this operand may capture.
bool onlyReadsMemory(unsigned OpNo) const
bool isDataOperand(const Use *U) const
This is the shared class of boolean and integer constants.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
LLVM_ABI DbgRecord * insertDbgAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *SrcVar, DIExpression *ValExpr, Value *Addr, DIExpression *AddrExpr, const DILocation *DL)
Insert a new dbg_assign record.
iterator_range< expr_op_iterator > expr_ops() const
DbgVariableFragmentInfo FragmentInfo
LLVM_ABI bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits, int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag, std::optional< DIExpression::FragmentInfo > &Result, int64_t &OffsetFromLocationInBits)
Computes a fragment, bit-extract operation if needed, and new constant offset to describe a part of a...
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI void moveBefore(DbgRecord *MoveBefore)
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI void setKillAddress()
Kill the address component.
LLVM_ABI bool isKillLocation() const
LocationType getType() const
LLVM_ABI bool isKillAddress() const
Check whether this kills the address component.
LLVM_ABI void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
Value * getValue(unsigned OpIdx=0) const
static LLVM_ABI DbgVariableRecord * createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, DIExpression *Expression, Value *Address, DIExpression *AddressExpression, const DILocation *DI)
LLVM_ABI void setAssignId(DIAssignID *New)
DIExpression * getExpression() const
static LLVM_ABI DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
static LLVM_ABI DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
DILocalVariable * getVariable() const
LLVM_ABI void setKillLocation()
bool isDbgDeclare() const
void setAddress(Value *V)
DIExpression * getAddressExpression() const
LLVM_ABI DILocation * getInlinedAt() const
Identifies a unique instance of a variable.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getVScaleValue() const
Return the value for vscale based on the vscale_range attribute or 0 when unknown.
const BasicBlock & getEntryBlock() const
LLVM_ABI bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
Value * getPointerOperand()
iterator_range< op_iterator > indices()
Type * getSourceElementType() const
LLVM_ABI GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
This provides the default implementation of the IRBuilder 'InsertHelper' method that is called whenev...
void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerIntPair - This class implements a pair of a pointer and small integer.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PtrUseVisitor(const DataLayout &DL)
LLVM_ABI SROAPass(SROAOptions Options)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Helper class for SSA formation on a set of values defined in multiple blocks.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void clear()
Completely clear the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool test(unsigned Idx) const
An instruction for storing to memory.
void setAlignment(Align Align)
Value * getValueOperand()
static unsigned getPointerOperandIndex()
Value * getPointerOperand()
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getSizeInBytes() const
LLVM_ABI unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
TypeSize getElementOffset(unsigned Idx) const
TypeSize getSizeInBits() const
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
element_iterator element_end() const
ArrayRef< Type * > elements() const
element_iterator element_begin() const
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Type::subtype_iterator element_iterator
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
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.
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
LLVM_ABI void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static VectorType * getWithSizeAndScalar(VectorType *SizeTy, Type *EltTy)
This static method attempts to construct a VectorType with the same size-in-bits as SizeTy but with a...
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
unsigned getNumElements(Type *Ty)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
LLVM_ABI bool RemoveRedundantDbgInstrs(BasicBlock *BB)
Try to remove redundant dbg.value instructions from given basic block.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
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.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void initializeSROALegacyPassPass(PassRegistry &)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRValues(Value *V)
As above, for DVRValues.
LLVM_ABI void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ, bool IgnoreFree=false)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI Align tryEnforceAlignment(Value *V, Align PrefAlign, const DataLayout &DL)
If the specified pointer points to an object that we control, try to modify the object's alignment to...
LLVM_ABI FunctionPass * createSROAPass(bool PreserveCFG=true, bool AggregateToVector=false)
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI std::optional< Register > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
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.