47#include "llvm/Config/llvm-config.h"
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 loads to allow promotion");
118STATISTIC(NumVectorized,
"Number of vectorized aggregates");
125class AllocaSliceRewriter;
129class SelectHandSpeculativity {
130 unsigned char Storage = 0;
134 SelectHandSpeculativity() =
default;
135 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
136 bool isSpeculatable(
bool isTrueVal)
const;
137 bool areAllSpeculatable()
const;
138 bool areAnySpeculatable()
const;
139 bool areNoneSpeculatable()
const;
141 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
142 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
144static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
146using PossiblySpeculatableLoad =
149using RewriteableMemOp =
150 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
233 static std::optional<RewriteableMemOps>
234 isSafeSelectToSpeculate(
SelectInst &SI,
bool PreserveCFG);
239 :
C(
C), DTU(DTU), AC(AC),
243 std::pair<
bool ,
bool > runSROA(
Function &
F);
246 friend class AllocaSliceRewriter;
248 bool presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS);
250 bool splitAlloca(
AllocaInst &AI, AllocaSlices &AS);
251 bool propagateStoredValuesToLoads(
AllocaInst &AI, AllocaSlices &AS);
252 std::pair<
bool ,
bool > runOnAlloca(
AllocaInst &AI);
253 void clobberUse(
Use &U);
255 bool promoteAllocas();
269enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
273 uint64_t NewStorageSliceOffsetInBits,
275 std::optional<DIExpression::FragmentInfo> StorageFragment,
276 std::optional<DIExpression::FragmentInfo> CurrentFragment,
280 if (StorageFragment) {
282 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
284 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
286 Target.SizeInBits = NewStorageSliceSizeInBits;
287 Target.OffsetInBits = NewStorageSliceOffsetInBits;
293 if (!CurrentFragment) {
297 if (
Target == CurrentFragment)
304 if (!CurrentFragment || *CurrentFragment ==
Target)
310 if (
Target.startInBits() < CurrentFragment->startInBits() ||
311 Target.endInBits() > CurrentFragment->endInBits())
344 if (DVRAssignMarkerRange.empty())
350 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
352 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
364 DVR->getExpression()->getFragmentInfo();
377 auto *Expr = DbgAssign->getExpression();
378 bool SetKillLocation =
false;
381 std::optional<DIExpression::FragmentInfo> BaseFragment;
384 if (R == BaseFragments.
end())
386 BaseFragment = R->second;
388 std::optional<DIExpression::FragmentInfo> CurrentFragment =
389 Expr->getFragmentInfo();
392 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
393 BaseFragment, CurrentFragment, NewFragment);
397 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
398 if (CurrentFragment) {
403 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
414 DIExpression::get(Expr->getContext(), {}),
416 SetKillLocation =
true;
424 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
430 Dest, DIExpression::get(Expr->getContext(), {}),
431 DbgAssign->getDebugLoc())));
444 Value && (DbgAssign->hasArgList() ||
445 !DbgAssign->getExpression()->isSingleLocationExpression());
462 NewAssign->
moveBefore(DbgAssign->getIterator());
465 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
468 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
516 : BeginOffset(BeginOffset), EndOffset(EndOffset),
517 UseAndIsSplittable(
U, IsSplittable) {}
519 uint64_t beginOffset()
const {
return BeginOffset; }
520 uint64_t endOffset()
const {
return EndOffset; }
522 bool isSplittable()
const {
return UseAndIsSplittable.
getInt(); }
523 void makeUnsplittable() { UseAndIsSplittable.
setInt(
false); }
525 Use *getUse()
const {
return UseAndIsSplittable.
getPointer(); }
527 bool isDead()
const {
return getUse() ==
nullptr; }
528 void kill() { UseAndIsSplittable.
setPointer(
nullptr); }
537 if (beginOffset() <
RHS.beginOffset())
539 if (beginOffset() >
RHS.beginOffset())
541 if (isSplittable() !=
RHS.isSplittable())
542 return !isSplittable();
543 if (endOffset() >
RHS.endOffset())
551 return LHS.beginOffset() < RHSOffset;
555 return LHSOffset <
RHS.beginOffset();
559 return isSplittable() ==
RHS.isSplittable() &&
560 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
581 bool isEscaped()
const {
return PointerEscapingInstr; }
582 bool isEscapedReadOnly()
const {
return PointerEscapingInstrReadOnly; }
590 iterator
end() {
return Slices.
end(); }
600 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
608 int OldSize = Slices.size();
609 Slices.append(NewSlices.
begin(), NewSlices.
end());
610 auto SliceI = Slices.begin() + OldSize;
611 std::stable_sort(SliceI, Slices.end());
612 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
617 class partition_iterator;
625 return DeadUseIfPromotable;
636#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
648 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
653#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
708 friend class AllocaSlices;
711 using iterator = AllocaSlices::iterator;
715 uint64_t BeginOffset = 0, EndOffset = 0;
725 Partition(iterator SI) :
SI(
SI), SJ(
SI) {}
731 uint64_t beginOffset()
const {
return BeginOffset; }
736 uint64_t endOffset()
const {
return EndOffset; }
742 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
743 return EndOffset - BeginOffset;
748 bool empty()
const {
return SI == SJ; }
759 iterator
begin()
const {
return SI; }
760 iterator
end()
const {
return SJ; }
792 AllocaSlices::iterator SE;
796 uint64_t MaxSplitSliceEndOffset = 0;
812 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
813 "Cannot advance past the end of the slices!");
816 if (!
P.SplitTails.empty()) {
817 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
819 P.SplitTails.clear();
820 MaxSplitSliceEndOffset = 0;
826 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
829 return S->endOffset() == MaxSplitSliceEndOffset;
831 "Could not find the current max split slice offset!");
834 return S->endOffset() <= MaxSplitSliceEndOffset;
836 "Max split slice end offset is not actually the max!");
843 assert(
P.SplitTails.empty() &&
"Failed to clear the split slices!");
853 if (S.isSplittable() && S.endOffset() >
P.EndOffset) {
854 P.SplitTails.push_back(&S);
855 MaxSplitSliceEndOffset =
856 std::max(S.endOffset(), MaxSplitSliceEndOffset);
864 P.BeginOffset =
P.EndOffset;
865 P.EndOffset = MaxSplitSliceEndOffset;
872 if (!
P.SplitTails.empty() &&
P.SI->beginOffset() !=
P.EndOffset &&
873 !
P.SI->isSplittable()) {
874 P.BeginOffset =
P.EndOffset;
875 P.EndOffset =
P.SI->beginOffset();
885 P.BeginOffset =
P.SplitTails.empty() ?
P.SI->beginOffset() :
P.EndOffset;
886 P.EndOffset =
P.SI->endOffset();
891 if (!
P.SI->isSplittable()) {
894 assert(
P.BeginOffset ==
P.SI->beginOffset());
898 while (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset) {
899 if (!
P.SJ->isSplittable())
900 P.EndOffset = std::max(
P.EndOffset,
P.SJ->endOffset());
912 assert(
P.SI->isSplittable() &&
"Forming a splittable partition!");
915 while (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset &&
916 P.SJ->isSplittable()) {
917 P.EndOffset = std::max(
P.EndOffset,
P.SJ->endOffset());
924 if (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset) {
926 P.EndOffset =
P.SJ->beginOffset();
933 "End iterators don't match between compared partition iterators!");
940 if (
P.SI ==
RHS.P.SI &&
P.SplitTails.empty() ==
RHS.P.SplitTails.empty()) {
942 "Same set of slices formed two different sized partitions!");
943 assert(
P.SplitTails.size() ==
RHS.P.SplitTails.size() &&
944 "Same slice position with differently sized non-empty split "
967 return make_range(partition_iterator(begin(), end()),
968 partition_iterator(end(), end()));
975 if (
ConstantInt *CI = dyn_cast<ConstantInt>(SI.getCondition()))
976 return SI.getOperand(1 + CI->isZero());
977 if (SI.getOperand(1) == SI.getOperand(2))
978 return SI.getOperand(1);
985 if (
PHINode *PN = dyn_cast<PHINode>(&
I)) {
987 return PN->hasConstantValue();
1014 AllocSize(
DL.getTypeAllocSize(AI.getAllocatedType()).getFixedValue()),
1019 if (VisitedDeadInsts.
insert(&
I).second)
1020 AS.DeadUsers.push_back(&
I);
1024 bool IsSplittable =
false) {
1030 <<
" which has zero size or starts outside of the "
1031 << AllocSize <<
" byte alloca:\n"
1032 <<
" alloca: " << AS.AI <<
"\n"
1033 <<
" use: " <<
I <<
"\n");
1034 return markAsDead(
I);
1046 assert(AllocSize >= BeginOffset);
1047 if (
Size > AllocSize - BeginOffset) {
1049 <<
Offset <<
" to remain within the " << AllocSize
1050 <<
" byte alloca:\n"
1051 <<
" alloca: " << AS.AI <<
"\n"
1052 <<
" use: " <<
I <<
"\n");
1053 EndOffset = AllocSize;
1056 AS.Slices.push_back(Slice(BeginOffset, EndOffset,
U, IsSplittable));
1061 return markAsDead(BC);
1068 return markAsDead(ASC);
1075 return markAsDead(GEPI);
1093 "All simple FCA loads should have been pre-split");
1101 if (
Size.isScalable()) {
1114 Value *ValOp =
SI.getValueOperand();
1122 unsigned VScale =
SI.getFunction()->getVScaleValue();
1140 <<
Offset <<
" which extends past the end of the "
1141 << AllocSize <<
" byte alloca:\n"
1142 <<
" alloca: " << AS.AI <<
"\n"
1143 <<
" use: " << SI <<
"\n");
1144 return markAsDead(SI);
1148 "All simple FCA stores should have been pre-split");
1153 assert(
II.getRawDest() == *
U &&
"Pointer use is not the destination?");
1158 return markAsDead(
II);
1173 return markAsDead(
II);
1177 if (VisitedDeadInsts.
count(&
II))
1190 MemTransferSliceMap.
find(&
II);
1191 if (MTPI != MemTransferSliceMap.
end())
1192 AS.Slices[MTPI->second].kill();
1193 return markAsDead(
II);
1201 if (*
U ==
II.getRawDest() && *
U ==
II.getRawSource()) {
1203 if (!
II.isVolatile())
1204 return markAsDead(
II);
1213 std::tie(MTPI, Inserted) =
1214 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1215 unsigned PrevIdx = MTPI->second;
1217 Slice &PrevP = AS.Slices[PrevIdx];
1221 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1223 return markAsDead(
II);
1228 PrevP.makeUnsplittable();
1235 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1236 "Map index doesn't point back to a slice with this user.");
1243 if (
II.isDroppable()) {
1244 AS.DeadUseIfPromotable.push_back(
U);
1251 if (
II.isLifetimeStartOrEnd()) {
1252 insertUse(
II,
Offset, AllocSize,
true);
1267 Uses.push_back(std::make_pair(cast<Instruction>(*
U), Root));
1274 std::tie(UsedI,
I) =
Uses.pop_back_val();
1276 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
1285 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1299 if (!
GEP->hasAllZeroIndices())
1301 }
else if (!isa<BitCastInst>(
I) && !isa<PHINode>(
I) &&
1302 !isa<SelectInst>(
I) && !isa<AddrSpaceCastInst>(
I)) {
1306 for (
User *
U :
I->users())
1307 if (Visited.
insert(cast<Instruction>(
U)).second)
1308 Uses.push_back(std::make_pair(
I, cast<Instruction>(
U)));
1309 }
while (!
Uses.empty());
1315 assert(isa<PHINode>(
I) || isa<SelectInst>(
I));
1317 return markAsDead(
I);
1322 if (isa<PHINode>(
I) &&
1323 I.getParent()->getFirstInsertionPt() ==
I.getParent()->end())
1342 AS.DeadOperands.push_back(
U);
1365 AS.DeadOperands.push_back(
U);
1372 void visitPHINode(
PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1374 void visitSelectInst(
SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1395#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1398 PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1399 SliceBuilder
PB(
DL, AI, *
this);
1400 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1401 if (PtrI.isEscaped() || PtrI.isAborted()) {
1404 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1405 : PtrI.getAbortingInst();
1406 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1409 PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
1411 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1418#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1422 printSlice(
OS,
I, Indent);
1424 printUse(
OS,
I, Indent);
1429 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1430 <<
" slice #" << (
I -
begin())
1431 << (
I->isSplittable() ?
" (splittable)" :
"");
1436 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1440 if (PointerEscapingInstr) {
1441 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1442 <<
" A pointer to this alloca escaped by:\n"
1443 <<
" " << *PointerEscapingInstr <<
"\n";
1447 if (PointerEscapingInstrReadOnly)
1448 OS <<
"Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly <<
"\n";
1450 OS <<
"Slices of alloca: " << AI <<
"\n";
1464static std::pair<Type *, IntegerType *>
1468 bool TyIsCommon =
true;
1473 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1474 Use *U =
I->getUse();
1475 if (isa<IntrinsicInst>(*U->getUser()))
1477 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1480 Type *UserTy =
nullptr;
1481 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
1483 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
1484 UserTy = SI->getValueOperand()->getType();
1487 if (
IntegerType *UserITy = dyn_cast_or_null<IntegerType>(UserTy)) {
1492 if (UserITy->getBitWidth() % 8 != 0 ||
1493 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1498 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1504 if (!UserTy || (Ty && Ty != UserTy))
1510 return {TyIsCommon ? Ty :
nullptr, ITy};
1541 Type *LoadType =
nullptr;
1543 LoadInst *LI = dyn_cast<LoadInst>(U);
1554 if (LoadType != LI->
getType())
1563 if (BBI->mayWriteToMemory())
1566 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1573 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1610 IRB.SetInsertPoint(&PN);
1612 PN.
getName() +
".sroa.speculated");
1642 IRB.SetInsertPoint(TI);
1644 LoadInst *Load = IRB.CreateAlignedLoad(
1645 LoadTy, InVal, Alignment,
1647 ++NumLoadsSpeculated;
1649 Load->setAAMetadata(AATags);
1651 InjectedLoads[Pred] = Load;
1658SelectHandSpeculativity &
1659SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1661 Bitfield::set<SelectHandSpeculativity::TrueVal>(Storage,
true);
1663 Bitfield::set<SelectHandSpeculativity::FalseVal>(Storage,
true);
1667bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1668 return isTrueVal ? Bitfield::get<SelectHandSpeculativity::TrueVal>(Storage)
1672bool SelectHandSpeculativity::areAllSpeculatable()
const {
1673 return isSpeculatable(
true) &&
1674 isSpeculatable(
false);
1677bool SelectHandSpeculativity::areAnySpeculatable()
const {
1678 return isSpeculatable(
true) ||
1679 isSpeculatable(
false);
1681bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1682 return !areAnySpeculatable();
1685static SelectHandSpeculativity
1688 SelectHandSpeculativity
Spec;
1691 for (
Value *
Value : {SI.getTrueValue(), SI.getFalseValue()})
1694 Spec.setAsSpeculatable(
Value == SI.getTrueValue());
1701std::optional<RewriteableMemOps>
1703 RewriteableMemOps Ops;
1705 for (
User *U :
SI.users()) {
1706 if (
auto *BC = dyn_cast<BitCastInst>(U); BC && BC->
hasOneUse())
1709 if (
auto *Store = dyn_cast<StoreInst>(U)) {
1715 Ops.emplace_back(Store);
1719 auto *LI = dyn_cast<LoadInst>(U);
1726 PossiblySpeculatableLoad
Load(LI);
1732 Ops.emplace_back(Load);
1736 SelectHandSpeculativity
Spec =
1742 Ops.emplace_back(Load);
1752 Value *TV = SI.getTrueValue();
1753 Value *FV = SI.getFalseValue();
1758 IRB.SetInsertPoint(&LI);
1762 LI.
getName() +
".sroa.speculate.load.true");
1765 LI.
getName() +
".sroa.speculate.load.false");
1766 NumLoadsSpeculated += 2;
1778 Value *V = IRB.CreateSelect(SI.getCondition(), TL, FL,
1779 LI.
getName() +
".sroa.speculated");
1785template <
typename T>
1787 SelectHandSpeculativity
Spec,
1789 assert((isa<LoadInst>(
I) || isa<StoreInst>(
I)) &&
"Only for load and store!");
1794 if (
Spec.areNoneSpeculatable())
1796 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1799 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1801 if (
Spec.isSpeculatable(
true))
1809 if (isa<LoadInst>(
I))
1812 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1813 int SuccIdx = IsThen ? 0 : 1;
1814 auto *NewMemOpBB = SuccBB ==
Tail ? Head : SuccBB;
1815 auto &CondMemOp = cast<T>(*
I.clone());
1816 if (NewMemOpBB != Head) {
1817 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1818 if (isa<LoadInst>(
I))
1819 ++NumLoadsPredicated;
1821 ++NumStoresPredicated;
1823 CondMemOp.dropUBImplyingAttrsAndMetadata();
1824 ++NumLoadsSpeculated;
1826 CondMemOp.insertBefore(NewMemOpBB->getTerminator()->getIterator());
1827 Value *
Ptr = SI.getOperand(1 + SuccIdx);
1828 CondMemOp.setOperand(
I.getPointerOperandIndex(),
Ptr);
1829 if (isa<LoadInst>(
I)) {
1830 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1835 if (isa<LoadInst>(
I)) {
1838 I.replaceAllUsesWith(PN);
1843 SelectHandSpeculativity
Spec,
1845 if (
auto *LI = dyn_cast<LoadInst>(&
I))
1847 else if (
auto *SI = dyn_cast<StoreInst>(&
I))
1854 const RewriteableMemOps &Ops,
1856 bool CFGChanged =
false;
1859 for (
const RewriteableMemOp &
Op : Ops) {
1860 SelectHandSpeculativity
Spec;
1862 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
1865 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
1866 I = PSL.getPointer();
1867 Spec = PSL.getInt();
1869 if (
Spec.areAllSpeculatable()) {
1872 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
1876 I->eraseFromParent();
1880 cast<BitCastInst>(U)->eraseFromParent();
1881 SI.eraseFromParent();
1889 const Twine &NamePrefix) {
1891 Ptr = IRB.CreateInBoundsPtrAdd(
Ptr, IRB.getInt(
Offset),
1892 NamePrefix +
"sroa_idx");
1893 return IRB.CreatePointerBitCastOrAddrSpaceCast(
Ptr,
PointerTy,
1894 NamePrefix +
"sroa_cast");
1909 unsigned VScale = 0) {
1916 if (isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) {
1919 "We can't have the same bitwidth for different int types");
1923 TypeSize NewSize =
DL.getTypeSizeInBits(NewTy);
1924 TypeSize OldSize =
DL.getTypeSizeInBits(OldTy);
1926 if ((isa<ScalableVectorType>(NewTy) && isa<FixedVectorType>(OldTy)) ||
1927 (isa<ScalableVectorType>(OldTy) && isa<FixedVectorType>(NewTy))) {
1938 if (isa<ScalableVectorType>(NewTy)) {
1939 if (!VectorType::getWithSizeAndScalar(cast<VectorType>(NewVTy), OldVTy))
1944 if (!VectorType::getWithSizeAndScalar(cast<VectorType>(OldVTy), NewVTy))
1951 if (NewSize != OldSize)
1967 return OldAS == NewAS ||
1968 (!
DL.isNonIntegralAddressSpace(OldAS) &&
1969 !
DL.isNonIntegralAddressSpace(NewAS) &&
1970 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
1976 return !
DL.isNonIntegralPointerType(NewTy);
1980 if (!
DL.isNonIntegralPointerType(OldTy))
2000 Type *OldTy = V->getType();
2007 "Value not convertable to type");
2013 assert(!(isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) &&
2014 "Integer types must be the exact same to convert.");
2018 auto CreateBitCastLike = [&IRB](
Value *In,
Type *Ty) ->
Value * {
2019 Type *InTy = In->getType();
2023 if (isa<FixedVectorType>(InTy) && isa<ScalableVectorType>(Ty)) {
2026 auto *VTy = VectorType::getWithSizeAndScalar(cast<VectorType>(Ty), InTy);
2027 return IRB.CreateBitCast(IRB.CreateInsertVector(VTy,
2033 if (isa<ScalableVectorType>(InTy) && isa<FixedVectorType>(Ty)) {
2036 auto *VTy = VectorType::getWithSizeAndScalar(cast<VectorType>(InTy), Ty);
2037 return IRB.CreateExtractVector(Ty, IRB.CreateBitCast(In, VTy),
2041 return IRB.CreateBitCast(In, Ty);
2050 return IRB.CreateIntToPtr(CreateBitCastLike(V,
DL.getIntPtrType(NewTy)),
2060 return CreateBitCastLike(IRB.CreatePtrToInt(V,
DL.getIntPtrType(OldTy)),
2073 if (OldAS != NewAS) {
2074 assert(
DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2075 return IRB.CreateIntToPtr(
2076 CreateBitCastLike(IRB.CreatePtrToInt(V,
DL.getIntPtrType(OldTy)),
2077 DL.getIntPtrType(NewTy)),
2082 return CreateBitCastLike(V, NewTy);
2096 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2097 uint64_t BeginIndex = BeginOffset / ElementSize;
2098 if (BeginIndex * ElementSize != BeginOffset ||
2101 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2102 uint64_t EndIndex = EndOffset / ElementSize;
2103 if (EndIndex * ElementSize != EndOffset ||
2107 assert(EndIndex > BeginIndex &&
"Empty vector!");
2108 uint64_t NumElements = EndIndex - BeginIndex;
2109 Type *SliceTy = (NumElements == 1)
2110 ? Ty->getElementType()
2116 Use *U = S.getUse();
2119 if (
MI->isVolatile())
2121 if (!S.isSplittable())
2123 }
else if (
IntrinsicInst *
II = dyn_cast<IntrinsicInst>(U->getUser())) {
2124 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2126 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2133 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2139 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2140 if (SI->isVolatile())
2142 Type *STy = SI->getValueOperand()->getType();
2146 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2167 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2171 if (ElementSize % 8)
2173 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2174 "vector size not a multiple of element size?");
2177 for (
const Slice &S :
P)
2181 for (
const Slice *S :
P.splitSliceTails())
2195 bool HaveCommonEltTy,
Type *CommonEltTy,
2196 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2197 VectorType *CommonVecPtrTy,
unsigned VScale) {
2199 if (CandidateTys.
empty())
2206 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2210 if (!HaveCommonEltTy && HaveVecPtrTy) {
2212 CandidateTys.
clear();
2214 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2217 if (!VTy->getElementType()->isIntegerTy())
2218 VTy = cast<VectorType>(VTy->getWithNewType(IntegerType::getIntNTy(
2219 VTy->getContext(), VTy->getScalarSizeInBits())));
2226 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2227 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2228 "Cannot have vector types of different sizes!");
2229 assert(RHSTy->getElementType()->isIntegerTy() &&
2230 "All non-integer types eliminated!");
2231 assert(LHSTy->getElementType()->isIntegerTy() &&
2232 "All non-integer types eliminated!");
2233 return cast<FixedVectorType>(RHSTy)->getNumElements() <
2234 cast<FixedVectorType>(LHSTy)->getNumElements();
2238 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2239 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2240 "Cannot have vector types of different sizes!");
2241 assert(RHSTy->getElementType()->isIntegerTy() &&
2242 "All non-integer types eliminated!");
2243 assert(LHSTy->getElementType()->isIntegerTy() &&
2244 "All non-integer types eliminated!");
2245 return cast<FixedVectorType>(RHSTy)->getNumElements() ==
2246 cast<FixedVectorType>(LHSTy)->getNumElements();
2248 llvm::sort(CandidateTys, RankVectorTypesComp);
2249 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2250 CandidateTys.end());
2256 assert(VTy->getElementType() == CommonEltTy &&
2257 "Unaccounted for element type!");
2258 assert(VTy == CandidateTys[0] &&
2259 "Different vector types with the same element type!");
2262 CandidateTys.resize(1);
2268 return cast<FixedVectorType>(VTy)->getNumElements() >
2269 std::numeric_limits<unsigned short>::max();
2283 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2284 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy,
unsigned VScale) {
2286 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2289 for (
Type *Ty : OtherTys) {
2290 if (!VectorType::isValidElementType(Ty))
2292 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2295 for (
VectorType *
const VTy : CandidateTysCopy) {
2297 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2298 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2299 unsigned ElementSize =
2300 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2304 CheckCandidateType(NewVTy);
2310 P,
DL, CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2311 HaveCommonVecPtrTy, CommonVecPtrTy, VScale);
2330 Type *CommonEltTy =
nullptr;
2332 bool HaveVecPtrTy =
false;
2333 bool HaveCommonEltTy =
true;
2334 bool HaveCommonVecPtrTy =
true;
2335 auto CheckCandidateType = [&](
Type *Ty) {
2336 if (
auto *VTy = dyn_cast<FixedVectorType>(Ty)) {
2338 if (!CandidateTys.
empty()) {
2340 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2341 DL.getTypeSizeInBits(V).getFixedValue()) {
2342 CandidateTys.
clear();
2347 Type *EltTy = VTy->getElementType();
2350 CommonEltTy = EltTy;
2351 else if (CommonEltTy != EltTy)
2352 HaveCommonEltTy =
false;
2355 HaveVecPtrTy =
true;
2356 if (!CommonVecPtrTy)
2357 CommonVecPtrTy = VTy;
2358 else if (CommonVecPtrTy != VTy)
2359 HaveCommonVecPtrTy =
false;
2365 for (
const Slice &S :
P) {
2367 if (
auto *LI = dyn_cast<LoadInst>(S.getUse()->getUser()))
2369 else if (
auto *SI = dyn_cast<StoreInst>(S.getUse()->getUser()))
2370 Ty = SI->getValueOperand()->getType();
2375 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2376 S.endOffset() !=
P.endOffset())) {
2383 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2384 CheckCandidateType(Ty);
2389 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2390 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2391 HaveCommonVecPtrTy, CommonVecPtrTy, VScale))
2394 CandidateTys.
clear();
2396 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2397 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2398 CommonVecPtrTy, VScale);
2409 bool &WholeAllocaOp) {
2412 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2413 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2415 Use *U = S.getUse();
2422 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2431 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2440 if (S.beginOffset() < AllocBeginOffset)
2445 if (!isa<VectorType>(LI->
getType()) && RelBegin == 0 && RelEnd ==
Size)
2446 WholeAllocaOp =
true;
2448 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2450 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2456 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2457 Type *ValueTy = SI->getValueOperand()->getType();
2458 if (SI->isVolatile())
2461 TypeSize StoreSize =
DL.getTypeStoreSize(ValueTy);
2466 if (S.beginOffset() < AllocBeginOffset)
2471 if (!isa<VectorType>(ValueTy) && RelBegin == 0 && RelEnd ==
Size)
2472 WholeAllocaOp =
true;
2473 if (
IntegerType *ITy = dyn_cast<IntegerType>(ValueTy)) {
2474 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2476 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2482 }
else if (
MemIntrinsic *
MI = dyn_cast<MemIntrinsic>(U->getUser())) {
2483 if (
MI->isVolatile() || !isa<Constant>(
MI->getLength()))
2485 if (!S.isSplittable())
2502 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2508 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2526 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2528 for (
const Slice &S :
P)
2533 for (
const Slice *S :
P.splitSliceTails())
2538 return WholeAllocaOp;
2545 IntegerType *IntTy = cast<IntegerType>(V->getType());
2547 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2548 "Element extends past full value");
2550 if (
DL.isBigEndian())
2551 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2552 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2554 V = IRB.CreateLShr(V, ShAmt,
Name +
".shift");
2558 "Cannot extract to a larger integer!");
2560 V = IRB.CreateTrunc(V, Ty,
Name +
".trunc");
2569 IntegerType *Ty = cast<IntegerType>(V->getType());
2571 "Cannot insert a larger integer!");
2574 V = IRB.CreateZExt(V, IntTy,
Name +
".ext");
2578 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2579 "Element store outside of alloca store");
2581 if (
DL.isBigEndian())
2582 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2583 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2585 V = IRB.CreateShl(V, ShAmt,
Name +
".shift");
2591 Old = IRB.CreateAnd(Old, Mask,
Name +
".mask");
2593 V = IRB.CreateOr(Old, V,
Name +
".insert");
2601 auto *VecTy = cast<FixedVectorType>(V->getType());
2602 unsigned NumElements = EndIndex - BeginIndex;
2605 if (NumElements == VecTy->getNumElements())
2608 if (NumElements == 1) {
2609 V = IRB.CreateExtractElement(V, IRB.getInt32(BeginIndex),
2615 auto Mask = llvm::to_vector<8>(llvm::seq<int>(BeginIndex, EndIndex));
2616 V = IRB.CreateShuffleVector(V, Mask,
Name +
".extract");
2622 unsigned BeginIndex,
const Twine &
Name) {
2624 assert(VecTy &&
"Can only insert a vector into a vector");
2626 VectorType *Ty = dyn_cast<VectorType>(V->getType());
2629 V = IRB.CreateInsertElement(Old, V, IRB.getInt32(BeginIndex),
2637 "Too many elements!");
2640 assert(V->getType() == VecTy &&
"Vector type mismatch");
2643 unsigned EndIndex = BeginIndex + cast<FixedVectorType>(Ty)->getNumElements();
2651 for (
unsigned i = 0; i != cast<FixedVectorType>(VecTy)->getNumElements(); ++i)
2652 if (i >= BeginIndex && i < EndIndex)
2653 Mask.push_back(i - BeginIndex);
2656 V = IRB.CreateShuffleVector(V, Mask,
Name +
".expand");
2661 for (
unsigned i = 0; i != cast<FixedVectorType>(VecTy)->getNumElements(); ++i)
2662 Mask2.
push_back(IRB.getInt1(i >= BeginIndex && i < EndIndex));
2678class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2688 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2717 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2720 bool IsSplittable =
false;
2721 bool IsSplit =
false;
2722 Use *OldUse =
nullptr;
2735 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2739 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2740 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2747 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2751 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2752 NewAllocaBeginOffset(NewAllocaBeginOffset),
2753 NewAllocaEndOffset(NewAllocaEndOffset),
2754 NewAllocaTy(NewAI.getAllocatedType()),
2757 ?
Type::getIntNTy(NewAI.getContext(),
2758 DL.getTypeSizeInBits(NewAI.getAllocatedType())
2761 VecTy(PromotableVecTy),
2762 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2763 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2765 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2768 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2769 "Only multiple-of-8 sized vector elements are viable");
2772 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2775 bool visit(AllocaSlices::const_iterator
I) {
2776 bool CanSROA =
true;
2777 BeginOffset =
I->beginOffset();
2778 EndOffset =
I->endOffset();
2779 IsSplittable =
I->isSplittable();
2781 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2782 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2787 assert(BeginOffset < NewAllocaEndOffset);
2788 assert(EndOffset > NewAllocaBeginOffset);
2789 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2790 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2792 SliceSize = NewEndOffset - NewBeginOffset;
2793 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2794 <<
") NewBegin:(" << NewBeginOffset <<
", "
2795 << NewEndOffset <<
") NewAllocaBegin:("
2796 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2798 assert(IsSplit || NewBeginOffset == BeginOffset);
2799 OldUse =
I->getUse();
2800 OldPtr = cast<Instruction>(OldUse->get());
2802 Instruction *OldUserI = cast<Instruction>(OldUse->getUser());
2803 IRB.SetInsertPoint(OldUserI);
2804 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2805 IRB.getInserter().SetNamePrefix(
Twine(NewAI.
getName()) +
"." +
2806 Twine(BeginOffset) +
".");
2808 CanSROA &=
visit(cast<Instruction>(OldUse->getUser()));
2827 assert(IsSplit || BeginOffset == NewBeginOffset);
2833 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
2835 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
2840 OldName = OldName.
substr(IndexEnd + 1);
2844 OldName = OldName.
substr(OffsetEnd + 1);
2848 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
2855 Twine(OldName) +
"."
2867 Align getSliceAlign() {
2869 NewBeginOffset - NewAllocaBeginOffset);
2873 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
2875 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
2881 void deleteIfTriviallyDead(
Value *V) {
2884 Pass.DeadInsts.push_back(
I);
2888 unsigned BeginIndex = getIndex(NewBeginOffset);
2889 unsigned EndIndex = getIndex(NewEndOffset);
2890 assert(EndIndex > BeginIndex &&
"Empty vector!");
2895 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
2896 LLVMContext::MD_access_group});
2897 return extractVector(IRB, Load, BeginIndex, EndIndex,
"vec");
2901 assert(IntTy &&
"We cannot insert an integer to the alloca");
2906 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
2908 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
2917 assert(cast<IntegerType>(LI.
getType())->getBitWidth() >= SliceSize * 8 &&
2918 "Can only handle an extract for an overly wide load");
2919 if (cast<IntegerType>(LI.
getType())->getBitWidth() > SliceSize * 8)
2920 V = IRB.CreateZExt(V, LI.
getType());
2935 bool IsPtrAdjusted =
false;
2938 V = rewriteVectorizedLoadInst(LI);
2940 V = rewriteIntegerLoad(LI);
2941 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
2942 NewEndOffset == NewAllocaEndOffset &&
2945 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize &&
2965 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
2973 if (
auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
2974 if (
auto *TITy = dyn_cast<IntegerType>(TargetTy))
2975 if (AITy->getBitWidth() < TITy->getBitWidth()) {
2976 V = IRB.CreateZExt(V, TITy,
"load.ext");
2977 if (
DL.isBigEndian())
2978 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
2982 Type *LTy = IRB.getPtrTy(AS);
2984 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
2989 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
2993 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
2994 LLVMContext::MD_access_group});
2997 IsPtrAdjusted =
true;
3004 "Only integer type loads and stores are split");
3005 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
3006 "Split load isn't smaller than original load");
3008 "Non-byte-multiple bit width");
3014 LIIt.setHeadBit(
true);
3015 IRB.SetInsertPoint(LI.
getParent(), LIIt);
3020 Value *Placeholder =
3026 Placeholder->replaceAllUsesWith(&LI);
3027 Placeholder->deleteValue();
3032 Pass.DeadInsts.push_back(&LI);
3033 deleteIfTriviallyDead(OldOp);
3043 if (
V->getType() != VecTy) {
3044 unsigned BeginIndex = getIndex(NewBeginOffset);
3045 unsigned EndIndex = getIndex(NewEndOffset);
3046 assert(EndIndex > BeginIndex &&
"Empty vector!");
3047 unsigned NumElements = EndIndex - BeginIndex;
3049 "Too many elements!");
3050 Type *SliceTy = (NumElements == 1)
3053 if (
V->getType() != SliceTy)
3062 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3063 LLVMContext::MD_access_group});
3067 Pass.DeadInsts.push_back(&SI);
3071 Store,
Store->getPointerOperand(), OrigV,
DL);
3077 assert(IntTy &&
"We cannot extract an integer from the alloca");
3079 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3084 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3090 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3091 LLVMContext::MD_access_group});
3097 Store,
Store->getPointerOperand(),
3098 Store->getValueOperand(),
DL);
3100 Pass.DeadInsts.push_back(&SI);
3107 Value *OldOp =
SI.getOperand(1);
3115 if (
V->getType()->isPointerTy())
3116 if (
AllocaInst *AI = dyn_cast<AllocaInst>(
V->stripInBoundsOffsets()))
3117 Pass.PostPromotionWorklist.insert(AI);
3119 TypeSize StoreSize =
DL.getTypeStoreSize(
V->getType());
3122 assert(
V->getType()->isIntegerTy() &&
3123 "Only integer type loads and stores are split");
3124 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3125 "Non-byte-multiple bit width");
3132 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3133 if (IntTy &&
V->getType()->isIntegerTy())
3134 return rewriteIntegerStore(V, SI, AATags);
3137 if (NewBeginOffset == NewAllocaBeginOffset &&
3138 NewEndOffset == NewAllocaEndOffset &&
3142 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3145 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3147 unsigned AS =
SI.getPointerAddressSpace();
3148 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3150 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3152 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3153 LLVMContext::MD_access_group});
3157 if (
SI.isVolatile())
3166 Pass.DeadInsts.push_back(&SI);
3167 deleteIfTriviallyDead(OldOp);
3185 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3193 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3203 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3216 if (!isa<ConstantInt>(
II.getLength())) {
3218 assert(NewBeginOffset == BeginOffset);
3219 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3220 II.setDestAlignment(getSliceAlign());
3225 "AT: Unexpected link to non-const GEP");
3226 deleteIfTriviallyDead(OldPtr);
3231 Pass.DeadInsts.push_back(&
II);
3236 const bool CanContinue = [&]() {
3239 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3242 auto *
C = cast<ConstantInt>(
II.getLength());
3244 if (Len > std::numeric_limits<unsigned>::max())
3246 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3249 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3255 Type *SizeTy =
II.getLength()->getType();
3256 unsigned Sz = NewEndOffset - NewBeginOffset;
3259 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3266 New,
New->getRawDest(),
nullptr,
DL);
3281 assert(ElementTy == ScalarTy);
3283 unsigned BeginIndex = getIndex(NewBeginOffset);
3284 unsigned EndIndex = getIndex(NewEndOffset);
3285 assert(EndIndex > BeginIndex &&
"Empty vector!");
3286 unsigned NumElements = EndIndex - BeginIndex;
3288 "Too many elements!");
3291 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3293 if (NumElements > 1)
3305 V = getIntegerSplat(
II.getValue(),
Size);
3307 if (IntTy && (BeginOffset != NewAllocaBeginOffset ||
3308 EndOffset != NewAllocaBeginOffset)) {
3315 assert(
V->getType() == IntTy &&
3316 "Wrong type for an alloca wide integer!");
3321 assert(NewBeginOffset == NewAllocaBeginOffset);
3322 assert(NewEndOffset == NewAllocaEndOffset);
3324 V = getIntegerSplat(
II.getValue(),
3325 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3326 if (
VectorType *AllocaVecTy = dyn_cast<VectorType>(AllocaTy))
3333 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3335 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3336 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3337 LLVMContext::MD_access_group});
3343 New,
New->getPointerOperand(), V,
DL);
3346 return !
II.isVolatile();
3357 bool IsDest = &
II.getRawDestUse() == OldUse;
3358 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3359 (!IsDest &&
II.getRawSource() == OldPtr));
3361 Align SliceAlign = getSliceAlign();
3369 if (!IsSplittable) {
3370 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3375 DbgAssign->getAddress() ==
II.getDest())
3376 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3378 II.setDest(AdjustedPtr);
3379 II.setDestAlignment(SliceAlign);
3381 II.setSource(AdjustedPtr);
3382 II.setSourceAlignment(SliceAlign);
3386 deleteIfTriviallyDead(OldPtr);
3399 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3408 if (EmitMemCpy && &OldAI == &NewAI) {
3410 assert(NewBeginOffset == BeginOffset);
3413 if (NewEndOffset != EndOffset)
3414 II.setLength(NewEndOffset - NewBeginOffset);
3418 Pass.DeadInsts.push_back(&
II);
3422 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3425 assert(AI != &OldAI && AI != &NewAI &&
3426 "Splittable transfers cannot reach the same alloca on both ends.");
3427 Pass.Worklist.insert(AI);
3434 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3435 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3437 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
3439 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
3447 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3448 Type *SizeTy =
II.getLength()->getType();
3449 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
3451 Value *DestPtr, *SrcPtr;
3456 DestAlign = SliceAlign;
3458 SrcAlign = OtherAlign;
3461 DestAlign = OtherAlign;
3463 SrcAlign = SliceAlign;
3465 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
3468 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
3473 &
II, New, DestPtr,
nullptr,
DL);
3478 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
3484 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
3485 NewEndOffset == NewAllocaEndOffset;
3487 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
3488 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
3489 unsigned NumElements = EndIndex - BeginIndex;
3496 if (VecTy && !IsWholeAlloca) {
3497 if (NumElements == 1)
3498 OtherTy = VecTy->getElementType();
3501 }
else if (IntTy && !IsWholeAlloca) {
3504 OtherTy = NewAllocaTy;
3518 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3522 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
3526 if (VecTy && !IsWholeAlloca && !IsDest) {
3530 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
3537 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
3538 II.isVolatile(),
"copyload");
3539 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3540 LLVMContext::MD_access_group});
3547 if (VecTy && !IsWholeAlloca && IsDest) {
3551 }
else if (IntTy && !IsWholeAlloca && IsDest) {
3561 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
3562 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3563 LLVMContext::MD_access_group});
3566 Src->getType(),
DL));
3572 Store, DstPtr, Src,
DL);
3577 &
II, Store, DstPtr, Src,
DL);
3581 return !
II.isVolatile();
3585 assert((
II.isLifetimeStartOrEnd() ||
II.isDroppable()) &&
3586 "Unexpected intrinsic!");
3590 Pass.DeadInsts.push_back(&
II);
3592 if (
II.isDroppable()) {
3593 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
3599 assert(
II.getArgOperand(0) == OldPtr);
3603 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
3604 New = IRB.CreateLifetimeStart(
Ptr);
3606 New = IRB.CreateLifetimeEnd(
Ptr);
3621 Uses.push_back(&Root);
3625 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
3629 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
3630 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
3634 assert(isa<BitCastInst>(
I) || isa<AddrSpaceCastInst>(
I) ||
3635 isa<PHINode>(
I) || isa<SelectInst>(
I) ||
3636 isa<GetElementPtrInst>(
I));
3637 for (
User *U :
I->users())
3638 if (Visited.
insert(cast<Instruction>(U)).second)
3639 Uses.push_back(cast<Instruction>(U));
3640 }
while (!
Uses.empty());
3643 bool visitPHINode(
PHINode &PN) {
3645 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
3646 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
3653 if (isa<PHINode>(OldPtr))
3655 OldPtr->
getParent()->getFirstInsertionPt());
3657 IRB.SetInsertPoint(OldPtr);
3658 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
3660 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3662 std::replace(PN.
op_begin(), PN.
op_end(), cast<Value>(OldPtr), NewPtr);
3665 deleteIfTriviallyDead(OldPtr);
3668 fixLoadStoreAlign(PN);
3679 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
3680 "Pointer isn't an operand!");
3681 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
3682 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
3684 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3686 if (
SI.getOperand(1) == OldPtr)
3687 SI.setOperand(1, NewPtr);
3688 if (
SI.getOperand(2) == OldPtr)
3689 SI.setOperand(2, NewPtr);
3692 deleteIfTriviallyDead(OldPtr);
3695 fixLoadStoreAlign(SI);
3710class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
3730 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
3731 :
DL(
DL), IRB(IRB) {}
3738 bool Changed =
false;
3739 while (!
Queue.empty()) {
3740 U =
Queue.pop_back_val();
3741 Changed |=
visit(cast<Instruction>(
U->getUser()));
3750 for (
Use &U :
I.uses())
3751 if (Visited.
insert(
U.getUser()).second)
3752 Queue.push_back(&U);
3756 bool visitInstruction(
Instruction &
I) {
return false; }
3759 template <
typename Derived>
class OpSplitter {
3791 BaseAlign(BaseAlign),
DL(
DL) {
3812 return static_cast<Derived *
>(
this)->emitFunc(
3816 if (
ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
3817 unsigned OldSize = Indices.
size();
3819 for (
unsigned Idx = 0,
Size = ATy->getNumElements();
Idx !=
Size;
3821 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
3824 emitSplitOps(ATy->getElementType(), Agg,
Name +
"." +
Twine(
Idx));
3831 if (
StructType *STy = dyn_cast<StructType>(Ty)) {
3832 unsigned OldSize = Indices.
size();
3834 for (
unsigned Idx = 0,
Size = STy->getNumElements();
Idx !=
Size;
3836 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
3850 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
3872 IRB.CreateInBoundsGEP(
BaseTy,
Ptr, GEPIndices,
Name +
".gep");
3874 IRB.CreateAlignedLoad(Ty,
GEP, Alignment,
Name +
".load");
3877 DL.getIndexSizeInBits(
Ptr->getType()->getPointerAddressSpace()), 0);
3880 Load->setAAMetadata(
3886 Agg = IRB.CreateInsertValue(Agg, Load, Indices,
Name +
".insert");
3891 void recordFakeUses(
LoadInst &LI) {
3893 if (
auto *
II = dyn_cast<IntrinsicInst>(
U.getUser()))
3894 if (
II->getIntrinsicID() == Intrinsic::fake_use)
3900 void emitFakeUses() {
3902 IRB.SetInsertPoint(
I);
3903 for (
auto *V : Components)
3904 IRB.CreateIntrinsic(Intrinsic::fake_use, {
V});
3905 I->eraseFromParent();
3919 Splitter.recordFakeUses(LI);
3922 Splitter.emitFakeUses();
3929 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
3935 AATags(AATags), AggStore(AggStore) {}
3946 Value *ExtractValue =
3947 IRB.CreateExtractValue(Agg, Indices,
Name +
".extract");
3948 Value *InBoundsGEP =
3949 IRB.CreateInBoundsGEP(
BaseTy,
Ptr, GEPIndices,
Name +
".gep");
3951 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
3954 DL.getIndexSizeInBits(
Ptr->getType()->getPointerAddressSpace()), 0);
3966 if (
auto *OldAI = dyn_cast<AllocaInst>(
Base)) {
3968 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
3970 SizeInBits, AggStore, Store,
3971 Store->getPointerOperand(),
Store->getValueOperand(),
3975 "AT: unexpected debug.assign linked to store through "
3983 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
3986 if (
V->getType()->isSingleValueType())
3991 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
3993 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
3998 SI.eraseFromParent();
4022 if (
auto *SI = dyn_cast<SelectInst>(
Op)) {
4027 if (!isa<ConstantInt>(
SI->getTrueValue()) ||
4028 !isa<ConstantInt>(
SI->getFalseValue()))
4032 if (
auto *ZI = dyn_cast<ZExtInst>(
Op)) {
4036 if (!ZI->getSrcTy()->isIntegerTy(1))
4041 if (!isa<ConstantInt>(
Op))
4049 dbgs() <<
" original: " << *Sel <<
"\n";
4050 dbgs() <<
" " << GEPI <<
"\n";);
4052 auto GetNewOps = [&](
Value *SelOp) {
4063 if (
auto *SI = dyn_cast<SelectInst>(Sel)) {
4064 Cond =
SI->getCondition();
4065 True =
SI->getTrueValue();
4066 False =
SI->getFalseValue();
4068 Cond = Sel->getOperand(0);
4069 True = ConstantInt::get(Sel->getType(), 1);
4070 False = ConstantInt::get(Sel->getType(), 0);
4075 IRB.SetInsertPoint(&GEPI);
4079 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
4080 True->
getName() +
".sroa.gep", NW);
4083 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
4084 False->
getName() +
".sroa.gep", NW);
4087 IRB.CreateSelect(
Cond, NTrue, NFalse, Sel->getName() +
".sroa.sel");
4088 Visited.
erase(&GEPI);
4093 enqueueUsers(*NSelI);
4096 dbgs() <<
" " << *NFalse <<
"\n";
4097 dbgs() <<
" " << *NSel <<
"\n";);
4111 auto IsInvalidPointerOperand = [](
Value *
V) {
4112 if (!isa<Instruction>(V))
4114 if (
auto *AI = dyn_cast<AllocaInst>(V))
4115 return !AI->isStaticAlloca();
4119 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4128 if (
auto *SI = dyn_cast<PHINode>(
Op)) {
4134 [](
Value *V) { return isa<ConstantInt>(V); }))
4139 if (!isa<ConstantInt>(
Op))
4147 dbgs() <<
" original: " << *
Phi <<
"\n";
4148 dbgs() <<
" " << GEPI <<
"\n";);
4150 auto GetNewOps = [&](
Value *PhiOp) {
4160 IRB.SetInsertPoint(Phi);
4162 Phi->getName() +
".sroa.phi");
4168 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4177 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4183 Visited.
erase(&GEPI);
4187 enqueueUsers(*NewPhi);
4193 dbgs() <<
"\n " << *NewPhi <<
'\n');
4199 if (unfoldGEPSelect(GEPI))
4202 if (unfoldGEPPhi(GEPI))
4209 bool visitPHINode(
PHINode &PN) {
4231 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4235 if (
ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
4236 InnerTy = ArrTy->getElementType();
4237 }
else if (
StructType *STy = dyn_cast<StructType>(Ty)) {
4240 InnerTy = STy->getElementType(Index);
4245 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4246 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4267 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4269 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4270 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4273 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty)) {
4276 if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
4277 ElementTy = AT->getElementType();
4278 TyNumElements = AT->getNumElements();
4282 auto *VT = cast<FixedVectorType>(Ty);
4283 ElementTy = VT->getElementType();
4284 TyNumElements = VT->getNumElements();
4286 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4288 if (NumSkippedElements >= TyNumElements)
4290 Offset -= NumSkippedElements * ElementSize;
4302 if (
Size == ElementSize)
4306 if (NumElements * ElementSize !=
Size)
4308 return ArrayType::get(ElementTy, NumElements);
4330 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4331 if (
Offset >= ElementSize)
4342 if (
Size == ElementSize)
4349 if (Index == EndIndex)
4359 assert(Index < EndIndex);
4398bool SROA::presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS) {
4412 struct SplitOffsets {
4414 std::vector<uint64_t> Splits;
4431 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
4432 for (
auto &
P : AS.partitions()) {
4433 for (Slice &S :
P) {
4434 Instruction *
I = cast<Instruction>(S.getUse()->getUser());
4435 if (!S.isSplittable() || S.endOffset() <=
P.endOffset()) {
4439 if (
auto *LI = dyn_cast<LoadInst>(
I))
4440 UnsplittableLoads.
insert(LI);
4441 else if (
auto *SI = dyn_cast<StoreInst>(
I))
4442 if (
auto *LI = dyn_cast<LoadInst>(
SI->getValueOperand()))
4443 UnsplittableLoads.
insert(LI);
4446 assert(
P.endOffset() > S.beginOffset() &&
4447 "Empty or backwards partition!");
4450 if (
auto *LI = dyn_cast<LoadInst>(
I)) {
4456 auto IsLoadSimplyStored = [](
LoadInst *LI) {
4458 auto *
SI = dyn_cast<StoreInst>(LU);
4459 if (!SI || !
SI->isSimple())
4464 if (!IsLoadSimplyStored(LI)) {
4465 UnsplittableLoads.
insert(LI);
4470 }
else if (
auto *SI = dyn_cast<StoreInst>(
I)) {
4471 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
4474 auto *StoredLoad = dyn_cast<LoadInst>(
SI->getValueOperand());
4475 if (!StoredLoad || !StoredLoad->isSimple())
4477 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
4487 auto &
Offsets = SplitOffsetsMap[
I];
4489 "Should not have splits the first time we see an instruction!");
4491 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
4496 for (Slice *S :
P.splitSliceTails()) {
4497 auto SplitOffsetsMapI =
4498 SplitOffsetsMap.
find(cast<Instruction>(S->getUse()->getUser()));
4499 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
4501 auto &
Offsets = SplitOffsetsMapI->second;
4505 "Cannot have an empty set of splits on the second partition!");
4507 P.beginOffset() -
Offsets.S->beginOffset() &&
4508 "Previous split does not end where this one begins!");
4512 if (S->endOffset() >
P.endOffset())
4524 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4527 if (UnsplittableLoads.
count(LI))
4530 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
4531 if (LoadOffsetsI == SplitOffsetsMap.
end())
4533 auto &LoadOffsets = LoadOffsetsI->second;
4536 auto &StoreOffsets = SplitOffsetsMap[
SI];
4541 if (LoadOffsets.Splits == StoreOffsets.Splits)
4545 <<
" " << *LI <<
"\n"
4546 <<
" " << *SI <<
"\n");
4552 UnsplittableLoads.
insert(LI);
4560 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4561 return UnsplittableLoads.
count(LI);
4566 return UnsplittableLoads.
count(LI);
4576 IRBuilderTy IRB(&AI);
4594 std::vector<LoadInst *> SplitLoads;
4599 auto &
Offsets = SplitOffsetsMap[LI];
4600 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
4602 "Load must have type size equal to store size");
4604 "Load must be >= slice size");
4607 assert(BaseOffset + SliceSize > BaseOffset &&
4608 "Cannot represent alloca access size using 64-bit integers!");
4611 IRB.SetInsertPoint(LI);
4621 LoadInst *PLoad = IRB.CreateAlignedLoad(
4624 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4625 PartPtrTy,
BasePtr->getName() +
"."),
4628 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
4629 LLVMContext::MD_access_group});
4633 SplitLoads.push_back(PLoad);
4637 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4641 <<
", " << NewSlices.
back().endOffset()
4642 <<
"): " << *PLoad <<
"\n");
4657 bool DeferredStores =
false;
4660 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
4661 DeferredStores =
true;
4667 Value *StoreBasePtr =
SI->getPointerOperand();
4668 IRB.SetInsertPoint(SI);
4671 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
4676 auto *PartPtrTy =
SI->getPointerOperandType();
4678 auto AS =
SI->getPointerAddressSpace();
4679 StoreInst *PStore = IRB.CreateAlignedStore(
4682 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4683 PartPtrTy, StoreBasePtr->
getName() +
"."),
4686 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
4687 LLVMContext::MD_access_group,
4688 LLVMContext::MD_DIAssignID});
4693 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
4700 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(StoreBasePtr)) {
4701 ResplitPromotableAllocas.
insert(OtherAI);
4702 Worklist.insert(OtherAI);
4703 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
4705 Worklist.insert(OtherAI);
4709 DeadInsts.push_back(SI);
4714 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
4717 DeadInsts.push_back(LI);
4727 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4731 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
4735 "Slice size should always match load size exactly!");
4737 assert(BaseOffset + StoreSize > BaseOffset &&
4738 "Cannot represent alloca access size using 64-bit integers!");
4741 Instruction *StoreBasePtr = cast<Instruction>(
SI->getPointerOperand());
4746 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
4747 std::vector<LoadInst *> *SplitLoads =
nullptr;
4748 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
4749 SplitLoads = &SplitLoadsMapI->second;
4751 "Too few split loads for the number of splits in the store!");
4761 auto *StorePartPtrTy =
SI->getPointerOperandType();
4766 PLoad = (*SplitLoads)[
Idx];
4768 IRB.SetInsertPoint(LI);
4770 PLoad = IRB.CreateAlignedLoad(
4773 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4774 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
4777 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
4778 LLVMContext::MD_access_group});
4782 IRB.SetInsertPoint(SI);
4783 auto AS =
SI->getPointerAddressSpace();
4784 StoreInst *PStore = IRB.CreateAlignedStore(
4787 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4788 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
4791 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
4792 LLVMContext::MD_access_group});
4796 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4800 <<
", " << NewSlices.
back().endOffset()
4801 <<
"): " << *PStore <<
"\n");
4822 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(LoadBasePtr)) {
4823 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
4824 ResplitPromotableAllocas.
insert(OtherAI);
4825 Worklist.insert(OtherAI);
4826 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
4828 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
4829 Worklist.insert(OtherAI);
4844 DeadInsts.push_back(LI);
4846 DeadInsts.push_back(SI);
4855 AS.insert(NewSlices);
4859 for (
auto I = AS.begin(), E = AS.end();
I != E; ++
I)
4865 PromotableAllocas.set_subtract(ResplitPromotableAllocas);
4885 Type *SliceTy =
nullptr;
4890 std::pair<Type *, IntegerType *> CommonUseTy =
4893 if (CommonUseTy.first) {
4894 TypeSize CommonUseSize =
DL.getTypeAllocSize(CommonUseTy.first);
4896 SliceTy = CommonUseTy.first;
4897 SliceVecTy = dyn_cast<VectorType>(SliceTy);
4903 P.beginOffset(),
P.size()))
4904 SliceTy = TypePartitionTy;
4907 if (!SliceTy && CommonUseTy.second)
4908 if (
DL.getTypeAllocSize(CommonUseTy.second).getFixedValue() >=
P.size()) {
4909 SliceTy = CommonUseTy.second;
4910 SliceVecTy = dyn_cast<VectorType>(SliceTy);
4912 if ((!SliceTy || (SliceTy->
isArrayTy() &&
4914 DL.isLegalInteger(
P.size() * 8)) {
4922 P.beginOffset(),
P.size())) {
4923 VectorType *TypePartitionVecTy = dyn_cast<VectorType>(TypePartitionTy);
4924 if (TypePartitionVecTy &&
4926 SliceTy = TypePartitionTy;
4931 assert(
DL.getTypeAllocSize(SliceTy).getFixedValue() >=
P.size());
4957 const bool IsUnconstrained = Alignment <=
DL.getABITypeAlign(SliceTy);
4960 IsUnconstrained ?
DL.getPrefTypeAlign(SliceTy) : Alignment,
4968 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
4969 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
4974 unsigned PPWOldSize = PostPromotionWorklist.size();
4975 unsigned NumUses = 0;
4979 AllocaSliceRewriter
Rewriter(
DL, AS, *
this, AI, *NewAI,
P.beginOffset(),
4980 P.endOffset(), IsIntegerPromotable, VecTy,
4981 PHIUsers, SelectUsers);
4982 bool Promotable =
true;
4983 for (Slice *S :
P.splitSliceTails()) {
4987 for (Slice &S :
P) {
4992 NumAllocaPartitionUses += NumUses;
4993 MaxUsesPerAllocaPartition.updateMax(NumUses);
5001 SelectUsers.
clear();
5006 NewSelectsToRewrite;
5009 std::optional<RewriteableMemOps> Ops =
5014 SelectUsers.clear();
5015 NewSelectsToRewrite.
clear();
5018 NewSelectsToRewrite.
emplace_back(std::make_pair(Sel, *Ops));
5022 for (
Use *U : AS.getDeadUsesIfPromotable()) {
5023 auto *OldInst = dyn_cast<Instruction>(
U->get());
5027 DeadInsts.push_back(OldInst);
5029 if (PHIUsers.empty() && SelectUsers.empty()) {
5031 PromotableAllocas.insert(NewAI);
5036 SpeculatablePHIs.insert_range(PHIUsers);
5037 SelectsToRewrite.reserve(SelectsToRewrite.size() +
5038 NewSelectsToRewrite.
size());
5040 std::make_move_iterator(NewSelectsToRewrite.
begin()),
5041 std::make_move_iterator(NewSelectsToRewrite.
end())))
5042 SelectsToRewrite.insert(std::move(KV));
5043 Worklist.insert(NewAI);
5047 while (PostPromotionWorklist.size() > PPWOldSize)
5048 PostPromotionWorklist.pop_back();
5058 Worklist.insert(NewAI);
5067 if (DVR->
getType() == DbgVariableRecord::LocationType::Assign)
5073 if (DVR->
getType() == DbgVariableRecord::LocationType::Assign)
5105 int64_t BitExtractOffset) {
5107 bool HasFragment =
false;
5108 bool HasBitExtract =
false;
5117 HasBitExtract =
true;
5118 int64_t ExtractOffsetInBits =
Op.getArg(0);
5119 int64_t ExtractSizeInBits =
Op.getArg(1);
5128 assert(BitExtractOffset <= 0);
5129 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5135 if (AdjustedOffset < 0)
5139 Ops.
push_back(std::max<int64_t>(0, AdjustedOffset));
5143 Op.appendToVector(Ops);
5148 if (HasFragment && HasBitExtract)
5151 if (!HasBitExtract) {
5156 return DIExpression::get(Expr->
getContext(), Ops);
5170 std::optional<DIExpression::FragmentInfo> NewFragment,
5171 int64_t BitExtractAdjustment) {
5181 BitExtractAdjustment);
5182 if (!NewFragmentExpr)
5188 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5201 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5207 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5215 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
5221bool SROA::splitAlloca(
AllocaInst &AI, AllocaSlices &AS) {
5222 if (AS.begin() == AS.end())
5225 unsigned NumPartitions = 0;
5226 bool Changed =
false;
5230 Changed |= presplitLoadsAndStores(AI, AS);
5238 bool IsSorted =
true;
5242 const uint64_t MaxBitVectorSize = 1024;
5243 if (AllocaSize <= MaxBitVectorSize) {
5248 for (
unsigned O = S.beginOffset() + 1;
5249 O < S.endOffset() && O < AllocaSize; O++)
5250 SplittableOffset.reset(O);
5252 for (Slice &S : AS) {
5253 if (!S.isSplittable())
5256 if ((S.beginOffset() > AllocaSize || SplittableOffset[S.beginOffset()]) &&
5257 (S.endOffset() > AllocaSize || SplittableOffset[S.endOffset()]))
5260 if (isa<LoadInst>(S.getUse()->getUser()) ||
5261 isa<StoreInst>(S.getUse()->getUser())) {
5262 S.makeUnsplittable();
5269 for (Slice &S : AS) {
5270 if (!S.isSplittable())
5273 if (S.beginOffset() == 0 && S.endOffset() >= AllocaSize)
5276 if (isa<LoadInst>(S.getUse()->getUser()) ||
5277 isa<StoreInst>(S.getUse()->getUser())) {
5278 S.makeUnsplittable();
5299 for (
auto &
P : AS.partitions()) {
5300 if (
AllocaInst *NewAI = rewritePartition(AI, AS,
P)) {
5307 uint64_t Size = std::min(AllocaSize,
P.size() * SizeOfByte);
5309 Fragment(NewAI,
P.beginOffset() * SizeOfByte,
Size));
5315 NumAllocaPartitions += NumPartitions;
5316 MaxPartitionsPerAlloca.updateMax(NumPartitions);
5330 int64_t CurrentExprOffsetInBytes = 0;
5337 int64_t ExtractOffsetInBits = 0;
5341 ExtractOffsetInBits =
Op.getArg(0);
5347 for (
auto Fragment : Fragments) {
5348 int64_t OffsetFromLocationInBits;
5349 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
5354 DL, &AI, Fragment.Offset, Fragment.Size, DbgPtr,
5355 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
5356 NewDbgFragment, OffsetFromLocationInBits))
5362 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
5367 if (!NewDbgFragment)
5372 int64_t OffestFromNewAllocaInBits =
5373 OffsetFromLocationInBits - ExtractOffsetInBits;
5376 int64_t BitExtractOffset =
5377 std::min<int64_t>(0, OffestFromNewAllocaInBits);
5382 OffestFromNewAllocaInBits =
5383 std::max(int64_t(0), OffestFromNewAllocaInBits);
5390 if (OffestFromNewAllocaInBits > 0) {
5391 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
5398 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
5399 return LHS->getVariable() ==
RHS->getVariable() &&
5400 LHS->getDebugLoc()->getInlinedAt() ==
5401 RHS->getDebugLoc()->getInlinedAt();
5404 OldDII->eraseFromParent();
5409 NewDbgFragment, BitExtractOffset);
5423void SROA::clobberUse(
Use &U) {
5431 if (
Instruction *OldI = dyn_cast<Instruction>(OldV))
5433 DeadInsts.push_back(OldI);
5444 return !isa<StoreInst>(
I) && !isa<AllocaInst>(
I);
5455bool SROA::propagateStoredValuesToLoads(
AllocaInst &AI, AllocaSlices &AS) {
5460 LLVM_DEBUG(
dbgs() <<
"Attempting to propagate values on " << AI <<
"\n");
5461 bool AllSameAndValid =
true;
5462 Type *PartitionType =
nullptr;
5467 auto Flush = [&]() {
5468 if (AllSameAndValid && !Insts.
empty()) {
5469 LLVM_DEBUG(
dbgs() <<
"Propagate values on slice [" << BeginOffset <<
", "
5470 << EndOffset <<
")\n");
5475 Promoter.run(Insts);
5477 AllSameAndValid =
true;
5478 PartitionType =
nullptr;
5482 for (Slice &S : AS) {
5483 auto *
User = cast<Instruction>(S.getUse()->getUser());
5486 dbgs() <<
"Ignoring slice: ";
5487 AS.print(
dbgs(), &S);
5491 if (S.beginOffset() >= EndOffset) {
5493 BeginOffset = S.beginOffset();
5494 EndOffset = S.endOffset();
5495 }
else if (S.beginOffset() != BeginOffset || S.endOffset() != EndOffset) {
5496 if (AllSameAndValid) {
5498 dbgs() <<
"Slice does not match range [" << BeginOffset <<
", "
5499 << EndOffset <<
")";
5500 AS.print(
dbgs(), &S);
5502 AllSameAndValid =
false;
5504 EndOffset = std::max(EndOffset, S.endOffset());
5508 if (
auto *LI = dyn_cast<LoadInst>(
User)) {
5511 if (!LI->
isSimple() || (PartitionType && UserTy != PartitionType))
5512 AllSameAndValid =
false;
5513 PartitionType = UserTy;
5515 }
else if (
auto *SI = dyn_cast<StoreInst>(
User)) {
5516 Type *UserTy =
SI->getValueOperand()->getType();
5517 if (!
SI->isSimple() || (PartitionType && UserTy != PartitionType))
5518 AllSameAndValid =
false;
5519 PartitionType = UserTy;
5522 AllSameAndValid =
false;
5535std::pair<
bool ,
bool >
5537 bool Changed =
false;
5538 bool CFGChanged =
false;
5541 ++NumAllocasAnalyzed;
5547 return {Changed, CFGChanged};
5555 Size.getFixedValue() == 0)
5556 return {Changed, CFGChanged};
5560 IRBuilderTy IRB(&AI);
5561 AggLoadStoreRewriter AggRewriter(
DL, IRB);
5562 Changed |= AggRewriter.rewrite(AI);
5565 AllocaSlices AS(
DL, AI);
5568 return {Changed, CFGChanged};
5570 if (AS.isEscapedReadOnly()) {
5571 Changed |= propagateStoredValuesToLoads(AI, AS);
5572 return {Changed, CFGChanged};
5578 for (
Use &DeadOp : DeadUser->operands())
5585 DeadInsts.push_back(DeadUser);
5588 for (
Use *DeadOp : AS.getDeadOperands()) {
5589 clobberUse(*DeadOp);
5594 if (AS.begin() == AS.end())
5595 return {Changed, CFGChanged};
5597 Changed |= splitAlloca(AI, AS);
5600 while (!SpeculatablePHIs.empty())
5604 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
5605 while (!RemainingSelectsToRewrite.empty()) {
5606 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
5611 return {Changed, CFGChanged};
5623bool SROA::deleteDeadInstructions(
5625 bool Changed =
false;
5626 while (!DeadInsts.empty()) {
5627 Instruction *
I = dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val());
5636 DeletedAllocas.
insert(AI);
5638 OldDII->eraseFromParent();
5644 for (
Use &Operand :
I->operands())
5645 if (
Instruction *U = dyn_cast<Instruction>(Operand)) {
5649 DeadInsts.push_back(U);
5653 I->eraseFromParent();
5663bool SROA::promoteAllocas() {
5664 if (PromotableAllocas.empty())
5671 NumPromoted += PromotableAllocas.size();
5672 PromoteMemToReg(PromotableAllocas.getArrayRef(), DTU->getDomTree(), AC);
5675 PromotableAllocas.clear();
5679std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
5689 PromotableAllocas.insert(AI);
5691 Worklist.insert(AI);
5695 bool Changed =
false;
5696 bool CFGChanged =
false;
5702 while (!Worklist.empty()) {
5703 auto [IterationChanged, IterationCFGChanged] =
5704 runOnAlloca(*Worklist.pop_back_val());
5705 Changed |= IterationChanged;
5706 CFGChanged |= IterationCFGChanged;
5708 Changed |= deleteDeadInstructions(DeletedAllocas);
5712 if (!DeletedAllocas.
empty()) {
5713 Worklist.set_subtract(DeletedAllocas);
5714 PostPromotionWorklist.set_subtract(DeletedAllocas);
5715 PromotableAllocas.set_subtract(DeletedAllocas);
5716 DeletedAllocas.
clear();
5720 Changed |= promoteAllocas();
5722 Worklist = PostPromotionWorklist;
5723 PostPromotionWorklist.clear();
5724 }
while (!Worklist.empty());
5726 assert((!CFGChanged || Changed) &&
"Can not only modify the CFG.");
5728 "Should not have modified the CFG when told to preserve it.");
5731 for (
auto &BB :
F) {
5736 return {Changed, CFGChanged};
5743 auto [Changed, CFGChanged] =
5757 OS, MapClassName2PassName);
5758 OS << (
PreserveCFG == SROAOptions::PreserveCFG ?
"<preserve-cfg>"
5779 if (skipFunction(
F))
5782 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
5784 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
5798 StringRef getPassName()
const override {
return "SROA"; }
5803char SROALegacyPass::ID = 0;
5811 "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 void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
#define LLVM_ATTRIBUTE_UNUSED
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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.
This file implements a map that provides insertion order iteration.
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
static unsigned getNumElements(Type *Ty)
bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> 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 bool checkVectorTypeForPromotion(Partition &P, VectorType *VTy, const DataLayout &DL, unsigned VScale)
Test whether a vector type is viable for promotion.
static cl::opt< bool > SROASkipMem2Reg("sroa-skip-mem2reg", cl::init(false), cl::Hidden)
Disable running mem2reg during SROA in order to test or debug SROA.
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.
Scalar Replacement Of Aggregates
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 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 bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
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)
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 Value * convertValue(const DataLayout &DL, IRBuilderTy &IRB, Value *V, Type *NewTy)
Generic routine to convert an SSA value to a value of a different type.
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 implements the SmallBitVector class.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Virtual Register Rewriter
Builder for the alloca slices.
SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
An iterator over partitions of the alloca's slices.
bool operator==(const partition_iterator &RHS) const
friend class AllocaSlices
partition_iterator & operator++()
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
This class represents a conversion between pointers from one address space to another.
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.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
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.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This class represents a no-op cast from one type to another.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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 class represents a function call, abstracting a target machine's calling convention.
ConstantFolder - Create constants with minimum, target independent, folding.
This is the shared class of boolean and integer constants.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
LLVM_ABI DbgInstPtr insertDbgAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *SrcVar, DIExpression *ValExpr, Value *Addr, DIExpression *AddrExpr, const DILocation *DL)
Insert a new llvm.dbg.assign intrinsic call.
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 ...
LLVM_ABI bool extractLeadingOffset(int64_t &OffsetInBytes, SmallVectorImpl< uint64_t > &RemainingOps) const
Assuming that the expression operates on an address, extract a constant offset and the successive ops...
LLVM_ABI std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
bool typeSizeEqualsStoreSize(Type *Ty) const
Returns true if no extra padding bits are needed when storing the specified type.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
DebugLoc getDebugLoc() const
LLVM_ABI void moveBefore(DbgRecord *MoveBefore)
void setDebugLoc(DebugLoc Loc)
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LocationType getType() const
LLVM_ABI bool isKillAddress() const
Check whether this kills the address component.
LLVM_ABI bool isKillLocation() const
Value * getValue(unsigned OpIdx=0) const
LLVM_ABI void setKillLocation()
static LLVM_ABI DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
static LLVM_ABI DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
DIExpression * getExpression() const
LLVM_ABI void setKillAddress()
Kill the address component.
DILocalVariable * getVariable() const
bool isDbgDeclare() const
static LLVM_ABI DbgVariableRecord * createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, DIExpression *Expression, Value *Address, DIExpression *AddressExpression, const DILocation *DI)
DIExpression * getAddressExpression() const
This class is used to track local variable information.
LLVM_ABI DILocation * getInlinedAt() const
Identifies a unique instance of a variable.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
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
Represents flags for the getelementptr instruction/expression.
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.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * getPointerOperand()
iterator_range< op_iterator > indices()
Type * getSourceElementType() const
LLVM_ABI GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
Legacy wrapper pass to provide the GlobalsAAResult object.
This provides the default implementation of the IRBuilder 'InsertHelper' method that is called whenev...
virtual void InsertHelper(Instruction *I, const Twine &Name, BasicBlock::iterator InsertPt) const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setAAMetadata(const AAMDNodes &N)
Sets the AA metadata on this instruction from the AAMDNodes structure.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
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 void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
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.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
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.
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.memcpy/memmove intrinsics.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
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...
Pass interface - Implemented by all 'passes'.
PointerIntPair - This class implements a pair of a pointer and small integer.
void setPointer(PointerTy PtrVal) &
void setInt(IntType IntVal) &
PointerTy getPointer() const
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.
A base class for visitors over the uses of a pointer value.
void visitCallBase(CallBase &CB)
void visitGetElementPtrInst(GetElementPtrInst &GEPI)
void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC)
void visitBitCastInst(BitCastInst &BC)
void visitIntrinsicInst(IntrinsicInst &II)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
SROAPass(SROAOptions PreserveCFG)
If PreserveCFG is set, then the pass is not allowed to modify CFG in any way, even if it would update...
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.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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)
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.
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.
StringRef - Represent a constant reference to a string, i.e.
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.
static constexpr size_t npos
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
element_iterator element_begin() const
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.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
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 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.
LLVM_ABI unsigned getIntegerBitWidth() const
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
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.
user_iterator user_begin()
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.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
iterator_range< user_iterator > users()
static LLVM_ABI void dropDroppableUse(Use &U)
Remove the droppable use U.
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.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
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.
void setAborted(Instruction *I)
Mark the visit as aborted.
void setEscapedAndAborted(Instruction *I)
Mark the pointer as escaped, and the visit as aborted.
void setEscapedReadOnly(Instruction *I)
Mark the pointer as escaped into a readonly-nocapture call.
APInt Offset
The constant offset of the use if that is known.
void enqueueUsers(Value &I)
Enqueue the users of this instruction in the visit worklist.
bool IsOffsetKnown
True if we have a known constant offset for the use currently being visited.
PtrInfo PI
The info collected about the pointer being visited thus far.
Use * U
The use currently being visited.
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()
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.
LLVM_ABI friend const_iterator begin(StringRef path, Style style)
Get begin iterator over path.
LLVM_ABI friend const_iterator end(StringRef path)
Get end iterator over path.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ C
The default llvm calling convention, compatible with C.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
Return a range of dbg_assign records for which Inst performs the assignment they encode.
LLVM_ABI void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_extract_bits_zext
Only used in LLVM metadata.
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
@ DW_OP_LLVM_extract_bits_sext
Only used in LLVM metadata.
NodeAddr< PhiNode * > Phi
LLVM_ABI const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
LLVM_ABI const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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.
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 successors(const MachineBasicBlock *BB)
bool operator!=(uint64_t V1, const APInt &V2)
LLVM_ABI void copyMetadataForLoad(LoadInst &Dest, const LoadInst &Source)
Copy the metadata from the source instruction to the destination (the replacement for the source inst...
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.
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 bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const DataLayout &DL, Instruction *ScanFrom, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)
Return true if we know that executing a load from this value cannot trap.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void initializeSROALegacyPassPass(PassRegistry &)
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.
LLVM_ABI bool isAssignmentTrackingEnabled(const Module &M)
Return true if assignment tracking is enabled for module M.
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.
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 ...
LLVM_ABI FunctionPass * createSROAPass(bool PreserveCFG=true)
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.
Holds functions to get, set or test bitfields.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A CRTP mix-in to automatically provide informational APIs needed for passes.
A MapVector that performs no allocations if smaller than a certain size.