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),
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(LI.
getParent(), 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);
4219 OldPtr->
getParent()->getFirstInsertionPt());
4221 IRB.SetInsertPoint(OldPtr);
4222 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4224 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4229 deleteIfTriviallyDead(OldPtr);
4232 fixLoadStoreAlign(PN);
4241 bool visitSelectInst(SelectInst &SI) {
4243 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4244 "Pointer isn't an operand!");
4245 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4246 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4248 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4250 if (
SI.getOperand(1) == OldPtr)
4251 SI.setOperand(1, NewPtr);
4252 if (
SI.getOperand(2) == OldPtr)
4253 SI.setOperand(2, NewPtr);
4256 deleteIfTriviallyDead(OldPtr);
4259 fixLoadStoreAlign(SI);
4274class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4276 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4282 SmallPtrSet<User *, 8> Visited;
4289 const DataLayout &
DL;
4294 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4295 :
DL(
DL), IRB(IRB) {}
4299 bool rewrite(Instruction &
I) {
4303 while (!
Queue.empty()) {
4304 U =
Queue.pop_back_val();
4313 void enqueueUsers(Instruction &
I) {
4314 for (Use &U :
I.uses())
4315 if (Visited.
insert(
U.getUser()).second)
4316 Queue.push_back(&U);
4320 bool visitInstruction(Instruction &
I) {
return false; }
4323 template <
typename Derived>
class OpSplitter {
4330 SmallVector<unsigned, 4> Indices;
4334 SmallVector<Value *, 4> GEPIndices;
4348 const DataLayout &
DL;
4352 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4353 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4354 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4355 BaseAlign(BaseAlign),
DL(
DL) {
4356 IRB.SetInsertPoint(InsertionPoint);
4373 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4375 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4376 return static_cast<Derived *
>(
this)->emitFunc(
4381 unsigned OldSize = Indices.
size();
4383 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4385 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4387 GEPIndices.
push_back(IRB.getInt32(Idx));
4388 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4396 unsigned OldSize = Indices.
size();
4398 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4400 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4402 GEPIndices.
push_back(IRB.getInt32(Idx));
4403 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4414 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4418 SmallVector<Value *, 4> Components;
4423 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4424 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4426 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4432 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4436 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4438 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4444 Load->setAAMetadata(
4450 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4455 void recordFakeUses(LoadInst &LI) {
4456 for (Use &U : LI.
uses())
4458 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4464 void emitFakeUses() {
4465 for (Instruction *
I : FakeUses) {
4466 IRB.SetInsertPoint(
I);
4467 for (
auto *V : Components)
4468 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4469 I->eraseFromParent();
4474 bool visitLoadInst(LoadInst &LI) {
4483 Splitter.recordFakeUses(LI);
4486 Splitter.emitFakeUses();
4493 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4494 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4495 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4496 const DataLayout &
DL, IRBuilderTy &IRB)
4497 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4499 AATags(AATags), AggStore(AggStore) {}
4501 StoreInst *AggStore;
4504 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4510 Value *ExtractValue =
4511 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4512 Value *InBoundsGEP =
4513 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4515 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4532 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4534 SizeInBits, AggStore,
Store,
4535 Store->getPointerOperand(),
Store->getValueOperand(),
4539 "AT: unexpected debug.assign linked to store through "
4546 bool visitStoreInst(StoreInst &SI) {
4547 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4550 if (
V->getType()->isSingleValueType())
4555 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4557 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4562 SI.eraseFromParent();
4566 bool visitBitCastInst(BitCastInst &BC) {
4571 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4581 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4600 if (!ZI->getSrcTy()->isIntegerTy(1))
4613 dbgs() <<
" original: " << *Sel <<
"\n";
4614 dbgs() <<
" " << GEPI <<
"\n";);
4616 auto GetNewOps = [&](
Value *SelOp) {
4629 Cond =
SI->getCondition();
4630 True =
SI->getTrueValue();
4631 False =
SI->getFalseValue();
4634 Cond = Sel->getOperand(0);
4635 True = ConstantInt::get(Sel->getType(), 1);
4636 False = ConstantInt::get(Sel->getType(), 0);
4641 IRB.SetInsertPoint(&GEPI);
4645 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4646 True->
getName() +
".sroa.gep", NW);
4649 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4650 False->
getName() +
".sroa.gep", NW);
4652 Value *NSel = MDFrom
4653 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4654 Sel->getName() +
".sroa.sel", MDFrom)
4655 : IRB.CreateSelectWithUnknownProfile(
4657 Sel->getName() +
".sroa.sel");
4658 Visited.
erase(&GEPI);
4663 enqueueUsers(*NSelI);
4666 dbgs() <<
" " << *NFalse <<
"\n";
4667 dbgs() <<
" " << *NSel <<
"\n";);
4676 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4681 auto IsInvalidPointerOperand = [](
Value *
V) {
4685 return !AI->isStaticAlloca();
4689 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4704 [](
Value *V) { return isa<ConstantInt>(V); }))
4717 dbgs() <<
" original: " << *
Phi <<
"\n";
4718 dbgs() <<
" " << GEPI <<
"\n";);
4720 auto GetNewOps = [&](
Value *PhiOp) {
4730 IRB.SetInsertPoint(Phi);
4731 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4732 Phi->getName() +
".sroa.phi");
4738 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4747 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4753 Visited.
erase(&GEPI);
4757 enqueueUsers(*NewPhi);
4763 dbgs() <<
"\n " << *NewPhi <<
'\n');
4768 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4769 if (unfoldGEPSelect(GEPI))
4772 if (unfoldGEPPhi(GEPI))
4779 bool visitPHINode(PHINode &PN) {
4784 bool visitSelectInst(SelectInst &SI) {
4798 if (Ty->isSingleValueType())
4801 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4806 InnerTy = ArrTy->getElementType();
4810 InnerTy = STy->getElementType(Index);
4815 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4816 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4837 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4839 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4840 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4847 ElementTy = AT->getElementType();
4848 TyNumElements = AT->getNumElements();
4853 ElementTy = VT->getElementType();
4854 TyNumElements = VT->getNumElements();
4856 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4858 if (NumSkippedElements >= TyNumElements)
4860 Offset -= NumSkippedElements * ElementSize;
4872 if (
Size == ElementSize)
4876 if (NumElements * ElementSize !=
Size)
4900 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4901 if (
Offset >= ElementSize)
4912 if (
Size == ElementSize)
4919 if (Index == EndIndex)
4929 assert(Index < EndIndex);
4949 InstructionSliceMap &SliceMap) {
4951 if (S.endOffset() - S.beginOffset() == 1)
4969 for (Slice *JS : SliceMap[J]) {
4970 if (S.beginOffset() > JS->beginOffset() &&
4971 S.beginOffset() < JS->endOffset())
4973 if (JS->beginOffset() > S.beginOffset() &&
4974 JS->beginOffset() < S.endOffset())
5005bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
5019 struct SplitOffsets {
5021 std::vector<uint64_t> Splits;
5023 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
5036 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
5038 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
5039 for (
auto &
P : AS.partitions()) {
5040 InstructionSliceMap SliceMap;
5041 for (Slice &S :
P) {
5044 for (Slice &S :
P) {
5046 bool ExtendsPastPartitionEnd = S.endOffset() >
P.endOffset();
5048 if (!S.isSplittable() || (!ExtendsPastPartitionEnd && !CopyOverlap)) {
5053 UnsplittableLoads.
insert(LI);
5056 UnsplittableLoads.
insert(LI);
5059 assert(
P.endOffset() > S.beginOffset() &&
5060 "Empty or backwards partition!");
5069 auto IsLoadSimplyStored = [](LoadInst *LI) {
5070 for (User *LU : LI->
users()) {
5072 if (!SI || !
SI->isSimple())
5077 if (!IsLoadSimplyStored(LI)) {
5078 UnsplittableLoads.
insert(LI);
5084 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
5088 if (!StoredLoad || !StoredLoad->isSimple())
5090 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
5100 auto &
Offsets = SplitOffsetsMap[
I];
5102 "Should not have splits the first time we see an instruction!");
5117 std::max(S.beginOffset(), CopyOverlap->beginOffset());
5118 uint64_t OverlapEnd = std::min(S.endOffset(), CopyOverlap->endOffset());
5119 uint64_t OverlapSize = OverlapEnd - OverlapStart;
5120 uint64_t SliceSize = S.endOffset() - S.beginOffset();
5121 uint64_t NonOverlapSize = SliceSize - OverlapSize;
5122 if (OverlapSize < NonOverlapSize) {
5127 Offsets.Splits.push_back(OverlapSize);
5128 Offsets.Splits.push_back(SliceSize - OverlapSize);
5129 }
else if (OverlapSize > NonOverlapSize) {
5132 for (
uint64_t Split = NonOverlapSize;
Split <= SliceSize / 2;
5133 Split += NonOverlapSize) {
5134 Offsets.Splits.push_back(Split);
5135 if (Split != SliceSize - Split) {
5136 Offsets.Splits.push_back(SliceSize - Split);
5144 Offsets.Splits.push_back(OverlapSize);
5147 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
5156 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5162 if (UnsplittableLoads.
count(LI))
5165 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5166 if (LoadOffsetsI == SplitOffsetsMap.
end())
5168 auto &LoadOffsets = LoadOffsetsI->second;
5171 auto &StoreOffsets = SplitOffsetsMap[
SI];
5176 if (LoadOffsets.Splits == StoreOffsets.Splits)
5180 <<
" " << *LI <<
"\n"
5181 <<
" " << *SI <<
"\n");
5187 UnsplittableLoads.
insert(LI);
5196 return UnsplittableLoads.
count(LI);
5201 return UnsplittableLoads.
count(LI);
5211 IRBuilderTy IRB(&AI);
5218 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5228 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5229 std::vector<LoadInst *> SplitLoads;
5230 const DataLayout &
DL = AI.getDataLayout();
5231 for (LoadInst *LI : Loads) {
5234 auto &
Offsets = SplitOffsetsMap[LI];
5235 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5237 "Load must have type size equal to store size");
5239 "Load must be >= slice size");
5242 assert(BaseOffset + SliceSize > BaseOffset &&
5243 "Cannot represent alloca access size using 64-bit integers!");
5246 IRB.SetInsertPoint(LI);
5253 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5256 LoadInst *PLoad = IRB.CreateAlignedLoad(
5259 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5260 PartPtrTy,
BasePtr->getName() +
"."),
5263 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5264 LLVMContext::MD_access_group});
5268 SplitLoads.push_back(PLoad);
5272 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5276 <<
", " << NewSlices.
back().endOffset()
5277 <<
"): " << *PLoad <<
"\n");
5284 PartOffset =
Offsets.Splits[Idx];
5286 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : SliceSize) - PartOffset;
5292 bool DeferredStores =
false;
5293 for (User *LU : LI->
users()) {
5295 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5296 DeferredStores =
true;
5302 Value *StoreBasePtr =
SI->getPointerOperand();
5303 IRB.SetInsertPoint(SI);
5304 AAMDNodes AATags =
SI->getAAMetadata();
5306 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5308 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5309 LoadInst *PLoad = SplitLoads[Idx];
5311 auto *PartPtrTy =
SI->getPointerOperandType();
5313 auto AS =
SI->getPointerAddressSpace();
5314 StoreInst *PStore = IRB.CreateAlignedStore(
5317 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5318 PartPtrTy, StoreBasePtr->
getName() +
"."),
5321 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5322 LLVMContext::MD_access_group,
5323 LLVMContext::MD_DIAssignID});
5328 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5336 ResplitPromotableAllocas.
insert(OtherAI);
5337 Worklist.insert(OtherAI);
5340 Worklist.insert(OtherAI);
5344 DeadInsts.push_back(SI);
5349 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5352 DeadInsts.push_back(LI);
5361 for (StoreInst *SI : Stores) {
5366 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5370 "Slice size should always match load size exactly!");
5372 assert(BaseOffset + StoreSize > BaseOffset &&
5373 "Cannot represent alloca access size using 64-bit integers!");
5381 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5382 std::vector<LoadInst *> *SplitLoads =
nullptr;
5383 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5384 SplitLoads = &SplitLoadsMapI->second;
5386 "Too few split loads for the number of splits in the store!");
5394 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5396 auto *StorePartPtrTy =
SI->getPointerOperandType();
5401 PLoad = (*SplitLoads)[Idx];
5403 IRB.SetInsertPoint(LI);
5405 PLoad = IRB.CreateAlignedLoad(
5408 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5409 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5412 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5413 LLVMContext::MD_access_group});
5417 IRB.SetInsertPoint(SI);
5418 auto AS =
SI->getPointerAddressSpace();
5419 StoreInst *PStore = IRB.CreateAlignedStore(
5422 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5423 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5426 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5427 LLVMContext::MD_access_group});
5431 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5435 <<
", " << NewSlices.
back().endOffset()
5436 <<
"): " << *PStore <<
"\n");
5446 PartOffset =
Offsets.Splits[Idx];
5448 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : StoreSize) - PartOffset;
5458 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5459 ResplitPromotableAllocas.
insert(OtherAI);
5460 Worklist.insert(OtherAI);
5463 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5464 Worklist.insert(OtherAI);
5479 DeadInsts.push_back(LI);
5481 DeadInsts.push_back(SI);
5490 AS.insert(NewSlices);
5494 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5500 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5537 bool IsIntegralPointerTy =
5538 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5540 !IsIntegralPointerTy)
5547 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5551 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5552 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5555 if (StructSize != VectorSize)
5558 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5561 auto *U = S.getUse();
5565 User *Usr = U->getUser();
5572 for (
const Slice &S :
P)
5573 if (!IsIgnorableOrMemIntrinsicSlice(S))
5576 for (
const Slice *S :
P.splitSliceTails())
5577 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5594static std::tuple<Type *, bool, VectorType *>
5598 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5600 dbgs() <<
"selectPartitionType path=" << Path
5605 dbgs() <<
"<unnamed>";
5606 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5607 <<
") size=" <<
P.size();
5609 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5611 dbgs() <<
" chosen=" << *SelectedTy;
5613 dbgs() <<
" vec=" << *SelectedVecTy;
5614 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5632 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5633 VecTy->getElementCount().getFixedValue() > 1) {
5634 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5635 return {VecTy,
false, VecTy};
5640 auto [CommonUseTy, LargestIntTy] =
5643 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5649 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5650 return {VecTy,
false, VecTy};
5653 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5654 return {CommonUseTy, IntWiden,
nullptr};
5661 P.beginOffset(),
P.size())) {
5665 if (TypePartitionTy->isArrayTy() &&
5666 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5667 DL.isLegalInteger(
P.size() * 8))
5671 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5672 return {TypePartitionTy,
true,
nullptr};
5675 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5676 return {VecTy,
false, VecTy};
5681 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5683 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5684 return {LargestIntTy,
true,
nullptr};
5689 if (AggregateToVector) {
5692 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5693 return {VTy,
false,
nullptr};
5699 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5700 return {TypePartitionTy,
false,
nullptr};
5705 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5706 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5707 return {LargestIntTy,
false,
nullptr};
5711 if (
DL.isLegalInteger(
P.size() * 8)) {
5713 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5714 return {IntTy,
false,
nullptr};
5719 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5720 return {ArrayTy,
false,
nullptr};
5733std::pair<AllocaInst *, uint64_t>
5734SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5735 const DataLayout &
DL = AI.getDataLayout();
5737 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5747 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5756 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5757 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5765 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5766 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5771 unsigned PPWOldSize = PostPromotionWorklist.size();
5772 unsigned NumUses = 0;
5773 SmallSetVector<PHINode *, 8> PHIUsers;
5774 SmallSetVector<SelectInst *, 8> SelectUsers;
5777 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5778 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5779 bool Promotable =
true;
5781 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5782 NumUses += DeletedValues->
size() + 1;
5783 for (
Value *V : *DeletedValues)
5784 DeadInsts.push_back(V);
5786 for (Slice *S :
P.splitSliceTails()) {
5790 for (Slice &S :
P) {
5796 NumAllocaPartitionUses += NumUses;
5797 MaxUsesPerAllocaPartition.updateMax(NumUses);
5803 for (PHINode *
PHI : PHIUsers) {
5814 SelectUsers.
clear();
5819 NewSelectsToRewrite;
5821 for (SelectInst *Sel : SelectUsers) {
5822 std::optional<RewriteableMemOps>
Ops =
5823 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5832 for (Use *U : AS.getDeadUsesIfPromotable()) {
5834 Value::dropDroppableUse(*U);
5837 DeadInsts.push_back(OldInst);
5839 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5840 SelectUsers.empty()) {
5842 PromotableAllocas.insert(NewAI);
5847 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5848 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5849 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5850 NewSelectsToRewrite.
size());
5852 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5853 std::make_move_iterator(NewSelectsToRewrite.
end())))
5854 SelectsToRewrite.insert(std::move(KV));
5855 Worklist.insert(NewAI);
5859 while (PostPromotionWorklist.size() > PPWOldSize)
5860 PostPromotionWorklist.pop_back();
5865 return {
nullptr, 0};
5870 Worklist.insert(NewAI);
5873 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5917 int64_t BitExtractOffset) {
5919 bool HasFragment =
false;
5920 bool HasBitExtract =
false;
5928 HasBitExtract =
true;
5929 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5930 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5939 assert(BitExtractOffset <= 0);
5940 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5946 if (AdjustedOffset < 0)
5949 Ops.push_back(
Op.getOp());
5950 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5951 Ops.push_back(ExtractSizeInBits);
5954 Op.appendToVector(
Ops);
5959 if (HasFragment && HasBitExtract)
5962 if (!HasBitExtract) {
5981 std::optional<DIExpression::FragmentInfo> NewFragment,
5982 int64_t BitExtractAdjustment) {
5992 BitExtractAdjustment);
5993 if (!NewFragmentExpr)
5999 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6012 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6018 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
6026 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
6032bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
6033 if (AS.begin() == AS.end())
6036 unsigned NumPartitions = 0;
6038 const DataLayout &
DL = AI.getModule()->getDataLayout();
6041 Changed |= presplitLoadsAndStores(AI, AS);
6049 bool IsSorted =
true;
6051 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
6059 SparseBitVector<> SplittableOffset;
6061 for (Slice &S : AS) {
6063 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
6065 if (S.beginOffset() >= CurEnd) {
6066 SplittableOffset.
set(S.beginOffset());
6069 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6070 SplittableOffset.
reset(CurEnd);
6072 CurBegin = S.beginOffset();
6076 if (S.endOffset() > CurEnd) {
6077 CurEnd = S.endOffset();
6078 SplittableOffset.
set(CurEnd);
6083 for (Slice &S : AS) {
6084 if (!S.isSplittable())
6087 if ((S.beginOffset() > AllocaSize ||
6088 SplittableOffset.
test(S.beginOffset())) &&
6089 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6094 S.makeUnsplittable();
6114 for (
auto &
P : AS.partitions()) {
6115 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6119 uint64_t SizeOfByte = 8;
6121 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6122 Fragments.push_back(
6123 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6129 NumAllocaPartitions += NumPartitions;
6130 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6134 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6139 const Value *DbgPtr = DbgVariable->getAddress();
6141 DbgVariable->getFragmentOrEntireVariable();
6144 int64_t CurrentExprOffsetInBytes = 0;
6145 SmallVector<uint64_t> PostOffsetOps;
6147 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6151 int64_t ExtractOffsetInBits = 0;
6154 ExtractOffsetInBits = Extract.getOffsetInBits();
6159 DIBuilder DIB(*AI.getModule(),
false);
6161 int64_t OffsetFromLocationInBits;
6162 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6168 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6169 NewDbgFragment, OffsetFromLocationInBits))
6175 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6180 if (!NewDbgFragment)
6181 NewDbgFragment = DbgVariable->getFragment();
6185 int64_t OffestFromNewAllocaInBits =
6186 OffsetFromLocationInBits - ExtractOffsetInBits;
6189 int64_t BitExtractOffset =
6190 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6195 OffestFromNewAllocaInBits =
6196 std::max(int64_t(0), OffestFromNewAllocaInBits);
6202 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6203 if (OffestFromNewAllocaInBits > 0) {
6204 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6210 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6211 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6212 return LHS->getVariable() ==
RHS->getVariable() &&
6213 LHS->getDebugLoc()->getInlinedAt() ==
6214 RHS->getDebugLoc()->getInlinedAt();
6216 if (SameVariableFragment(OldDII, DbgVariable))
6217 OldDII->eraseFromParent();
6222 NewDbgFragment, BitExtractOffset);
6236void SROA::clobberUse(Use &U) {
6246 DeadInsts.push_back(OldI);
6268bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6273 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6274 bool AllSameAndValid =
true;
6275 Type *PartitionType =
nullptr;
6276 SmallVector<Instruction *> Insts;
6280 auto Flush = [&]() {
6281 if (AllSameAndValid && !Insts.
empty()) {
6282 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6283 << EndOffset <<
")\n");
6285 SSAUpdater
SSA(&NewPHIs);
6287 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6288 Promoter.run(Insts);
6290 AllSameAndValid =
true;
6291 PartitionType =
nullptr;
6295 for (Slice &S : AS) {
6299 dbgs() <<
"Ignoring slice: ";
6300 AS.print(
dbgs(), &S);
6304 if (S.beginOffset() >= EndOffset) {
6306 BeginOffset = S.beginOffset();
6307 EndOffset = S.endOffset();
6308 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6309 if (AllSameAndValid) {
6311 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6312 << EndOffset <<
")";
6313 AS.print(
dbgs(), &S);
6315 AllSameAndValid =
false;
6317 EndOffset = std::max(EndOffset, S.endOffset());
6324 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6325 AllSameAndValid =
false;
6326 PartitionType = UserTy;
6329 Type *UserTy =
SI->getValueOperand()->getType();
6330 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6331 AllSameAndValid =
false;
6332 PartitionType = UserTy;
6335 AllSameAndValid =
false;
6348std::pair<
bool ,
bool >
6349SROA::runOnAlloca(AllocaInst &AI) {
6351 bool CFGChanged =
false;
6354 ++NumAllocasAnalyzed;
6357 if (AI.use_empty()) {
6358 AI.eraseFromParent();
6362 const DataLayout &
DL = AI.getDataLayout();
6365 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6366 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6371 IRBuilderTy IRB(&AI);
6372 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6373 Changed |= AggRewriter.rewrite(AI);
6376 AllocaSlices AS(
DL, AI);
6381 if (AS.isEscapedReadOnly()) {
6382 Changed |= propagateStoredValuesToLoads(AI, AS);
6387 for (Instruction *DeadUser : AS.getDeadUsers()) {
6389 for (Use &DeadOp : DeadUser->operands())
6396 DeadInsts.push_back(DeadUser);
6399 for (Use *DeadOp : AS.getDeadOperands()) {
6400 clobberUse(*DeadOp);
6405 if (AS.begin() == AS.end())
6408 Changed |= splitAlloca(AI, AS);
6411 while (!SpeculatablePHIs.empty())
6415 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6416 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6417 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6423 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6424 while (!RemainingSelectsToRewrite.empty()) {
6425 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6442bool SROA::deleteDeadInstructions(
6443 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6445 while (!DeadInsts.empty()) {
6455 DeletedAllocas.
insert(AI);
6457 OldDII->eraseFromParent();
6463 for (Use &Operand :
I->operands())
6468 DeadInsts.push_back(U);
6472 I->eraseFromParent();
6482bool SROA::promoteAllocas() {
6483 if (PromotableAllocas.empty())
6490 NumPromoted += PromotableAllocas.size();
6491 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6494 PromotableAllocas.clear();
6498std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6501 const DataLayout &
DL =
F.getDataLayout();
6506 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6508 PromotableAllocas.insert(AI);
6510 Worklist.insert(AI);
6515 bool CFGChanged =
false;
6518 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6521 while (!Worklist.empty()) {
6522 auto [IterationChanged, IterationCFGChanged] =
6523 runOnAlloca(*Worklist.pop_back_val());
6525 CFGChanged |= IterationCFGChanged;
6527 Changed |= deleteDeadInstructions(DeletedAllocas);
6531 if (!DeletedAllocas.
empty()) {
6532 Worklist.set_subtract(DeletedAllocas);
6533 PostPromotionWorklist.set_subtract(DeletedAllocas);
6534 PromotableAllocas.set_subtract(DeletedAllocas);
6535 DeletedAllocas.
clear();
6541 Worklist = PostPromotionWorklist;
6542 PostPromotionWorklist.clear();
6543 }
while (!Worklist.empty());
6545 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6546 assert((!CFGChanged || !PreserveCFG) &&
6547 "Should not have modified the CFG when told to preserve it.");
6550 for (
auto &BB :
F) {
6563 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6575 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6576 OS, MapClassName2PassName);
6580 if (Options.AggregateToVector)
6581 OS <<
";aggregate-to-vector";
6602 if (skipFunction(
F))
6605 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6607 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6613 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6620 StringRef getPassName()
const override {
return "SROA"; }
6625char SROALegacyPass::ID = 0;
6630 AggregateToVector));
6634 "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.
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...
virtual void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerIntPair - This class implements a pair of a pointer and small integer.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PtrUseVisitor(const DataLayout &DL)
LLVM_ABI SROAPass(SROAOptions Options)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Helper class for SSA formation on a set of values defined in multiple blocks.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void clear()
Completely clear the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool test(unsigned Idx) const
An instruction for storing to memory.
void setAlignment(Align Align)
Value * getValueOperand()
static unsigned getPointerOperandIndex()
Value * getPointerOperand()
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getSizeInBytes() const
LLVM_ABI unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
TypeSize getElementOffset(unsigned Idx) const
TypeSize getSizeInBits() const
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
element_iterator element_end() const
ArrayRef< Type * > elements() const
element_iterator element_begin() const
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Type::subtype_iterator element_iterator
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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.