102#define DEBUG_TYPE "sroa"
104STATISTIC(NumAllocasAnalyzed,
"Number of allocas analyzed for replacement");
105STATISTIC(NumAllocaPartitions,
"Number of alloca partitions formed");
106STATISTIC(MaxPartitionsPerAlloca,
"Maximum number of partitions per alloca");
107STATISTIC(NumAllocaPartitionUses,
"Number of alloca partition uses rewritten");
108STATISTIC(MaxUsesPerAllocaPartition,
"Maximum number of uses of a partition");
109STATISTIC(NumNewAllocas,
"Number of new, smaller allocas introduced");
110STATISTIC(NumPromoted,
"Number of allocas promoted to SSA values");
111STATISTIC(NumLoadsSpeculated,
"Number of loads speculated to allow promotion");
113 "Number of loads rewritten into predicated loads to allow promotion");
116 "Number of stores rewritten into predicated stores to allow promotion");
118STATISTIC(NumVectorized,
"Number of vectorized aggregates");
122class AllocaSliceRewriter;
127class SelectHandSpeculativity {
128 unsigned char Storage = 0;
132 SelectHandSpeculativity() =
default;
133 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
134 bool isSpeculatable(
bool isTrueVal)
const;
135 bool areAllSpeculatable()
const;
136 bool areAnySpeculatable()
const;
137 bool areNoneSpeculatable()
const;
139 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
140 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
142static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
144using PossiblySpeculatableLoad =
147using RewriteableMemOp =
148 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
150using InstructionSliceMap =
172 LLVMContext *
const C;
173 DomTreeUpdater *
const DTU;
174 AssumptionCache *
const AC;
175 const bool PreserveCFG;
176 const bool AggregateToVector;
185 SmallSetVector<AllocaInst *, 16> Worklist;
200 SmallSetVector<AllocaInst *, 16> PostPromotionWorklist;
203 SetVector<AllocaInst *, SmallVector<AllocaInst *>,
204 SmallPtrSet<AllocaInst *, 16>, 16>
212 SmallSetVector<PHINode *, 8> SpeculatablePHIs;
219 SmallSetVector<PHINode *, 8> PHIsWithStoreToRewrite;
223 SmallMapVector<SelectInst *, RewriteableMemOps, 8> SelectsToRewrite;
239 static std::optional<RewriteableMemOps>
240 isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG);
243 SROA(LLVMContext *C, DomTreeUpdater *DTU, AssumptionCache *AC,
245 : C(C), DTU(DTU), AC(AC),
246 PreserveCFG(
Options.
CFG == SROAOptions::PreserveCFG),
247 AggregateToVector(
Options.AggregateToVector) {}
250 std::pair<
bool ,
bool > runSROA(
Function &
F);
253 friend class AllocaSliceRewriter;
255 bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
256 std::pair<AllocaInst *, uint64_t>
257 rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P);
258 bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
259 bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
260 std::pair<
bool ,
bool > runOnAlloca(AllocaInst &AI);
261 void clobberUse(Use &U);
262 bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
263 bool promoteAllocas();
277enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
281 uint64_t NewStorageSliceOffsetInBits,
283 std::optional<DIExpression::FragmentInfo> StorageFragment,
284 std::optional<DIExpression::FragmentInfo> CurrentFragment,
288 if (StorageFragment) {
290 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
292 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
294 Target.SizeInBits = NewStorageSliceSizeInBits;
295 Target.OffsetInBits = NewStorageSliceOffsetInBits;
301 if (!CurrentFragment) {
302 if (
auto Size = Variable->getSizeInBits()) {
305 if (
Target == CurrentFragment)
312 if (!CurrentFragment || *CurrentFragment ==
Target)
318 if (
Target.startInBits() < CurrentFragment->startInBits() ||
319 Target.endInBits() > CurrentFragment->endInBits())
358 if (DVRAssignMarkerRange.empty())
364 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
366 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
378 DVR->getExpression()->getFragmentInfo();
391 auto *Expr = DbgAssign->getExpression();
392 bool SetKillLocation =
false;
395 std::optional<DIExpression::FragmentInfo> BaseFragment;
398 if (R == BaseFragments.
end())
400 BaseFragment = R->second;
402 std::optional<DIExpression::FragmentInfo> CurrentFragment =
403 Expr->getFragmentInfo();
406 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
407 BaseFragment, CurrentFragment, NewFragment);
411 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
412 if (CurrentFragment) {
417 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
430 SetKillLocation =
true;
438 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
445 Inst, NewValue, DbgAssign->getVariable(), Expr, Dest,
449 NewAssign = DbgAssign;
468 Value && (DbgAssign->hasArgList() ||
469 !DbgAssign->getExpression()->isSingleLocationExpression());
486 if (NewAssign != DbgAssign) {
487 NewAssign->
moveBefore(DbgAssign->getIterator());
490 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
493 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
503 Twine getNameWithPrefix(
const Twine &Name)
const {
508 void SetNamePrefix(
const Twine &
P) { Prefix =
P.str(); }
510 void InsertHelper(Instruction *
I,
const Twine &Name,
535 PointerIntPair<Use *, 1, bool> UseAndIsSplittable;
541 : BeginOffset(BeginOffset), EndOffset(EndOffset),
542 UseAndIsSplittable(
U, IsSplittable) {}
544 uint64_t beginOffset()
const {
return BeginOffset; }
545 uint64_t endOffset()
const {
return EndOffset; }
547 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
548 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
550 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
552 bool isDead()
const {
return getUse() ==
nullptr; }
553 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
562 if (beginOffset() <
RHS.beginOffset())
564 if (beginOffset() >
RHS.beginOffset())
566 if (isSplittable() !=
RHS.isSplittable())
567 return !isSplittable();
568 if (endOffset() >
RHS.endOffset())
575 return LHS.beginOffset() < RHSOffset;
578 return LHSOffset <
RHS.beginOffset();
582 return isSplittable() ==
RHS.isSplittable() &&
583 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
598 AllocaSlices(
const DataLayout &
DL, AllocaInst &AI);
604 bool isEscaped()
const {
return PointerEscapingInstr; }
605 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
610 using range = iterator_range<iterator>;
612 iterator
begin() {
return Slices.begin(); }
613 iterator
end() {
return Slices.end(); }
616 using const_range = iterator_range<const_iterator>;
618 const_iterator
begin()
const {
return Slices.begin(); }
619 const_iterator
end()
const {
return Slices.end(); }
623 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
631 int OldSize = Slices.size();
632 Slices.append(NewSlices.
begin(), NewSlices.
end());
633 auto SliceI = Slices.begin() + OldSize;
634 std::stable_sort(SliceI, Slices.end());
635 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
644 ArrayRef<Instruction *> getDeadUsers()
const {
return DeadUsers; }
648 return DeadUseIfPromotable;
659#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
660 void print(raw_ostream &OS, const_iterator
I, StringRef Indent =
" ")
const;
661 void printSlice(raw_ostream &OS, const_iterator
I,
662 StringRef Indent =
" ")
const;
663 void printUse(raw_ostream &OS, const_iterator
I,
664 StringRef Indent =
" ")
const;
665 void print(raw_ostream &OS)
const;
666 void dump(const_iterator
I)
const;
671 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
674 friend class AllocaSlices::SliceBuilder;
676#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
704 SmallVector<Instruction *, 8> DeadUsers;
731 friend class AllocaSlices;
732 friend class AllocaSlices::partition_iterator;
734 using iterator = AllocaSlices::iterator;
738 uint64_t BeginOffset = 0, EndOffset = 0;
748 Partition(iterator SI) : SI(SI), SJ(SI) {}
754 uint64_t beginOffset()
const {
return BeginOffset; }
759 uint64_t endOffset()
const {
return EndOffset; }
765 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
766 return EndOffset - BeginOffset;
771 bool empty()
const {
return SI == SJ; }
782 iterator
begin()
const {
return SI; }
783 iterator
end()
const {
return SJ; }
815 AllocaSlices::iterator SE;
819 uint64_t MaxSplitSliceEndOffset = 0;
823 partition_iterator(AllocaSlices::iterator
SI, AllocaSlices::iterator SE)
835 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
836 "Cannot advance past the end of the slices!");
839 if (!
P.SplitTails.empty()) {
840 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
842 P.SplitTails.clear();
843 MaxSplitSliceEndOffset = 0;
849 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
852 return S->endOffset() == MaxSplitSliceEndOffset;
854 "Could not find the current max split slice offset!");
857 return S->endOffset() <= MaxSplitSliceEndOffset;
859 "Max split slice end offset is not actually the max!");
866 assert(P.SplitTails.empty() &&
"Failed to clear the split slices!");
876 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
877 P.SplitTails.push_back(&S);
878 MaxSplitSliceEndOffset =
879 std::max(S.endOffset(), MaxSplitSliceEndOffset);
887 P.BeginOffset = P.EndOffset;
888 P.EndOffset = MaxSplitSliceEndOffset;
895 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
896 !P.SI->isSplittable()) {
897 P.BeginOffset = P.EndOffset;
898 P.EndOffset = P.SI->beginOffset();
908 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
909 P.EndOffset = P.SI->endOffset();
914 if (!P.SI->isSplittable()) {
917 assert(P.BeginOffset == P.SI->beginOffset());
921 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
922 if (!P.SJ->isSplittable())
923 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
935 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
938 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
939 P.SJ->isSplittable()) {
940 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
947 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
948 assert(!P.SJ->isSplittable());
949 P.EndOffset = P.SJ->beginOffset();
956 "End iterators don't match between compared partition iterators!");
963 if (P.SI == RHS.P.SI && P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
964 assert(P.SJ == RHS.P.SJ &&
965 "Same set of slices formed two different sized partitions!");
966 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
967 "Same slice position with differently sized non-empty split "
990 return make_range(partition_iterator(begin(), end()),
991 partition_iterator(end(), end()));
999 return SI.getOperand(1 + CI->isZero());
1000 if (
SI.getOperand(1) ==
SI.getOperand(2))
1001 return SI.getOperand(1);
1010 return PN->hasConstantValue();
1025 const uint64_t AllocSize;
1041 if (VisitedDeadInsts.
insert(&
I).second)
1046 bool IsSplittable =
false) {
1052 <<
" which has zero size or starts outside of the "
1053 << AllocSize <<
" byte alloca:\n"
1054 <<
" alloca: " << AS.AI <<
"\n"
1055 <<
" use: " <<
I <<
"\n");
1056 return markAsDead(
I);
1068 assert(AllocSize >= BeginOffset);
1069 if (
Size > AllocSize - BeginOffset) {
1071 <<
Offset <<
" to remain within the " << AllocSize
1072 <<
" byte alloca:\n"
1073 <<
" alloca: " << AS.AI <<
"\n"
1074 <<
" use: " <<
I <<
"\n");
1075 EndOffset = AllocSize;
1078 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
1081 void visitBitCastInst(BitCastInst &BC) {
1083 return markAsDead(BC);
1085 return Base::visitBitCastInst(BC);
1088 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
1090 return markAsDead(ASC);
1092 return Base::visitAddrSpaceCastInst(ASC);
1095 void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
1097 return markAsDead(GEPI);
1099 return Base::visitGetElementPtrInst(GEPI);
1102 void handleLoadOrStore(
Type *Ty, Instruction &
I,
const APInt &
Offset,
1113 void visitLoadInst(LoadInst &LI) {
1115 "All simple FCA loads should have been pre-split");
1120 return PI.setEscapedReadOnly(&LI);
1123 if (
Size.isScalable()) {
1126 return PI.setAborted(&LI);
1135 void visitStoreInst(StoreInst &SI) {
1136 Value *ValOp =
SI.getValueOperand();
1138 return PI.setEscapedAndAborted(&SI);
1140 return PI.setAborted(&SI);
1142 TypeSize StoreSize =
DL.getTypeStoreSize(ValOp->
getType());
1144 unsigned VScale =
SI.getFunction()->getVScaleValue();
1146 return PI.setAborted(&SI);
1162 <<
Offset <<
" which extends past the end of the "
1163 << AllocSize <<
" byte alloca:\n"
1164 <<
" alloca: " << AS.AI <<
"\n"
1165 <<
" use: " << SI <<
"\n");
1166 return markAsDead(SI);
1170 "All simple FCA stores should have been pre-split");
1174 void visitMemSetInst(MemSetInst &
II) {
1175 assert(
II.getRawDest() == *U &&
"Pointer use is not the destination?");
1178 (IsOffsetKnown &&
Offset.uge(AllocSize)))
1180 return markAsDead(
II);
1183 return PI.setAborted(&
II);
1187 : AllocSize -
Offset.getLimitedValue(),
1191 void visitMemTransferInst(MemTransferInst &
II) {
1195 return markAsDead(
II);
1199 if (VisitedDeadInsts.
count(&
II))
1203 return PI.setAborted(&
II);
1210 if (
Offset.uge(AllocSize)) {
1211 auto MTPI = MemTransferSliceMap.
find(&
II);
1212 if (MTPI != MemTransferSliceMap.
end())
1213 AS.Slices[MTPI->second].kill();
1214 return markAsDead(
II);
1222 if (*U ==
II.getRawDest() && *U ==
II.getRawSource()) {
1224 if (!
II.isVolatile())
1225 return markAsDead(
II);
1233 SmallDenseMap<Instruction *, unsigned>::iterator MTPI;
1234 std::tie(MTPI, Inserted) =
1235 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1236 unsigned PrevIdx = MTPI->second;
1238 Slice &PrevP = AS.Slices[PrevIdx];
1242 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1244 return markAsDead(
II);
1249 PrevP.makeUnsplittable();
1256 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1257 "Map index doesn't point back to a slice with this user.");
1263 void visitIntrinsicInst(IntrinsicInst &
II) {
1264 if (
II.isDroppable()) {
1265 AS.DeadUseIfPromotable.push_back(U);
1270 return PI.setAborted(&
II);
1272 if (
II.isLifetimeStartOrEnd()) {
1273 insertUse(
II,
Offset, AllocSize,
true);
1277 Base::visitIntrinsicInst(
II);
1285 SmallPtrSet<Instruction *, 4> Visited;
1295 std::tie(UsedI,
I) =
Uses.pop_back_val();
1298 TypeSize LoadSize =
DL.getTypeStoreSize(LI->
getType());
1310 TypeSize StoreSize =
DL.getTypeStoreSize(
Op->getType());
1320 if (!
GEP->hasAllZeroIndices())
1327 for (User *U :
I->users())
1330 }
while (!
Uses.empty());
1335 void visitPHINodeOrSelectInst(Instruction &
I) {
1338 return markAsDead(
I);
1344 return PI.setAborted(&
I);
1362 AS.DeadOperands.push_back(U);
1368 return PI.setAborted(&
I);
1374 if (Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&
I,
Size))
1375 return PI.setAborted(UnsafeI);
1384 if (
Offset.uge(AllocSize)) {
1385 AS.DeadOperands.push_back(U);
1392 void visitPHINode(PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1394 void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1397 void visitInstruction(Instruction &
I) { PI.setAborted(&
I); }
1399 void visitCallBase(CallBase &CB) {
1405 PI.setEscapedReadOnly(&CB);
1409 Base::visitCallBase(CB);
1413AllocaSlices::AllocaSlices(
const DataLayout &
DL, AllocaInst &AI)
1415#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1418 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1420 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1421 if (PtrI.isEscaped() || PtrI.isAborted()) {
1424 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1425 : PtrI.getAbortingInst();
1426 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1429 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1431 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1438#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1440void AllocaSlices::print(raw_ostream &OS, const_iterator
I,
1441 StringRef Indent)
const {
1442 printSlice(OS,
I, Indent);
1444 printUse(OS,
I, Indent);
1447void AllocaSlices::printSlice(raw_ostream &OS, const_iterator
I,
1448 StringRef Indent)
const {
1449 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1450 <<
" slice #" << (
I -
begin())
1451 << (
I->isSplittable() ?
" (splittable)" :
"");
1454void AllocaSlices::printUse(raw_ostream &OS, const_iterator
I,
1455 StringRef Indent)
const {
1456 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1459void AllocaSlices::print(raw_ostream &OS)
const {
1460 if (PointerEscapingInstr) {
1461 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1462 <<
" A pointer to this alloca escaped by:\n"
1463 <<
" " << *PointerEscapingInstr <<
"\n";
1467 if (PointerEscapingInstrReadOnly)
1468 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1470 OS <<
"Slices of alloca: " << AI <<
"\n";
1491 for (
User *U :
I.users()) {
1492 Type *UserTy =
nullptr;
1498 UserTy =
Store->getValueOperand()->getType();
1500 if (!UserTy || (Ty && Ty != UserTy))
1510static std::pair<Type *, IntegerType *>
1514 bool TyIsCommon =
true;
1519 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1520 Use *U =
I->getUse();
1523 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1526 Type *UserTy =
nullptr;
1530 UserTy =
SI->getValueOperand()->getType();
1541 if (UserITy->getBitWidth() % 8 != 0 ||
1542 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1547 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1553 if (!UserTy || (Ty && Ty != UserTy))
1559 return {TyIsCommon ? Ty :
nullptr, ITy};
1589 Type *LoadType =
nullptr;
1602 if (LoadType != LI->
getType())
1611 if (BBI->mayWriteToMemory())
1614 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1621 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1664 if (!
SI ||
SI->getPointerOperand() != &PN)
1667 if (
SI->isVolatile())
1675 Value *StoredValue =
SI->getValueOperand();
1681 if (!SeenPreds.
insert(Pred).second)
1714 IRB.SetInsertPoint(&PN);
1716 PN.
getName() +
".sroa.speculated");
1746 IRB.SetInsertPoint(TI);
1749 LoadTy, InVal, Alignment,
1750 (PN.
getName() +
".sroa.speculate.load." + Pred->getName()));
1751 ++NumLoadsSpeculated;
1753 Load->setAAMetadata(AATags);
1755 InjectedLoads[Pred] =
Load;
1767 <<
" " <<
SI <<
"\n");
1775 if (!SeenPreds.
insert(Pred).second)
1785 bool CFGChanged =
false;
1787 for (
auto [Pred, InVal] : IncomingValues) {
1789 if (Pred->getTerminator()->getNumSuccessors() != 1) {
1791 assert(StoreBB &&
"store edge was not checked for splitting");
1798 ++NumStoresPredicated;
1802 SI.eraseFromParent();
1807SelectHandSpeculativity &
1808SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1816bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1821bool SelectHandSpeculativity::areAllSpeculatable()
const {
1822 return isSpeculatable(
true) &&
1823 isSpeculatable(
false);
1826bool SelectHandSpeculativity::areAnySpeculatable()
const {
1827 return isSpeculatable(
true) ||
1828 isSpeculatable(
false);
1830bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1831 return !areAnySpeculatable();
1834static SelectHandSpeculativity
1837 SelectHandSpeculativity
Spec;
1843 Spec.setAsSpeculatable(
Value ==
SI.getTrueValue());
1844 else if (PreserveCFG)
1850std::optional<RewriteableMemOps>
1851SROA::isSafeSelectToSpeculate(SelectInst &SI,
bool PreserveCFG) {
1852 RewriteableMemOps
Ops;
1854 for (User *U :
SI.users()) {
1859 if (
Store->isVolatile() || PreserveCFG)
1872 PossiblySpeculatableLoad
Load(LI);
1882 SelectHandSpeculativity Spec =
1884 if (PreserveCFG && !Spec.areAllSpeculatable())
1898 Value *TV =
SI.getTrueValue();
1899 Value *FV =
SI.getFalseValue();
1904 IRB.SetInsertPoint(&LI);
1908 LI.
getName() +
".sroa.speculate.load.true");
1911 LI.
getName() +
".sroa.speculate.load.false");
1912 NumLoadsSpeculated += 2;
1924 Value *V = IRB.CreateSelect(
SI.getCondition(), TL, FL,
1925 LI.
getName() +
".sroa.speculated", &
SI);
1931template <
typename T>
1933 SelectHandSpeculativity
Spec,
1940 if (
Spec.areNoneSpeculatable())
1942 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1945 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1947 if (
Spec.isSpeculatable(
true))
1953 Tail->setName(Head->
getName() +
".cont");
1958 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1959 int SuccIdx = IsThen ? 0 : 1;
1960 auto *NewMemOpBB = SuccBB == Tail ? Head : SuccBB;
1961 auto &CondMemOp =
cast<T>(*
I.clone());
1962 if (NewMemOpBB != Head) {
1963 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1965 ++NumLoadsPredicated;
1967 ++NumStoresPredicated;
1969 CondMemOp.dropUBImplyingAttrsAndMetadata();
1970 ++NumLoadsSpeculated;
1972 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
1973 Value *Ptr =
SI.getOperand(1 + SuccIdx);
1974 CondMemOp.setOperand(
I.getPointerOperandIndex(), Ptr);
1976 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1984 I.replaceAllUsesWith(PN);
1989 SelectHandSpeculativity
Spec,
2000 const RewriteableMemOps &
Ops,
2002 bool CFGChanged =
false;
2005 for (
const RewriteableMemOp &
Op :
Ops) {
2006 SelectHandSpeculativity
Spec;
2008 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
2011 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
2012 I = PSL.getPointer();
2013 Spec = PSL.getInt();
2015 if (
Spec.areAllSpeculatable()) {
2018 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
2022 I->eraseFromParent();
2027 SI.eraseFromParent();
2035 const Twine &NamePrefix) {
2037 Ptr = IRB.CreateInBoundsPtrAdd(Ptr, IRB.getInt(
Offset),
2038 NamePrefix +
"sroa_idx");
2039 return IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr,
PointerTy,
2040 NamePrefix +
"sroa_cast");
2055 unsigned VScale = 0) {
2065 "We can't have the same bitwidth for different int types");
2069 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
2070 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
2097 if (NewSize != OldSize)
2113 return OldAS == NewAS ||
2114 (!
DL.isNonIntegralAddressSpace(OldAS) &&
2115 !
DL.isNonIntegralAddressSpace(NewAS) &&
2116 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2122 return !
DL.isNonIntegralPointerType(NewTy);
2126 if (!
DL.isNonIntegralPointerType(OldTy))
2149 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2150 uint64_t BeginIndex = BeginOffset / ElementSize;
2151 if (BeginIndex * ElementSize != BeginOffset ||
2154 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2155 uint64_t EndIndex = EndOffset / ElementSize;
2156 if (EndIndex * ElementSize != EndOffset ||
2160 assert(EndIndex > BeginIndex &&
"Empty vector!");
2161 uint64_t NumElements = EndIndex - BeginIndex;
2162 Type *SliceTy = (NumElements == 1)
2163 ? Ty->getElementType()
2169 Use *U = S.getUse();
2172 if (
MI->isVolatile())
2174 if (!S.isSplittable())
2182 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2189 if (LTy->isStructTy())
2191 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2192 assert(LTy->isIntegerTy());
2198 if (
SI->isVolatile())
2200 Type *STy =
SI->getValueOperand()->getType();
2204 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2224 bool HaveCommonEltTy,
Type *CommonEltTy,
2225 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2226 VectorType *CommonVecPtrTy,
unsigned VScale) {
2228 if (CandidateTys.
empty())
2235 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2239 if (!HaveCommonEltTy && HaveVecPtrTy) {
2241 CandidateTys.
clear();
2243 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2246 if (!VTy->getElementType()->isIntegerTy())
2248 VTy->getContext(), VTy->getScalarSizeInBits())));
2255 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2256 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2257 "Cannot have vector types of different sizes!");
2258 assert(RHSTy->getElementType()->isIntegerTy() &&
2259 "All non-integer types eliminated!");
2260 assert(LHSTy->getElementType()->isIntegerTy() &&
2261 "All non-integer types eliminated!");
2267 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2268 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2269 "Cannot have vector types of different sizes!");
2270 assert(RHSTy->getElementType()->isIntegerTy() &&
2271 "All non-integer types eliminated!");
2272 assert(LHSTy->getElementType()->isIntegerTy() &&
2273 "All non-integer types eliminated!");
2277 llvm::sort(CandidateTys, RankVectorTypesComp);
2278 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2279 CandidateTys.end());
2285 assert(VTy->getElementType() == CommonEltTy &&
2286 "Unaccounted for element type!");
2287 assert(VTy == CandidateTys[0] &&
2288 "Different vector types with the same element type!");
2291 CandidateTys.resize(1);
2298 std::numeric_limits<unsigned short>::max();
2304 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2308 if (ElementSize % 8)
2310 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2311 "vector size not a multiple of element size?");
2314 for (
const Slice &S :
P)
2318 for (
const Slice *S :
P.splitSliceTails())
2324 return VTy != CandidateTys.
end() ? *VTy :
nullptr;
2331 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2332 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2334 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2337 for (
Type *Ty : OtherTys) {
2340 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2343 for (
VectorType *
const VTy : CandidateTysCopy) {
2345 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2346 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2347 unsigned ElementSize =
2348 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2352 CheckCandidateType(NewVTy);
2358 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2359 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2378 Type *CommonEltTy =
nullptr;
2380 bool HaveVecPtrTy =
false;
2381 bool HaveCommonEltTy =
true;
2382 bool HaveCommonVecPtrTy =
true;
2383 auto CheckCandidateType = [&](
Type *Ty) {
2386 if (!CandidateTys.
empty()) {
2388 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2389 DL.getTypeSizeInBits(V).getFixedValue()) {
2390 CandidateTys.
clear();
2395 Type *EltTy = VTy->getElementType();
2398 CommonEltTy = EltTy;
2399 else if (CommonEltTy != EltTy)
2400 HaveCommonEltTy =
false;
2403 HaveVecPtrTy =
true;
2404 if (!CommonVecPtrTy)
2405 CommonVecPtrTy = VTy;
2406 else if (CommonVecPtrTy != VTy)
2407 HaveCommonVecPtrTy =
false;
2413 for (
const Slice &S :
P) {
2418 Ty =
SI->getValueOperand()->getType();
2422 auto CandTy = Ty->getScalarType();
2423 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2424 S.endOffset() !=
P.endOffset())) {
2431 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2432 CheckCandidateType(Ty);
2437 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2438 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2439 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2442 CandidateTys.
clear();
2444 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2445 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2446 CommonVecPtrTy, VScale);
2457 bool &WholeAllocaOp) {
2460 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2461 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2463 Use *U = S.getUse();
2470 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2488 if (S.beginOffset() < AllocBeginOffset)
2494 WholeAllocaOp =
true;
2496 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2498 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2505 Type *ValueTy =
SI->getValueOperand()->getType();
2506 if (
SI->isVolatile())
2509 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2514 if (S.beginOffset() < AllocBeginOffset)
2520 WholeAllocaOp =
true;
2522 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2524 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2533 if (!S.isSplittable())
2550 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2556 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2574 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2576 for (
const Slice &S :
P)
2581 for (
const Slice *S :
P.splitSliceTails())
2586 return WholeAllocaOp;
2591 const Twine &Name) {
2595 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2596 "Element extends past full value");
2598 if (
DL.isBigEndian())
2599 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2600 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2602 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2605 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2606 "Cannot extract to a larger integer!");
2608 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2618 assert(Ty->getBitWidth() <= IntTy->getBitWidth() &&
2619 "Cannot insert a larger integer!");
2622 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2626 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2627 "Element store outside of alloca store");
2629 if (
DL.isBigEndian())
2630 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2631 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2633 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2637 if (ShAmt || Ty->getBitWidth() < IntTy->getBitWidth()) {
2638 APInt Mask = ~Ty->getMask().zext(IntTy->getBitWidth()).shl(ShAmt);
2639 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2641 V = IRB.CreateOr(Old, V, Name +
".insert");
2648 unsigned EndIndex,
const Twine &Name) {
2650 unsigned NumElements = EndIndex - BeginIndex;
2651 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2653 if (NumElements == VecTy->getNumElements())
2656 if (NumElements == 1) {
2657 V = IRB.CreateExtractElement(V, BeginIndex, Name +
".extract");
2663 V = IRB.CreateShuffleVector(V, Mask, Name +
".extract");
2669 unsigned BeginIndex,
const Twine &Name) {
2671 assert(VecTy &&
"Can only insert a vector into a vector");
2676 V = IRB.CreateInsertElement(Old, V, BeginIndex, Name +
".insert");
2684 assert(NumSubElements <= NumElements &&
"Too many elements!");
2685 if (NumSubElements == NumElements) {
2686 assert(V->getType() == VecTy &&
"Vector type mismatch");
2689 unsigned EndIndex = BeginIndex + NumSubElements;
2696 Mask.reserve(NumElements);
2697 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2698 if (Idx >= BeginIndex && Idx < EndIndex)
2699 Mask.push_back(Idx - BeginIndex);
2702 V = IRB.CreateShuffleVector(V, Mask, Name +
".expand");
2706 for (
unsigned Idx = 0; Idx != NumElements; ++Idx)
2707 if (Idx >= BeginIndex && Idx < EndIndex)
2708 Mask.push_back(Idx);
2710 Mask.push_back(Idx + NumElements);
2711 V = IRB.CreateShuffleVector(V, Old, Mask, Name +
"blend");
2750 const char *DebugName) {
2751 Type *EltType = VecType->getElementType();
2752 if (EltType != NewAIEltTy) {
2754 unsigned TotalBits =
2755 VecType->getNumElements() *
DL.getTypeSizeInBits(EltType);
2756 unsigned NewNumElts = TotalBits /
DL.getTypeSizeInBits(NewAIEltTy);
2759 V = Builder.CreateBitCast(V, NewVecType);
2760 VecType = NewVecType;
2761 LLVM_DEBUG(
dbgs() <<
" bitcast " << DebugName <<
": " << *V <<
"\n");
2765 BitcastIfNeeded(V0, VecType0,
"V0");
2766 BitcastIfNeeded(
V1, VecType1,
"V1");
2768 unsigned NumElts0 = VecType0->getNumElements();
2769 unsigned NumElts1 = VecType1->getNumElements();
2773 if (NumElts0 == NumElts1) {
2774 for (
unsigned i = 0; i < NumElts0 + NumElts1; ++i)
2775 ShuffleMask.push_back(i);
2779 unsigned SmallSize = std::min(NumElts0, NumElts1);
2780 unsigned LargeSize = std::max(NumElts0, NumElts1);
2781 bool IsV0Smaller = NumElts0 < NumElts1;
2782 Value *&ExtendedVec = IsV0Smaller ? V0 :
V1;
2784 for (
unsigned i = 0; i < SmallSize; ++i)
2786 for (
unsigned i = SmallSize; i < LargeSize; ++i)
2788 ExtendedVec = Builder.CreateShuffleVector(
2790 LLVM_DEBUG(
dbgs() <<
" shufflevector: " << *ExtendedVec <<
"\n");
2791 for (
unsigned i = 0; i < NumElts0; ++i)
2792 ShuffleMask.push_back(i);
2793 for (
unsigned i = 0; i < NumElts1; ++i)
2794 ShuffleMask.push_back(LargeSize + i);
2797 return Builder.CreateShuffleVector(V0,
V1, ShuffleMask);
2808class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2810 friend class InstVisitor<AllocaSliceRewriter, bool>;
2812 using Base = InstVisitor<AllocaSliceRewriter, bool>;
2814 const DataLayout &
DL;
2817 AllocaInst &OldAI, &NewAI;
2818 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2847 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2850 bool IsSplittable =
false;
2851 bool IsSplit =
false;
2852 Use *OldUse =
nullptr;
2856 SmallSetVector<PHINode *, 8> &PHIUsers;
2857 SmallSetVector<SelectInst *, 8> &SelectUsers;
2865 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2869 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2870 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2874 AllocaSliceRewriter(
const DataLayout &
DL, AllocaSlices &AS, SROA &
Pass,
2875 AllocaInst &OldAI, AllocaInst &NewAI,
Type *NewAllocaTy,
2877 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2878 VectorType *PromotableVecTy,
2879 SmallSetVector<PHINode *, 8> &PHIUsers,
2880 SmallSetVector<SelectInst *, 8> &SelectUsers)
2881 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2882 NewAllocaBeginOffset(NewAllocaBeginOffset),
2883 NewAllocaEndOffset(NewAllocaEndOffset), NewAllocaTy(NewAllocaTy),
2884 IntTy(IsIntegerPromotable
2887 DL.getTypeSizeInBits(NewAllocaTy).getFixedValue())
2889 VecTy(PromotableVecTy),
2890 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2891 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2893 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2894 IRB(*NewAI.getModule(), ConstantFolder()) {
2896 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2897 "Only multiple-of-8 sized vector elements are viable");
2900 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2903 bool visit(AllocaSlices::const_iterator
I) {
2904 bool CanSROA =
true;
2905 BeginOffset =
I->beginOffset();
2906 EndOffset =
I->endOffset();
2907 IsSplittable =
I->isSplittable();
2909 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2910 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2915 assert(BeginOffset < NewAllocaEndOffset);
2916 assert(EndOffset > NewAllocaBeginOffset);
2917 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2918 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2920 SliceSize = NewEndOffset - NewBeginOffset;
2921 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2922 <<
") NewBegin:(" << NewBeginOffset <<
", "
2923 << NewEndOffset <<
") NewAllocaBegin:("
2924 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2926 assert(IsSplit || NewBeginOffset == BeginOffset);
2927 OldUse =
I->getUse();
2931 IRB.SetInsertPoint(OldUserI);
2932 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2934 if (!IRB.getContext().shouldDiscardValueNames())
2935 IRB.getInserter().SetNamePrefix(Twine(NewAI.
getName()) +
"." +
2936 Twine(BeginOffset) +
".");
2998 std::optional<SmallVector<Value *, 4>>
2999 rewriteTreeStructuredMerge(Partition &
P) {
3001 if (
P.splitSliceTails().size() > 0)
3002 return std::nullopt;
3011 :
Store(
SI), BeginOffset(Begin), EndOffset(
End), StoredValue(Val) {}
3021 LoadInst *FullLoad =
nullptr;
3022 StoreInst *InitStore =
nullptr;
3026 Type *AllocatedEltTy =
3030 unsigned AllocatedEltTySize =
DL.getTypeSizeInBits(AllocatedEltTy);
3037 auto IsTypeValidForTreeStructuredMerge = [&](
Type *Ty) ->
bool {
3039 return FixedVecTy &&
3040 DL.getTypeSizeInBits(FixedVecTy->getElementType()) % 8 == 0 &&
3041 !FixedVecTy->getElementType()->isPointerTy();
3044 for (Slice &S :
P) {
3048 bool IsFullWidth = (S.beginOffset() == NewAllocaBeginOffset &&
3049 S.endOffset() == NewAllocaEndOffset);
3053 !IsTypeValidForTreeStructuredMerge(LI->
getType()))
3054 return std::nullopt;
3059 return std::nullopt;
3063 LoadInfos.
push_back({LI, S.beginOffset(), S.endOffset()});
3075 if (!
SI->isSimple() || !IsTypeValidForTreeStructuredMerge(
3076 SI->getValueOperand()->getType()))
3077 return std::nullopt;
3079 unsigned NumElts = StVecTy->getNumElements();
3080 unsigned EltSize =
DL.getTypeSizeInBits(StVecTy->getElementType());
3081 if (NumElts * EltSize % AllocatedEltTySize != 0)
3082 return std::nullopt;
3087 return std::nullopt;
3090 StoreInfos.
emplace_back(SI, S.beginOffset(), S.endOffset(),
3091 SI->getValueOperand());
3096 return std::nullopt;
3103 if (StoreInfos.
size() < 2)
3104 return std::nullopt;
3112 bool IsRMWPattern = InitStore && VecTy && !LoadInfos.
empty();
3113 bool IsStoresOnlyPattern = !InitStore && FullLoad && LoadInfos.
empty();
3114 if (!IsRMWPattern && !IsStoresOnlyPattern)
3115 return std::nullopt;
3119 BasicBlock *StoreBB = StoreInfos[0].Store->getParent();
3120 for (
auto &Info : StoreInfos)
3121 if (
Info.Store->getParent() != StoreBB)
3122 return std::nullopt;
3124 SmallVector<Value *, 4> DeletedValues;
3131 auto TreeMerge = [&](SmallVectorImpl<Value *> &Vals,
3134 while (Vals.
size() > 1) {
3135 SmallVector<Value *, 8>
Next;
3136 for (
unsigned I = 0,
E = Vals.
size();
I + 1 <
E;
I += 2) {
3142 if (Vals.
size() % 2 == 1)
3144 Vals = std::move(
Next);
3153 auto ReplaceFullLoad = [&](LoadInst *LoadToReplace,
Value *Merged) {
3155 Value *NewLoad = LoadBuilder.CreateAlignedLoad(
3156 Merged->getType(), &NewAI, getSliceAlign(),
3158 LoadToReplace->
getName() +
".sroa.new.load");
3160 NewLoad = LoadBuilder.CreateBitCast(NewLoad, LoadToReplace->
getType());
3165 if (IsStoresOnlyPattern) {
3168 llvm::sort(StoreInfos, [](
const StoreInfo &
A,
const StoreInfo &
B) {
3169 return A.BeginOffset <
B.BeginOffset;
3174 uint64_t Expected = NewAllocaBeginOffset;
3175 for (
auto &Info : StoreInfos) {
3176 if (
Info.BeginOffset != Expected)
3177 return std::nullopt;
3178 Expected =
Info.EndOffset;
3181 if (Expected != NewAllocaEndOffset)
3182 return std::nullopt;
3192 if (LoadBB == StoreBB) {
3193 for (
auto &Info : StoreInfos)
3194 if (!
Info.Store->comesBefore(FullLoad))
3195 return std::nullopt;
3199 dbgs() <<
"Tree structured merge rewrite (stores-only):\n";
3200 dbgs() <<
" Load: " << *FullLoad <<
"\n Ordered stores:\n";
3201 for (
auto [
I, Info] :
enumerate(StoreInfos)) {
3202 dbgs() <<
" [" <<
I <<
"] Range[" <<
Info.BeginOffset <<
", "
3203 <<
Info.EndOffset <<
") \tStore: " << *
Info.Store
3204 <<
"\tValue: " << *
Info.StoredValue <<
"\n";
3217 SmallVector<Value *, 8> Vals;
3218 for (
const auto &Info : StoreInfos) {
3223 Value *Merged = TreeMerge(Vals, Builder);
3224 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3227 ReplaceFullLoad(FullLoad, Merged);
3228 return DeletedValues;
3236 return std::nullopt;
3237 if (
any_of(LoadInfos, [&](
const LoadInfo &
I) {
3238 return I.Load->getParent() != StoreBB;
3240 return std::nullopt;
3256 Accesses.reserve(LoadInfos.
size() + StoreInfos.size());
3257 for (
const auto &L : LoadInfos)
3258 Accesses.push_back({
L.Load,
L.BeginOffset,
L.EndOffset,
false});
3259 for (
const auto &S : StoreInfos)
3260 Accesses.push_back({S.Store, S.BeginOffset, S.EndOffset,
true});
3262 return A.Inst->comesBefore(
B.Inst);
3270 return std::nullopt;
3276 if (FullLoad && FullLoad->
getParent() == StoreBB &&
3277 !
Accesses.back().Inst->comesBefore(FullLoad))
3278 return std::nullopt;
3289 using SliceRange = std::pair<uint64_t, uint64_t>;
3293 SortedRanges.
emplace_back(Acc.BeginOffset, Acc.EndOffset);
3297 uint64_t Expected = NewAllocaBeginOffset;
3298 for (
auto &
Range : SortedRanges) {
3299 if (
Range.first != Expected)
3300 return std::nullopt;
3301 Expected =
Range.second;
3303 if (Expected != NewAllocaEndOffset)
3304 return std::nullopt;
3307 dbgs() <<
"Tree structured merge rewrite (RMW):\n";
3308 dbgs() <<
" Init store: " << *InitStore <<
"\n";
3310 dbgs() <<
" Final load: " << *FullLoad <<
"\n";
3311 dbgs() <<
" Slice ranges (" << SortedRanges.size() <<
"):\n";
3312 for (
auto &
Range : SortedRanges)
3323 if (InitVec->
getType() != NewAllocaTy)
3324 InitVec = IRB.CreateBitCast(InitVec, NewAllocaTy,
"init.cast");
3325 DenseMap<SliceRange, Value *> SliceValues;
3326 for (
auto &
Range : SortedRanges) {
3327 unsigned BeginIdx = getIndex(
Range.first);
3328 unsigned EndIdx = getIndex(
Range.second);
3329 SliceValues[
Range] = IRB.CreateShuffleVector(
3345 SliceRange
Range{Acc.BeginOffset, Acc.EndOffset};
3348 if (
V->getType() != Acc.Inst->getType()) {
3350 V = IRB.CreateBitCast(V, Acc.Inst->getType());
3352 Acc.Inst->replaceAllUsesWith(V);
3369 SmallVector<Value *, 8> Vals;
3370 for (
auto &
Range : SortedRanges)
3372 Value *Merged = TreeMerge(Vals, Builder);
3373 Builder.CreateAlignedStore(Merged, &NewAI, getSliceAlign());
3378 ReplaceFullLoad(FullLoad, Merged);
3380 return DeletedValues;
3388 bool visitInstruction(Instruction &
I) {
3396 assert(IsSplit || BeginOffset == NewBeginOffset);
3399 StringRef OldName = OldPtr->
getName();
3401 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
3403 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
3408 OldName = OldName.
substr(IndexEnd + 1);
3412 OldName = OldName.
substr(OffsetEnd + 1);
3416 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
3428 Align getSliceAlign() {
3430 NewBeginOffset - NewAllocaBeginOffset);
3434 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
3436 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
3437 uint32_t
Index = RelOffset / ElementSize;
3438 assert(Index * ElementSize == RelOffset);
3442 void deleteIfTriviallyDead(
Value *V) {
3445 Pass.DeadInsts.push_back(
I);
3448 Value *rewriteVectorizedLoadInst(LoadInst &LI) {
3449 unsigned BeginIndex = getIndex(NewBeginOffset);
3450 unsigned EndIndex = getIndex(NewEndOffset);
3451 assert(EndIndex > BeginIndex &&
"Empty vector!");
3454 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3456 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3457 LLVMContext::MD_access_group});
3461 Value *rewriteIntegerLoad(LoadInst &LI) {
3462 assert(IntTy &&
"We cannot insert an integer to the alloca");
3465 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3466 V = IRB.CreateBitPreservingCastChain(
DL, V, IntTy);
3467 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3469 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
3470 IntegerType *ExtractTy = Type::getIntNTy(LI.
getContext(), SliceSize * 8);
3479 "Can only handle an extract for an overly wide load");
3481 V = IRB.CreateZExt(V, LI.
getType());
3485 bool visitLoadInst(LoadInst &LI) {
3494 Type *TargetTy = IsSplit ? Type::getIntNTy(LI.
getContext(), SliceSize * 8)
3496 bool IsPtrAdjusted =
false;
3499 V = rewriteVectorizedLoadInst(LI);
3501 V = rewriteIntegerLoad(LI);
3502 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
3503 NewEndOffset == NewAllocaEndOffset &&
3506 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
3509 getPtrToNewAI(LI.getPointerAddressSpace(), LI.isVolatile());
3510 LoadInst *NewLI = IRB.CreateAlignedLoad(
3511 NewAllocaTy, NewPtr, NewAI.getAlign(), LI.isVolatile(), LI.getName());
3512 if (LI.isVolatile())
3513 NewLI->setAtomic(LI.getOrdering(), LI.getSyncScopeID());
3514 if (NewLI->isAtomic())
3515 NewLI->setAlignment(LI.getAlign());
3520 copyMetadataForLoad(*NewLI, LI);
3524 NewLI->setAAMetadata(AATags.adjustForAccess(
3525 NewBeginOffset - BeginOffset, NewLI->getType(), DL));
3533 if (auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
3534 if (auto *TITy = dyn_cast<IntegerType>(TargetTy))
3535 if (AITy->getBitWidth() < TITy->getBitWidth()) {
3536 V = IRB.CreateZExt(V, TITy,
"load.ext");
3537 if (DL.isBigEndian())
3538 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
3542 Type *LTy = IRB.getPtrTy(AS);
3544 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
3549 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
3553 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
3554 LLVMContext::MD_access_group});
3557 IsPtrAdjusted =
true;
3559 V = IRB.CreateBitPreservingCastChain(
DL, V, TargetTy);
3564 "Only integer type loads and stores are split");
3565 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3566 "Split load isn't smaller than original load");
3568 "Non-byte-multiple bit width");
3574 LIIt.setHeadBit(
true);
3575 IRB.SetInsertPoint(LIIt);
3580 Value *Placeholder =
3586 Placeholder->replaceAllUsesWith(&LI);
3587 Placeholder->deleteValue();
3592 Pass.DeadInsts.push_back(&LI);
3593 deleteIfTriviallyDead(OldOp);
3598 bool rewriteVectorizedStoreInst(
Value *V, StoreInst &SI,
Value *OldOp,
3603 if (
V->getType() != VecTy) {
3604 unsigned BeginIndex = getIndex(NewBeginOffset);
3605 unsigned EndIndex = getIndex(NewEndOffset);
3606 assert(EndIndex > BeginIndex &&
"Empty vector!");
3607 unsigned NumElements = EndIndex - BeginIndex;
3609 "Too many elements!");
3610 Type *SliceTy = (NumElements == 1)
3612 : FixedVectorType::
get(ElementTy, NumElements);
3613 if (
V->getType() != SliceTy)
3614 V = IRB.CreateBitPreservingCastChain(
DL, V, SliceTy);
3618 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
3621 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3622 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3623 LLVMContext::MD_access_group});
3627 Pass.DeadInsts.push_back(&SI);
3636 bool rewriteIntegerStore(
Value *V, StoreInst &SI, AAMDNodes AATags) {
3637 assert(IntTy &&
"We cannot extract an integer from the alloca");
3639 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3641 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3643 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3644 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3648 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3649 StoreInst *
Store = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlign());
3650 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3651 LLVMContext::MD_access_group});
3658 Store->getValueOperand(),
DL);
3660 Pass.DeadInsts.push_back(&SI);
3665 bool visitStoreInst(StoreInst &SI) {
3667 Value *OldOp =
SI.getOperand(1);
3670 AAMDNodes AATags =
SI.getAAMetadata();
3675 if (
V->getType()->isPointerTy())
3677 Pass.PostPromotionWorklist.insert(AI);
3679 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3682 assert(
V->getType()->isIntegerTy() &&
3683 "Only integer type loads and stores are split");
3684 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3685 "Non-byte-multiple bit width");
3686 IntegerType *NarrowTy = Type::getIntNTy(
SI.getContext(), SliceSize * 8);
3692 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3693 if (IntTy &&
V->getType()->isIntegerTy())
3694 return rewriteIntegerStore(V, SI, AATags);
3697 if (NewBeginOffset == NewAllocaBeginOffset &&
3698 NewEndOffset == NewAllocaEndOffset &&
3700 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3702 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3705 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3707 unsigned AS =
SI.getPointerAddressSpace();
3708 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3710 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3712 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3713 LLVMContext::MD_access_group});
3717 if (
SI.isVolatile())
3726 Pass.DeadInsts.push_back(&SI);
3727 deleteIfTriviallyDead(OldOp);
3745 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3753 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3763 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3768 bool visitMemSetInst(MemSetInst &
II) {
3772 AAMDNodes AATags =
II.getAAMetadata();
3778 assert(NewBeginOffset == BeginOffset);
3779 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3780 II.setDestAlignment(getSliceAlign());
3785 "AT: Unexpected link to non-const GEP");
3786 deleteIfTriviallyDead(OldPtr);
3791 Pass.DeadInsts.push_back(&
II);
3795 const bool CanContinue = [&]() {
3798 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3803 if (Len > std::numeric_limits<unsigned>::max())
3805 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3808 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3814 Type *SizeTy =
II.getLength()->getType();
3815 unsigned Sz = NewEndOffset - NewBeginOffset;
3818 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3819 MaybeAlign(getSliceAlign()),
II.isVolatile()));
3825 New,
New->getRawDest(),
nullptr,
DL);
3840 assert(ElementTy == ScalarTy);
3842 unsigned BeginIndex = getIndex(NewBeginOffset);
3843 unsigned EndIndex = getIndex(NewEndOffset);
3844 assert(EndIndex > BeginIndex &&
"Empty vector!");
3845 unsigned NumElements = EndIndex - BeginIndex;
3847 "Too many elements!");
3850 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3851 Splat = IRB.CreateBitPreservingCastChain(
DL,
Splat, ElementTy);
3852 if (NumElements > 1)
3855 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
3864 V = getIntegerSplat(
II.getValue(),
Size);
3866 if (IntTy && (NewBeginOffset != NewAllocaBeginOffset ||
3867 NewEndOffset != NewAllocaEndOffset)) {
3868 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI,
3870 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
3874 assert(
V->getType() == IntTy &&
3875 "Wrong type for an alloca wide integer!");
3877 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3880 assert(NewBeginOffset == NewAllocaBeginOffset);
3881 assert(NewEndOffset == NewAllocaEndOffset);
3883 V = getIntegerSplat(
II.getValue(),
3884 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3889 V = IRB.CreateBitPreservingCastChain(
DL, V, NewAllocaTy);
3892 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3894 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3895 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3896 LLVMContext::MD_access_group});
3902 New,
New->getPointerOperand(), V,
DL);
3905 return !
II.isVolatile();
3908 bool visitMemTransferInst(MemTransferInst &
II) {
3914 AAMDNodes AATags =
II.getAAMetadata();
3916 bool IsDest = &
II.getRawDestUse() == OldUse;
3917 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3918 (!IsDest &&
II.getRawSource() == OldPtr));
3920 Align SliceAlign = getSliceAlign();
3928 if (!IsSplittable) {
3929 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3934 DbgAssign->getAddress() ==
II.getDest())
3935 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3937 II.setDest(AdjustedPtr);
3938 II.setDestAlignment(SliceAlign);
3940 II.setSource(AdjustedPtr);
3941 II.setSourceAlignment(SliceAlign);
3945 deleteIfTriviallyDead(OldPtr);
3958 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3959 SliceSize !=
DL.getTypeStoreSize(NewAllocaTy).getFixedValue() ||
3960 !
DL.typeSizeEqualsStoreSize(NewAllocaTy) ||
3966 if (EmitMemCpy && &OldAI == &NewAI) {
3968 assert(NewBeginOffset == BeginOffset);
3971 if (NewEndOffset != EndOffset)
3972 II.setLength(NewEndOffset - NewBeginOffset);
3976 Pass.DeadInsts.push_back(&
II);
3980 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3981 if (AllocaInst *AI =
3983 assert(AI != &OldAI && AI != &NewAI &&
3984 "Splittable transfers cannot reach the same alloca on both ends.");
3985 Pass.Worklist.insert(AI);
3992 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3993 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3995 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
3997 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
4005 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4006 Type *SizeTy =
II.getLength()->getType();
4007 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
4009 Value *DestPtr, *SrcPtr;
4010 MaybeAlign DestAlign, SrcAlign;
4014 DestAlign = SliceAlign;
4016 SrcAlign = OtherAlign;
4019 DestAlign = OtherAlign;
4021 SrcAlign = SliceAlign;
4023 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
4026 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
4031 &
II, New, DestPtr,
nullptr,
DL);
4036 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
4042 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
4043 NewEndOffset == NewAllocaEndOffset;
4045 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
4046 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
4047 unsigned NumElements = EndIndex - BeginIndex;
4048 IntegerType *SubIntTy =
4049 IntTy ? Type::getIntNTy(IntTy->
getContext(),
Size * 8) : nullptr;
4054 if (VecTy && !IsWholeAlloca) {
4055 if (NumElements == 1)
4056 OtherTy = VecTy->getElementType();
4059 }
else if (IntTy && !IsWholeAlloca) {
4062 OtherTy = NewAllocaTy;
4067 MaybeAlign SrcAlign = OtherAlign;
4068 MaybeAlign DstAlign = SliceAlign;
4076 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
4080 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
4084 if (VecTy && !IsWholeAlloca && !IsDest) {
4086 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4088 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
4090 IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
"load");
4091 Src = IRB.CreateBitPreservingCastChain(
DL, Src, IntTy);
4095 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
4096 II.isVolatile(),
"copyload");
4097 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4098 LLVMContext::MD_access_group});
4105 if (VecTy && !IsWholeAlloca && IsDest) {
4106 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4109 }
else if (IntTy && !IsWholeAlloca && IsDest) {
4110 Value *Old = IRB.CreateAlignedLoad(NewAllocaTy, &NewAI, NewAI.
getAlign(),
4112 Old = IRB.CreateBitPreservingCastChain(
DL, Old, IntTy);
4115 Src = IRB.CreateBitPreservingCastChain(
DL, Src, NewAllocaTy);
4119 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
4120 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
4121 LLVMContext::MD_access_group});
4124 Src->getType(),
DL));
4139 return !
II.isVolatile();
4142 bool visitIntrinsicInst(IntrinsicInst &
II) {
4143 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
4144 "Unexpected intrinsic!");
4148 Pass.DeadInsts.push_back(&
II);
4150 if (
II.isDroppable()) {
4151 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
4157 assert(
II.getArgOperand(0) == OldPtr);
4161 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
4162 New = IRB.CreateLifetimeStart(Ptr);
4164 New = IRB.CreateLifetimeEnd(Ptr);
4172 void fixLoadStoreAlign(Instruction &Root) {
4176 SmallPtrSet<Instruction *, 4> Visited;
4177 SmallVector<Instruction *, 4>
Uses;
4179 Uses.push_back(&Root);
4188 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
4195 for (User *U :
I->users())
4198 }
while (!
Uses.empty());
4201 bool visitPHINode(PHINode &PN) {
4203 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
4204 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
4210 IRBuilderBase::InsertPointGuard Guard(IRB);
4212 IRB.SetInsertPoint(OldPtr->
getParent()->getFirstInsertionPt());
4214 IRB.SetInsertPoint(OldPtr);
4215 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
4217 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4222 deleteIfTriviallyDead(OldPtr);
4225 fixLoadStoreAlign(PN);
4234 bool visitSelectInst(SelectInst &SI) {
4236 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
4237 "Pointer isn't an operand!");
4238 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
4239 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
4241 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
4243 if (
SI.getOperand(1) == OldPtr)
4244 SI.setOperand(1, NewPtr);
4245 if (
SI.getOperand(2) == OldPtr)
4246 SI.setOperand(2, NewPtr);
4249 deleteIfTriviallyDead(OldPtr);
4252 fixLoadStoreAlign(SI);
4267class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
4269 friend class InstVisitor<AggLoadStoreRewriter, bool>;
4275 SmallPtrSet<User *, 8> Visited;
4282 const DataLayout &
DL;
4287 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
4288 :
DL(
DL), IRB(IRB) {}
4292 bool rewrite(Instruction &
I) {
4296 while (!
Queue.empty()) {
4297 U =
Queue.pop_back_val();
4306 void enqueueUsers(Instruction &
I) {
4307 for (Use &U :
I.uses())
4308 if (Visited.
insert(
U.getUser()).second)
4309 Queue.push_back(&U);
4313 bool visitInstruction(Instruction &
I) {
return false; }
4316 template <
typename Derived>
class OpSplitter {
4323 SmallVector<unsigned, 4> Indices;
4327 SmallVector<Value *, 4> GEPIndices;
4341 const DataLayout &
DL;
4345 OpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4346 Align BaseAlign,
const DataLayout &
DL, IRBuilderTy &IRB)
4347 : IRB(IRB), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr), BaseTy(BaseTy),
4348 BaseAlign(BaseAlign),
DL(
DL) {
4349 IRB.SetInsertPoint(InsertionPoint);
4366 void emitSplitOps(
Type *Ty,
Value *&Agg,
const Twine &Name) {
4368 unsigned Offset =
DL.getIndexedOffsetInType(BaseTy, GEPIndices);
4369 return static_cast<Derived *
>(
this)->emitFunc(
4374 unsigned OldSize = Indices.
size();
4376 for (
unsigned Idx = 0,
Size = ATy->getNumElements(); Idx !=
Size;
4378 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4380 GEPIndices.
push_back(IRB.getInt32(Idx));
4381 emitSplitOps(ATy->getElementType(), Agg, Name +
"." + Twine(Idx));
4389 unsigned OldSize = Indices.
size();
4391 for (
unsigned Idx = 0,
Size = STy->getNumElements(); Idx !=
Size;
4393 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
4395 GEPIndices.
push_back(IRB.getInt32(Idx));
4396 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." + Twine(Idx));
4407 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
4411 SmallVector<Value *, 4> Components;
4416 LoadOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4417 AAMDNodes AATags, Align BaseAlign,
const DataLayout &
DL,
4419 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
DL,
4425 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4429 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4431 IRB.CreateAlignedLoad(Ty,
GEP, Alignment, Name +
".load");
4437 Load->setAAMetadata(
4443 Agg = IRB.CreateInsertValue(Agg,
Load, Indices, Name +
".insert");
4448 void recordFakeUses(LoadInst &LI) {
4449 for (Use &U : LI.
uses())
4451 if (
II->getIntrinsicID() == Intrinsic::fake_use)
4457 void emitFakeUses() {
4458 for (Instruction *
I : FakeUses) {
4459 IRB.SetInsertPoint(
I);
4460 for (
auto *V : Components)
4461 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
4462 I->eraseFromParent();
4467 bool visitLoadInst(LoadInst &LI) {
4476 Splitter.recordFakeUses(LI);
4479 Splitter.emitFakeUses();
4486 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
4487 StoreOpSplitter(Instruction *InsertionPoint,
Value *Ptr,
Type *BaseTy,
4488 AAMDNodes AATags, StoreInst *AggStore, Align BaseAlign,
4489 const DataLayout &
DL, IRBuilderTy &IRB)
4490 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr, BaseTy, BaseAlign,
4492 AATags(AATags), AggStore(AggStore) {}
4494 StoreInst *AggStore;
4497 void emitFunc(
Type *Ty,
Value *&Agg, Align Alignment,
const Twine &Name) {
4503 Value *ExtractValue =
4504 IRB.CreateExtractValue(Agg, Indices, Name +
".extract");
4505 Value *InBoundsGEP =
4506 IRB.CreateInBoundsGEP(BaseTy, Ptr, GEPIndices, Name +
".gep");
4508 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
4525 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
4527 SizeInBits, AggStore,
Store,
4528 Store->getPointerOperand(),
Store->getValueOperand(),
4532 "AT: unexpected debug.assign linked to store through "
4539 bool visitStoreInst(StoreInst &SI) {
4540 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
4543 if (
V->getType()->isSingleValueType())
4548 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
4550 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
4555 SI.eraseFromParent();
4559 bool visitBitCastInst(BitCastInst &BC) {
4564 bool visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) {
4574 bool unfoldGEPSelect(GetElementPtrInst &GEPI) {
4593 if (!ZI->getSrcTy()->isIntegerTy(1))
4606 dbgs() <<
" original: " << *Sel <<
"\n";
4607 dbgs() <<
" " << GEPI <<
"\n";);
4609 auto GetNewOps = [&](
Value *SelOp) {
4622 Cond =
SI->getCondition();
4623 True =
SI->getTrueValue();
4627 Cond = Sel->getOperand(0);
4628 True = ConstantInt::get(Sel->getType(), 1);
4629 False = ConstantInt::get(Sel->getType(), 0);
4634 IRB.SetInsertPoint(&GEPI);
4638 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4639 True->getName() +
".sroa.gep", NW);
4642 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4643 False->getName() +
".sroa.gep", NW);
4645 Value *NSel = MDFrom
4646 ? IRB.CreateSelect(
Cond, NTrue, NFalse,
4647 Sel->getName() +
".sroa.sel", MDFrom)
4648 : IRB.CreateSelectWithUnknownProfile(
4650 Sel->getName() +
".sroa.sel");
4651 Visited.
erase(&GEPI);
4656 enqueueUsers(*NSelI);
4659 dbgs() <<
" " << *NFalse <<
"\n";
4660 dbgs() <<
" " << *NSel <<
"\n";);
4669 bool unfoldGEPPhi(GetElementPtrInst &GEPI) {
4674 auto IsInvalidPointerOperand = [](
Value *
V) {
4678 return !AI->isStaticAlloca();
4682 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4697 [](
Value *V) { return isa<ConstantInt>(V); }))
4710 dbgs() <<
" original: " << *
Phi <<
"\n";
4711 dbgs() <<
" " << GEPI <<
"\n";);
4713 auto GetNewOps = [&](
Value *PhiOp) {
4723 IRB.SetInsertPoint(Phi);
4724 PHINode *NewPhi = IRB.CreatePHI(GEPI.
getType(),
Phi->getNumIncomingValues(),
4725 Phi->getName() +
".sroa.phi");
4731 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4740 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4746 Visited.
erase(&GEPI);
4750 enqueueUsers(*NewPhi);
4756 dbgs() <<
"\n " << *NewPhi <<
'\n');
4761 bool visitGetElementPtrInst(GetElementPtrInst &GEPI) {
4762 if (unfoldGEPSelect(GEPI))
4765 if (unfoldGEPPhi(GEPI))
4772 bool visitPHINode(PHINode &PN) {
4777 bool visitSelectInst(SelectInst &SI) {
4791 if (Ty->isSingleValueType())
4794 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4799 InnerTy = ArrTy->getElementType();
4803 InnerTy = STy->getElementType(Index);
4808 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4809 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4830 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4832 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4833 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4840 ElementTy = AT->getElementType();
4841 TyNumElements = AT->getNumElements();
4846 ElementTy = VT->getElementType();
4847 TyNumElements = VT->getNumElements();
4849 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4851 if (NumSkippedElements >= TyNumElements)
4853 Offset -= NumSkippedElements * ElementSize;
4865 if (
Size == ElementSize)
4869 if (NumElements * ElementSize !=
Size)
4893 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4894 if (
Offset >= ElementSize)
4905 if (
Size == ElementSize)
4912 if (Index == EndIndex)
4922 assert(Index < EndIndex);
4942 InstructionSliceMap &SliceMap) {
4944 if (S.endOffset() - S.beginOffset() == 1)
4962 for (Slice *JS : SliceMap[J]) {
4963 if (S.beginOffset() > JS->beginOffset() &&
4964 S.beginOffset() < JS->endOffset())
4966 if (JS->beginOffset() > S.beginOffset() &&
4967 JS->beginOffset() < S.endOffset())
4998bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) {
5012 struct SplitOffsets {
5014 std::vector<uint64_t> Splits;
5016 SmallDenseMap<Instruction *, SplitOffsets, 8> SplitOffsetsMap;
5029 SmallPtrSet<LoadInst *, 8> UnsplittableLoads;
5031 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
5032 for (
auto &
P : AS.partitions()) {
5033 InstructionSliceMap SliceMap;
5034 for (Slice &S :
P) {
5037 for (Slice &S :
P) {
5039 bool ExtendsPastPartitionEnd = S.endOffset() >
P.endOffset();
5041 if (!S.isSplittable() || (!ExtendsPastPartitionEnd && !CopyOverlap)) {
5046 UnsplittableLoads.
insert(LI);
5049 UnsplittableLoads.
insert(LI);
5052 assert(
P.endOffset() > S.beginOffset() &&
5053 "Empty or backwards partition!");
5062 auto IsLoadSimplyStored = [](LoadInst *LI) {
5063 for (User *LU : LI->
users()) {
5065 if (!SI || !
SI->isSimple())
5070 if (!IsLoadSimplyStored(LI)) {
5071 UnsplittableLoads.
insert(LI);
5077 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
5081 if (!StoredLoad || !StoredLoad->isSimple())
5083 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
5093 auto &
Offsets = SplitOffsetsMap[
I];
5095 "Should not have splits the first time we see an instruction!");
5110 std::max(S.beginOffset(), CopyOverlap->beginOffset());
5111 uint64_t OverlapEnd = std::min(S.endOffset(), CopyOverlap->endOffset());
5112 uint64_t OverlapSize = OverlapEnd - OverlapStart;
5113 uint64_t SliceSize = S.endOffset() - S.beginOffset();
5114 uint64_t NonOverlapSize = SliceSize - OverlapSize;
5115 if (OverlapSize < NonOverlapSize) {
5120 Offsets.Splits.push_back(OverlapSize);
5121 Offsets.Splits.push_back(SliceSize - OverlapSize);
5122 }
else if (OverlapSize > NonOverlapSize) {
5125 for (
uint64_t Split = NonOverlapSize;
Split <= SliceSize / 2;
5126 Split += NonOverlapSize) {
5127 Offsets.Splits.push_back(Split);
5128 if (Split != SliceSize - Split) {
5129 Offsets.Splits.push_back(SliceSize - Split);
5137 Offsets.Splits.push_back(OverlapSize);
5140 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
5149 llvm::erase_if(Stores, [&UnsplittableLoads, &SplitOffsetsMap](StoreInst *SI) {
5155 if (UnsplittableLoads.
count(LI))
5158 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
5159 if (LoadOffsetsI == SplitOffsetsMap.
end())
5161 auto &LoadOffsets = LoadOffsetsI->second;
5164 auto &StoreOffsets = SplitOffsetsMap[
SI];
5169 if (LoadOffsets.Splits == StoreOffsets.Splits)
5173 <<
" " << *LI <<
"\n"
5174 <<
" " << *SI <<
"\n");
5180 UnsplittableLoads.
insert(LI);
5189 return UnsplittableLoads.
count(LI);
5194 return UnsplittableLoads.
count(LI);
5204 IRBuilderTy IRB(&AI);
5211 SmallPtrSet<AllocaInst *, 4> ResplitPromotableAllocas;
5221 SmallDenseMap<LoadInst *, std::vector<LoadInst *>, 1> SplitLoadsMap;
5222 std::vector<LoadInst *> SplitLoads;
5223 const DataLayout &
DL = AI.getDataLayout();
5224 for (LoadInst *LI : Loads) {
5227 auto &
Offsets = SplitOffsetsMap[LI];
5228 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
5230 "Load must have type size equal to store size");
5232 "Load must be >= slice size");
5235 assert(BaseOffset + SliceSize > BaseOffset &&
5236 "Cannot represent alloca access size using 64-bit integers!");
5239 IRB.SetInsertPoint(LI);
5246 auto *PartTy = Type::getIntNTy(LI->
getContext(), PartSize * 8);
5249 LoadInst *PLoad = IRB.CreateAlignedLoad(
5252 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5253 PartPtrTy,
BasePtr->getName() +
"."),
5256 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5257 LLVMContext::MD_access_group});
5261 SplitLoads.push_back(PLoad);
5265 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5269 <<
", " << NewSlices.
back().endOffset()
5270 <<
"): " << *PLoad <<
"\n");
5285 bool DeferredStores =
false;
5286 for (User *LU : LI->
users()) {
5288 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
5289 DeferredStores =
true;
5295 Value *StoreBasePtr =
SI->getPointerOperand();
5296 IRB.SetInsertPoint(SI);
5297 AAMDNodes AATags =
SI->getAAMetadata();
5299 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
5301 for (
int Idx = 0,
Size = SplitLoads.size(); Idx <
Size; ++Idx) {
5302 LoadInst *PLoad = SplitLoads[
Idx];
5304 auto *PartPtrTy =
SI->getPointerOperandType();
5306 auto AS =
SI->getPointerAddressSpace();
5307 StoreInst *PStore = IRB.CreateAlignedStore(
5310 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5311 PartPtrTy, StoreBasePtr->
getName() +
"."),
5314 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5315 LLVMContext::MD_access_group,
5316 LLVMContext::MD_DIAssignID});
5321 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
5329 ResplitPromotableAllocas.
insert(OtherAI);
5330 Worklist.insert(OtherAI);
5333 Worklist.insert(OtherAI);
5337 DeadInsts.push_back(SI);
5342 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
5345 DeadInsts.push_back(LI);
5354 for (StoreInst *SI : Stores) {
5359 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
5363 "Slice size should always match load size exactly!");
5365 assert(BaseOffset + StoreSize > BaseOffset &&
5366 "Cannot represent alloca access size using 64-bit integers!");
5374 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
5375 std::vector<LoadInst *> *SplitLoads =
nullptr;
5376 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
5377 SplitLoads = &SplitLoadsMapI->second;
5379 "Too few split loads for the number of splits in the store!");
5387 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
5389 auto *StorePartPtrTy =
SI->getPointerOperandType();
5394 PLoad = (*SplitLoads)[
Idx];
5396 IRB.SetInsertPoint(LI);
5398 PLoad = IRB.CreateAlignedLoad(
5401 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5402 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
5405 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
5406 LLVMContext::MD_access_group});
5410 IRB.SetInsertPoint(SI);
5411 auto AS =
SI->getPointerAddressSpace();
5412 StoreInst *PStore = IRB.CreateAlignedStore(
5415 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
5416 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
5419 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
5420 LLVMContext::MD_access_group});
5424 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
5428 <<
", " << NewSlices.
back().endOffset()
5429 <<
"): " << *PStore <<
"\n");
5451 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5452 ResplitPromotableAllocas.
insert(OtherAI);
5453 Worklist.insert(OtherAI);
5456 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
5457 Worklist.insert(OtherAI);
5472 DeadInsts.push_back(LI);
5474 DeadInsts.push_back(SI);
5483 AS.insert(NewSlices);
5487 for (
auto I = AS.begin(),
E = AS.end();
I !=
E; ++
I)
5493 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
5530 bool IsIntegralPointerTy =
5531 EltTy->
isPointerTy() && !
DL.isNonIntegralPointerType(EltTy);
5533 !IsIntegralPointerTy)
5540 if (
DL.getTypeSizeInBits(EltTy) !=
DL.getTypeAllocSizeInBits(EltTy))
5544 TypeSize StructSize =
DL.getStructLayout(STy)->getSizeInBytes();
5545 TypeSize VectorSize =
DL.getTypeStoreSize(VTy);
5548 if (StructSize != VectorSize)
5551 auto IsIgnorableOrMemIntrinsicSlice = [](
const Slice &S) {
5554 auto *U = S.getUse();
5558 User *Usr = U->getUser();
5565 for (
const Slice &S :
P)
5566 if (!IsIgnorableOrMemIntrinsicSlice(S))
5569 for (
const Slice *S :
P.splitSliceTails())
5570 if (!IsIgnorableOrMemIntrinsicSlice(*S))
5587static std::tuple<Type *, bool, VectorType *>
5591 VectorType *SelectedVecTy,
bool SelectedIntWidening) {
5593 dbgs() <<
"selectPartitionType path=" << Path
5598 dbgs() <<
"<unnamed>";
5599 dbgs() <<
" partition=[" <<
P.beginOffset() <<
"," <<
P.endOffset()
5600 <<
") size=" <<
P.size();
5602 dbgs() <<
" alloc-size=" << AllocSize->getKnownMinValue();
5604 dbgs() <<
" chosen=" << *SelectedTy;
5606 dbgs() <<
" vec=" << *SelectedVecTy;
5607 dbgs() <<
" intwiden=" << SelectedIntWidening <<
"\n";
5625 if (VecTy && VecTy->getElementType()->isFloatingPointTy() &&
5626 VecTy->getElementCount().getFixedValue() > 1) {
5627 LogSelection(
"direct-fp-vecty", VecTy, VecTy,
false);
5628 return {VecTy,
false, VecTy};
5633 auto [CommonUseTy, LargestIntTy] =
5636 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy);
5642 LogSelection(
"common-type-vecty", VecTy, VecTy,
false);
5643 return {VecTy,
false, VecTy};
5646 LogSelection(
"common-type", CommonUseTy,
nullptr, IntWiden);
5647 return {CommonUseTy, IntWiden,
nullptr};
5654 P.beginOffset(),
P.size())) {
5658 if (TypePartitionTy->isArrayTy() &&
5659 TypePartitionTy->getArrayElementType()->isIntegerTy() &&
5660 DL.isLegalInteger(
P.size() * 8))
5664 LogSelection(
"type-partition-int-widen", TypePartitionTy,
nullptr,
true);
5665 return {TypePartitionTy,
true,
nullptr};
5668 LogSelection(
"type-partition-vecty", VecTy, VecTy,
false);
5669 return {VecTy,
false, VecTy};
5674 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size() &&
5676 LogSelection(
"largest-int-int-widen", LargestIntTy,
nullptr,
true);
5677 return {LargestIntTy,
true,
nullptr};
5682 if (AggregateToVector) {
5685 LogSelection(
"struct-fallback-vecty", VTy,
nullptr,
false);
5686 return {VTy,
false,
nullptr};
5692 LogSelection(
"type-partition-fallback", TypePartitionTy,
nullptr,
false);
5693 return {TypePartitionTy,
false,
nullptr};
5698 DL.getTypeAllocSize(LargestIntTy).getFixedValue() >=
P.size()) {
5699 LogSelection(
"largest-int-fallback", LargestIntTy,
nullptr,
false);
5700 return {LargestIntTy,
false,
nullptr};
5704 if (
DL.isLegalInteger(
P.size() * 8)) {
5706 LogSelection(
"legal-int-fallback", IntTy,
nullptr,
false);
5707 return {IntTy,
false,
nullptr};
5712 LogSelection(
"byte-array-fallback", ArrayTy,
nullptr,
false);
5713 return {ArrayTy,
false,
nullptr};
5726std::pair<AllocaInst *, uint64_t>
5727SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &
P) {
5728 const DataLayout &
DL = AI.getDataLayout();
5730 auto [PartitionTy, IsIntegerWideningViable, VecTy] =
5740 if (PartitionTy == AI.getAllocatedType() &&
P.beginOffset() == 0) {
5749 new AllocaInst(PartitionTy, AI.getAddressSpace(),
nullptr, Alignment,
5750 AI.getName() +
".sroa." + Twine(
P.begin() - AS.begin()),
5758 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
5759 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
5764 unsigned PPWOldSize = PostPromotionWorklist.size();
5765 unsigned NumUses = 0;
5766 SmallSetVector<PHINode *, 8> PHIUsers;
5767 SmallSetVector<SelectInst *, 8> SelectUsers;
5770 DL, AS, *
this, AI, *NewAI, PartitionTy,
P.beginOffset(),
P.endOffset(),
5771 IsIntegerWideningViable, VecTy, PHIUsers, SelectUsers);
5772 bool Promotable =
true;
5774 if (
auto DeletedValues =
Rewriter.rewriteTreeStructuredMerge(
P)) {
5775 NumUses += DeletedValues->
size() + 1;
5776 for (
Value *V : *DeletedValues)
5777 DeadInsts.push_back(V);
5779 for (Slice *S :
P.splitSliceTails()) {
5783 for (Slice &S :
P) {
5789 NumAllocaPartitionUses += NumUses;
5790 MaxUsesPerAllocaPartition.updateMax(NumUses);
5796 for (PHINode *
PHI : PHIUsers) {
5807 SelectUsers.
clear();
5812 NewSelectsToRewrite;
5814 for (SelectInst *Sel : SelectUsers) {
5815 std::optional<RewriteableMemOps>
Ops =
5816 isSafeSelectToSpeculate(*Sel, PreserveCFG);
5825 for (Use *U : AS.getDeadUsesIfPromotable()) {
5827 Value::dropDroppableUse(*U);
5830 DeadInsts.push_back(OldInst);
5832 if (NewSpeculatablePHIs.
empty() && NewPHIsWithStoreToRewrite.
empty() &&
5833 SelectUsers.empty()) {
5835 PromotableAllocas.insert(NewAI);
5840 SpeculatablePHIs.insert_range(NewSpeculatablePHIs);
5841 PHIsWithStoreToRewrite.insert_range(NewPHIsWithStoreToRewrite);
5842 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5843 NewSelectsToRewrite.
size());
5845 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5846 std::make_move_iterator(NewSelectsToRewrite.
end())))
5847 SelectsToRewrite.insert(std::move(KV));
5848 Worklist.insert(NewAI);
5852 while (PostPromotionWorklist.size() > PPWOldSize)
5853 PostPromotionWorklist.pop_back();
5858 return {
nullptr, 0};
5863 Worklist.insert(NewAI);
5866 return {NewAI,
DL.getTypeSizeInBits(PartitionTy).getFixedValue()};
5910 int64_t BitExtractOffset) {
5912 bool HasFragment =
false;
5913 bool HasBitExtract =
false;
5921 HasBitExtract =
true;
5922 int64_t ExtractOffsetInBits = Extract.getOffsetInBits();
5923 int64_t ExtractSizeInBits = Extract.getSizeInBits();
5932 assert(BitExtractOffset <= 0);
5933 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5939 if (AdjustedOffset < 0)
5942 Ops.push_back(
Op.getOp());
5943 Ops.push_back(std::max<int64_t>(0, AdjustedOffset));
5944 Ops.push_back(ExtractSizeInBits);
5947 Op.appendToVector(
Ops);
5952 if (HasFragment && HasBitExtract)
5955 if (!HasBitExtract) {
5974 std::optional<DIExpression::FragmentInfo> NewFragment,
5975 int64_t BitExtractAdjustment) {
5985 BitExtractAdjustment);
5986 if (!NewFragmentExpr)
5992 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6005 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
6011 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
6019 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
6025bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
6026 if (AS.begin() == AS.end())
6029 unsigned NumPartitions = 0;
6031 const DataLayout &
DL = AI.getDataLayout();
6034 Changed |= presplitLoadsAndStores(AI, AS);
6042 bool IsSorted =
true;
6044 uint64_t AllocaSize = AI.getAllocationSize(
DL)->getFixedValue();
6052 SparseBitVector<> SplittableOffset;
6054 for (Slice &S : AS) {
6056 if (S.beginOffset() > CurBegin || S.endOffset() > CurEnd) {
6058 if (S.beginOffset() >= CurEnd) {
6059 SplittableOffset.
set(S.beginOffset());
6062 if (CurEnd > S.beginOffset() && CurEnd < S.endOffset()) {
6063 SplittableOffset.
reset(CurEnd);
6065 CurBegin = S.beginOffset();
6069 if (S.endOffset() > CurEnd) {
6070 CurEnd = S.endOffset();
6071 SplittableOffset.
set(CurEnd);
6076 for (Slice &S : AS) {
6077 if (!S.isSplittable())
6080 if ((S.beginOffset() > AllocaSize ||
6081 SplittableOffset.
test(S.beginOffset())) &&
6082 (S.endOffset() > AllocaSize || SplittableOffset.
test(S.endOffset())))
6087 S.makeUnsplittable();
6107 for (
auto &
P : AS.partitions()) {
6108 auto [NewAI, ActiveBits] = rewritePartition(AI, AS, P);
6112 uint64_t SizeOfByte = 8;
6114 uint64_t Size = std::min(ActiveBits, P.size() * SizeOfByte);
6115 Fragments.push_back(
6116 Fragment(NewAI, P.beginOffset() * SizeOfByte, Size));
6122 NumAllocaPartitions += NumPartitions;
6123 MaxPartitionsPerAlloca.updateMax(NumPartitions);
6127 auto MigrateOne = [&](DbgVariableRecord *DbgVariable) {
6132 const Value *DbgPtr = DbgVariable->getAddress();
6134 DbgVariable->getFragmentOrEntireVariable();
6137 int64_t CurrentExprOffsetInBytes = 0;
6138 SmallVector<uint64_t> PostOffsetOps;
6140 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
6144 int64_t ExtractOffsetInBits = 0;
6147 ExtractOffsetInBits = Extract.getOffsetInBits();
6152 DIBuilder DIB(*AI.getModule(),
false);
6154 int64_t OffsetFromLocationInBits;
6155 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
6161 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
6162 NewDbgFragment, OffsetFromLocationInBits))
6168 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
6173 if (!NewDbgFragment)
6174 NewDbgFragment = DbgVariable->getFragment();
6178 int64_t OffestFromNewAllocaInBits =
6179 OffsetFromLocationInBits - ExtractOffsetInBits;
6182 int64_t BitExtractOffset =
6183 std::min<int64_t>(0, OffestFromNewAllocaInBits);
6188 OffestFromNewAllocaInBits =
6189 std::max(int64_t(0), OffestFromNewAllocaInBits);
6195 DIExpression *NewExpr = DIExpression::get(AI.getContext(), PostOffsetOps);
6196 if (OffestFromNewAllocaInBits > 0) {
6197 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
6203 auto RemoveOne = [DbgVariable](
auto *OldDII) {
6204 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
6205 return LHS->getVariable() ==
RHS->getVariable() &&
6206 LHS->getDebugLoc()->getInlinedAt() ==
6207 RHS->getDebugLoc()->getInlinedAt();
6209 if (SameVariableFragment(OldDII, DbgVariable))
6210 OldDII->eraseFromParent();
6215 NewDbgFragment, BitExtractOffset);
6229void SROA::clobberUse(Use &U) {
6239 DeadInsts.push_back(OldI);
6261bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
6266 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
6267 bool AllSameAndValid =
true;
6268 Type *PartitionType =
nullptr;
6269 SmallVector<Instruction *> Insts;
6273 auto Flush = [&]() {
6274 if (AllSameAndValid && !Insts.
empty()) {
6275 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
6276 << EndOffset <<
")\n");
6278 SSAUpdater
SSA(&NewPHIs);
6280 BasicLoadAndStorePromoter Promoter(Insts,
SSA, PartitionType);
6281 Promoter.run(Insts);
6283 AllSameAndValid =
true;
6284 PartitionType =
nullptr;
6288 for (Slice &S : AS) {
6292 dbgs() <<
"Ignoring slice: ";
6293 AS.print(
dbgs(), &S);
6297 if (S.beginOffset() >= EndOffset) {
6299 BeginOffset = S.beginOffset();
6300 EndOffset = S.endOffset();
6301 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
6302 if (AllSameAndValid) {
6304 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
6305 << EndOffset <<
")";
6306 AS.print(
dbgs(), &S);
6308 AllSameAndValid =
false;
6310 EndOffset = std::max(EndOffset, S.endOffset());
6317 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
6318 AllSameAndValid =
false;
6319 PartitionType = UserTy;
6322 Type *UserTy =
SI->getValueOperand()->getType();
6323 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
6324 AllSameAndValid =
false;
6325 PartitionType = UserTy;
6328 AllSameAndValid =
false;
6341std::pair<
bool ,
bool >
6342SROA::runOnAlloca(AllocaInst &AI) {
6344 bool CFGChanged =
false;
6347 ++NumAllocasAnalyzed;
6350 if (AI.use_empty()) {
6351 AI.eraseFromParent();
6355 const DataLayout &
DL = AI.getDataLayout();
6358 std::optional<TypeSize>
Size = AI.getAllocationSize(
DL);
6359 if (AI.isArrayAllocation() || !
Size ||
Size->isScalable() ||
Size->isZero())
6364 IRBuilderTy IRB(&AI);
6365 AggLoadStoreRewriter AggRewriter(
DL, IRB);
6366 Changed |= AggRewriter.rewrite(AI);
6369 AllocaSlices AS(
DL, AI);
6374 if (AS.isEscapedReadOnly()) {
6375 Changed |= propagateStoredValuesToLoads(AI, AS);
6380 for (Instruction *DeadUser : AS.getDeadUsers()) {
6382 for (Use &DeadOp : DeadUser->operands())
6389 DeadInsts.push_back(DeadUser);
6392 for (Use *DeadOp : AS.getDeadOperands()) {
6393 clobberUse(*DeadOp);
6398 if (AS.begin() == AS.end())
6401 Changed |= splitAlloca(AI, AS);
6404 while (!SpeculatablePHIs.empty())
6408 auto RemainingPHIsWithStoreToRewrite = PHIsWithStoreToRewrite.takeVector();
6409 while (!RemainingPHIsWithStoreToRewrite.empty()) {
6410 PHINode *PN = RemainingPHIsWithStoreToRewrite.pop_back_val();
6416 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
6417 while (!RemainingSelectsToRewrite.empty()) {
6418 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
6435bool SROA::deleteDeadInstructions(
6436 SmallPtrSetImpl<AllocaInst *> &DeletedAllocas) {
6438 while (!DeadInsts.empty()) {
6448 DeletedAllocas.
insert(AI);
6450 OldDII->eraseFromParent();
6456 for (Use &Operand :
I->operands())
6461 DeadInsts.push_back(U);
6465 I->eraseFromParent();
6475bool SROA::promoteAllocas() {
6476 if (PromotableAllocas.empty())
6479 if (ScalarOptions::Global.sroa_skip_mem2reg) {
6483 NumPromoted += PromotableAllocas.size();
6484 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
6487 PromotableAllocas.clear();
6491std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
6494 const DataLayout &
DL =
F.getDataLayout();
6499 std::optional<TypeSize>
Size = AI->getAllocationSize(
DL);
6501 PromotableAllocas.insert(AI);
6503 Worklist.insert(AI);
6508 bool CFGChanged =
false;
6511 SmallPtrSet<AllocaInst *, 4> DeletedAllocas;
6514 while (!Worklist.empty()) {
6515 auto [IterationChanged, IterationCFGChanged] =
6516 runOnAlloca(*Worklist.pop_back_val());
6518 CFGChanged |= IterationCFGChanged;
6520 Changed |= deleteDeadInstructions(DeletedAllocas);
6524 if (!DeletedAllocas.
empty()) {
6525 Worklist.set_subtract(DeletedAllocas);
6526 PostPromotionWorklist.set_subtract(DeletedAllocas);
6527 PromotableAllocas.set_subtract(DeletedAllocas);
6528 DeletedAllocas.
clear();
6534 Worklist = PostPromotionWorklist;
6535 PostPromotionWorklist.clear();
6536 }
while (!Worklist.empty());
6538 assert((!CFGChanged ||
Changed) &&
"Can not only modify the CFG.");
6539 assert((!CFGChanged || !PreserveCFG) &&
6540 "Should not have modified the CFG when told to preserve it.");
6543 for (
auto &BB :
F) {
6556 SROA(&
F.getContext(), &DTU, &AC, Options).runSROA(
F);
6568 static_cast<PassInfoMixin<SROAPass> *
>(
this)->
printPipeline(
6569 OS, MapClassName2PassName);
6573 if (Options.AggregateToVector)
6574 OS <<
";aggregate-to-vector";
6595 if (skipFunction(
F))
6598 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
6600 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
6606 void getAnalysisUsage(AnalysisUsage &AU)
const override {
6613 StringRef getPassName()
const override {
return "SROA"; }
6618char SROALegacyPass::ID = 0;
6623 AggregateToVector));
6627 "Scalar Replacement Of Aggregates",
false,
false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DXIL Forward Handle Accesses
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
This file implements a map that provides insertion order iteration.
static std::optional< AllocFnsTy > getAllocationSize(const CallBase *CB, const TargetLibraryInfo *TLI)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PointerIntPair class.
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, uint64_t OldAllocaOffsetInBits, uint64_t SliceSizeInBits, Instruction *OldInst, Instruction *Inst, Value *Dest, Value *Value, const DataLayout &DL)
Find linked dbg.assign and generate a new one with the correct FragmentInfo.
static VectorType * isVectorPromotionViable(Partition &P, const DataLayout &DL, unsigned VScale)
Test whether the given alloca partitioning and range of slices can be promoted to a vector.
static Align getAdjustedAlignment(Instruction *I, uint64_t Offset)
Compute the adjusted alignment for a load or store from an offset.
static VectorType * checkVectorTypesForPromotion(Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool HaveCommonEltTy, Type *CommonEltTy, bool HaveVecPtrTy, bool HaveCommonVecPtrTy, VectorType *CommonVecPtrTy, unsigned VScale)
Test whether any vector type in CandidateTys is viable for promotion.
static std::pair< Type *, IntegerType * > findCommonType(AllocaSlices::const_iterator B, AllocaSlices::const_iterator E, uint64_t EndOffset)
Walk the range of a partitioning looking for a common type to cover this sequence of slices.
static Type * stripAggregateTypeWrapping(const DataLayout &DL, Type *Ty)
Strip aggregate type wrapping.
static FragCalcResult calculateFragment(DILocalVariable *Variable, uint64_t NewStorageSliceOffsetInBits, uint64_t NewStorageSliceSizeInBits, std::optional< DIExpression::FragmentInfo > StorageFragment, std::optional< DIExpression::FragmentInfo > CurrentFragment, DIExpression::FragmentInfo &Target)
static DIExpression * createOrReplaceFragment(const DIExpression *Expr, DIExpression::FragmentInfo Frag, int64_t BitExtractOffset)
Create or replace an existing fragment in a DIExpression with Frag.
static Value * insertInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *Old, Value *V, uint64_t Offset, const Twine &Name)
static bool isVectorPromotionViableForSlice(Partition &P, const Slice &S, VectorType *Ty, uint64_t ElementSize, const DataLayout &DL, unsigned VScale)
Test whether the given slice use can be promoted to a vector.
static Value * getAdjustedPtr(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, APInt Offset, Type *PointerTy, const Twine &NamePrefix)
Compute an adjusted pointer from Ptr by Offset bytes where the resulting pointer has PointerTy.
static bool isIntegerWideningViableForSlice(const Slice &S, uint64_t AllocBeginOffset, Type *AllocaTy, const DataLayout &DL, bool &WholeAllocaOp)
Test whether a slice of an alloca is valid for integer widening.
static bool rewritePHINodeStore(PHINode &PN, StoreInst &SI, DomTreeUpdater &DTU, SmallSetVector< AllocaInst *, 16 > &Worklist)
Move a store through a pointer PHI onto each of the PHI's incoming edges.
static Value * extractVector(IRBuilderTy &IRB, Value *V, unsigned BeginIndex, unsigned EndIndex, const Twine &Name)
static Value * foldPHINodeOrSelectInst(Instruction &I)
A helper that folds a PHI node or a select.
static bool rewriteSelectInstMemOps(SelectInst &SI, const RewriteableMemOps &Ops, IRBuilderTy &IRB, DomTreeUpdater *DTU)
static void rewriteMemOpOfSelect(SelectInst &SI, T &I, SelectHandSpeculativity Spec, DomTreeUpdater &DTU)
static Slice * findOverlappingCopySlice(Slice &S, InstructionSliceMap &SliceMap)
Try to find a slice in the map that partially overlaps with S, i.e.
static Value * foldSelectInst(SelectInst &SI)
bool isKillAddress(const DbgVariableRecord *DVR)
static Value * insertVector(IRBuilderTy &IRB, Value *Old, Value *V, unsigned BeginIndex, const Twine &Name)
static bool isIntegerWideningViable(Partition &P, Type *AllocaTy, const DataLayout &DL)
Test whether the given alloca partition's integer operations can be widened to promotable ones.
static void speculatePHINodeLoads(IRBuilderTy &IRB, PHINode &PN)
static VectorType * createAndCheckVectorTypesForPromotion(SetVector< Type * > &OtherTys, ArrayRef< VectorType * > CandidateTysCopy, function_ref< void(Type *)> CheckCandidateType, Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool &HaveCommonEltTy, Type *&CommonEltTy, bool &HaveVecPtrTy, bool &HaveCommonVecPtrTy, VectorType *&CommonVecPtrTy, unsigned VScale)
static DebugVariable getAggregateVariable(DbgVariableRecord *DVR)
static std::tuple< Type *, bool, VectorType * > selectPartitionType(Partition &P, const DataLayout &DL, AllocaInst &AI, LLVMContext &C, bool AggregateToVector)
Select a partition type for an alloca partition.
static bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
static FixedVectorType * tryCanonicalizeStructToVector(StructType *STy, Partition &P, const DataLayout &DL)
Try to canonicalize a homogeneous struct partition to a vector type.
static Value * extractInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *V, IntegerType *Ty, uint64_t Offset, const Twine &Name)
static void insertNewDbgInst(DIBuilder &DIB, DbgVariableRecord *Orig, AllocaInst *NewAddr, DIExpression *NewAddrExpr, Instruction *BeforeInst, std::optional< DIExpression::FragmentInfo > NewFragment, int64_t BitExtractAdjustment)
Insert a new DbgRecord.
static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, IRBuilderTy &IRB)
static Value * mergeTwoVectors(Value *V0, Value *V1, const DataLayout &DL, Type *NewAIEltTy, IRBuilder<> &Builder)
This function takes two vector values and combines them into a single vector by concatenating their e...
const DIExpression * getAddressExpression(const DbgVariableRecord *DVR)
static Type * getTypePartition(const DataLayout &DL, Type *Ty, uint64_t Offset, uint64_t Size)
Try to find a partition of the aggregate type passed in for a given offset and size.
static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy, unsigned VScale=0)
Test whether we can convert a value from the old to the new type.
static SelectHandSpeculativity isSafeLoadOfSelectToSpeculate(LoadInst &LI, SelectInst &SI, bool PreserveCFG)
static StoreInst * getPHIStoreToRewrite(PHINode &PN, bool PreserveCFG, DominatorTree &DT)
Check whether a single store through PN can be moved onto each incoming edge.
static Type * findCommonTypeThroughPHIOrSelect(Instruction &I)
Find a common load/store type used through a pointer PHI or select.
This file provides the interface for LLVM's Scalar Replacement of Aggregates pass.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the SparseBitVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
virt reg Virtual Register Rewriter
Builder for the alloca slices.
SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
An iterator over partitions of the alloca's slices.
bool operator==(const partition_iterator &RHS) const
friend class AllocaSlices
partition_iterator & operator++()
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI bool canSplitPredecessors() const
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
LLVM_ABI CaptureInfo getCaptureInfo(unsigned OpNo) const
Return which pointer components this operand may capture.
bool onlyReadsMemory(unsigned OpNo) const
bool isDataOperand(const Use *U) const
This is the shared class of boolean and integer constants.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
LLVM_ABI DbgRecord * insertDbgAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *SrcVar, DIExpression *ValExpr, Value *Addr, DIExpression *AddrExpr, const DILocation *DL)
Insert a new dbg_assign record.
iterator_range< expr_op_iterator > expr_ops() const
DbgVariableFragmentInfo FragmentInfo
LLVM_ABI bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits, int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag, std::optional< DIExpression::FragmentInfo > &Result, int64_t &OffsetFromLocationInBits)
Computes a fragment, bit-extract operation if needed, and new constant offset to describe a part of a...
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI void moveBefore(DbgRecord *MoveBefore)
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI void setKillAddress()
Kill the address component.
LLVM_ABI bool isKillLocation() const
LocationType getType() const
LLVM_ABI bool isKillAddress() const
Check whether this kills the address component.
LLVM_ABI void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
Value * getValue(unsigned OpIdx=0) const
static LLVM_ABI DbgVariableRecord * createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, DIExpression *Expression, Value *Address, DIExpression *AddressExpression, const DILocation *DI)
LLVM_ABI void setAssignId(DIAssignID *New)
DIExpression * getExpression() const
static LLVM_ABI DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
static LLVM_ABI DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
DILocalVariable * getVariable() const
LLVM_ABI void setKillLocation()
bool isDbgDeclare() const
void setAddress(Value *V)
DIExpression * getAddressExpression() const
LLVM_ABI DILocation * getInlinedAt() const
Identifies a unique instance of a variable.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class to represent fixed width SIMD vectors.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getVScaleValue() const
Return the value for vscale based on the vscale_range attribute or 0 when unknown.
const BasicBlock & getEntryBlock() const
LLVM_ABI bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
Value * getPointerOperand()
iterator_range< op_iterator > indices()
Type * getSourceElementType() const
LLVM_ABI GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
This provides the default implementation of the IRBuilder 'InsertHelper' method that is called whenev...
void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
op_range incoming_values()
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerIntPair - This class implements a pair of a pointer and small integer.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
PtrUseVisitor(const DataLayout &DL)
LLVM_ABI SROAPass(SROAOptions Options)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Helper class for SSA formation on a set of values defined in multiple blocks.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void clear()
Completely clear the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
typename SuperClass::const_iterator const_iterator
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool test(unsigned Idx) const
An instruction for storing to memory.
void setAlignment(Align Align)
Value * getValueOperand()
static unsigned getPointerOperandIndex()
Value * getPointerOperand()
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
LLVM_ABI size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getSizeInBytes() const
LLVM_ABI unsigned getElementContainingOffset(uint64_t FixedOffset) const
Given a valid byte offset into the structure, returns the structure index that contains it.
TypeSize getElementOffset(unsigned Idx) const
TypeSize getSizeInBits() const
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
element_iterator element_end() const
ArrayRef< Type * > elements() const
element_iterator element_begin() const
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Type::subtype_iterator element_iterator
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isStructTy() const
True if this is an instance of StructType.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
const Use & getOperandUse(unsigned i) const
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI bool hasOneUser() const
Return true if there is exactly one user of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
LLVM_ABI void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
static VectorType * getWithSizeAndScalar(VectorType *SizeTy, Type *EltTy)
This static method attempts to construct a VectorType with the same size-in-bits as SizeTy but with a...
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ BasicBlock
Various leaf nodes.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI iterator begin() const
unsigned getNumElements(Type *Ty)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
LLVM_ABI bool RemoveRedundantDbgInstrs(BasicBlock *BB)
Try to remove redundant dbg.value instructions from given basic block.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
LLVM_ABI bool isAssumeLikeIntrinsic(const Instruction *I)
Return true if it is an intrinsic that cannot be speculated but also cannot trap.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI std::optional< RegOrConstant > getVectorSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
auto unique(Range &&R, Predicate P)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
bool capturesFullProvenance(CaptureComponents CC)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void initializeSROALegacyPassPass(PassRegistry &)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRValues(Value *V)
As above, for DVRValues.
LLVM_ABI void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr int PoisonMaskElem
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ, bool IgnoreFree=false)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
DWARFExpression::Operation Op
LLVM_ABI Align tryEnforceAlignment(Value *V, Align PrefAlign, const DataLayout &DL)
If the specified pointer points to an object that we control, try to modify the object's alignment to...
LLVM_ABI FunctionPass * createSROAPass(bool PreserveCFG=true, bool AggregateToVector=false)
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
AAMDNodes shift(size_t Offset) const
Create a new AAMDNode that describes this AAMDNode after applying a constant offset to the start of t...
LLVM_ABI AAMDNodes adjustForAccess(unsigned AccessSize)
Create a new AAMDNode for accessing AccessSize bytes of this AAMDNode.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Describes an element of a Bitfield.
static Bitfield::Type get(StorageType Packed)
Unpacks the field from the Packed value.
static void set(StorageType &Packed, typename Bitfield::Type Value)
Sets the typed value in the provided Packed value.