102#define DEBUG_TYPE "sroa"
104STATISTIC(NumAllocasAnalyzed,
"Number of allocas analyzed for replacement");
105STATISTIC(NumAllocaPartitions,
"Number of alloca partitions formed");
106STATISTIC(MaxPartitionsPerAlloca,
"Maximum number of partitions per alloca");
107STATISTIC(NumAllocaPartitionUses,
"Number of alloca partition uses rewritten");
108STATISTIC(MaxUsesPerAllocaPartition,
"Maximum number of uses of a partition");
109STATISTIC(NumNewAllocas,
"Number of new, smaller allocas introduced");
110STATISTIC(NumPromoted,
"Number of allocas promoted to SSA values");
111STATISTIC(NumLoadsSpeculated,
"Number of loads speculated to allow promotion");
113 "Number of loads rewritten into predicated loads to allow promotion");
116 "Number of stores rewritten into predicated stores to allow promotion");
118STATISTIC(NumVectorized,
"Number of vectorized aggregates");
128class AllocaSliceRewriter;
133class SelectHandSpeculativity {
134 unsigned char Storage = 0;
138 SelectHandSpeculativity() =
default;
139 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
140 bool isSpeculatable(
bool isTrueVal)
const;
141 bool areAllSpeculatable()
const;
142 bool areAnySpeculatable()
const;
143 bool areNoneSpeculatable()
const;
145 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
146 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
148static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
150using PossiblySpeculatableLoad =
153using RewriteableMemOp =
154 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
156using InstructionSliceMap =
178 LLVMContext *
const C;
179 DomTreeUpdater *
const DTU;
180 AssumptionCache *
const AC;
181 const bool PreserveCFG;
182 const bool AggregateToVector;
191 SmallSetVector<AllocaInst *, 16> Worklist;
206 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
209 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
210 SmallPtrSet<AllocaInst *, 16>, 16>
218 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
225 SmallSetVector<PHINode *, 8> PHIsWithStoreToRewrite;
229 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
245 static std::optional<RewriteableMemOps>
246 isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG);
249 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
251 : C(C), DTU(DTU), AC(AC),
252 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
253 AggregateToVector(
Options.AggregateToVector) {}
256 std::pair<
bool ,
bool > runSROA(
Function &
F);
259 friend class AllocaSliceRewriter;
261 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
262 std::pair<AllocaInst *, uint64_t>
263 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
264 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
265 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
266 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
267 void clobberUse(Use &U);
268 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
269 bool promoteAllocas();
283enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
287 uint64_t NewStorageSliceOffsetInBits,
289 std::optional<DIExpression::FragmentInfo> StorageFragment,
290 std::optional<DIExpression::FragmentInfo> CurrentFragment,
294 if (StorageFragment) {
296 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
298 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
300 Target.SizeInBits = NewStorageSliceSizeInBits;
301 Target.OffsetInBits = NewStorageSliceOffsetInBits;
307 if (!CurrentFragment) {
308 if (
auto Size = Variable->getSizeInBits()) {
311 if (
Target == CurrentFragment)
318 if (!CurrentFragment || *CurrentFragment ==
Target)
324 if (
Target.startInBits() < CurrentFragment->startInBits() ||
325 Target.endInBits() > CurrentFragment->endInBits())
364 if (DVRAssignMarkerRange.empty())
370 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
372 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
384 DVR->getExpression()->getFragmentInfo();
397 auto *Expr = DbgAssign->getExpression();
398 bool SetKillLocation =
false;
401 std::optional<DIExpression::FragmentInfo> BaseFragment;
404 if (R == BaseFragments.
end())
406 BaseFragment = R->second;
408 std::optional<DIExpression::FragmentInfo> CurrentFragment =
409 Expr->getFragmentInfo();
412 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
413 BaseFragment, CurrentFragment, NewFragment);
417 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
418 if (CurrentFragment) {
423 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
436 SetKillLocation =
true;
444 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
451 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
455 NewAssign = DbgAssign;
474 Value && (DbgAssign->hasArgList() ||
475 !DbgAssign->getExpression()->isSingleLocationExpression());
492 if (NewAssign != DbgAssign) {
493 NewAssign->
moveBefore(DbgAssign->getIterator());
496 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
499 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
509 Twine getNameWithPrefix(
const Twine &Name)
const {
514 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
516 void InsertHelper(Instruction *
I,
const Twine &Name,
541 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
547 : BeginOffset(BeginOffset), EndOffset(EndOffset),
548 UseAndIsSplittable(
U, IsSplittable) {}
550 uint64_t beginOffset()
const {
return BeginOffset; }
551 uint64_t endOffset()
const {
return EndOffset; }
553 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
554 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
556 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
558 bool isDead()
const {
return getUse() ==
nullptr; }
559 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
568 if (beginOffset() <
RHS.beginOffset())
570 if (beginOffset() >
RHS.beginOffset())
572 if (isSplittable() !=
RHS.isSplittable())
573 return !isSplittable();
574 if (endOffset() >
RHS.endOffset())
581 return LHS.beginOffset() < RHSOffset;
584 return LHSOffset <
RHS.beginOffset();
588 return isSplittable() ==
RHS.isSplittable() &&
589 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
604 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
610 bool isEscaped()
const {
return PointerEscapingInstr; }
611 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
616 using range = iterator_range<iterator>;
618 iterator
begin() {
return Slices.begin(); }
619 iterator
end() {
return Slices.end(); }
622 using const_range = iterator_range<const_iterator>;
624 const_iterator
begin()
const {
return Slices.begin(); }
625 const_iterator
end()
const {
return Slices.end(); }
629 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
637 int OldSize = Slices.size();
638 Slices.append(NewSlices.
begin(), NewSlices.
end());
639 auto SliceI = Slices.begin() + OldSize;
640 std::stable_sort(SliceI, Slices.end());
641 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
650 ArrayRef<Instruction *> getDeadUsers()
const {
return DeadUsers; }
654 return DeadUseIfPromotable;
665#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
666 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
667 void printSlice(raw_ostream &OS, const_iterator
I,
668 StringRef Indent =
" ")
const;
669 void printUse(raw_ostream &OS, const_iterator
I,
670 StringRef Indent =
" ")
const;
671 void print(raw_ostream &OS)
const;
672 void dump(const_iterator
I)
const;
677 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
680 friend class AllocaSlices::SliceBuilder;
682#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
710 SmallVector<Instruction *, 8> DeadUsers;
737 friend class AllocaSlices;
738 friend class AllocaSlices::partition_iterator;
740 using iterator = AllocaSlices::iterator;
744 uint64_t BeginOffset = 0, EndOffset = 0;
754 Partition(iterator SI) : SI(SI), SJ(SI) {}
760 uint64_t beginOffset()
const {
return BeginOffset; }
765 uint64_t endOffset()
const {
return EndOffset; }
771 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
772 return EndOffset - BeginOffset;
777 bool empty()
const {
return SI == SJ; }
788 iterator
begin()
const {
return SI; }
789 iterator
end()
const {
return SJ; }
821 AllocaSlices::iterator SE;
825 uint64_t MaxSplitSliceEndOffset = 0;
829 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
841 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
842 "Cannot advance past the end of the slices!");
845 if (!
P.SplitTails.empty()) {
846 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
848 P.SplitTails.clear();
849 MaxSplitSliceEndOffset = 0;
855 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
858 return S->endOffset() == MaxSplitSliceEndOffset;
860 "Could not find the current max split slice offset!");
863 return S->endOffset() <= MaxSplitSliceEndOffset;
865 "Max split slice end offset is not actually the max!");
872 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
882 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
883 P.SplitTails.push_back(&S);
884 MaxSplitSliceEndOffset =
885 std::max(S.endOffset(), MaxSplitSliceEndOffset);
893 P.BeginOffset = P.EndOffset;
894 P.EndOffset = MaxSplitSliceEndOffset;
901 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
902 !P.SI->isSplittable()) {
903 P.BeginOffset = P.EndOffset;
904 P.EndOffset = P.SI->beginOffset();
914 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
915 P.EndOffset = P.SI->endOffset();
920 if (!P.SI->isSplittable()) {
923 assert(P.BeginOffset == P.SI->beginOffset());
927 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
928 if (!P.SJ->isSplittable())
929 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
941 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
944 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
945 P.SJ->isSplittable()) {
946 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
953 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
954 assert(!P.SJ->isSplittable());
955 P.EndOffset = P.SJ->beginOffset();
962 "End iterators don't match between compared partition iterators!");
969 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
970 assert(P.SJ == RHS.P.SJ &&
971 "Same set of slices formed two different sized partitions!");
972 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
973 "Same slice position with differently sized non-empty split "
996 return make_range(partition_iterator(begin(), end()),
997 partition_iterator(end(), end()));
1005 return SI.getOperand(1 + CI->isZero());
1006 if (
SI.getOperand(1) ==
SI.getOperand(2))
1007 return SI.getOperand(1);
1016 return PN->hasConstantValue();
1031 const uint64_t AllocSize;
1047 if (VisitedDeadInsts.
insert(&
I).second)
1052 bool IsSplittable =
false) {
1058 <<
" which has zero size or starts outside of the "
1059 << AllocSize <<
" byte alloca:\n"
1060 <<
" alloca: " << AS.AI <<
"\n"
1061 <<
" use: " <<
I <<
"\n");
1062 return markAsDead(
I);
1074 assert(AllocSize >= BeginOffset);
1075 if (
Size > AllocSize - BeginOffset) {
1077 <<
Offset <<
" to remain within the " << AllocSize
1078 <<
" byte alloca:\n"
1079 <<
" alloca: " << AS.AI <<
"\n"
1080 <<
" use: " <<
I <<
"\n");
1081 EndOffset = AllocSize;
1084 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1087 void visitBitCastInst(BitCastInst &BC) {
1089 return markAsDead(BC);
1091 return Base::visitBitCastInst(BC);
1094 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1096 return markAsDead(ASC);
1098 return Base::visitAddrSpaceCastInst(ASC);
1101 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1103 return markAsDead(GEPI);
1105 return Base::visitGetElementPtrInst(GEPI);
1108 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1119 void visitLoadInst(LoadInst &LI) {
1121 "All simple FCA loads should have been pre-split");
1126 return PI.setEscapedReadOnly(&LI);
1129 if (
Size.isScalable()) {
1132 return PI.setAborted(&LI);
1141 void visitStoreInst(StoreInst &SI) {
1142 Value *ValOp =
SI.getValueOperand();
1144 return PI.setEscapedAndAborted(&SI);
1146 return PI.setAborted(&SI);
1148 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1150 unsigned VScale =
SI.getFunction()->getVScaleValue();
1152 return PI.setAborted(&SI);
1168 <<
Offset <<
" which extends past the end of the "
1169 << AllocSize <<
" byte alloca:\n"
1170 <<
" alloca: " << AS.AI <<
"\n"
1171 <<
" use: " << SI <<
"\n");
1172 return markAsDead(SI);
1176 "All simple FCA stores should have been pre-split");
1180 void visitMemSetInst(MemSetInst &
II) {
1181 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1184 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1186 return markAsDead(
II);
1189 return PI.setAborted(&
II);
1193 : AllocSize -
Offset.getLimitedValue(),
1197 void visitMemTransferInst(MemTransferInst &
II) {
1201 return markAsDead(
II);
1205 if (VisitedDeadInsts.
count(&
II))
1209 return PI.setAborted(&
II);
1216 if (
Offset.uge(AllocSize)) {
1217 auto MTPI = MemTransferSliceMap.
find(&
II);
1218 if (MTPI != MemTransferSliceMap.
end())
1219 AS.Slices[MTPI->second].kill();
1220 return markAsDead(
II);
1228 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1230 if (!
II.isVolatile())
1231 return markAsDead(
II);
1239 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1240 std::tie(MTPI, Inserted) =
1241 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1242 unsigned PrevIdx = MTPI->second;
1244 Slice &PrevP = AS.Slices[PrevIdx];
1248 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1250 return markAsDead(
II);
1255 PrevP.makeUnsplittable();
1262 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1263 "Map index doesn't point back to a slice with this user.");
1269 void visitIntrinsicInst(IntrinsicInst &
II) {
1270 if (
II.isDroppable()) {
1271 AS.DeadUseIfPromotable.push_back(U);
1276 return PI.setAborted(&
II);
1278 if (
II.isLifetimeStartOrEnd()) {
1279 insertUse(
II,
Offset, AllocSize,
true);
1283 Base::visitIntrinsicInst(
II);
1291 SmallPtrSet<Instruction *, 4> Visited;
1301 std::tie(UsedI,
I) =
Uses.pop_back_val();
1304 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1316 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1326 if (!
GEP->hasAllZeroIndices())
1333 for (User *U :
I->users())
1336 }
while (!
Uses.empty());
1341 void visitPHINodeOrSelectInst(Instruction &
I) {
1344 return markAsDead(
I);
1350 return PI.setAborted(&
I);
1368 AS.DeadOperands.push_back(U);
1374 return PI.setAborted(&
I);
1380 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1381 return PI.setAborted(UnsafeI);
1390 if (
Offset.uge(AllocSize)) {
1391 AS.DeadOperands.push_back(U);
1398 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1400 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1403 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1405 void visitCallBase(CallBase &CB) {
1411 PI.setEscapedReadOnly(&CB);
1415 Base::visitCallBase(CB);
1419AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1421#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1424 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1426 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1427 if (PtrI.isEscaped() || PtrI.isAborted()) {
1430 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1431 : PtrI.getAbortingInst();
1432 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1435 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1437 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1444#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1446void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1447 StringRef Indent)
const {
1448 printSlice(OS,
I, Indent);
1450 printUse(OS,
I, Indent);
1453void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1454 StringRef Indent)
const {
1455 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1456 <<
" slice #" << (
I -
begin())
1457 << (
I->isSplittable() ?
" (splittable)" :
"");
1460void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1461 StringRef Indent)
const {
1462 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1465void AllocaSlices::print(raw_ostream &OS)
const {
1466 if (PointerEscapingInstr) {
1467 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1468 <<
" A pointer to this alloca escaped by:\n"
1469 <<
" " << *PointerEscapingInstr <<
"\n";
1473 if (PointerEscapingInstrReadOnly)
1474 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1476 OS <<
"Slices of alloca: " << AI <<
"\n";
1497 for (
User *U :
I.users()) {
1498 Type *UserTy =
nullptr;
1504 UserTy =
Store->getValueOperand()->getType();
1506 if (!UserTy || (Ty && Ty != UserTy))
1516static std::pair<Type *, IntegerType *>
1520 bool TyIsCommon =
true;
1525 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1526 Use *U =
I->getUse();
1529 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1532 Type *UserTy =
nullptr;
1536 UserTy =
SI->getValueOperand()->getType();
1547 if (UserITy->getBitWidth() % 8 != 0 ||
1548 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1553 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1559 if (!UserTy || (Ty && Ty != UserTy))
1565 return {TyIsCommon ? Ty :
nullptr, ITy};
1595 Type *LoadType =
nullptr;
1608 if (LoadType != LI->
getType())
1617 if (BBI->mayWriteToMemory())
1620 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1627 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1670 if (!
SI ||
SI->getPointerOperand() != &PN)
1673 if (
SI->isVolatile())
1681 Value *StoredValue =
SI->getValueOperand();
1687 if (!SeenPreds.
insert(Pred).second)
1720 IRB.SetInsertPoint(&PN);
1722 PN.
getName() +
".sroa.speculated");
1752 IRB.SetInsertPoint(TI);
1755 LoadTy, InVal, Alignment,
1756 (PN.
getName() +
".sroa.speculate.load." + Pred->getName()));
1757 ++NumLoadsSpeculated;
1759 Load->setAAMetadata(AATags);
1761 InjectedLoads[Pred] =
Load;
1773 <<
" " <<
SI <<
"\n");
1781 if (!SeenPreds.
insert(Pred).second)
1791 bool CFGChanged =
false;
1793 for (
auto [Pred, InVal] : IncomingValues) {
1795 if (Pred->getTerminator()->getNumSuccessors() != 1) {
1797 assert(StoreBB &&
"store edge was not checked for splitting");
1804 ++NumStoresPredicated;
1808 SI.eraseFromParent();
1813SelectHandSpeculativity &
1814SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1822bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1827bool SelectHandSpeculativity::areAllSpeculatable()
const {
1828 return isSpeculatable(
true) &&
1829 isSpeculatable(
false);
1832bool SelectHandSpeculativity::areAnySpeculatable()
const {
1833 return isSpeculatable(
true) ||
1834 isSpeculatable(
false);
1836bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1837 return !areAnySpeculatable();
1840static SelectHandSpeculativity
1843 SelectHandSpeculativity
Spec;
1849 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1850 else if (PreserveCFG)
1856std::optional<RewriteableMemOps>
1857SROA::isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG) {
1858 RewriteableMemOps
Ops;
1860 for (User *U :
SI.users()) {
1865 if (
Store->isVolatile() || PreserveCFG)
1878 PossiblySpeculatableLoad
Load(LI);
1888 SelectHandSpeculativity Spec =
1890 if (PreserveCFG && !Spec.areAllSpeculatable())
1904 Value *TV =
SI.getTrueValue();
1905 Value *FV =
SI.getFalseValue();
1910 IRB.SetInsertPoint(&LI);
1914 LI.
getName() +
".sroa.speculate.load.true");
1917 LI.
getName() +
".sroa.speculate.load.false");
1918 NumLoadsSpeculated += 2;
1930 Value *V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1931 LI.
getName() +
".sroa.speculated", &
SI);
1937template <
typename T>
1939 SelectHandSpeculativity
Spec,
1946 if (
Spec.areNoneSpeculatable())
1948 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1951 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1953 if (
Spec.isSpeculatable(
true))
1959 Tail->setName(Head->
getName() +
".cont");
1964 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1965 int SuccIdx = IsThen ? 0 : 1;
1966 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
1967 auto &CondMemOp =
cast<T>(*
I.clone());
1968 if (NewMemOpBB != Head) {
1969 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1971 ++NumLoadsPredicated;
1973 ++NumStoresPredicated;
1975 CondMemOp.dropUBImplyingAttrsAndMetadata();
1976 ++NumLoadsSpeculated;
1978 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
1979 Value *Ptr =
SI.getOperand(1 + SuccIdx);
1980 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
1982 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1990 I.replaceAllUsesWith(PN);
1995 SelectHandSpeculativity
Spec,
2006 const RewriteableMemOps &
Ops,
2008 bool CFGChanged =
false;
2011 for (
const RewriteableMemOp &
Op :
Ops) {
2012 SelectHandSpeculativity
Spec;
2014 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
2017 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
2018 I = PSL.getPointer();
2019 Spec = PSL.getInt();
2021 if (
Spec.areAllSpeculatable()) {
2024 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
2028 I->eraseFromParent();
2033 SI.eraseFromParent();
2041 const Twine &NamePrefix) {
2043 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
2044 NamePrefix +
"sroa_idx");
2045 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
2046 NamePrefix +
"sroa_cast");
2061 unsigned VScale = 0) {
2071 "We can't have the same bitwidth for different int types");
2075 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
2076 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
2103 if (NewSize != OldSize)
2119 return OldAS == NewAS ||
2120 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2121 !
DL.isNonIntegralAddressSpace(NewAS) &&
2122 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2128 return !
DL.isNonIntegralPointerType(NewTy);
2132 if (!
DL.isNonIntegralPointerType(OldTy))
2155 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2156 uint64_t BeginIndex = BeginOffset / ElementSize;
2157 if (BeginIndex * ElementSize != BeginOffset ||
2160 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2161 uint64_t EndIndex = EndOffset / ElementSize;
2162 if (EndIndex * ElementSize != EndOffset ||
2166 assert(EndIndex > BeginIndex &&
"Empty vector!");
2167 uint64_t NumElements = EndIndex - BeginIndex;
2168 Type *SliceTy = (NumElements == 1)
2169 ? Ty->getElementType()
2175 Use *U = S.getUse();
2178 if (
MI->isVolatile())
2180 if (!S.isSplittable())
2188 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2195 if (LTy->isStructTy())
2197 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2198 assert(LTy->isIntegerTy());
2204 if (
SI->isVolatile())
2206 Type *STy =
SI->getValueOperand()->getType();
2210 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2230 bool HaveCommonEltTy,
Type *CommonEltTy,
2231 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2232 VectorType *CommonVecPtrTy,
unsigned VScale) {
2234 if (CandidateTys.
empty())
2241 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2245 if (!HaveCommonEltTy && HaveVecPtrTy) {
2247 CandidateTys.
clear();
2249 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2252 if (!VTy->getElementType()->isIntegerTy())
2254 VTy->getContext(), VTy->getScalarSizeInBits())));
2261 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2262 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2263 "Cannot have vector types of different sizes!");
2264 assert(RHSTy->getElementType()->isIntegerTy() &&
2265 "All non-integer types eliminated!");
2266 assert(LHSTy->getElementType()->isIntegerTy() &&
2267 "All non-integer types eliminated!");
2273 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2274 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2275 "Cannot have vector types of different sizes!");
2276 assert(RHSTy->getElementType()->isIntegerTy() &&
2277 "All non-integer types eliminated!");
2278 assert(LHSTy->getElementType()->isIntegerTy() &&
2279 "All non-integer types eliminated!");
2283 llvm::sort(CandidateTys, RankVectorTypesComp);
2284 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2285 CandidateTys.end());
2291 assert(VTy->getElementType() == CommonEltTy &&
2292 "Unaccounted for element type!");
2293 assert(VTy == CandidateTys[0] &&
2294 "Different vector types with the same element type!");
2297 CandidateTys.resize(1);
2304 std::numeric_limits<unsigned short>::max();
2310 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2314 if (ElementSize % 8)
2316 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2317 "vector size not a multiple of element size?");
2320 for (
const Slice &S :
P)
2324 for (
const Slice *S :
P.splitSliceTails())
2330 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2337 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2338 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2340 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2343 for (
Type *Ty : OtherTys) {
2346 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2349 for (
VectorType *
const VTy : CandidateTysCopy) {
2351 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2352 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2353 unsigned ElementSize =
2354 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2358 CheckCandidateType(NewVTy);
2364 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2365 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2384 Type *CommonEltTy =
nullptr;
2386 bool HaveVecPtrTy =
false;
2387 bool HaveCommonEltTy =
true;
2388 bool HaveCommonVecPtrTy =
true;
2389 auto CheckCandidateType = [&](
Type *Ty) {
2392 if (!CandidateTys.
empty()) {
2394 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2395 DL.getTypeSizeInBits(V).getFixedValue()) {
2396 CandidateTys.
clear();
2401 Type *EltTy = VTy->getElementType();
2404 CommonEltTy = EltTy;
2405 else if (CommonEltTy != EltTy)
2406 HaveCommonEltTy =
false;
2409 HaveVecPtrTy =
true;
2410 if (!CommonVecPtrTy)
2411 CommonVecPtrTy = VTy;
2412 else if (CommonVecPtrTy != VTy)
2413 HaveCommonVecPtrTy =
false;
2419 for (
const Slice &S :
P) {
2424 Ty =
SI->getValueOperand()->getType();
2428 auto CandTy = Ty->getScalarType();
2429 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2430 S.endOffset() !=
P.endOffset())) {
2437 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2438 CheckCandidateType(Ty);
2443 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2444 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2445 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2448 CandidateTys.
clear();
2450 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2451 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2452 CommonVecPtrTy, VScale);
2463 bool &WholeAllocaOp) {
2466 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2467 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2469 Use *U = S.getUse();
2476 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2494 if (S.beginOffset() < AllocBeginOffset)
2500 WholeAllocaOp =
true;
2502 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2504 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2511 Type *ValueTy =
SI->getValueOperand()->getType();
2512 if (
SI->isVolatile())
2515 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2520 if (S.beginOffset() < AllocBeginOffset)
2526 WholeAllocaOp =
true;
2528 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2530 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2539 if (!S.isSplittable())
2556 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2562 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2580 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2582 for (
const Slice &S :
P)
2587 for (
const Slice *S :
P.splitSliceTails())
2592 return WholeAllocaOp;
2597 const Twine &Name) {
2601 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2602 "Element extends past full value");
2604 if (
DL.isBigEndian())
2605 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2606 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2608 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2611 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2612 "Cannot extract to a larger integer!");
2614 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2624 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2625 "Cannot insert a larger integer!");
2628 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2632 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2633 "Element store outside of alloca store");
2635 if (
DL.isBigEndian())
2636 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2637 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2639 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2643 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2644 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2645 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2647 V = IRB.CreateOr(Old, V, Name +
".insert");
2654 unsigned EndIndex,
const Twine &Name) {
2656 unsigned NumElements = EndIndex - BeginIndex;
2657 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2659 if (NumElements == VecTy->getNumElements())
2662 if (NumElements == 1) {
2663 V = IRB.CreateExtractElement(V, BeginIndex, Name +
".extract");
2669 V = IRB.CreateShuffleVector(V, Mask, Name +
".extract");
2675 unsigned BeginIndex,
const Twine &Name) {
2677 assert(VecTy &&
"Can only insert a vector into a vector");
2682 V = IRB.CreateInsertElement(Old, V, BeginIndex, Name +
".insert");
2690 assert(NumSubElements <= NumElements &&
"Too many elements!");
2691 if (NumSubElements == NumElements) {
2692 assert(V->getType() == VecTy &&
"Vector type mismatch");
2695 unsigned EndIndex = BeginIndex + NumSubElements;
2702 Mask.reserve(NumElements);
2703 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2704 if (Idx >= BeginIndex && Idx < EndIndex)
2705 Mask.push_back(Idx - BeginIndex);
2708 V = IRB.CreateShuffleVector(V, Mask, Name +
".expand");
2712 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2713 if (Idx >= BeginIndex && Idx < EndIndex)
2714 Mask.push_back(Idx);
2716 Mask.push_back(Idx + NumElements);
2717 V = IRB.CreateShuffleVector(V, Old, Mask, Name +
"blend");
2756 const char *DebugName) {
2757 Type *EltType = VecType->getElementType();
2758 if (EltType != NewAIEltTy) {
2760 unsigned TotalBits =
2761 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2762 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2765 V = Builder.CreateBitCast(V, NewVecType);
2766 VecType = NewVecType;
2767 LLVM_DEBUG(
dbgs() <<
" bitcast " << DebugName <<
": " << *V <<
"\n");
2771 BitcastIfNeeded(V0, VecType0,
"V0");
2772 BitcastIfNeeded(
V1, VecType1,
"V1");
2774 unsigned NumElts0 = VecType0->getNumElements();
2775 unsigned NumElts1 = VecType1->getNumElements();
2779 if (NumElts0 == NumElts1) {
2780 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2781 ShuffleMask.push_back(i);
2785 unsigned SmallSize = std::min(NumElts0, NumElts1);
2786 unsigned LargeSize = std::max(NumElts0, NumElts1);
2787 bool IsV0Smaller = NumElts0 < NumElts1;
2788 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2790 for (
unsigned i = 0; i < SmallSize; ++i)
2792 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2794 ExtendedVec = Builder.CreateShuffleVector(
2796 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2797 for (
unsigned i = 0; i < NumElts0; ++i)
2798 ShuffleMask.push_back(i);
2799 for (
unsigned i = 0; i < NumElts1; ++i)
2800 ShuffleMask.push_back(LargeSize + i);
2803 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2814class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2816 friend class InstVisitor<AllocaSliceRewriter, bool>;
2818 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2820 const DataLayout &
DL;
2823 AllocaInst &OldAI, &NewAI;
2824 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2853 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2856 bool IsSplittable =
false;
2857 bool IsSplit =
false;
2858 Use *OldUse =
nullptr;
2862 SmallSetVector<PHINode *, 8> &PHIUsers;
2863 SmallSetVector<SelectInst *, 8> &SelectUsers;
2871 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2875 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2876 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2880 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2881 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2883 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2884 VectorType *PromotableVecTy,
2885 SmallSetVector<PHINode *, 8> &PHIUsers,
2886 SmallSetVector<SelectInst *, 8> &SelectUsers)
2887 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2888 NewAllocaBeginOffset(NewAllocaBeginOffset),
2889 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2890 IntTy(IsIntegerPromotable
2893 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2895 VecTy(PromotableVecTy),
2896 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2897 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2899 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2900 IRB(*NewAI.getModule(), ConstantFolder()) {
2902 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2903 "Only multiple-of-8 sized vector elements are viable");
2906 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2909 bool visit(AllocaSlices::const_iterator
I) {
2910 bool CanSROA =
true;
2911 BeginOffset =
I->beginOffset();
2912 EndOffset =
I->endOffset();
2913 IsSplittable =
I->isSplittable();
2915 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2916 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2921 assert(BeginOffset < NewAllocaEndOffset);
2922 assert(EndOffset > NewAllocaBeginOffset);
2923 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2924 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2926 SliceSize = NewEndOffset - NewBeginOffset;
2927 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2928 <<
") NewBegin:(" << NewBeginOffset <<
", "
2929 << NewEndOffset <<
") NewAllocaBegin:("
2930 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2932 assert(IsSplit || NewBeginOffset == BeginOffset);
2933 OldUse =
I->getUse();
2937 IRB.SetInsertPoint(OldUserI);
2938 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2940 if (!IRB.getContext().shouldDiscardValueNames())
2941 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2942 Twine(BeginOffset) +
".");
3004 std::optional<SmallVector<Value *, 4>>
3005 rewriteTreeStructuredMerge(Partition &
P) {
3007 if (
P.splitSliceTails().size() > 0)
3008 return std::nullopt;
3017 :
Store(
SI), BeginOffset(Begin), EndOffset(End), StoredValue(Val) {}
3027 LoadInst *FullLoad =
nullptr;
3028 StoreInst *InitStore =
nullptr;
3032 Type *AllocatedEltTy =
3036 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
3043 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
3045 return FixedVecTy &&
3046 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
3047 !FixedVecTy->getElementType()->isPointerTy();
3050 for (Slice &S :
P) {
3054 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
3055 S.endOffset() == NewAllocaEndOffset);
3059 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
3060 return std::nullopt;
3065 return std::nullopt;
3069 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
3081 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
3082 SI->getValueOperand()->getType()))
3083 return std::nullopt;
3085 unsigned NumElts = StVecTy->getNumElements();
3086 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
3087 if (NumElts * EltSize % AllocatedEltTySize != 0)
3088 return std::nullopt;
3093 return std::nullopt;
3096 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
3097 SI->getValueOperand());
3102 return std::nullopt;
3109 if (StoreInfos.
size() < 2)
3110 return std::nullopt;
3118 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3119 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3120 if (!IsRMWPattern && !IsStoresOnlyPattern)
3121 return std::nullopt;
3125 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3126 for (
auto &Info : StoreInfos)
3127 if (
Info.Store->getParent() != StoreBB)
3128 return std::nullopt;
3130 SmallVector<Value *, 4> DeletedValues;
3137 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3140 while (Vals.
size() > 1) {
3141 SmallVector<Value *, 8>
Next;
3142 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3148 if (Vals.
size() % 2 == 1)
3150 Vals = std::move(
Next);
3159 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3161 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3162 Merged->getType(), &NewAI, getSliceAlign(),
3164 LoadToReplace->
getName() +
".sroa.new.load");
3166 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3171 if (IsStoresOnlyPattern) {
3174 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3175 return A.BeginOffset <
B.BeginOffset;
3180 uint64_t Expected = NewAllocaBeginOffset;
3181 for (
auto &Info : StoreInfos) {
3182 if (
Info.BeginOffset != Expected)
3183 return std::nullopt;
3184 Expected =
Info.EndOffset;
3187 if (Expected != NewAllocaEndOffset)
3188 return std::nullopt;
3198 if (LoadBB == StoreBB) {
3199 for (
auto &Info : StoreInfos)
3200 if (!
Info.Store->comesBefore(FullLoad))
3201 return std::nullopt;
3205 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3206 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3207 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3208 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3209 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3210 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3223 SmallVector<Value *, 8> Vals;
3224 for (
const auto &Info : StoreInfos) {
3229 Value *Merged = TreeMerge(Vals, Builder);
3230 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3233 ReplaceFullLoad(FullLoad, Merged);
3234 return DeletedValues;
3242 return std::nullopt;
3243 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3244 return I.Load->getParent() != StoreBB;
3246 return std::nullopt;
3262 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3263 for (
const auto &L : LoadInfos)
3264 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3265 for (
const auto &S : StoreInfos)
3266 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3268 return A.Inst->comesBefore(
B.Inst);
3276 return std::nullopt;
3282 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3283 !
Accesses.back().Inst->comesBefore(FullLoad))
3284 return std::nullopt;
3295 using SliceRange = std::pair<uint64_t, uint64_t>;
3299 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3303 uint64_t Expected = NewAllocaBeginOffset;
3304 for (
auto &
Range : SortedRanges) {
3305 if (
Range.first != Expected)
3306 return std::nullopt;
3307 Expected =
Range.second;
3309 if (Expected != NewAllocaEndOffset)
3310 return std::nullopt;
3313 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3314 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3316 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3317 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3318 for (
auto &
Range : SortedRanges)
3329 if (InitVec->
getType() != NewAllocaTy)
3330 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3331 DenseMap<SliceRange, Value *> SliceValues;
3332 for (
auto &
Range : SortedRanges) {
3333 unsigned BeginIdx = getIndex(
Range.first);
3334 unsigned EndIdx = getIndex(
Range.second);
3335 SliceValues[
Range] = IRB.CreateShuffleVector(
3351 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3354 if (
V->getType() != Acc.Inst->getType()) {
3356 V = IRB.CreateBitCast(V, Acc.Inst->getType());
3358 Acc.Inst->replaceAllUsesWith(V);
3375 SmallVector<Value *, 8> Vals;
3376 for (
auto &
Range : SortedRanges)
3378 Value *Merged = TreeMerge(Vals, Builder);
3379 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3384 ReplaceFullLoad(FullLoad, Merged);
3386 return DeletedValues;
3394 bool visitInstruction(Instruction &
I) {
3402 assert(IsSplit || BeginOffset == NewBeginOffset);
3405 StringRef OldName = OldPtr->
getName();
3407 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3409 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3414 OldName = OldName.
substr(IndexEnd + 1);
3418 OldName = OldName.
substr(OffsetEnd + 1);
3422 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3434 Align getSliceAlign() {
3436 NewBeginOffset - NewAllocaBeginOffset);
3440 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3442 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3443 uint32_t
Index = RelOffset / ElementSize;
3444 assert(Index * ElementSize == RelOffset);
3448 void deleteIfTriviallyDead(
Value *V) {
3451 Pass.DeadInsts.push_back(
I);
3454 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3455 unsigned BeginIndex = getIndex(NewBeginOffset);
3456 unsigned EndIndex = getIndex(NewEndOffset);
3457 assert(EndIndex > BeginIndex &&
"Empty vector!");
3460 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3462 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3463 LLVMContext::MD_access_group});
3467 Value *rewriteIntegerLoad(LoadInst &LI) {
3468 assert(IntTy &&
"We cannot insert an integer to the alloca");
3471 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3472 V = IRB.CreateBitPreservingCastChain(
DL, V, IntTy);
3473 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3475 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3476 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3485 "Can only handle an extract for an overly wide load");
3487 V = IRB.CreateZExt(V, LI.
getType());
3491 bool visitLoadInst(LoadInst &LI) {
3500 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3502 bool IsPtrAdjusted =
false;
3505 V = rewriteVectorizedLoadInst(LI);
3507 V = rewriteIntegerLoad(LI);
3508 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3509 NewEndOffset == NewAllocaEndOffset &&
3512 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3515 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3516 LoadInst *NewLI = IRB.CreateAlignedLoad(
3517 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3518 if (LI.isVolatile())
3519 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3520 if (NewLI->isAtomic())
3521 NewLI->setAlignment(LI.getAlign());
3526 copyMetadataForLoad(*NewLI, LI);
3530 NewLI->setAAMetadata(AATags.adjustForAccess(
3531 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3539 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3540 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3541 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3542 V = IRB.CreateZExt(V, TITy,
"load.ext");
3543 if (DL.isBigEndian())
3544 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3548 Type *LTy = IRB.getPtrTy(AS);
3550 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3555 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3559 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3560 LLVMContext::MD_access_group});
3563 IsPtrAdjusted =
true;
3565 V = IRB.CreateBitPreservingCastChain(
DL, V, TargetTy);
3570 "Only integer type loads and stores are split");
3571 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3572 "Split load isn't smaller than original load");
3574 "Non-byte-multiple bit width");
3580 LIIt.setHeadBit(
true);
3581 IRB.SetInsertPoint(LIIt);
3586 Value *Placeholder =
3592 Placeholder->replaceAllUsesWith(&LI);
3593 Placeholder->deleteValue();
3598 Pass.DeadInsts.push_back(&LI);
3599 deleteIfTriviallyDead(OldOp);
3604 bool rewriteVectorizedStoreInst(
Value *V, StoreInst &SI,
Value *OldOp,
3609 if (
V->getType() != VecTy) {
3610 unsigned BeginIndex = getIndex(NewBeginOffset);
3611 unsigned EndIndex = getIndex(NewEndOffset);
3612 assert(EndIndex > BeginIndex &&
"Empty vector!");
3613 unsigned NumElements = EndIndex - BeginIndex;
3615 "Too many elements!");
3616 Type *SliceTy = (NumElements == 1)
3618 : FixedVectorType::
get(ElementTy, NumElements);
3619 if (
V->getType() != SliceTy)
3620 V = IRB.CreateBitPreservingCastChain(
DL, V, SliceTy);
3624 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3627 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3628 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3629 LLVMContext::MD_access_group});
3633 Pass.DeadInsts.push_back(&SI);
3642 bool rewriteIntegerStore(
Value *V, StoreInst &SI, AAMDNodes AATags) {
3643 assert(IntTy &&
"We cannot extract an integer from the alloca");
3645 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3647 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3649 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3650 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3654 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3655 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3656 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3657 LLVMContext::MD_access_group});
3664 Store->getValueOperand(),
DL);
3666 Pass.DeadInsts.push_back(&SI);
3671 bool visitStoreInst(StoreInst &SI) {
3673 Value *OldOp =
SI.getOperand(1);
3676 AAMDNodes AATags =
SI.getAAMetadata();
3681 if (
V->getType()->isPointerTy())
3683 Pass.PostPromotionWorklist.insert(AI);
3685 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3688 assert(
V->getType()->isIntegerTy() &&
3689 "Only integer type loads and stores are split");
3690 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3691 "Non-byte-multiple bit width");
3692 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3698 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3699 if (IntTy &&
V->getType()->isIntegerTy())
3700 return rewriteIntegerStore(V, SI, AATags);
3703 if (NewBeginOffset == NewAllocaBeginOffset &&
3704 NewEndOffset == NewAllocaEndOffset &&
3706 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3708 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3711 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3713 unsigned AS =
SI.getPointerAddressSpace();
3714 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3716 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3718 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3719 LLVMContext::MD_access_group});
3723 if (
SI.isVolatile())
3732 Pass.DeadInsts.push_back(&SI);
3733 deleteIfTriviallyDead(OldOp);
3751 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3759 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3769 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3774 bool visitMemSetInst(MemSetInst &
II) {
3778 AAMDNodes AATags =
II.getAAMetadata();
3784 assert(NewBeginOffset == BeginOffset);
3785 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3786 II.setDestAlignment(getSliceAlign());
3791 "AT: Unexpected link to non-const GEP");
3792 deleteIfTriviallyDead(OldPtr);
3797 Pass.DeadInsts.push_back(&
II);
3801 const bool CanContinue = [&]() {
3804 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3809 if (Len > std::numeric_limits<unsigned>::max())
3811 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3814 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3820 Type *SizeTy =
II.getLength()->getType();
3821 unsigned Sz = NewEndOffset - NewBeginOffset;
3824 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3825 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3831 New,
New->getRawDest(),
nullptr,
DL);
3846 assert(ElementTy == ScalarTy);
3848 unsigned BeginIndex = getIndex(NewBeginOffset);
3849 unsigned EndIndex = getIndex(NewEndOffset);
3850 assert(EndIndex > BeginIndex &&
"Empty vector!");
3851 unsigned NumElements = EndIndex - BeginIndex;
3853 "Too many elements!");
3856 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3857 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3858 if (NumElements > 1)
3861 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3870 V = getIntegerSplat(
II.getValue(),
Size);
3872 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3873 NewEndOffset != NewAllocaEndOffset)) {
3874 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3876 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3880 assert(
V->getType() == IntTy &&
3881 "Wrong type for an alloca wide integer!");
3883 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3886 assert(NewBeginOffset == NewAllocaBeginOffset);
3887 assert(NewEndOffset == NewAllocaEndOffset);
3889 V = getIntegerSplat(
II.getValue(),
3890 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3895 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3898 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3900 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3901 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3902 LLVMContext::MD_access_group});
3908 New,
New->getPointerOperand(), V,
DL);
3911 return !
II.isVolatile();
3914 bool visitMemTransferInst(MemTransferInst &
II) {
3920 AAMDNodes AATags =
II.getAAMetadata();
3922 bool IsDest = &
II.getRawDestUse() == OldUse;
3923 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3924 (!IsDest &&
II.getRawSource() == OldPtr));
3926 Align SliceAlign = getSliceAlign();
3934 if (!IsSplittable) {
3935 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3940 DbgAssign->getAddress() ==
II.getDest())
3941 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3943 II.setDest(AdjustedPtr);
3944 II.setDestAlignment(SliceAlign);
3946 II.setSource(AdjustedPtr);
3947 II.setSourceAlignment(SliceAlign);
3951 deleteIfTriviallyDead(OldPtr);
3964 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3965 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
3966 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
3972 if (EmitMemCpy && &OldAI == &NewAI) {
3974 assert(NewBeginOffset == BeginOffset);
3977 if (NewEndOffset != EndOffset)
3978 II.setLength(NewEndOffset - NewBeginOffset);
3982 Pass.DeadInsts.push_back(&
II);
3986 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3987 if (AllocaInst *AI =
3989 assert(AI != &OldAI && AI != &NewAI &&
3990 "Splittable transfers cannot reach the same alloca on both ends.");
3991 Pass.Worklist.insert(AI);
3998 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3999 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
4001 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
4003 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
4011 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4012 Type *SizeTy =
II.getLength()->getType();
4013 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
4015 Value *DestPtr, *SrcPtr;
4016 MaybeAlign DestAlign, SrcAlign;
4020 DestAlign = SliceAlign;
4022 SrcAlign = OtherAlign;
4025 DestAlign = OtherAlign;
4027 SrcAlign = SliceAlign;
4029 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
4032 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
4037 &
II, New, DestPtr,
nullptr,
DL);
4042 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
4048 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
4049 NewEndOffset == NewAllocaEndOffset;
4051 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
4052 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
4053 unsigned NumElements = EndIndex - BeginIndex;
4054 IntegerType *SubIntTy =
4055 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
4060 if (VecTy && !IsWholeAlloca) {
4061 if (NumElements == 1)
4062 OtherTy = VecTy->getElementType();
4065 }
else if (IntTy && !IsWholeAlloca) {
4068 OtherTy = NewAllocaTy;
4073 MaybeAlign SrcAlign = OtherAlign;
4074 MaybeAlign DstAlign = SliceAlign;
4082 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
4086 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
4090 if (VecTy && !IsWholeAlloca && !IsDest) {
4092 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4094 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
4096 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4097 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
4101 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
4102 II.isVolatile(),
"copyload");
4103 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4104 LLVMContext::MD_access_group});
4111 if (VecTy && !IsWholeAlloca && IsDest) {
4112 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4115 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4116 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4118 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4121 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4125 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4126 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4127 LLVMContext::MD_access_group});
4130 Src->getType(),
DL));
4145 return !
II.isVolatile();
4148 bool visitIntrinsicInst(IntrinsicInst &
II) {
4149 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4150 "Unexpected intrinsic!");
4154 Pass.DeadInsts.push_back(&
II);
4156 if (
II.isDroppable()) {
4157 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4163 assert(
II.getArgOperand(0) == OldPtr);
4167 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4168 New = IRB.CreateLifetimeStart(Ptr);
4170 New = IRB.CreateLifetimeEnd(Ptr);
4178 void fixLoadStoreAlign(Instruction &Root) {
4182 SmallPtrSet<Instruction *, 4> Visited;
4183 SmallVector<Instruction *, 4>
Uses;
4185 Uses.push_back(&Root);
4194 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4201 for (User *U :
I->users())
4204 }
while (!
Uses.empty());
4207 bool visitPHINode(PHINode &PN) {
4209 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4210 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4216 IRBuilderBase::InsertPointGuard Guard(IRB);
4218 IRB.SetInsertPoint(OldPtr->
getParent()->getFirstInsertionPt());
4220 IRB.SetInsertPoint(OldPtr);
4221 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4223 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4228 deleteIfTriviallyDead(OldPtr);
4231 fixLoadStoreAlign(PN);
4240 bool visitSelectInst(SelectInst &SI) {
4242 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4243 "Pointer isn't an operand!");
4244 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4245 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4247 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4249 if (
SI.getOperand(1) == OldPtr)
4250 SI.setOperand(1, NewPtr);
4251 if (
SI.getOperand(2) == OldPtr)
4252 SI.setOperand(2, NewPtr);
4255 deleteIfTriviallyDead(OldPtr);
4258 fixLoadStoreAlign(SI);
4273class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4275 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4281 SmallPtrSet<User *, 8> Visited;
4288 const DataLayout &
DL;
4293 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4294 :
DL(
DL), IRB(IRB) {}
4298 bool rewrite(Instruction &
I) {
4302 while (!
Queue.empty()) {
4303 U =
Queue.pop_back_val();
4312 void enqueueUsers(Instruction &
I) {
4313 for (Use &U :
I.uses())
4314 if (Visited.
insert(
U.getUser()).second)
4315 Queue.push_back(&U);
4319 bool visitInstruction(Instruction &
I) {
return false; }
4322 template <
typename Derived>
class OpSplitter {
4329 SmallVector<unsigned, 4> Indices;
4333 SmallVector<Value *, 4> GEPIndices;
4347 const DataLayout &
DL;
4351 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4352 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4353 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4354 BaseAlign(BaseAlign),
DL(
DL) {
4355 IRB.SetInsertPoint(InsertionPoint);
4372 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4374 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4375 return static_cast<Derived *
>(
this)->emitFunc(
4380 unsigned OldSize = Indices.
size();
4382 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4384 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4386 GEPIndices.
push_back(IRB.getInt32(Idx));
4387 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4395 unsigned OldSize = Indices.
size();
4397 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4399 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4401 GEPIndices.
push_back(IRB.getInt32(Idx));
4402 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4413 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4417 SmallVector<Value *, 4> Components;
4422 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4423 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4425 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4431 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4435 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4437 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4443 Load->setAAMetadata(
4449 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4454 void recordFakeUses(LoadInst &LI) {
4455 for (Use &U : LI.
uses())
4457 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4463 void emitFakeUses() {
4464 for (Instruction *
I : FakeUses) {
4465 IRB.SetInsertPoint(
I);
4466 for (
auto *V : Components)
4467 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4468 I->eraseFromParent();
4473 bool visitLoadInst(LoadInst &LI) {
4482 Splitter.recordFakeUses(LI);
4485 Splitter.emitFakeUses();
4492 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4493 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4494 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4495 const DataLayout &
DL, IRBuilderTy &IRB)
4496 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4498 AATags(AATags), AggStore(AggStore) {}
4500 StoreInst *AggStore;
4503 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4509 Value *ExtractValue =
4510 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4511 Value *InBoundsGEP =
4512 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4514 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4531 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4533 SizeInBits, AggStore,
Store,
4534 Store->getPointerOperand(),
Store->getValueOperand(),
4538 "AT: unexpected debug.assign linked to store through "
4545 bool visitStoreInst(StoreInst &SI) {
4546 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4549 if (
V->getType()->isSingleValueType())
4554 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4556 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4561 SI.eraseFromParent();
4565 bool visitBitCastInst(BitCastInst &BC) {
4570 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4580 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4599 if (!ZI->getSrcTy()->isIntegerTy(1))
4612 dbgs() <<
" original: " << *Sel <<
"\n";
4613 dbgs() <<
" " << GEPI <<
"\n";);
4615 auto GetNewOps = [&](
Value *SelOp) {
4628 Cond =
SI->getCondition();
4629 True =
SI->getTrueValue();
4633 Cond = Sel->getOperand(0);
4634 True = ConstantInt::get(Sel->getType(), 1);
4635 False = ConstantInt::get(Sel->getType(), 0);
4640 IRB.SetInsertPoint(&GEPI);
4644 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4645 True->getName() +
".sroa.gep", NW);
4648 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4649 False->getName() +
".sroa.gep", NW);
4651 Value *NSel = MDFrom
4652 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4653 Sel->getName() +
".sroa.sel", MDFrom)
4654 : IRB.CreateSelectWithUnknownProfile(
4656 Sel->getName() +
".sroa.sel");
4657 Visited.
erase(&GEPI);
4662 enqueueUsers(*NSelI);
4665 dbgs() <<
" " << *NFalse <<
"\n";
4666 dbgs() <<
" " << *NSel <<
"\n";);
4675 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4680 auto IsInvalidPointerOperand = [](
Value *
V) {
4684 return !AI->isStaticAlloca();
4688 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4703 [](
Value *V) { return isa<ConstantInt>(V); }))
4716 dbgs() <<
" original: " << *
Phi <<
"\n";
4717 dbgs() <<
" " << GEPI <<
"\n";);
4719 auto GetNewOps = [&](
Value *PhiOp) {
4729 IRB.SetInsertPoint(Phi);
4730 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4731 Phi->getName() +
".sroa.phi");
4737 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4746 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4752 Visited.
erase(&GEPI);
4756 enqueueUsers(*NewPhi);
4762 dbgs() <<
"\n " << *NewPhi <<
'\n');
4767 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4768 if (unfoldGEPSelect(GEPI))
4771 if (unfoldGEPPhi(GEPI))
4778 bool visitPHINode(PHINode &PN) {
4783 bool visitSelectInst(SelectInst &SI) {
4797 if (Ty->isSingleValueType())
4800 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4805 InnerTy = ArrTy->getElementType();
4809 InnerTy = STy->getElementType(Index);
4814 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4815 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4836 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4838 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4839 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4846 ElementTy = AT->getElementType();
4847 TyNumElements = AT->getNumElements();
4852 ElementTy = VT->getElementType();
4853 TyNumElements = VT->getNumElements();
4855 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4857 if (NumSkippedElements >= TyNumElements)
4859 Offset -= NumSkippedElements * ElementSize;
4871 if (
Size == ElementSize)
4875 if (NumElements * ElementSize !=
Size)
4899 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4900 if (
Offset >= ElementSize)
4911 if (
Size == ElementSize)
4918 if (Index == EndIndex)
4928 assert(Index < EndIndex);
4948 InstructionSliceMap &SliceMap) {
4950 if (S.endOffset() - S.beginOffset() == 1)
4968 for (Slice *JS : SliceMap[J]) {
4969 if (S.beginOffset() > JS->beginOffset() &&
4970 S.beginOffset() < JS->endOffset())
4972 if (JS->beginOffset() > S.beginOffset() &&
4973 JS->beginOffset() < S.endOffset())
5004bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
5018 struct SplitOffsets {
5020 std::vector<uint64_t> Splits;
5022 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
5035 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
5037 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
5038 for (
auto &
P : AS.partitions()) {
5039 InstructionSliceMap SliceMap;
5040 for (Slice &S :
P) {
5043 for (Slice &S :
P) {
5045 bool ExtendsPastPartitionEnd = S.endOffset() >
P.endOffset();
5047 if (!S.isSplittable() || (!ExtendsPastPartitionEnd && !CopyOverlap)) {
5052 UnsplittableLoads.
insert(LI);
5055 UnsplittableLoads.
insert(LI);
5058 assert(
P.endOffset() > S.beginOffset() &&
5059 "Empty or backwards partition!");
5068 auto IsLoadSimplyStored = [](LoadInst *LI) {
5069 for (User *LU : LI->
users()) {
5071 if (!SI || !
SI->isSimple())
5076 if (!IsLoadSimplyStored(LI)) {
5077 UnsplittableLoads.
insert(LI);
5083 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
5087 if (!StoredLoad || !StoredLoad->isSimple())
5089 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
5099 auto &
Offsets = SplitOffsetsMap[
I];
5101 "Should not have splits the first time we see an instruction!");
5116 std::max(S.beginOffset(), CopyOverlap->beginOffset());
5117 uint64_t OverlapEnd = std::min(S.endOffset(), CopyOverlap->endOffset());
5118 uint64_t OverlapSize = OverlapEnd - OverlapStart;
5119 uint64_t SliceSize = S.endOffset() - S.beginOffset();
5120 uint64_t NonOverlapSize = SliceSize - OverlapSize;
5121 if (OverlapSize < NonOverlapSize) {
5126 Offsets.Splits.push_back(OverlapSize);
5127 Offsets.Splits.push_back(SliceSize - OverlapSize);
5128 }
else if (OverlapSize > NonOverlapSize) {
5131 for (
uint64_t Split = NonOverlapSize;
Split <= SliceSize / 2;
5132 Split += NonOverlapSize) {
5133 Offsets.Splits.push_back(Split);
5134 if (Split != SliceSize - Split) {
5135 Offsets.Splits.push_back(SliceSize - Split);
5143 Offsets.Splits.push_back(OverlapSize);
5146 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
5155 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5161 if (UnsplittableLoads.
count(LI))
5164 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5165 if (LoadOffsetsI == SplitOffsetsMap.
end())
5167 auto &LoadOffsets = LoadOffsetsI->second;
5170 auto &StoreOffsets = SplitOffsetsMap[
SI];
5175 if (LoadOffsets.Splits == StoreOffsets.Splits)
5179 <<
" " << *LI <<
"\n"
5180 <<
" " << *SI <<
"\n");
5186 UnsplittableLoads.
insert(LI);
5195 return UnsplittableLoads.
count(LI);
5200 return UnsplittableLoads.
count(LI);
5210 IRBuilderTy IRB(&AI);
5217 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5227 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5228 std::vector<LoadInst *> SplitLoads;
5229 const DataLayout &
DL = AI.getDataLayout();
5230 for (LoadInst *LI : Loads) {
5233 auto &
Offsets = SplitOffsetsMap[LI];
5234 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5236 "Load must have type size equal to store size");
5238 "Load must be >= slice size");
5241 assert(BaseOffset + SliceSize > BaseOffset &&
5242 "Cannot represent alloca access size using 64-bit integers!");
5245 IRB.SetInsertPoint(LI);
5252 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5255 LoadInst *PLoad = IRB.CreateAlignedLoad(
5258 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5259 PartPtrTy,
BasePtr->getName() +
"."),
5262 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5263 LLVMContext::MD_access_group});
5267 SplitLoads.push_back(PLoad);
5271 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5275 <<
", " << NewSlices.
back().endOffset()
5276 <<
"): " << *PLoad <<
"\n");
5291 bool DeferredStores =
false;
5292 for (User *LU : LI->
users()) {
5294 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5295 DeferredStores =
true;
5301 Value *StoreBasePtr =
SI->getPointerOperand();
5302 IRB.SetInsertPoint(SI);
5303 AAMDNodes AATags =
SI->getAAMetadata();
5305 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5307 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5308 LoadInst *PLoad = SplitLoads[
Idx];
5310 auto *PartPtrTy =
SI->getPointerOperandType();
5312 auto AS =
SI->getPointerAddressSpace();
5313 StoreInst *PStore = IRB.CreateAlignedStore(
5316 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5317 PartPtrTy, StoreBasePtr->
getName() +
"."),
5320 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5321 LLVMContext::MD_access_group,
5322 LLVMContext::MD_DIAssignID});
5327 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5335 ResplitPromotableAllocas.
insert(OtherAI);
5336 Worklist.insert(OtherAI);
5339 Worklist.insert(OtherAI);
5343 DeadInsts.push_back(SI);
5348 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5351 DeadInsts.push_back(LI);
5360 for (StoreInst *SI : Stores) {
5365 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5369 "Slice size should always match load size exactly!");
5371 assert(BaseOffset + StoreSize > BaseOffset &&
5372 "Cannot represent alloca access size using 64-bit integers!");
5380 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5381 std::vector<LoadInst *> *SplitLoads =
nullptr;
5382 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5383 SplitLoads = &SplitLoadsMapI->second;
5385 "Too few split loads for the number of splits in the store!");
5393 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5395 auto *StorePartPtrTy =
SI->getPointerOperandType();
5400 PLoad = (*SplitLoads)[
Idx];
5402 IRB.SetInsertPoint(LI);
5404 PLoad = IRB.CreateAlignedLoad(
5407 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5408 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5411 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5412 LLVMContext::MD_access_group});
5416 IRB.SetInsertPoint(SI);
5417 auto AS =
SI->getPointerAddressSpace();
5418 StoreInst *PStore = IRB.CreateAlignedStore(
5421 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5422 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5425 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5426 LLVMContext::MD_access_group});
5430 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5434 <<
", " << NewSlices.
back().endOffset()
5435 <<
"): " << *PStore <<
"\n");
5457 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5458 ResplitPromotableAllocas.
insert(OtherAI);
5459 Worklist.insert(OtherAI);
5462 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5463 Worklist.insert(OtherAI);
5478 DeadInsts.push_back(LI);
5480 DeadInsts.push_back(SI);
5489 AS.insert(NewSlices);
5493 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5499 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5536 bool IsIntegralPointerTy =
5537 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5539 !IsIntegralPointerTy)
5546 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5550 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5551 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5554 if (StructSize != VectorSize)
5557 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5560 auto *U = S.getUse();
5564 User *Usr = U->getUser();
5571 for (
const Slice &S :
P)
5572 if (!IsIgnorableOrMemIntrinsicSlice(S))
5575 for (
const Slice *S :
P.splitSliceTails())
5576 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5593static std::tuple<Type *, bool, VectorType *>
5597 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5599 dbgs() <<
"selectPartitionType path=" << Path
5604 dbgs() <<
"<unnamed>";
5605 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5606 <<
") size=" <<
P.size();
5608 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5610 dbgs() <<
" chosen=" << *SelectedTy;
5612 dbgs() <<
" vec=" << *SelectedVecTy;
5613 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5631 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5632 VecTy->getElementCount().getFixedValue() > 1) {
5633 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5634 return {VecTy,
false, VecTy};
5639 auto [CommonUseTy, LargestIntTy] =
5642 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5648 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5649 return {VecTy,
false, VecTy};
5652 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5653 return {CommonUseTy, IntWiden,
nullptr};
5660 P.beginOffset(),
P.size())) {
5664 if (TypePartitionTy->isArrayTy() &&
5665 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5666 DL.isLegalInteger(
P.size() * 8))
5670 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5671 return {TypePartitionTy,
true,
nullptr};
5674 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5675 return {VecTy,
false, VecTy};
5680 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5682 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5683 return {LargestIntTy,
true,
nullptr};
5688 if (AggregateToVector) {
5691 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5692 return {VTy,
false,
nullptr};
5698 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5699 return {TypePartitionTy,
false,
nullptr};
5704 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5705 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5706 return {LargestIntTy,
false,
nullptr};
5710 if (
DL.isLegalInteger(
P.size() * 8)) {
5712 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5713 return {IntTy,
false,
nullptr};
5718 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5719 return {ArrayTy,
false,
nullptr};
5732std::pair<AllocaInst *, uint64_t>
5733SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5734 const DataLayout &
DL = AI.getDataLayout();
5736 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5746 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5755 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5756 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5764 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5765 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5770 unsigned PPWOldSize = PostPromotionWorklist.size();
5771 unsigned NumUses = 0;
5772 SmallSetVector<PHINode *, 8> PHIUsers;
5773 SmallSetVector<SelectInst *, 8> SelectUsers;
5776 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5777 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5778 bool Promotable =
true;
5780 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5781 NumUses += DeletedValues->
size() + 1;
5782 for (
Value *V : *DeletedValues)
5783 DeadInsts.push_back(V);
5785 for (Slice *S :
P.splitSliceTails()) {
5789 for (Slice &S :
P) {
5795 NumAllocaPartitionUses += NumUses;
5796 MaxUsesPerAllocaPartition.updateMax(NumUses);
5802 for (PHINode *
PHI : PHIUsers) {
5813 SelectUsers.
clear();
5818 NewSelectsToRewrite;
5820 for (SelectInst *Sel : SelectUsers) {
5821 std::optional<RewriteableMemOps>
Ops =
5822 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5831 for (Use *U : AS.getDeadUsesIfPromotable()) {
5833 Value::dropDroppableUse(*U);
5836 DeadInsts.push_back(OldInst);
5838 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5839 SelectUsers.empty()) {
5841 PromotableAllocas.insert(NewAI);
5846 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5847 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5848 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5849 NewSelectsToRewrite.
size());
5851 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5852 std::make_move_iterator(NewSelectsToRewrite.
end())))
5853 SelectsToRewrite.insert(std::move(KV));
5854 Worklist.insert(NewAI);
5858 while (PostPromotionWorklist.size() > PPWOldSize)
5859 PostPromotionWorklist.pop_back();
5864 return {
nullptr, 0};
5869 Worklist.insert(NewAI);
5872 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5916 int64_t BitExtractOffset) {
5918 bool HasFragment =
false;
5919 bool HasBitExtract =
false;
5927 HasBitExtract =
true;
5928 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5929 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5938 assert(BitExtractOffset <= 0);
5939 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5945 if (AdjustedOffset < 0)
5948 Ops.push_back(
Op.getOp());
5949 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5950 Ops.push_back(ExtractSizeInBits);
5953 Op.appendToVector(
Ops);
5958 if (HasFragment && HasBitExtract)
5961 if (!HasBitExtract) {
5980 std::optional<DIExpression::FragmentInfo> NewFragment,
5981 int64_t BitExtractAdjustment) {
5991 BitExtractAdjustment);
5992 if (!NewFragmentExpr)
5998 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6011 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6017 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
6025 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
6031bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
6032 if (AS.begin() == AS.end())
6035 unsigned NumPartitions = 0;
6037 const DataLayout &
DL = AI.getDataLayout();
6040 Changed |= presplitLoadsAndStores(AI, AS);
6048 bool IsSorted =
true;
6050 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
6058 SparseBitVector<> SplittableOffset;
6060 for (Slice &S : AS) {
6062 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
6064 if (S.beginOffset() >= CurEnd) {
6065 SplittableOffset.
set(S.beginOffset());
6068 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6069 SplittableOffset.
reset(CurEnd);
6071 CurBegin = S.beginOffset();
6075 if (S.endOffset() > CurEnd) {
6076 CurEnd = S.endOffset();
6077 SplittableOffset.
set(CurEnd);
6082 for (Slice &S : AS) {
6083 if (!S.isSplittable())
6086 if ((S.beginOffset() > AllocaSize ||
6087 SplittableOffset.
test(S.beginOffset())) &&
6088 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6093 S.makeUnsplittable();
6113 for (
auto &
P : AS.partitions()) {
6114 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6118 uint64_t SizeOfByte = 8;
6120 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6121 Fragments.push_back(
6122 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6128 NumAllocaPartitions += NumPartitions;
6129 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6133 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6138 const Value *DbgPtr = DbgVariable->getAddress();
6140 DbgVariable->getFragmentOrEntireVariable();
6143 int64_t CurrentExprOffsetInBytes = 0;
6144 SmallVector<uint64_t> PostOffsetOps;
6146 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6150 int64_t ExtractOffsetInBits = 0;
6153 ExtractOffsetInBits = Extract.getOffsetInBits();
6158 DIBuilder DIB(*AI.getModule(),
false);
6160 int64_t OffsetFromLocationInBits;
6161 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6167 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6168 NewDbgFragment, OffsetFromLocationInBits))
6174 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6179 if (!NewDbgFragment)
6180 NewDbgFragment = DbgVariable->getFragment();
6184 int64_t OffestFromNewAllocaInBits =
6185 OffsetFromLocationInBits - ExtractOffsetInBits;
6188 int64_t BitExtractOffset =
6189 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6194 OffestFromNewAllocaInBits =
6195 std::max(int64_t(0), OffestFromNewAllocaInBits);
6201 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6202 if (OffestFromNewAllocaInBits > 0) {
6203 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6209 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6210 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6211 return LHS->getVariable() ==
RHS->getVariable() &&
6212 LHS->getDebugLoc()->getInlinedAt() ==
6213 RHS->getDebugLoc()->getInlinedAt();
6215 if (SameVariableFragment(OldDII, DbgVariable))
6216 OldDII->eraseFromParent();
6221 NewDbgFragment, BitExtractOffset);
6235void SROA::clobberUse(Use &U) {
6245 DeadInsts.push_back(OldI);
6267bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6272 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6273 bool AllSameAndValid =
true;
6274 Type *PartitionType =
nullptr;
6275 SmallVector<Instruction *> Insts;
6279 auto Flush = [&]() {
6280 if (AllSameAndValid && !Insts.
empty()) {
6281 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6282 << EndOffset <<
")\n");
6284 SSAUpdater
SSA(&NewPHIs);
6286 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6287 Promoter.run(Insts);
6289 AllSameAndValid =
true;
6290 PartitionType =
nullptr;
6294 for (Slice &S : AS) {
6298 dbgs() <<
"Ignoring slice: ";
6299 AS.print(
dbgs(), &S);
6303 if (S.beginOffset() >= EndOffset) {
6305 BeginOffset = S.beginOffset();
6306 EndOffset = S.endOffset();
6307 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6308 if (AllSameAndValid) {
6310 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6311 << EndOffset <<
")";
6312 AS.print(
dbgs(), &S);
6314 AllSameAndValid =
false;
6316 EndOffset = std::max(EndOffset, S.endOffset());
6323 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6324 AllSameAndValid =
false;
6325 PartitionType = UserTy;
6328 Type *UserTy =
SI->getValueOperand()->getType();
6329 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6330 AllSameAndValid =
false;
6331 PartitionType = UserTy;
6334 AllSameAndValid =
false;
6347std::pair<
bool ,
bool >
6348SROA::runOnAlloca(AllocaInst &AI) {
6350 bool CFGChanged =
false;
6353 ++NumAllocasAnalyzed;
6356 if (AI.use_empty()) {
6357 AI.eraseFromParent();
6361 const DataLayout &
DL = AI.getDataLayout();
6364 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6365 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6370 IRBuilderTy IRB(&AI);
6371 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6372 Changed |= AggRewriter.rewrite(AI);
6375 AllocaSlices AS(
DL, AI);
6380 if (AS.isEscapedReadOnly()) {
6381 Changed |= propagateStoredValuesToLoads(AI, AS);
6386 for (Instruction *DeadUser : AS.getDeadUsers()) {
6388 for (Use &DeadOp : DeadUser->operands())
6395 DeadInsts.push_back(DeadUser);
6398 for (Use *DeadOp : AS.getDeadOperands()) {
6399 clobberUse(*DeadOp);
6404 if (AS.begin() == AS.end())
6407 Changed |= splitAlloca(AI, AS);
6410 while (!SpeculatablePHIs.empty())
6414 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6415 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6416 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6422 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6423 while (!RemainingSelectsToRewrite.empty()) {
6424 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6441bool SROA::deleteDeadInstructions(
6442 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6444 while (!DeadInsts.empty()) {
6454 DeletedAllocas.
insert(AI);
6456 OldDII->eraseFromParent();
6462 for (Use &Operand :
I->operands())
6467 DeadInsts.push_back(U);
6471 I->eraseFromParent();
6481bool SROA::promoteAllocas() {
6482 if (PromotableAllocas.empty())
6489 NumPromoted += PromotableAllocas.size();
6490 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6493 PromotableAllocas.clear();
6497std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6500 const DataLayout &
DL =
F.getDataLayout();
6505 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6507 PromotableAllocas.insert(AI);
6509 Worklist.insert(AI);
6514 bool CFGChanged =
false;
6517 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6520 while (!Worklist.empty()) {
6521 auto [IterationChanged, IterationCFGChanged] =
6522 runOnAlloca(*Worklist.pop_back_val());
6524 CFGChanged |= IterationCFGChanged;
6526 Changed |= deleteDeadInstructions(DeletedAllocas);
6530 if (!DeletedAllocas.
empty()) {
6531 Worklist.set_subtract(DeletedAllocas);
6532 PostPromotionWorklist.set_subtract(DeletedAllocas);
6533 PromotableAllocas.set_subtract(DeletedAllocas);
6534 DeletedAllocas.
clear();
6540 Worklist = PostPromotionWorklist;
6541 PostPromotionWorklist.clear();
6542 }
while (!Worklist.empty());
6544 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6545 assert((!CFGChanged || !PreserveCFG) &&
6546 "Should not have modified the CFG when told to preserve it.");
6549 for (
auto &BB :
F) {
6562 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6574 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6575 OS, MapClassName2PassName);
6579 if (Options.AggregateToVector)
6580 OS <<
";aggregate-to-vector";
6601 if (skipFunction(
F))
6604 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6606 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6612 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6619 StringRef getPassName()
const override {
return "SROA"; }
6624char SROALegacyPass::ID = 0;
6629 AggregateToVector));
6633 "Scalar Replacement Of Aggregates",
false,
false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DXIL Forward Handle Accesses
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
This file implements a map that provides insertion order iteration.
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PointerIntPair class.
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, uint64_t OldAllocaOffsetInBits, uint64_t SliceSizeInBits, Instruction *OldInst, Instruction *Inst, Value *Dest, Value *Value, const DataLayout &DL)
Find linked dbg.assign and generate a new one with the correct FragmentInfo.
static VectorType * isVectorPromotionViable(Partition &P, const DataLayout &DL, unsigned VScale)
Test whether the given alloca partitioning and range of slices can be promoted to a vector.
static Align getAdjustedAlignment(Instruction *I, uint64_t Offset)
Compute the adjusted alignment for a load or store from an offset.
static VectorType * checkVectorTypesForPromotion(Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool HaveCommonEltTy, Type *CommonEltTy, bool HaveVecPtrTy, bool HaveCommonVecPtrTy, VectorType *CommonVecPtrTy, unsigned VScale)
Test whether any vector type in CandidateTys is viable for promotion.
static std::pair< Type *, IntegerType * > findCommonType(AllocaSlices::const_iterator B, AllocaSlices::const_iterator E, uint64_t EndOffset)
Walk the range of a partitioning looking for a common type to cover this sequence of slices.
static Type * stripAggregateTypeWrapping(const DataLayout &DL, Type *Ty)
Strip aggregate type wrapping.
static FragCalcResult calculateFragment(DILocalVariable *Variable, uint64_t NewStorageSliceOffsetInBits, uint64_t NewStorageSliceSizeInBits, std::optional< DIExpression::FragmentInfo > StorageFragment, std::optional< DIExpression::FragmentInfo > CurrentFragment, DIExpression::FragmentInfo &Target)
static DIExpression * createOrReplaceFragment(const DIExpression *Expr, DIExpression::FragmentInfo Frag, int64_t BitExtractOffset)
Create or replace an existing fragment in a DIExpression with Frag.
static Value * insertInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *Old, Value *V, uint64_t Offset, const Twine &Name)
static bool isVectorPromotionViableForSlice(Partition &P, const Slice &S, VectorType *Ty, uint64_t ElementSize, const DataLayout &DL, unsigned VScale)
Test whether the given slice use can be promoted to a vector.
static Value * getAdjustedPtr(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, APInt Offset, Type *PointerTy, const Twine &NamePrefix)
Compute an adjusted pointer from Ptr by Offset bytes where the resulting pointer has PointerTy.
static bool isIntegerWideningViableForSlice(const Slice &S, uint64_t AllocBeginOffset, Type *AllocaTy, const DataLayout &DL, bool &WholeAllocaOp)
Test whether a slice of an alloca is valid for integer widening.
static bool rewritePHINodeStore(PHINode &PN, StoreInst &SI, DomTreeUpdater &DTU, SmallSetVector< AllocaInst *, 16 > &Worklist)
Move a store through a pointer PHI onto each of the PHI's incoming edges.
static Value * extractVector(IRBuilderTy &IRB, Value *V, unsigned BeginIndex, unsigned EndIndex, const Twine &Name)
static Value * foldPHINodeOrSelectInst(Instruction &I)
A helper that folds a PHI node or a select.
static bool rewriteSelectInstMemOps(SelectInst &SI, const RewriteableMemOps &Ops, IRBuilderTy &IRB, DomTreeUpdater *DTU)
static void rewriteMemOpOfSelect(SelectInst &SI, T &I, SelectHandSpeculativity Spec, DomTreeUpdater &DTU)
static 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 getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI bool canSplitPredecessors() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
LLVM_ABI CaptureInfo getCaptureInfo(unsigned OpNo) const
Return which pointer components this operand may capture.
bool onlyReadsMemory(unsigned OpNo) const
bool isDataOperand(const Use *U) const
This is the shared class of boolean and integer constants.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
LLVM_ABI DbgRecord * insertDbgAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *SrcVar, DIExpression *ValExpr, Value *Addr, DIExpression *AddrExpr, const DILocation *DL)
Insert a new dbg_assign record.
iterator_range< expr_op_iterator > expr_ops() const
DbgVariableFragmentInfo FragmentInfo
LLVM_ABI bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits, int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag, std::optional< DIExpression::FragmentInfo > &Result, int64_t &OffsetFromLocationInBits)
Computes a fragment, bit-extract operation if needed, and new constant offset to describe a part of a...
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI void moveBefore(DbgRecord *MoveBefore)
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI void setKillAddress()
Kill the address component.
LLVM_ABI bool isKillLocation() const
LocationType getType() const
LLVM_ABI bool isKillAddress() const
Check whether this kills the address component.
LLVM_ABI void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
Value * getValue(unsigned OpIdx=0) const
static LLVM_ABI DbgVariableRecord * createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, DIExpression *Expression, Value *Address, DIExpression *AddressExpression, const DILocation *DI)
LLVM_ABI void setAssignId(DIAssignID *New)
DIExpression * getExpression() const
static LLVM_ABI DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
static LLVM_ABI DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
DILocalVariable * getVariable() const
LLVM_ABI void setKillLocation()
bool isDbgDeclare() const
void setAddress(Value *V)
DIExpression * getAddressExpression() const
LLVM_ABI DILocation * getInlinedAt() const
Identifies a unique instance of a variable.
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.
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
unsigned getNumElements(Type *Ty)
This is an optimization pass for GlobalISel generic memory operations.
static cl::opt< bool > SROASkipMem2Reg("sroa-skip-mem2reg", cl::init(false), cl::Hidden)
Disable running mem2reg during SROA in order to test or debug SROA.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
LLVM_ABI bool RemoveRedundantDbgInstrs(BasicBlock *BB)
Try to remove redundant dbg.value instructions from given basic block.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
LLVM_ABI bool isAssumeLikeIntrinsic(const Instruction *I)
Return true if it is an intrinsic that cannot be speculated but also cannot trap.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI std::optional< RegOrConstant > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
auto unique(Range &&R, Predicate P)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
bool capturesFullProvenance(CaptureComponents CC)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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 isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI Align tryEnforceAlignment(Value *V, Align PrefAlign, const DataLayout &DL)
If the specified pointer points to an object that we control, try to modify the object's alignment to...
LLVM_ABI FunctionPass * createSROAPass(bool PreserveCFG=true, bool AggregateToVector=false)
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes shift(size_t Offset) const
Create a new AAMDNode that describes this AAMDNode after applying a constant offset to the start of t...
LLVM_ABI AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Describes an element of a Bitfield.
static Bitfield::Type get(StorageType Packed)
Unpacks the field from the Packed value.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.