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());
5153 for (Slice *S :
P.splitSliceTails()) {
5154 auto SplitOffsetsMapI =
5156 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
5158 auto &
Offsets = SplitOffsetsMapI->second;
5162 "Cannot have an empty set of splits on the second partition!");
5164 P.beginOffset() -
Offsets.S->beginOffset() &&
5165 "Previous split does not end where this one begins!");
5169 if (S->endOffset() >
P.endOffset())
5178 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5184 if (UnsplittableLoads.
count(LI))
5187 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5188 if (LoadOffsetsI == SplitOffsetsMap.
end())
5190 auto &LoadOffsets = LoadOffsetsI->second;
5193 auto &StoreOffsets = SplitOffsetsMap[
SI];
5198 if (LoadOffsets.Splits == StoreOffsets.Splits)
5202 <<
" " << *LI <<
"\n"
5203 <<
" " << *SI <<
"\n");
5209 UnsplittableLoads.
insert(LI);
5218 return UnsplittableLoads.
count(LI);
5223 return UnsplittableLoads.
count(LI);
5233 IRBuilderTy IRB(&AI);
5240 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5250 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5251 std::vector<LoadInst *> SplitLoads;
5252 const DataLayout &
DL = AI.getDataLayout();
5253 for (LoadInst *LI : Loads) {
5256 auto &
Offsets = SplitOffsetsMap[LI];
5257 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5259 "Load must have type size equal to store size");
5261 "Load must be >= slice size");
5264 assert(BaseOffset + SliceSize > BaseOffset &&
5265 "Cannot represent alloca access size using 64-bit integers!");
5268 IRB.SetInsertPoint(LI);
5275 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5278 LoadInst *PLoad = IRB.CreateAlignedLoad(
5281 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5282 PartPtrTy,
BasePtr->getName() +
"."),
5285 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5286 LLVMContext::MD_access_group});
5290 SplitLoads.push_back(PLoad);
5294 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5298 <<
", " << NewSlices.
back().endOffset()
5299 <<
"): " << *PLoad <<
"\n");
5306 PartOffset =
Offsets.Splits[Idx];
5308 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : SliceSize) - PartOffset;
5314 bool DeferredStores =
false;
5315 for (User *LU : LI->
users()) {
5317 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5318 DeferredStores =
true;
5324 Value *StoreBasePtr =
SI->getPointerOperand();
5325 IRB.SetInsertPoint(SI);
5326 AAMDNodes AATags =
SI->getAAMetadata();
5328 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5330 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5331 LoadInst *PLoad = SplitLoads[Idx];
5333 auto *PartPtrTy =
SI->getPointerOperandType();
5335 auto AS =
SI->getPointerAddressSpace();
5336 StoreInst *PStore = IRB.CreateAlignedStore(
5339 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5340 PartPtrTy, StoreBasePtr->
getName() +
"."),
5343 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5344 LLVMContext::MD_access_group,
5345 LLVMContext::MD_DIAssignID});
5350 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5358 ResplitPromotableAllocas.
insert(OtherAI);
5359 Worklist.insert(OtherAI);
5362 Worklist.insert(OtherAI);
5366 DeadInsts.push_back(SI);
5371 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5374 DeadInsts.push_back(LI);
5383 for (StoreInst *SI : Stores) {
5388 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5392 "Slice size should always match load size exactly!");
5394 assert(BaseOffset + StoreSize > BaseOffset &&
5395 "Cannot represent alloca access size using 64-bit integers!");
5403 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5404 std::vector<LoadInst *> *SplitLoads =
nullptr;
5405 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5406 SplitLoads = &SplitLoadsMapI->second;
5408 "Too few split loads for the number of splits in the store!");
5416 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5418 auto *StorePartPtrTy =
SI->getPointerOperandType();
5423 PLoad = (*SplitLoads)[Idx];
5425 IRB.SetInsertPoint(LI);
5427 PLoad = IRB.CreateAlignedLoad(
5430 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5431 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5434 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5435 LLVMContext::MD_access_group});
5439 IRB.SetInsertPoint(SI);
5440 auto AS =
SI->getPointerAddressSpace();
5441 StoreInst *PStore = IRB.CreateAlignedStore(
5444 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5445 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5448 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5449 LLVMContext::MD_access_group});
5453 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5457 <<
", " << NewSlices.
back().endOffset()
5458 <<
"): " << *PStore <<
"\n");
5468 PartOffset =
Offsets.Splits[Idx];
5470 PartSize = (Idx <
Size ?
Offsets.Splits[Idx] : StoreSize) - PartOffset;
5480 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5481 ResplitPromotableAllocas.
insert(OtherAI);
5482 Worklist.insert(OtherAI);
5485 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5486 Worklist.insert(OtherAI);
5501 DeadInsts.push_back(LI);
5503 DeadInsts.push_back(SI);
5512 AS.insert(NewSlices);
5516 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5522 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5559 bool IsIntegralPointerTy =
5560 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5562 !IsIntegralPointerTy)
5569 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5573 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5574 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5577 if (StructSize != VectorSize)
5580 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5583 auto *U = S.getUse();
5587 User *Usr = U->getUser();
5594 for (
const Slice &S :
P)
5595 if (!IsIgnorableOrMemIntrinsicSlice(S))
5598 for (
const Slice *S :
P.splitSliceTails())
5599 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5616static std::tuple<Type *, bool, VectorType *>
5620 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5622 dbgs() <<
"selectPartitionType path=" << Path
5627 dbgs() <<
"<unnamed>";
5628 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5629 <<
") size=" <<
P.size();
5631 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5633 dbgs() <<
" chosen=" << *SelectedTy;
5635 dbgs() <<
" vec=" << *SelectedVecTy;
5636 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5654 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5655 VecTy->getElementCount().getFixedValue() > 1) {
5656 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5657 return {VecTy,
false, VecTy};
5662 auto [CommonUseTy, LargestIntTy] =
5665 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5671 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5672 return {VecTy,
false, VecTy};
5675 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5676 return {CommonUseTy, IntWiden,
nullptr};
5683 P.beginOffset(),
P.size())) {
5687 if (TypePartitionTy->isArrayTy() &&
5688 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5689 DL.isLegalInteger(
P.size() * 8))
5693 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5694 return {TypePartitionTy,
true,
nullptr};
5697 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5698 return {VecTy,
false, VecTy};
5703 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5705 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5706 return {LargestIntTy,
true,
nullptr};
5711 if (AggregateToVector) {
5714 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5715 return {VTy,
false,
nullptr};
5721 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5722 return {TypePartitionTy,
false,
nullptr};
5727 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5728 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5729 return {LargestIntTy,
false,
nullptr};
5733 if (
DL.isLegalInteger(
P.size() * 8)) {
5735 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5736 return {IntTy,
false,
nullptr};
5741 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5742 return {ArrayTy,
false,
nullptr};
5755std::pair<AllocaInst *, uint64_t>
5756SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5757 const DataLayout &
DL = AI.getDataLayout();
5759 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5769 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5778 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5779 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5787 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5788 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5793 unsigned PPWOldSize = PostPromotionWorklist.size();
5794 unsigned NumUses = 0;
5795 SmallSetVector<PHINode *, 8> PHIUsers;
5796 SmallSetVector<SelectInst *, 8> SelectUsers;
5799 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5800 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5801 bool Promotable =
true;
5803 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5804 NumUses += DeletedValues->
size() + 1;
5805 for (
Value *V : *DeletedValues)
5806 DeadInsts.push_back(V);
5808 for (Slice *S :
P.splitSliceTails()) {
5812 for (Slice &S :
P) {
5818 NumAllocaPartitionUses += NumUses;
5819 MaxUsesPerAllocaPartition.updateMax(NumUses);
5825 for (PHINode *
PHI : PHIUsers) {
5836 SelectUsers.
clear();
5841 NewSelectsToRewrite;
5843 for (SelectInst *Sel : SelectUsers) {
5844 std::optional<RewriteableMemOps>
Ops =
5845 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5854 for (Use *U : AS.getDeadUsesIfPromotable()) {
5856 Value::dropDroppableUse(*U);
5859 DeadInsts.push_back(OldInst);
5861 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5862 SelectUsers.empty()) {
5864 PromotableAllocas.insert(NewAI);
5869 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5870 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5871 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5872 NewSelectsToRewrite.
size());
5874 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5875 std::make_move_iterator(NewSelectsToRewrite.
end())))
5876 SelectsToRewrite.insert(std::move(KV));
5877 Worklist.insert(NewAI);
5881 while (PostPromotionWorklist.size() > PPWOldSize)
5882 PostPromotionWorklist.pop_back();
5887 return {
nullptr, 0};
5892 Worklist.insert(NewAI);
5895 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5939 int64_t BitExtractOffset) {
5941 bool HasFragment =
false;
5942 bool HasBitExtract =
false;
5950 HasBitExtract =
true;
5951 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5952 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5961 assert(BitExtractOffset <= 0);
5962 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5968 if (AdjustedOffset < 0)
5971 Ops.push_back(
Op.getOp());
5972 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5973 Ops.push_back(ExtractSizeInBits);
5976 Op.appendToVector(
Ops);
5981 if (HasFragment && HasBitExtract)
5984 if (!HasBitExtract) {
6003 std::optional<DIExpression::FragmentInfo> NewFragment,
6004 int64_t BitExtractAdjustment) {
6014 BitExtractAdjustment);
6015 if (!NewFragmentExpr)
6021 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6034 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6040 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
6048 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
6054bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
6055 if (AS.begin() == AS.end())
6058 unsigned NumPartitions = 0;
6060 const DataLayout &
DL = AI.getModule()->getDataLayout();
6063 Changed |= presplitLoadsAndStores(AI, AS);
6071 bool IsSorted =
true;
6073 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
6081 SparseBitVector<> SplittableOffset;
6083 for (Slice &S : AS) {
6085 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
6087 if (S.beginOffset() >= CurEnd) {
6088 SplittableOffset.
set(S.beginOffset());
6091 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6092 SplittableOffset.
reset(CurEnd);
6094 CurBegin = S.beginOffset();
6098 if (S.endOffset() > CurEnd) {
6099 CurEnd = S.endOffset();
6100 SplittableOffset.
set(CurEnd);
6105 for (Slice &S : AS) {
6106 if (!S.isSplittable())
6109 if ((S.beginOffset() > AllocaSize ||
6110 SplittableOffset.
test(S.beginOffset())) &&
6111 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6116 S.makeUnsplittable();
6136 for (
auto &
P : AS.partitions()) {
6137 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6141 uint64_t SizeOfByte = 8;
6143 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6144 Fragments.push_back(
6145 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6151 NumAllocaPartitions += NumPartitions;
6152 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6156 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6161 const Value *DbgPtr = DbgVariable->getAddress();
6163 DbgVariable->getFragmentOrEntireVariable();
6166 int64_t CurrentExprOffsetInBytes = 0;
6167 SmallVector<uint64_t> PostOffsetOps;
6169 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6173 int64_t ExtractOffsetInBits = 0;
6176 ExtractOffsetInBits = Extract.getOffsetInBits();
6181 DIBuilder DIB(*AI.getModule(),
false);
6183 int64_t OffsetFromLocationInBits;
6184 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6190 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6191 NewDbgFragment, OffsetFromLocationInBits))
6197 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6202 if (!NewDbgFragment)
6203 NewDbgFragment = DbgVariable->getFragment();
6207 int64_t OffestFromNewAllocaInBits =
6208 OffsetFromLocationInBits - ExtractOffsetInBits;
6211 int64_t BitExtractOffset =
6212 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6217 OffestFromNewAllocaInBits =
6218 std::max(int64_t(0), OffestFromNewAllocaInBits);
6224 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6225 if (OffestFromNewAllocaInBits > 0) {
6226 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6232 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6233 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6234 return LHS->getVariable() ==
RHS->getVariable() &&
6235 LHS->getDebugLoc()->getInlinedAt() ==
6236 RHS->getDebugLoc()->getInlinedAt();
6238 if (SameVariableFragment(OldDII, DbgVariable))
6239 OldDII->eraseFromParent();
6244 NewDbgFragment, BitExtractOffset);
6258void SROA::clobberUse(Use &U) {
6268 DeadInsts.push_back(OldI);
6290bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6295 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6296 bool AllSameAndValid =
true;
6297 Type *PartitionType =
nullptr;
6298 SmallVector<Instruction *> Insts;
6302 auto Flush = [&]() {
6303 if (AllSameAndValid && !Insts.
empty()) {
6304 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6305 << EndOffset <<
")\n");
6307 SSAUpdater
SSA(&NewPHIs);
6309 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6310 Promoter.run(Insts);
6312 AllSameAndValid =
true;
6313 PartitionType =
nullptr;
6317 for (Slice &S : AS) {
6321 dbgs() <<
"Ignoring slice: ";
6322 AS.print(
dbgs(), &S);
6326 if (S.beginOffset() >= EndOffset) {
6328 BeginOffset = S.beginOffset();
6329 EndOffset = S.endOffset();
6330 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6331 if (AllSameAndValid) {
6333 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6334 << EndOffset <<
")";
6335 AS.print(
dbgs(), &S);
6337 AllSameAndValid =
false;
6339 EndOffset = std::max(EndOffset, S.endOffset());
6346 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6347 AllSameAndValid =
false;
6348 PartitionType = UserTy;
6351 Type *UserTy =
SI->getValueOperand()->getType();
6352 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6353 AllSameAndValid =
false;
6354 PartitionType = UserTy;
6357 AllSameAndValid =
false;
6370std::pair<
bool ,
bool >
6371SROA::runOnAlloca(AllocaInst &AI) {
6373 bool CFGChanged =
false;
6376 ++NumAllocasAnalyzed;
6379 if (AI.use_empty()) {
6380 AI.eraseFromParent();
6384 const DataLayout &
DL = AI.getDataLayout();
6387 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6388 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6393 IRBuilderTy IRB(&AI);
6394 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6395 Changed |= AggRewriter.rewrite(AI);
6398 AllocaSlices AS(
DL, AI);
6403 if (AS.isEscapedReadOnly()) {
6404 Changed |= propagateStoredValuesToLoads(AI, AS);
6409 for (Instruction *DeadUser : AS.getDeadUsers()) {
6411 for (Use &DeadOp : DeadUser->operands())
6418 DeadInsts.push_back(DeadUser);
6421 for (Use *DeadOp : AS.getDeadOperands()) {
6422 clobberUse(*DeadOp);
6427 if (AS.begin() == AS.end())
6430 Changed |= splitAlloca(AI, AS);
6433 while (!SpeculatablePHIs.empty())
6437 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6438 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6439 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6445 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6446 while (!RemainingSelectsToRewrite.empty()) {
6447 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6464bool SROA::deleteDeadInstructions(
6465 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6467 while (!DeadInsts.empty()) {
6477 DeletedAllocas.
insert(AI);
6479 OldDII->eraseFromParent();
6485 for (Use &Operand :
I->operands())
6490 DeadInsts.push_back(U);
6494 I->eraseFromParent();
6504bool SROA::promoteAllocas() {
6505 if (PromotableAllocas.empty())
6512 NumPromoted += PromotableAllocas.size();
6513 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6516 PromotableAllocas.clear();
6520std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6523 const DataLayout &
DL =
F.getDataLayout();
6528 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6530 PromotableAllocas.insert(AI);
6532 Worklist.insert(AI);
6537 bool CFGChanged =
false;
6540 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6543 while (!Worklist.empty()) {
6544 auto [IterationChanged, IterationCFGChanged] =
6545 runOnAlloca(*Worklist.pop_back_val());
6547 CFGChanged |= IterationCFGChanged;
6549 Changed |= deleteDeadInstructions(DeletedAllocas);
6553 if (!DeletedAllocas.
empty()) {
6554 Worklist.set_subtract(DeletedAllocas);
6555 PostPromotionWorklist.set_subtract(DeletedAllocas);
6556 PromotableAllocas.set_subtract(DeletedAllocas);
6557 DeletedAllocas.
clear();
6563 Worklist = PostPromotionWorklist;
6564 PostPromotionWorklist.clear();
6565 }
while (!Worklist.empty());
6567 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6568 assert((!CFGChanged || !PreserveCFG) &&
6569 "Should not have modified the CFG when told to preserve it.");
6572 for (
auto &BB :
F) {
6585 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6597 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6598 OS, MapClassName2PassName);
6602 if (Options.AggregateToVector)
6603 OS <<
";aggregate-to-vector";
6624 if (skipFunction(
F))
6627 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6629 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6635 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6642 StringRef getPassName()
const override {
return "SROA"; }
6647char SROALegacyPass::ID = 0;
6652 AggregateToVector));
6656 "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.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getVScaleValue() const
Return the value for vscale based on the vscale_range attribute or 0 when unknown.
const BasicBlock & getEntryBlock() const
LLVM_ABI bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
Value * getPointerOperand()
iterator_range< op_iterator > indices()
Type * getSourceElementType() const
LLVM_ABI GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
This provides the default implementation of the IRBuilder 'InsertHelper' method that is called whenev...
virtual void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerIntPair - This class implements a pair of a pointer and small integer.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PtrUseVisitor(const DataLayout &DL)
LLVM_ABI SROAPass(SROAOptions Options)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Helper class for SSA formation on a set of values defined in multiple blocks.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void clear()
Completely clear the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool test(unsigned Idx) const
An instruction for storing to memory.
void setAlignment(Align Align)
Value * getValueOperand()
static unsigned getPointerOperandIndex()
Value * getPointerOperand()
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getSizeInBytes() const
LLVM_ABI unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
TypeSize getElementOffset(unsigned Idx) const
TypeSize getSizeInBits() const
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
element_iterator element_end() const
ArrayRef< Type * > elements() const
element_iterator element_begin() const
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Type::subtype_iterator element_iterator
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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.
LLVM_ABI void initializeSROALegacyPassPass(PassRegistry &)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRValues(Value *V)
As above, for DVRValues.
LLVM_ABI void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI Align tryEnforceAlignment(Value *V, Align PrefAlign, const DataLayout &DL)
If the specified pointer points to an object that we control, try to modify the object's alignment to...
LLVM_ABI FunctionPass * createSROAPass(bool PreserveCFG=true, bool AggregateToVector=false)
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes shift(size_t Offset) const
Create a new AAMDNode that describes this AAMDNode after applying a constant offset to the start of t...
LLVM_ABI AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Describes an element of a Bitfield.
static Bitfield::Type get(StorageType Packed)
Unpacks the field from the Packed value.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.