46#include "llvm/Config/llvm-config.h"
101#define DEBUG_TYPE "sroa"
103STATISTIC(NumAllocasAnalyzed,
"Number of allocas analyzed for replacement");
104STATISTIC(NumAllocaPartitions,
"Number of alloca partitions formed");
105STATISTIC(MaxPartitionsPerAlloca,
"Maximum number of partitions per alloca");
106STATISTIC(NumAllocaPartitionUses,
"Number of alloca partition uses rewritten");
107STATISTIC(MaxUsesPerAllocaPartition,
"Maximum number of uses of a partition");
108STATISTIC(NumNewAllocas,
"Number of new, smaller allocas introduced");
109STATISTIC(NumPromoted,
"Number of allocas promoted to SSA values");
110STATISTIC(NumLoadsSpeculated,
"Number of loads speculated to allow promotion");
112 "Number of loads rewritten into predicated loads to allow promotion");
115 "Number of stores rewritten into predicated loads to allow promotion");
117STATISTIC(NumVectorized,
"Number of vectorized aggregates");
124class AllocaSliceRewriter;
128class SelectHandSpeculativity {
129 unsigned char Storage = 0;
133 SelectHandSpeculativity() =
default;
134 SelectHandSpeculativity &setAsSpeculatable(
bool isTrueVal);
135 bool isSpeculatable(
bool isTrueVal)
const;
136 bool areAllSpeculatable()
const;
137 bool areAnySpeculatable()
const;
138 bool areNoneSpeculatable()
const;
140 explicit operator intptr_t()
const {
return static_cast<intptr_t
>(Storage); }
141 explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {}
143static_assert(
sizeof(SelectHandSpeculativity) ==
sizeof(
unsigned char));
145using PossiblySpeculatableLoad =
148using RewriteableMemOp =
149 std::variant<PossiblySpeculatableLoad, UnspeculatableStore>;
201 std::vector<AllocaInst *> PromotableAllocas;
230 static std::optional<RewriteableMemOps>
231 isSafeSelectToSpeculate(
SelectInst &SI,
bool PreserveCFG);
236 :
C(
C), DTU(DTU), AC(AC),
240 std::pair<
bool ,
bool > runSROA(
Function &
F);
243 friend class AllocaSliceRewriter;
245 bool presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS);
247 bool splitAlloca(
AllocaInst &AI, AllocaSlices &AS);
248 std::pair<
bool ,
bool > runOnAlloca(
AllocaInst &AI);
249 void clobberUse(
Use &U);
265enum FragCalcResult { UseFrag, UseNoFrag,
Skip };
269 uint64_t NewStorageSliceOffsetInBits,
271 std::optional<DIExpression::FragmentInfo> StorageFragment,
272 std::optional<DIExpression::FragmentInfo> CurrentFragment,
276 if (StorageFragment) {
278 std::min(NewStorageSliceSizeInBits, StorageFragment->SizeInBits);
280 NewStorageSliceOffsetInBits + StorageFragment->OffsetInBits;
282 Target.SizeInBits = NewStorageSliceSizeInBits;
283 Target.OffsetInBits = NewStorageSliceOffsetInBits;
289 if (!CurrentFragment) {
293 if (
Target == CurrentFragment)
300 if (!CurrentFragment || *CurrentFragment ==
Target)
306 if (
Target.startInBits() < CurrentFragment->startInBits() ||
307 Target.endInBits() > CurrentFragment->endInBits())
357 if (MarkerRange.empty() && DVRAssignMarkerRange.empty())
363 LLVM_DEBUG(
dbgs() <<
" OldAllocaOffsetInBits: " << OldAllocaOffsetInBits
365 LLVM_DEBUG(
dbgs() <<
" SliceSizeInBits: " << SliceSizeInBits <<
"\n");
377 DAI->getExpression()->getFragmentInfo();
380 DVR->getExpression()->getFragmentInfo();
390 auto MigrateDbgAssign = [&](
auto *DbgAssign) {
393 auto *Expr = DbgAssign->getExpression();
394 bool SetKillLocation =
false;
397 std::optional<DIExpression::FragmentInfo> BaseFragment;
400 if (R == BaseFragments.
end())
402 BaseFragment = R->second;
404 std::optional<DIExpression::FragmentInfo> CurrentFragment =
405 Expr->getFragmentInfo();
408 DbgAssign->getVariable(), OldAllocaOffsetInBits, SliceSizeInBits,
409 BaseFragment, CurrentFragment, NewFragment);
413 if (Result == UseFrag && !(NewFragment == CurrentFragment)) {
414 if (CurrentFragment) {
419 NewFragment.
OffsetInBits -= CurrentFragment->OffsetInBits;
430 DIExpression::get(Expr->getContext(), std::nullopt),
432 SetKillLocation =
true;
440 Inst->
setMetadata(LLVMContext::MD_DIAssignID, NewID);
447 DIExpression::get(Expr->getContext(), std::nullopt),
448 DbgAssign->getDebugLoc()),
462 Value && (DbgAssign->hasArgList() ||
463 !DbgAssign->getExpression()->isSingleLocationExpression());
465 NewAssign->setKillLocation();
480 NewAssign->moveBefore(DbgAssign);
482 NewAssign->setDebugLoc(DbgAssign->getDebugLoc());
483 LLVM_DEBUG(
dbgs() <<
"Created new assign: " << *NewAssign <<
"\n");
486 for_each(MarkerRange, MigrateDbgAssign);
487 for_each(DVRAssignMarkerRange, MigrateDbgAssign);
535 : BeginOffset(BeginOffset), EndOffset(EndOffset),
536 UseAndIsSplittable(
U, IsSplittable) {}
538 uint64_t beginOffset()
const {
return BeginOffset; }
539 uint64_t endOffset()
const {
return EndOffset; }
541 bool isSplittable()
const {
return UseAndIsSplittable.
getInt(); }
542 void makeUnsplittable() { UseAndIsSplittable.
setInt(
false); }
544 Use *getUse()
const {
return UseAndIsSplittable.
getPointer(); }
546 bool isDead()
const {
return getUse() ==
nullptr; }
547 void kill() { UseAndIsSplittable.
setPointer(
nullptr); }
556 if (beginOffset() <
RHS.beginOffset())
558 if (beginOffset() >
RHS.beginOffset())
560 if (isSplittable() !=
RHS.isSplittable())
561 return !isSplittable();
562 if (endOffset() >
RHS.endOffset())
570 return LHS.beginOffset() < RHSOffset;
574 return LHSOffset <
RHS.beginOffset();
578 return isSplittable() ==
RHS.isSplittable() &&
579 beginOffset() ==
RHS.beginOffset() && endOffset() ==
RHS.endOffset();
600 bool isEscaped()
const {
return PointerEscapingInstr; }
608 iterator
end() {
return Slices.
end(); }
618 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
626 int OldSize = Slices.size();
627 Slices.append(NewSlices.
begin(), NewSlices.
end());
628 auto SliceI = Slices.begin() + OldSize;
629 std::stable_sort(SliceI, Slices.end());
630 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
635 class partition_iterator;
643 return DeadUseIfPromotable;
654#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
666 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
671#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
725 friend class AllocaSlices;
728 using iterator = AllocaSlices::iterator;
732 uint64_t BeginOffset = 0, EndOffset = 0;
742 Partition(iterator SI) :
SI(
SI), SJ(
SI) {}
748 uint64_t beginOffset()
const {
return BeginOffset; }
753 uint64_t endOffset()
const {
return EndOffset; }
759 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
760 return EndOffset - BeginOffset;
765 bool empty()
const {
return SI == SJ; }
776 iterator
begin()
const {
return SI; }
777 iterator
end()
const {
return SJ; }
809 AllocaSlices::iterator SE;
813 uint64_t MaxSplitSliceEndOffset = 0;
829 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
830 "Cannot advance past the end of the slices!");
833 if (!
P.SplitTails.empty()) {
834 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
836 P.SplitTails.clear();
837 MaxSplitSliceEndOffset = 0;
843 [&](Slice *S) { return S->endOffset() <= P.EndOffset; });
846 return S->endOffset() == MaxSplitSliceEndOffset;
848 "Could not find the current max split slice offset!");
851 return S->endOffset() <= MaxSplitSliceEndOffset;
853 "Max split slice end offset is not actually the max!");
860 assert(
P.SplitTails.empty() &&
"Failed to clear the split slices!");
870 if (S.isSplittable() && S.endOffset() >
P.EndOffset) {
871 P.SplitTails.push_back(&S);
872 MaxSplitSliceEndOffset =
873 std::max(S.endOffset(), MaxSplitSliceEndOffset);
881 P.BeginOffset =
P.EndOffset;
882 P.EndOffset = MaxSplitSliceEndOffset;
889 if (!
P.SplitTails.empty() &&
P.SI->beginOffset() !=
P.EndOffset &&
890 !
P.SI->isSplittable()) {
891 P.BeginOffset =
P.EndOffset;
892 P.EndOffset =
P.SI->beginOffset();
902 P.BeginOffset =
P.SplitTails.empty() ?
P.SI->beginOffset() :
P.EndOffset;
903 P.EndOffset =
P.SI->endOffset();
908 if (!
P.SI->isSplittable()) {
911 assert(
P.BeginOffset ==
P.SI->beginOffset());
915 while (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset) {
916 if (!
P.SJ->isSplittable())
917 P.EndOffset = std::max(
P.EndOffset,
P.SJ->endOffset());
929 assert(
P.SI->isSplittable() &&
"Forming a splittable partition!");
932 while (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset &&
933 P.SJ->isSplittable()) {
934 P.EndOffset = std::max(
P.EndOffset,
P.SJ->endOffset());
941 if (
P.SJ != SE &&
P.SJ->beginOffset() <
P.EndOffset) {
943 P.EndOffset =
P.SJ->beginOffset();
950 "End iterators don't match between compared partition iterators!");
957 if (
P.SI ==
RHS.P.SI &&
P.SplitTails.empty() ==
RHS.P.SplitTails.empty()) {
959 "Same set of slices formed two different sized partitions!");
960 assert(
P.SplitTails.size() ==
RHS.P.SplitTails.size() &&
961 "Same slice position with differently sized non-empty split "
984 return make_range(partition_iterator(begin(), end()),
985 partition_iterator(end(), end()));
992 if (
ConstantInt *CI = dyn_cast<ConstantInt>(SI.getCondition()))
993 return SI.getOperand(1 + CI->isZero());
994 if (SI.getOperand(1) == SI.getOperand(2))
995 return SI.getOperand(1);
1002 if (
PHINode *PN = dyn_cast<PHINode>(&
I)) {
1004 return PN->hasConstantValue();
1031 AllocSize(
DL.getTypeAllocSize(AI.getAllocatedType()).getFixedValue()),
1036 if (VisitedDeadInsts.
insert(&
I).second)
1037 AS.DeadUsers.push_back(&
I);
1041 bool IsSplittable =
false) {
1047 <<
" which has zero size or starts outside of the "
1048 << AllocSize <<
" byte alloca:\n"
1049 <<
" alloca: " << AS.AI <<
"\n"
1050 <<
" use: " <<
I <<
"\n");
1051 return markAsDead(
I);
1063 assert(AllocSize >= BeginOffset);
1064 if (
Size > AllocSize - BeginOffset) {
1066 <<
Offset <<
" to remain within the " << AllocSize
1067 <<
" byte alloca:\n"
1068 <<
" alloca: " << AS.AI <<
"\n"
1069 <<
" use: " <<
I <<
"\n");
1070 EndOffset = AllocSize;
1073 AS.Slices.push_back(Slice(BeginOffset, EndOffset,
U, IsSplittable));
1078 return markAsDead(BC);
1085 return markAsDead(ASC);
1092 return markAsDead(GEPI);
1110 "All simple FCA loads should have been pre-split");
1116 if (
Size.isScalable())
1124 Value *ValOp =
SI.getValueOperand();
1145 <<
Offset <<
" which extends past the end of the "
1146 << AllocSize <<
" byte alloca:\n"
1147 <<
" alloca: " << AS.AI <<
"\n"
1148 <<
" use: " << SI <<
"\n");
1149 return markAsDead(SI);
1153 "All simple FCA stores should have been pre-split");
1158 assert(
II.getRawDest() == *
U &&
"Pointer use is not the destination?");
1163 return markAsDead(
II);
1178 return markAsDead(
II);
1182 if (VisitedDeadInsts.
count(&
II))
1195 MemTransferSliceMap.
find(&
II);
1196 if (MTPI != MemTransferSliceMap.
end())
1197 AS.Slices[MTPI->second].kill();
1198 return markAsDead(
II);
1206 if (*
U ==
II.getRawDest() && *
U ==
II.getRawSource()) {
1208 if (!
II.isVolatile())
1209 return markAsDead(
II);
1218 std::tie(MTPI, Inserted) =
1219 MemTransferSliceMap.
insert(std::make_pair(&
II, AS.Slices.size()));
1220 unsigned PrevIdx = MTPI->second;
1222 Slice &PrevP = AS.Slices[PrevIdx];
1226 if (!
II.isVolatile() && PrevP.beginOffset() == RawOffset) {
1228 return markAsDead(
II);
1233 PrevP.makeUnsplittable();
1240 assert(AS.Slices[PrevIdx].getUse()->getUser() == &
II &&
1241 "Map index doesn't point back to a slice with this user.");
1249 if (
II.isDroppable()) {
1250 AS.DeadUseIfPromotable.push_back(
U);
1257 if (
II.isLifetimeStartOrEnd()) {
1260 Length->getLimitedValue());
1265 if (
II.isLaunderOrStripInvariantGroup()) {
1266 insertUse(
II,
Offset, AllocSize,
true);
1282 Uses.push_back(std::make_pair(cast<Instruction>(*
U), Root));
1289 std::tie(UsedI,
I) =
Uses.pop_back_val();
1291 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
1300 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1314 if (!
GEP->hasAllZeroIndices())
1316 }
else if (!isa<BitCastInst>(
I) && !isa<PHINode>(
I) &&
1317 !isa<SelectInst>(
I) && !isa<AddrSpaceCastInst>(
I)) {
1321 for (
User *
U :
I->users())
1322 if (Visited.
insert(cast<Instruction>(
U)).second)
1323 Uses.push_back(std::make_pair(
I, cast<Instruction>(
U)));
1324 }
while (!
Uses.empty());
1330 assert(isa<PHINode>(
I) || isa<SelectInst>(
I));
1332 return markAsDead(
I);
1337 if (isa<PHINode>(
I) &&
1338 I.getParent()->getFirstInsertionPt() ==
I.getParent()->end())
1357 AS.DeadOperands.push_back(
U);
1380 AS.DeadOperands.push_back(
U);
1387 void visitPHINode(
PHINode &PN) { visitPHINodeOrSelectInst(PN); }
1389 void visitSelectInst(
SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
1397#
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1400 PointerEscapingInstr(nullptr) {
1401 SliceBuilder
PB(
DL, AI, *
this);
1402 SliceBuilder::PtrInfo PtrI =
PB.visitPtr(AI);
1403 if (PtrI.isEscaped() || PtrI.isAborted()) {
1406 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1407 : PtrI.getAbortingInst();
1408 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1412 llvm::erase_if(Slices, [](
const Slice &S) {
return S.isDead(); });
1419#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1423 printSlice(
OS,
I, Indent);
1425 printUse(
OS,
I, Indent);
1430 OS << Indent <<
"[" <<
I->beginOffset() <<
"," <<
I->endOffset() <<
")"
1431 <<
" slice #" << (
I -
begin())
1432 << (
I->isSplittable() ?
" (splittable)" :
"");
1437 OS << Indent <<
" used by: " << *
I->getUse()->getUser() <<
"\n";
1441 if (PointerEscapingInstr) {
1442 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1443 <<
" A pointer to this alloca escaped by:\n"
1444 <<
" " << *PointerEscapingInstr <<
"\n";
1448 OS <<
"Slices of alloca: " << AI <<
"\n";
1462static std::pair<Type *, IntegerType *>
1466 bool TyIsCommon =
true;
1471 for (AllocaSlices::const_iterator
I =
B;
I !=
E; ++
I) {
1472 Use *U =
I->getUse();
1473 if (isa<IntrinsicInst>(*U->getUser()))
1475 if (
I->beginOffset() !=
B->beginOffset() ||
I->endOffset() != EndOffset)
1478 Type *UserTy =
nullptr;
1479 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
1481 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
1482 UserTy = SI->getValueOperand()->getType();
1485 if (
IntegerType *UserITy = dyn_cast_or_null<IntegerType>(UserTy)) {
1490 if (UserITy->getBitWidth() % 8 != 0 ||
1491 UserITy->getBitWidth() / 8 > (EndOffset -
B->beginOffset()))
1496 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1502 if (!UserTy || (Ty && Ty != UserTy))
1508 return {TyIsCommon ? Ty :
nullptr, ITy};
1539 Type *LoadType =
nullptr;
1541 LoadInst *LI = dyn_cast<LoadInst>(U);
1552 if (LoadType != LI->
getType())
1561 if (BBI->mayWriteToMemory())
1564 MaxAlign = std::max(MaxAlign, LI->
getAlign());
1571 APInt(APWidth,
DL.getTypeStoreSize(LoadType).getFixedValue());
1608 IRB.SetInsertPoint(&PN);
1610 PN.
getName() +
".sroa.speculated");
1640 IRB.SetInsertPoint(TI);
1642 LoadInst *Load = IRB.CreateAlignedLoad(
1643 LoadTy, InVal, Alignment,
1645 ++NumLoadsSpeculated;
1647 Load->setAAMetadata(AATags);
1649 InjectedLoads[Pred] = Load;
1656SelectHandSpeculativity &
1657SelectHandSpeculativity::setAsSpeculatable(
bool isTrueVal) {
1659 Bitfield::set<SelectHandSpeculativity::TrueVal>(Storage,
true);
1661 Bitfield::set<SelectHandSpeculativity::FalseVal>(Storage,
true);
1665bool SelectHandSpeculativity::isSpeculatable(
bool isTrueVal)
const {
1666 return isTrueVal ? Bitfield::get<SelectHandSpeculativity::TrueVal>(Storage)
1670bool SelectHandSpeculativity::areAllSpeculatable()
const {
1671 return isSpeculatable(
true) &&
1672 isSpeculatable(
false);
1675bool SelectHandSpeculativity::areAnySpeculatable()
const {
1676 return isSpeculatable(
true) ||
1677 isSpeculatable(
false);
1679bool SelectHandSpeculativity::areNoneSpeculatable()
const {
1680 return !areAnySpeculatable();
1683static SelectHandSpeculativity
1686 SelectHandSpeculativity
Spec;
1689 for (
Value *
Value : {SI.getTrueValue(), SI.getFalseValue()})
1692 Spec.setAsSpeculatable(
Value == SI.getTrueValue());
1699std::optional<RewriteableMemOps>
1701 RewriteableMemOps Ops;
1703 for (
User *U :
SI.users()) {
1704 if (
auto *BC = dyn_cast<BitCastInst>(U); BC && BC->
hasOneUse())
1707 if (
auto *Store = dyn_cast<StoreInst>(U)) {
1713 Ops.emplace_back(Store);
1717 auto *LI = dyn_cast<LoadInst>(U);
1724 PossiblySpeculatableLoad
Load(LI);
1730 Ops.emplace_back(Load);
1734 SelectHandSpeculativity
Spec =
1740 Ops.emplace_back(Load);
1750 Value *TV = SI.getTrueValue();
1751 Value *FV = SI.getFalseValue();
1756 IRB.SetInsertPoint(&LI);
1760 LI.
getName() +
".sroa.speculate.load.true");
1763 LI.
getName() +
".sroa.speculate.load.false");
1764 NumLoadsSpeculated += 2;
1776 Value *V = IRB.CreateSelect(SI.getCondition(), TL, FL,
1777 LI.
getName() +
".sroa.speculated");
1783template <
typename T>
1785 SelectHandSpeculativity
Spec,
1787 assert((isa<LoadInst>(
I) || isa<StoreInst>(
I)) &&
"Only for load and store!");
1792 if (
Spec.areNoneSpeculatable())
1794 SI.getMetadata(LLVMContext::MD_prof), &DTU);
1797 SI.getMetadata(LLVMContext::MD_prof), &DTU,
1799 if (
Spec.isSpeculatable(
true))
1807 if (isa<LoadInst>(
I))
1810 bool IsThen = SuccBB == HeadBI->getSuccessor(0);
1811 int SuccIdx = IsThen ? 0 : 1;
1812 auto *NewMemOpBB = SuccBB ==
Tail ? Head : SuccBB;
1813 auto &CondMemOp = cast<T>(*
I.clone());
1814 if (NewMemOpBB != Head) {
1815 NewMemOpBB->setName(Head->
getName() + (IsThen ?
".then" :
".else"));
1816 if (isa<LoadInst>(
I))
1817 ++NumLoadsPredicated;
1819 ++NumStoresPredicated;
1821 CondMemOp.dropUBImplyingAttrsAndMetadata();
1822 ++NumLoadsSpeculated;
1824 CondMemOp.insertBefore(NewMemOpBB->getTerminator());
1825 Value *
Ptr = SI.getOperand(1 + SuccIdx);
1826 CondMemOp.setOperand(
I.getPointerOperandIndex(),
Ptr);
1827 if (isa<LoadInst>(
I)) {
1828 CondMemOp.setName(
I.getName() + (IsThen ?
".then" :
".else") +
".val");
1833 if (isa<LoadInst>(
I)) {
1836 I.replaceAllUsesWith(PN);
1841 SelectHandSpeculativity
Spec,
1843 if (
auto *LI = dyn_cast<LoadInst>(&
I))
1845 else if (
auto *SI = dyn_cast<StoreInst>(&
I))
1852 const RewriteableMemOps &Ops,
1854 bool CFGChanged =
false;
1857 for (
const RewriteableMemOp &
Op : Ops) {
1858 SelectHandSpeculativity
Spec;
1860 if (
auto *
const *US = std::get_if<UnspeculatableStore>(&
Op)) {
1863 auto PSL = std::get<PossiblySpeculatableLoad>(
Op);
1864 I = PSL.getPointer();
1865 Spec = PSL.getInt();
1867 if (
Spec.areAllSpeculatable()) {
1870 assert(DTU &&
"Should not get here when not allowed to modify the CFG!");
1874 I->eraseFromParent();
1878 cast<BitCastInst>(U)->eraseFromParent();
1879 SI.eraseFromParent();
1887 const Twine &NamePrefix) {
1889 Ptr = IRB.CreateInBoundsPtrAdd(
Ptr, IRB.getInt(
Offset),
1890 NamePrefix +
"sroa_idx");
1891 return IRB.CreatePointerBitCastOrAddrSpaceCast(
Ptr,
PointerTy,
1892 NamePrefix +
"sroa_cast");
1913 if (isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) {
1916 "We can't have the same bitwidth for different int types");
1920 if (
DL.getTypeSizeInBits(NewTy).getFixedValue() !=
1921 DL.getTypeSizeInBits(OldTy).getFixedValue())
1937 return OldAS == NewAS ||
1938 (!
DL.isNonIntegralAddressSpace(OldAS) &&
1939 !
DL.isNonIntegralAddressSpace(NewAS) &&
1940 DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
1946 return !
DL.isNonIntegralPointerType(NewTy);
1950 if (!
DL.isNonIntegralPointerType(OldTy))
1970 Type *OldTy = V->getType();
1976 assert(!(isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) &&
1977 "Integer types must be the exact same to convert.");
1985 return IRB.CreateIntToPtr(IRB.CreateBitCast(V,
DL.getIntPtrType(NewTy)),
1995 return IRB.CreateBitCast(IRB.CreatePtrToInt(V,
DL.getIntPtrType(OldTy)),
2008 if (OldAS != NewAS) {
2009 assert(
DL.getPointerSize(OldAS) ==
DL.getPointerSize(NewAS));
2010 return IRB.CreateIntToPtr(IRB.CreatePtrToInt(V,
DL.getIntPtrType(OldTy)),
2015 return IRB.CreateBitCast(V, NewTy);
2028 std::max(S.beginOffset(),
P.beginOffset()) -
P.beginOffset();
2029 uint64_t BeginIndex = BeginOffset / ElementSize;
2030 if (BeginIndex * ElementSize != BeginOffset ||
2033 uint64_t EndOffset = std::min(S.endOffset(),
P.endOffset()) -
P.beginOffset();
2034 uint64_t EndIndex = EndOffset / ElementSize;
2035 if (EndIndex * ElementSize != EndOffset ||
2039 assert(EndIndex > BeginIndex &&
"Empty vector!");
2040 uint64_t NumElements = EndIndex - BeginIndex;
2041 Type *SliceTy = (NumElements == 1)
2042 ? Ty->getElementType()
2048 Use *U = S.getUse();
2051 if (
MI->isVolatile())
2053 if (!S.isSplittable())
2055 }
else if (
IntrinsicInst *
II = dyn_cast<IntrinsicInst>(U->getUser())) {
2056 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
2058 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2065 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2071 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2072 if (SI->isVolatile())
2074 Type *STy = SI->getValueOperand()->getType();
2078 if (
P.beginOffset() > S.beginOffset() ||
P.endOffset() < S.endOffset()) {
2099 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2103 if (ElementSize % 8)
2105 assert((
DL.getTypeSizeInBits(VTy).getFixedValue() % 8) == 0 &&
2106 "vector size not a multiple of element size?");
2109 for (
const Slice &S :
P)
2113 for (
const Slice *S :
P.splitSliceTails())
2127 bool HaveCommonEltTy,
Type *CommonEltTy,
2128 bool HaveVecPtrTy,
bool HaveCommonVecPtrTy,
2131 if (CandidateTys.
empty())
2138 if (HaveVecPtrTy && !HaveCommonVecPtrTy)
2142 if (!HaveCommonEltTy && HaveVecPtrTy) {
2144 CandidateTys.
clear();
2146 }
else if (!HaveCommonEltTy && !HaveVecPtrTy) {
2149 if (!VTy->getElementType()->isIntegerTy())
2150 VTy = cast<VectorType>(VTy->getWithNewType(IntegerType::getIntNTy(
2151 VTy->getContext(), VTy->getScalarSizeInBits())));
2158 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2159 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2160 "Cannot have vector types of different sizes!");
2161 assert(RHSTy->getElementType()->isIntegerTy() &&
2162 "All non-integer types eliminated!");
2163 assert(LHSTy->getElementType()->isIntegerTy() &&
2164 "All non-integer types eliminated!");
2165 return cast<FixedVectorType>(RHSTy)->getNumElements() <
2166 cast<FixedVectorType>(LHSTy)->getNumElements();
2170 assert(
DL.getTypeSizeInBits(RHSTy).getFixedValue() ==
2171 DL.getTypeSizeInBits(LHSTy).getFixedValue() &&
2172 "Cannot have vector types of different sizes!");
2173 assert(RHSTy->getElementType()->isIntegerTy() &&
2174 "All non-integer types eliminated!");
2175 assert(LHSTy->getElementType()->isIntegerTy() &&
2176 "All non-integer types eliminated!");
2177 return cast<FixedVectorType>(RHSTy)->getNumElements() ==
2178 cast<FixedVectorType>(LHSTy)->getNumElements();
2180 llvm::sort(CandidateTys, RankVectorTypesComp);
2181 CandidateTys.erase(
llvm::unique(CandidateTys, RankVectorTypesEq),
2182 CandidateTys.end());
2188 assert(VTy->getElementType() == CommonEltTy &&
2189 "Unaccounted for element type!");
2190 assert(VTy == CandidateTys[0] &&
2191 "Different vector types with the same element type!");
2194 CandidateTys.resize(1);
2200 return cast<FixedVectorType>(VTy)->getNumElements() >
2201 std::numeric_limits<unsigned short>::max();
2215 bool &HaveCommonEltTy,
Type *&CommonEltTy,
bool &HaveVecPtrTy,
2216 bool &HaveCommonVecPtrTy,
VectorType *&CommonVecPtrTy) {
2218 CandidateTysCopy.
size() ? CandidateTysCopy[0] :
nullptr;
2221 for (
Type *Ty : OtherTys) {
2222 if (!VectorType::isValidElementType(Ty))
2224 unsigned TypeSize =
DL.getTypeSizeInBits(Ty).getFixedValue();
2227 for (
VectorType *
const VTy : CandidateTysCopy) {
2229 assert(CandidateTysCopy[0] == OriginalElt &&
"Different Element");
2230 unsigned VectorSize =
DL.getTypeSizeInBits(VTy).getFixedValue();
2231 unsigned ElementSize =
2232 DL.getTypeSizeInBits(VTy->getElementType()).getFixedValue();
2236 CheckCandidateType(NewVTy);
2242 CommonEltTy, HaveVecPtrTy,
2243 HaveCommonVecPtrTy, CommonVecPtrTy);
2261 Type *CommonEltTy =
nullptr;
2263 bool HaveVecPtrTy =
false;
2264 bool HaveCommonEltTy =
true;
2265 bool HaveCommonVecPtrTy =
true;
2266 auto CheckCandidateType = [&](
Type *Ty) {
2267 if (
auto *VTy = dyn_cast<VectorType>(Ty)) {
2269 if (!CandidateTys.
empty()) {
2271 if (
DL.getTypeSizeInBits(VTy).getFixedValue() !=
2272 DL.getTypeSizeInBits(V).getFixedValue()) {
2273 CandidateTys.
clear();
2278 Type *EltTy = VTy->getElementType();
2281 CommonEltTy = EltTy;
2282 else if (CommonEltTy != EltTy)
2283 HaveCommonEltTy =
false;
2286 HaveVecPtrTy =
true;
2287 if (!CommonVecPtrTy)
2288 CommonVecPtrTy = VTy;
2289 else if (CommonVecPtrTy != VTy)
2290 HaveCommonVecPtrTy =
false;
2296 for (
const Slice &S :
P) {
2298 if (
auto *LI = dyn_cast<LoadInst>(S.getUse()->getUser()))
2300 else if (
auto *SI = dyn_cast<StoreInst>(S.getUse()->getUser()))
2301 Ty = SI->getValueOperand()->getType();
2306 if (CandTy->isPointerTy() && (S.beginOffset() !=
P.beginOffset() ||
2307 S.endOffset() !=
P.endOffset())) {
2314 if (S.beginOffset() ==
P.beginOffset() && S.endOffset() ==
P.endOffset())
2315 CheckCandidateType(Ty);
2320 LoadStoreTys, CandidateTysCopy, CheckCandidateType,
P,
DL,
2321 CandidateTys, HaveCommonEltTy, CommonEltTy, HaveVecPtrTy,
2322 HaveCommonVecPtrTy, CommonVecPtrTy))
2325 CandidateTys.
clear();
2327 DeferredTys, CandidateTysCopy, CheckCandidateType,
P,
DL, CandidateTys,
2328 HaveCommonEltTy, CommonEltTy, HaveVecPtrTy, HaveCommonVecPtrTy,
2340 bool &WholeAllocaOp) {
2343 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2344 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2346 Use *U = S.getUse();
2353 if (
II->isLifetimeStartOrEnd() ||
II->isDroppable())
2362 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2366 if (
DL.getTypeStoreSize(LI->
getType()).getFixedValue() >
Size)
2370 if (S.beginOffset() < AllocBeginOffset)
2375 if (!isa<VectorType>(LI->
getType()) && RelBegin == 0 && RelEnd ==
Size)
2376 WholeAllocaOp =
true;
2378 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2380 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2386 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2387 Type *ValueTy = SI->getValueOperand()->getType();
2388 if (SI->isVolatile())
2391 if (
DL.getTypeStoreSize(ValueTy).getFixedValue() >
Size)
2395 if (S.beginOffset() < AllocBeginOffset)
2400 if (!isa<VectorType>(ValueTy) && RelBegin == 0 && RelEnd ==
Size)
2401 WholeAllocaOp =
true;
2402 if (
IntegerType *ITy = dyn_cast<IntegerType>(ValueTy)) {
2403 if (ITy->getBitWidth() <
DL.getTypeStoreSizeInBits(ITy).getFixedValue())
2405 }
else if (RelBegin != 0 || RelEnd !=
Size ||
2411 }
else if (
MemIntrinsic *
MI = dyn_cast<MemIntrinsic>(U->getUser())) {
2412 if (
MI->isVolatile() || !isa<Constant>(
MI->getLength()))
2414 if (!S.isSplittable())
2431 uint64_t SizeInBits =
DL.getTypeSizeInBits(AllocaTy).getFixedValue();
2437 if (SizeInBits !=
DL.getTypeStoreSizeInBits(AllocaTy).getFixedValue())
2455 bool WholeAllocaOp =
P.empty() &&
DL.isLegalInteger(SizeInBits);
2457 for (
const Slice &S :
P)
2462 for (
const Slice *S :
P.splitSliceTails())
2467 return WholeAllocaOp;
2474 IntegerType *IntTy = cast<IntegerType>(V->getType());
2476 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2477 "Element extends past full value");
2479 if (
DL.isBigEndian())
2480 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2481 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2483 V = IRB.CreateLShr(V, ShAmt,
Name +
".shift");
2487 "Cannot extract to a larger integer!");
2489 V = IRB.CreateTrunc(V, Ty,
Name +
".trunc");
2498 IntegerType *Ty = cast<IntegerType>(V->getType());
2500 "Cannot insert a larger integer!");
2503 V = IRB.CreateZExt(V, IntTy,
Name +
".ext");
2507 DL.getTypeStoreSize(IntTy).getFixedValue() &&
2508 "Element store outside of alloca store");
2510 if (
DL.isBigEndian())
2511 ShAmt = 8 * (
DL.getTypeStoreSize(IntTy).getFixedValue() -
2512 DL.getTypeStoreSize(Ty).getFixedValue() -
Offset);
2514 V = IRB.CreateShl(V, ShAmt,
Name +
".shift");
2520 Old = IRB.CreateAnd(Old, Mask,
Name +
".mask");
2522 V = IRB.CreateOr(Old, V,
Name +
".insert");
2530 auto *VecTy = cast<FixedVectorType>(V->getType());
2531 unsigned NumElements = EndIndex - BeginIndex;
2534 if (NumElements == VecTy->getNumElements())
2537 if (NumElements == 1) {
2538 V = IRB.CreateExtractElement(V, IRB.getInt32(BeginIndex),
2544 auto Mask = llvm::to_vector<8>(llvm::seq<int>(BeginIndex, EndIndex));
2545 V = IRB.CreateShuffleVector(V, Mask,
Name +
".extract");
2551 unsigned BeginIndex,
const Twine &
Name) {
2553 assert(VecTy &&
"Can only insert a vector into a vector");
2555 VectorType *Ty = dyn_cast<VectorType>(V->getType());
2558 V = IRB.CreateInsertElement(Old, V, IRB.getInt32(BeginIndex),
2566 "Too many elements!");
2569 assert(V->getType() == VecTy &&
"Vector type mismatch");
2572 unsigned EndIndex = BeginIndex + cast<FixedVectorType>(Ty)->getNumElements();
2580 for (
unsigned i = 0; i != cast<FixedVectorType>(VecTy)->getNumElements(); ++i)
2581 if (i >= BeginIndex && i < EndIndex)
2582 Mask.push_back(i - BeginIndex);
2585 V = IRB.CreateShuffleVector(V, Mask,
Name +
".expand");
2590 for (
unsigned i = 0; i != cast<FixedVectorType>(VecTy)->getNumElements(); ++i)
2591 Mask2.
push_back(IRB.getInt1(i >= BeginIndex && i < EndIndex));
2607class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2617 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2646 uint64_t NewBeginOffset = 0, NewEndOffset = 0;
2649 bool IsSplittable =
false;
2650 bool IsSplit =
false;
2651 Use *OldUse =
nullptr;
2664 Value *getPtrToNewAI(
unsigned AddrSpace,
bool IsVolatile) {
2668 Type *AccessTy = IRB.getPtrTy(AddrSpace);
2669 return IRB.CreateAddrSpaceCast(&NewAI, AccessTy);
2676 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2680 :
DL(
DL), AS(AS),
Pass(
Pass), OldAI(OldAI), NewAI(NewAI),
2681 NewAllocaBeginOffset(NewAllocaBeginOffset),
2682 NewAllocaEndOffset(NewAllocaEndOffset),
2683 NewAllocaTy(NewAI.getAllocatedType()),
2686 ?
Type::getIntNTy(NewAI.getContext(),
2687 DL.getTypeSizeInBits(NewAI.getAllocatedType())
2690 VecTy(PromotableVecTy),
2691 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2692 ElementSize(VecTy ?
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8
2694 PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2697 assert((
DL.getTypeSizeInBits(ElementTy).getFixedValue() % 8) == 0 &&
2698 "Only multiple-of-8 sized vector elements are viable");
2701 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2704 bool visit(AllocaSlices::const_iterator
I) {
2705 bool CanSROA =
true;
2706 BeginOffset =
I->beginOffset();
2707 EndOffset =
I->endOffset();
2708 IsSplittable =
I->isSplittable();
2710 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2711 LLVM_DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2716 assert(BeginOffset < NewAllocaEndOffset);
2717 assert(EndOffset > NewAllocaBeginOffset);
2718 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2719 NewEndOffset = std::min(EndOffset, NewAllocaEndOffset);
2721 SliceSize = NewEndOffset - NewBeginOffset;
2722 LLVM_DEBUG(
dbgs() <<
" Begin:(" << BeginOffset <<
", " << EndOffset
2723 <<
") NewBegin:(" << NewBeginOffset <<
", "
2724 << NewEndOffset <<
") NewAllocaBegin:("
2725 << NewAllocaBeginOffset <<
", " << NewAllocaEndOffset
2727 assert(IsSplit || NewBeginOffset == BeginOffset);
2728 OldUse =
I->getUse();
2729 OldPtr = cast<Instruction>(OldUse->get());
2731 Instruction *OldUserI = cast<Instruction>(OldUse->getUser());
2732 IRB.SetInsertPoint(OldUserI);
2733 IRB.SetCurrentDebugLocation(OldUserI->
getDebugLoc());
2734 IRB.getInserter().SetNamePrefix(
Twine(NewAI.
getName()) +
"." +
2735 Twine(BeginOffset) +
".");
2737 CanSROA &= visit(cast<Instruction>(OldUse->getUser()));
2756 assert(IsSplit || BeginOffset == NewBeginOffset);
2762 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
2764 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
2769 OldName = OldName.
substr(IndexEnd + 1);
2773 OldName = OldName.
substr(OffsetEnd + 1);
2777 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
2784 Twine(OldName) +
"."
2796 Align getSliceAlign() {
2798 NewBeginOffset - NewAllocaBeginOffset);
2802 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
2804 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
2810 void deleteIfTriviallyDead(
Value *V) {
2813 Pass.DeadInsts.push_back(
I);
2817 unsigned BeginIndex = getIndex(NewBeginOffset);
2818 unsigned EndIndex = getIndex(NewEndOffset);
2819 assert(EndIndex > BeginIndex &&
"Empty vector!");
2824 Load->copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
2825 LLVMContext::MD_access_group});
2826 return extractVector(IRB, Load, BeginIndex, EndIndex,
"vec");
2830 assert(IntTy &&
"We cannot insert an integer to the alloca");
2835 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
2837 if (
Offset > 0 || NewEndOffset < NewAllocaEndOffset) {
2846 assert(cast<IntegerType>(LI.
getType())->getBitWidth() >= SliceSize * 8 &&
2847 "Can only handle an extract for an overly wide load");
2848 if (cast<IntegerType>(LI.
getType())->getBitWidth() > SliceSize * 8)
2849 V = IRB.CreateZExt(V, LI.
getType());
2864 const bool IsLoadPastEnd =
2865 DL.getTypeStoreSize(TargetTy).getFixedValue() > SliceSize;
2866 bool IsPtrAdjusted =
false;
2869 V = rewriteVectorizedLoadInst(LI);
2871 V = rewriteIntegerLoad(LI);
2872 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
2873 NewEndOffset == NewAllocaEndOffset &&
2895 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
2903 if (
auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
2904 if (
auto *TITy = dyn_cast<IntegerType>(TargetTy))
2905 if (AITy->getBitWidth() < TITy->getBitWidth()) {
2906 V = IRB.CreateZExt(V, TITy,
"load.ext");
2907 if (
DL.isBigEndian())
2908 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
2912 Type *LTy = IRB.getPtrTy(AS);
2914 IRB.CreateAlignedLoad(TargetTy, getNewAllocaSlicePtr(IRB, LTy),
2919 NewBeginOffset - BeginOffset, NewLI->
getType(),
DL));
2923 NewLI->
copyMetadata(LI, {LLVMContext::MD_mem_parallel_loop_access,
2924 LLVMContext::MD_access_group});
2927 IsPtrAdjusted =
true;
2934 "Only integer type loads and stores are split");
2935 assert(SliceSize <
DL.getTypeStoreSize(LI.
getType()).getFixedValue() &&
2936 "Split load isn't smaller than original load");
2938 "Non-byte-multiple bit width");
2944 LIIt.setHeadBit(
true);
2945 IRB.SetInsertPoint(LI.
getParent(), LIIt);
2950 Value *Placeholder =
2956 Placeholder->replaceAllUsesWith(&LI);
2957 Placeholder->deleteValue();
2962 Pass.DeadInsts.push_back(&LI);
2963 deleteIfTriviallyDead(OldOp);
2973 if (
V->getType() != VecTy) {
2974 unsigned BeginIndex = getIndex(NewBeginOffset);
2975 unsigned EndIndex = getIndex(NewEndOffset);
2976 assert(EndIndex > BeginIndex &&
"Empty vector!");
2977 unsigned NumElements = EndIndex - BeginIndex;
2979 "Too many elements!");
2980 Type *SliceTy = (NumElements == 1)
2983 if (
V->getType() != SliceTy)
2992 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
2993 LLVMContext::MD_access_group});
2997 Pass.DeadInsts.push_back(&SI);
3001 Store,
Store->getPointerOperand(), OrigV,
DL);
3007 assert(IntTy &&
"We cannot extract an integer from the alloca");
3009 if (
DL.getTypeSizeInBits(
V->getType()).getFixedValue() !=
3014 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
3020 Store->copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3021 LLVMContext::MD_access_group});
3027 Store,
Store->getPointerOperand(),
3028 Store->getValueOperand(),
DL);
3030 Pass.DeadInsts.push_back(&SI);
3037 Value *OldOp =
SI.getOperand(1);
3045 if (
V->getType()->isPointerTy())
3046 if (
AllocaInst *AI = dyn_cast<AllocaInst>(
V->stripInBoundsOffsets()))
3047 Pass.PostPromotionWorklist.insert(AI);
3049 if (SliceSize <
DL.getTypeStoreSize(
V->getType()).getFixedValue()) {
3051 assert(
V->getType()->isIntegerTy() &&
3052 "Only integer type loads and stores are split");
3053 assert(
DL.typeSizeEqualsStoreSize(
V->getType()) &&
3054 "Non-byte-multiple bit width");
3061 return rewriteVectorizedStoreInst(V, SI, OldOp, AATags);
3062 if (IntTy &&
V->getType()->isIntegerTy())
3063 return rewriteIntegerStore(V, SI, AATags);
3066 if (NewBeginOffset == NewAllocaBeginOffset &&
3067 NewEndOffset == NewAllocaEndOffset &&
3071 getPtrToNewAI(
SI.getPointerAddressSpace(),
SI.isVolatile());
3074 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
SI.isVolatile());
3076 unsigned AS =
SI.getPointerAddressSpace();
3077 Value *NewPtr = getNewAllocaSlicePtr(IRB, IRB.getPtrTy(AS));
3079 IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(),
SI.isVolatile());
3081 NewSI->
copyMetadata(SI, {LLVMContext::MD_mem_parallel_loop_access,
3082 LLVMContext::MD_access_group});
3086 if (
SI.isVolatile())
3095 Pass.DeadInsts.push_back(&SI);
3096 deleteIfTriviallyDead(OldOp);
3114 assert(
Size > 0 &&
"Expected a positive number of bytes.");
3122 IRB.CreateZExt(V, SplatIntTy,
"zext"),
3132 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
3145 if (!isa<ConstantInt>(
II.getLength())) {
3147 assert(NewBeginOffset == BeginOffset);
3148 II.setDest(getNewAllocaSlicePtr(IRB, OldPtr->
getType()));
3149 II.setDestAlignment(getSliceAlign());
3155 "AT: Unexpected link to non-const GEP");
3156 deleteIfTriviallyDead(OldPtr);
3161 Pass.DeadInsts.push_back(&
II);
3166 const bool CanContinue = [&]() {
3169 if (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset)
3172 auto *
C = cast<ConstantInt>(
II.getLength());
3174 if (Len > std::numeric_limits<unsigned>::max())
3176 auto *Int8Ty = IntegerType::getInt8Ty(NewAI.
getContext());
3179 DL.isLegalInteger(
DL.getTypeSizeInBits(ScalarTy).getFixedValue());
3185 Type *SizeTy =
II.getLength()->getType();
3186 unsigned Sz = NewEndOffset - NewBeginOffset;
3189 getNewAllocaSlicePtr(IRB, OldPtr->
getType()),
II.getValue(),
Size,
3196 New,
New->getRawDest(),
nullptr,
DL);
3211 assert(ElementTy == ScalarTy);
3213 unsigned BeginIndex = getIndex(NewBeginOffset);
3214 unsigned EndIndex = getIndex(NewEndOffset);
3215 assert(EndIndex > BeginIndex &&
"Empty vector!");
3216 unsigned NumElements = EndIndex - BeginIndex;
3218 "Too many elements!");
3221 II.getValue(),
DL.getTypeSizeInBits(ElementTy).getFixedValue() / 8);
3223 if (NumElements > 1)
3235 V = getIntegerSplat(
II.getValue(),
Size);
3237 if (IntTy && (BeginOffset != NewAllocaBeginOffset ||
3238 EndOffset != NewAllocaBeginOffset)) {
3245 assert(
V->getType() == IntTy &&
3246 "Wrong type for an alloca wide integer!");
3251 assert(NewBeginOffset == NewAllocaBeginOffset);
3252 assert(NewEndOffset == NewAllocaEndOffset);
3254 V = getIntegerSplat(
II.getValue(),
3255 DL.getTypeSizeInBits(ScalarTy).getFixedValue() / 8);
3256 if (
VectorType *AllocaVecTy = dyn_cast<VectorType>(AllocaTy))
3263 Value *NewPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3265 IRB.CreateAlignedStore(V, NewPtr, NewAI.
getAlign(),
II.isVolatile());
3266 New->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3267 LLVMContext::MD_access_group});
3273 New,
New->getPointerOperand(), V,
DL);
3276 return !
II.isVolatile();
3287 bool IsDest = &
II.getRawDestUse() == OldUse;
3288 assert((IsDest &&
II.getRawDest() == OldPtr) ||
3289 (!IsDest &&
II.getRawSource() == OldPtr));
3291 Align SliceAlign = getSliceAlign();
3299 if (!IsSplittable) {
3300 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3303 auto UpdateAssignAddress = [&](
auto *DbgAssign) {
3305 DbgAssign->getAddress() ==
II.getDest())
3306 DbgAssign->replaceVariableLocationOp(
II.getDest(), AdjustedPtr);
3310 II.setDest(AdjustedPtr);
3311 II.setDestAlignment(SliceAlign);
3313 II.setSource(AdjustedPtr);
3314 II.setSourceAlignment(SliceAlign);
3318 deleteIfTriviallyDead(OldPtr);
3331 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
3340 if (EmitMemCpy && &OldAI == &NewAI) {
3342 assert(NewBeginOffset == BeginOffset);
3345 if (NewEndOffset != EndOffset)
3346 II.setLength(ConstantInt::get(
II.getLength()->getType(),
3347 NewEndOffset - NewBeginOffset));
3351 Pass.DeadInsts.push_back(&
II);
3355 Value *OtherPtr = IsDest ?
II.getRawSource() :
II.getRawDest();
3358 assert(AI != &OldAI && AI != &NewAI &&
3359 "Splittable transfers cannot reach the same alloca on both ends.");
3360 Pass.Worklist.insert(AI);
3367 unsigned OffsetWidth =
DL.getIndexSizeInBits(OtherAS);
3368 APInt OtherOffset(OffsetWidth, NewBeginOffset - BeginOffset);
3370 (IsDest ?
II.getSourceAlign() :
II.getDestAlign()).valueOrOne();
3372 commonAlignment(OtherAlign, OtherOffset.zextOrTrunc(64).getZExtValue());
3380 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3381 Type *SizeTy =
II.getLength()->getType();
3382 Constant *
Size = ConstantInt::get(SizeTy, NewEndOffset - NewBeginOffset);
3384 Value *DestPtr, *SrcPtr;
3389 DestAlign = SliceAlign;
3391 SrcAlign = OtherAlign;
3394 DestAlign = OtherAlign;
3396 SrcAlign = SliceAlign;
3398 CallInst *
New = IRB.CreateMemCpy(DestPtr, DestAlign, SrcPtr, SrcAlign,
3401 New->setAAMetadata(AATags.
shift(NewBeginOffset - BeginOffset));
3406 &
II, New, DestPtr,
nullptr,
DL);
3411 SliceSize * 8, &
II, New, DestPtr,
nullptr,
DL);
3417 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
3418 NewEndOffset == NewAllocaEndOffset;
3420 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
3421 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
3422 unsigned NumElements = EndIndex - BeginIndex;
3429 if (VecTy && !IsWholeAlloca) {
3430 if (NumElements == 1)
3431 OtherTy = VecTy->getElementType();
3434 }
else if (IntTy && !IsWholeAlloca) {
3437 OtherTy = NewAllocaTy;
3451 DstPtr = getPtrToNewAI(
II.getDestAddressSpace(),
II.isVolatile());
3455 SrcPtr = getPtrToNewAI(
II.getSourceAddressSpace(),
II.isVolatile());
3459 if (VecTy && !IsWholeAlloca && !IsDest) {
3463 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
3470 LoadInst *
Load = IRB.CreateAlignedLoad(OtherTy, SrcPtr, SrcAlign,
3471 II.isVolatile(),
"copyload");
3472 Load->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3473 LLVMContext::MD_access_group});
3480 if (VecTy && !IsWholeAlloca && IsDest) {
3484 }
else if (IntTy && !IsWholeAlloca && IsDest) {
3494 IRB.CreateAlignedStore(Src, DstPtr, DstAlign,
II.isVolatile()));
3495 Store->copyMetadata(
II, {LLVMContext::MD_mem_parallel_loop_access,
3496 LLVMContext::MD_access_group});
3499 Src->getType(),
DL));
3505 Store, DstPtr, Src,
DL);
3510 &
II, Store, DstPtr, Src,
DL);
3514 return !
II.isVolatile();
3518 assert((
II.isLifetimeStartOrEnd() ||
II.isLaunderOrStripInvariantGroup() ||
3519 II.isDroppable()) &&
3520 "Unexpected intrinsic!");
3524 Pass.DeadInsts.push_back(&
II);
3526 if (
II.isDroppable()) {
3527 assert(
II.getIntrinsicID() == Intrinsic::assume &&
"Expected assume");
3533 if (
II.isLaunderOrStripInvariantGroup())
3536 assert(
II.getArgOperand(1) == OldPtr);
3544 if (NewBeginOffset != NewAllocaBeginOffset ||
3545 NewEndOffset != NewAllocaEndOffset)
3549 ConstantInt::get(cast<IntegerType>(
II.getArgOperand(0)->getType()),
3550 NewEndOffset - NewBeginOffset);
3556 if (
II.getIntrinsicID() == Intrinsic::lifetime_start)
3574 Uses.push_back(&Root);
3578 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
3582 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
3583 SI->setAlignment(std::min(
SI->getAlign(), getSliceAlign()));
3587 assert(isa<BitCastInst>(
I) || isa<AddrSpaceCastInst>(
I) ||
3588 isa<PHINode>(
I) || isa<SelectInst>(
I) ||
3589 isa<GetElementPtrInst>(
I));
3590 for (
User *U :
I->users())
3591 if (Visited.
insert(cast<Instruction>(U)).second)
3592 Uses.push_back(cast<Instruction>(U));
3593 }
while (!
Uses.empty());
3596 bool visitPHINode(
PHINode &PN) {
3598 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
3599 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
3606 if (isa<PHINode>(OldPtr))
3608 OldPtr->
getParent()->getFirstInsertionPt());
3610 IRB.SetInsertPoint(OldPtr);
3611 IRB.SetCurrentDebugLocation(OldPtr->
getDebugLoc());
3613 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3615 std::replace(PN.
op_begin(), PN.
op_end(), cast<Value>(OldPtr), NewPtr);
3618 deleteIfTriviallyDead(OldPtr);
3621 fixLoadStoreAlign(PN);
3632 assert((
SI.getTrueValue() == OldPtr ||
SI.getFalseValue() == OldPtr) &&
3633 "Pointer isn't an operand!");
3634 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
3635 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
3637 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->
getType());
3639 if (
SI.getOperand(1) == OldPtr)
3640 SI.setOperand(1, NewPtr);
3641 if (
SI.getOperand(2) == OldPtr)
3642 SI.setOperand(2, NewPtr);
3645 deleteIfTriviallyDead(OldPtr);
3648 fixLoadStoreAlign(SI);
3663class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
3683 AggLoadStoreRewriter(
const DataLayout &
DL, IRBuilderTy &IRB)
3684 :
DL(
DL), IRB(IRB) {}
3691 bool Changed =
false;
3692 while (!
Queue.empty()) {
3693 U =
Queue.pop_back_val();
3694 Changed |= visit(cast<Instruction>(
U->getUser()));
3703 for (
Use &U :
I.uses())
3704 if (Visited.
insert(
U.getUser()).second)
3705 Queue.push_back(&U);
3709 bool visitInstruction(
Instruction &
I) {
return false; }
3712 template <
typename Derived>
class OpSplitter {
3744 BaseAlign(BaseAlign),
DL(
DL) {
3745 IRB.SetInsertPoint(InsertionPoint);
3765 return static_cast<Derived *
>(
this)->emitFunc(
3769 if (
ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
3770 unsigned OldSize = Indices.
size();
3772 for (
unsigned Idx = 0,
Size = ATy->getNumElements();
Idx !=
Size;
3774 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
3777 emitSplitOps(ATy->getElementType(), Agg,
Name +
"." +
Twine(
Idx));
3784 if (
StructType *STy = dyn_cast<StructType>(Ty)) {
3785 unsigned OldSize = Indices.
size();
3787 for (
unsigned Idx = 0,
Size = STy->getNumElements();
Idx !=
Size;
3789 assert(Indices.
size() == OldSize &&
"Did not return to the old size");
3803 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
3809 : OpSplitter<LoadOpSplitter>(InsertionPoint,
Ptr,
BaseTy, BaseAlign,
DL,
3819 IRB.CreateInBoundsGEP(
BaseTy,
Ptr, GEPIndices,
Name +
".gep");
3821 IRB.CreateAlignedLoad(Ty,
GEP, Alignment,
Name +
".load");
3824 DL.getIndexSizeInBits(
Ptr->getType()->getPointerAddressSpace()), 0);
3827 Load->setAAMetadata(
3830 Agg = IRB.CreateInsertValue(Agg, Load, Indices,
Name +
".insert");
3852 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
3856 : OpSplitter<StoreOpSplitter>(InsertionPoint,
Ptr,
BaseTy, BaseAlign,
3858 AATags(AATags), AggStore(AggStore) {}
3869 Value *ExtractValue =
3870 IRB.CreateExtractValue(Agg, Indices,
Name +
".extract");
3871 Value *InBoundsGEP =
3872 IRB.CreateInBoundsGEP(
BaseTy,
Ptr, GEPIndices,
Name +
".gep");
3874 IRB.CreateAlignedStore(ExtractValue, InBoundsGEP, Alignment);
3877 DL.getIndexSizeInBits(
Ptr->getType()->getPointerAddressSpace()), 0);
3889 if (
auto *OldAI = dyn_cast<AllocaInst>(
Base)) {
3891 DL.getTypeSizeInBits(
Store->getValueOperand()->getType());
3893 SizeInBits, AggStore, Store,
3894 Store->getPointerOperand(),
Store->getValueOperand(),
3899 "AT: unexpected debug.assign linked to store through "
3907 if (!
SI.isSimple() ||
SI.getPointerOperand() != *U)
3910 if (
V->getType()->isSingleValueType())
3915 StoreOpSplitter Splitter(&SI, *U,
V->getType(),
SI.getAAMetadata(), &SI,
3917 Splitter.emitSplitOps(
V->getType(), V,
V->getName() +
".fca");
3922 SI.eraseFromParent();
3945 if (
auto *SI = dyn_cast<SelectInst>(
Op)) {
3956 if (!isa<ConstantInt>(
Op))
3964 dbgs() <<
" original: " << *Sel <<
"\n";
3965 dbgs() <<
" " << GEPI <<
"\n";);
3967 auto GetNewOps = [&](
Value *SelOp) {
3977 Value *True = Sel->getTrueValue();
3978 Value *False = Sel->getFalseValue();
3982 IRB.SetInsertPoint(&GEPI);
3986 Value *NTrue = IRB.CreateGEP(Ty, TrueOps[0],
ArrayRef(TrueOps).drop_front(),
3987 True->
getName() +
".sroa.gep", NW);
3990 IRB.CreateGEP(Ty, FalseOps[0],
ArrayRef(FalseOps).drop_front(),
3991 False->
getName() +
".sroa.gep", NW);
3993 Value *NSel = IRB.CreateSelect(Sel->getCondition(), NTrue, NFalse,
3994 Sel->getName() +
".sroa.sel");
3995 Visited.
erase(&GEPI);
4000 enqueueUsers(*NSelI);
4003 dbgs() <<
" " << *NFalse <<
"\n";
4004 dbgs() <<
" " << *NSel <<
"\n";);
4018 auto IsInvalidPointerOperand = [](
Value *
V) {
4019 if (!isa<Instruction>(V))
4021 if (
auto *AI = dyn_cast<AllocaInst>(V))
4022 return !AI->isStaticAlloca();
4026 if (
any_of(
Phi->operands(), IsInvalidPointerOperand))
4035 if (
auto *SI = dyn_cast<PHINode>(
Op)) {
4041 [](
Value *V) { return isa<ConstantInt>(V); }))
4046 if (!isa<ConstantInt>(
Op))
4054 dbgs() <<
" original: " << *
Phi <<
"\n";
4055 dbgs() <<
" " << GEPI <<
"\n";);
4057 auto GetNewOps = [&](
Value *PhiOp) {
4067 IRB.SetInsertPoint(Phi);
4069 Phi->getName() +
".sroa.phi");
4075 for (
unsigned I = 0,
E =
Phi->getNumIncomingValues();
I !=
E; ++
I) {
4084 IRB.CreateGEP(SourceTy, NewOps[0],
ArrayRef(NewOps).drop_front(),
4090 Visited.
erase(&GEPI);
4094 enqueueUsers(*NewPhi);
4100 dbgs() <<
"\n " << *NewPhi <<
'\n');
4106 if (unfoldGEPSelect(GEPI))
4109 if (unfoldGEPPhi(GEPI))
4116 bool visitPHINode(
PHINode &PN) {
4138 uint64_t AllocSize =
DL.getTypeAllocSize(Ty).getFixedValue();
4142 if (
ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
4143 InnerTy = ArrTy->getElementType();
4144 }
else if (
StructType *STy = dyn_cast<StructType>(Ty)) {
4147 InnerTy = STy->getElementType(
Index);
4152 if (AllocSize >
DL.getTypeAllocSize(InnerTy).getFixedValue() ||
4153 TypeSize >
DL.getTypeSizeInBits(InnerTy).getFixedValue())
4174 if (
Offset == 0 &&
DL.getTypeAllocSize(Ty).getFixedValue() ==
Size)
4176 if (
Offset >
DL.getTypeAllocSize(Ty).getFixedValue() ||
4177 (
DL.getTypeAllocSize(Ty).getFixedValue() -
Offset) <
Size)
4180 if (isa<ArrayType>(Ty) || isa<VectorType>(Ty)) {
4183 if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
4184 ElementTy = AT->getElementType();
4185 TyNumElements = AT->getNumElements();
4189 auto *VT = cast<FixedVectorType>(Ty);
4190 ElementTy = VT->getElementType();
4191 TyNumElements = VT->getNumElements();
4193 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4195 if (NumSkippedElements >= TyNumElements)
4197 Offset -= NumSkippedElements * ElementSize;
4209 if (
Size == ElementSize)
4213 if (NumElements * ElementSize !=
Size)
4215 return ArrayType::get(ElementTy, NumElements);
4237 uint64_t ElementSize =
DL.getTypeAllocSize(ElementTy).getFixedValue();
4238 if (
Offset >= ElementSize)
4249 if (
Size == ElementSize)
4256 if (
Index == EndIndex)
4305bool SROA::presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS) {
4319 struct SplitOffsets {
4321 std::vector<uint64_t> Splits;
4338 LLVM_DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
4339 for (
auto &
P : AS.partitions()) {
4340 for (Slice &S :
P) {
4341 Instruction *
I = cast<Instruction>(S.getUse()->getUser());
4342 if (!S.isSplittable() || S.endOffset() <=
P.endOffset()) {
4346 if (
auto *LI = dyn_cast<LoadInst>(
I))
4347 UnsplittableLoads.
insert(LI);
4348 else if (
auto *SI = dyn_cast<StoreInst>(
I))
4349 if (
auto *LI = dyn_cast<LoadInst>(
SI->getValueOperand()))
4350 UnsplittableLoads.
insert(LI);
4353 assert(
P.endOffset() > S.beginOffset() &&
4354 "Empty or backwards partition!");
4357 if (
auto *LI = dyn_cast<LoadInst>(
I)) {
4363 auto IsLoadSimplyStored = [](
LoadInst *LI) {
4365 auto *
SI = dyn_cast<StoreInst>(LU);
4366 if (!SI || !
SI->isSimple())
4371 if (!IsLoadSimplyStored(LI)) {
4372 UnsplittableLoads.
insert(LI);
4377 }
else if (
auto *SI = dyn_cast<StoreInst>(
I)) {
4378 if (S.getUse() != &
SI->getOperandUse(
SI->getPointerOperandIndex()))
4381 auto *StoredLoad = dyn_cast<LoadInst>(
SI->getValueOperand());
4382 if (!StoredLoad || !StoredLoad->isSimple())
4384 assert(!
SI->isVolatile() &&
"Cannot split volatile stores!");
4394 auto &
Offsets = SplitOffsetsMap[
I];
4396 "Should not have splits the first time we see an instruction!");
4398 Offsets.Splits.push_back(
P.endOffset() - S.beginOffset());
4403 for (Slice *S :
P.splitSliceTails()) {
4404 auto SplitOffsetsMapI =
4405 SplitOffsetsMap.
find(cast<Instruction>(S->getUse()->getUser()));
4406 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
4408 auto &
Offsets = SplitOffsetsMapI->second;
4412 "Cannot have an empty set of splits on the second partition!");
4414 P.beginOffset() -
Offsets.S->beginOffset() &&
4415 "Previous split does not end where this one begins!");
4419 if (S->endOffset() >
P.endOffset())
4431 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4434 if (UnsplittableLoads.
count(LI))
4437 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
4438 if (LoadOffsetsI == SplitOffsetsMap.
end())
4440 auto &LoadOffsets = LoadOffsetsI->second;
4443 auto &StoreOffsets = SplitOffsetsMap[
SI];
4448 if (LoadOffsets.Splits == StoreOffsets.Splits)
4452 <<
" " << *LI <<
"\n"
4453 <<
" " << *SI <<
"\n");
4459 UnsplittableLoads.
insert(LI);
4467 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4468 return UnsplittableLoads.
count(LI);
4473 return UnsplittableLoads.
count(LI);
4483 IRBuilderTy IRB(&AI);
4501 std::vector<LoadInst *> SplitLoads;
4506 auto &
Offsets = SplitOffsetsMap[LI];
4507 unsigned SliceSize =
Offsets.S->endOffset() -
Offsets.S->beginOffset();
4509 "Load must have type size equal to store size");
4511 "Load must be >= slice size");
4514 assert(BaseOffset + SliceSize > BaseOffset &&
4515 "Cannot represent alloca access size using 64-bit integers!");
4518 IRB.SetInsertPoint(LI);
4528 LoadInst *PLoad = IRB.CreateAlignedLoad(
4531 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4532 PartPtrTy,
BasePtr->getName() +
"."),
4535 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
4536 LLVMContext::MD_access_group});
4540 SplitLoads.push_back(PLoad);
4544 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4548 <<
", " << NewSlices.
back().endOffset()
4549 <<
"): " << *PLoad <<
"\n");
4564 bool DeferredStores =
false;
4567 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
4568 DeferredStores =
true;
4574 Value *StoreBasePtr =
SI->getPointerOperand();
4575 IRB.SetInsertPoint(SI);
4578 LLVM_DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
4583 auto *PartPtrTy =
SI->getPointerOperandType();
4585 auto AS =
SI->getPointerAddressSpace();
4586 StoreInst *PStore = IRB.CreateAlignedStore(
4589 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4590 PartPtrTy, StoreBasePtr->
getName() +
"."),
4593 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
4594 LLVMContext::MD_access_group,
4595 LLVMContext::MD_DIAssignID});
4600 LLVM_DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
4607 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(StoreBasePtr)) {
4608 ResplitPromotableAllocas.
insert(OtherAI);
4609 Worklist.insert(OtherAI);
4610 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
4612 Worklist.insert(OtherAI);
4616 DeadInsts.push_back(SI);
4621 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
4624 DeadInsts.push_back(LI);
4634 auto *LI = cast<LoadInst>(
SI->getValueOperand());
4638 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
4642 "Slice size should always match load size exactly!");
4644 assert(BaseOffset + StoreSize > BaseOffset &&
4645 "Cannot represent alloca access size using 64-bit integers!");
4648 Instruction *StoreBasePtr = cast<Instruction>(
SI->getPointerOperand());
4653 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
4654 std::vector<LoadInst *> *SplitLoads =
nullptr;
4655 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
4656 SplitLoads = &SplitLoadsMapI->second;
4658 "Too few split loads for the number of splits in the store!");
4668 auto *StorePartPtrTy =
SI->getPointerOperandType();
4673 PLoad = (*SplitLoads)[
Idx];
4675 IRB.SetInsertPoint(LI);
4677 PLoad = IRB.CreateAlignedLoad(
4680 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4681 LoadPartPtrTy, LoadBasePtr->
getName() +
"."),
4684 PLoad->
copyMetadata(*LI, {LLVMContext::MD_mem_parallel_loop_access,
4685 LLVMContext::MD_access_group});
4689 IRB.SetInsertPoint(SI);
4690 auto AS =
SI->getPointerAddressSpace();
4691 StoreInst *PStore = IRB.CreateAlignedStore(
4694 APInt(
DL.getIndexSizeInBits(AS), PartOffset),
4695 StorePartPtrTy, StoreBasePtr->
getName() +
"."),
4698 PStore->
copyMetadata(*SI, {LLVMContext::MD_mem_parallel_loop_access,
4699 LLVMContext::MD_access_group});
4703 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
4707 <<
", " << NewSlices.
back().endOffset()
4708 <<
"): " << *PStore <<
"\n");
4729 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(LoadBasePtr)) {
4730 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
4731 ResplitPromotableAllocas.
insert(OtherAI);
4732 Worklist.insert(OtherAI);
4733 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
4735 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
4736 Worklist.insert(OtherAI);
4751 DeadInsts.push_back(LI);
4753 DeadInsts.push_back(SI);
4762 AS.insert(NewSlices);
4766 for (
auto I = AS.begin(), E = AS.end();
I != E; ++
I)
4773 return ResplitPromotableAllocas.
count(AI);
4794 Type *SliceTy =
nullptr;
4797 std::pair<Type *, IntegerType *> CommonUseTy =
4800 if (CommonUseTy.first)
4801 if (
DL.getTypeAllocSize(CommonUseTy.first).getFixedValue() >=
P.size()) {
4802 SliceTy = CommonUseTy.first;
4803 SliceVecTy = dyn_cast<VectorType>(SliceTy);
4808 P.beginOffset(),
P.size()))
4809 SliceTy = TypePartitionTy;
4812 if (!SliceTy && CommonUseTy.second)
4813 if (
DL.getTypeAllocSize(CommonUseTy.second).getFixedValue() >=
P.size()) {
4814 SliceTy = CommonUseTy.second;
4815 SliceVecTy = dyn_cast<VectorType>(SliceTy);
4817 if ((!SliceTy || (SliceTy->
isArrayTy() &&
4819 DL.isLegalInteger(
P.size() * 8)) {
4827 P.beginOffset(),
P.size())) {
4828 VectorType *TypePartitionVecTy = dyn_cast<VectorType>(TypePartitionTy);
4829 if (TypePartitionVecTy &&
4831 SliceTy = TypePartitionTy;
4836 assert(
DL.getTypeAllocSize(SliceTy).getFixedValue() >=
P.size());
4862 const bool IsUnconstrained = Alignment <=
DL.getABITypeAlign(SliceTy);
4865 IsUnconstrained ?
DL.getPrefTypeAlign(SliceTy) : Alignment,
4873 LLVM_DEBUG(
dbgs() <<
"Rewriting alloca partition " <<
"[" <<
P.beginOffset()
4874 <<
"," <<
P.endOffset() <<
") to: " << *NewAI <<
"\n");
4879 unsigned PPWOldSize = PostPromotionWorklist.size();
4880 unsigned NumUses = 0;
4884 AllocaSliceRewriter
Rewriter(
DL, AS, *
this, AI, *NewAI,
P.beginOffset(),
4885 P.endOffset(), IsIntegerPromotable, VecTy,
4886 PHIUsers, SelectUsers);
4887 bool Promotable =
true;
4888 for (Slice *S :
P.splitSliceTails()) {
4892 for (Slice &S :
P) {
4897 NumAllocaPartitionUses += NumUses;
4898 MaxUsesPerAllocaPartition.updateMax(NumUses);
4906 SelectUsers.
clear();
4911 NewSelectsToRewrite;
4914 std::optional<RewriteableMemOps> Ops =
4919 SelectUsers.clear();
4920 NewSelectsToRewrite.
clear();
4923 NewSelectsToRewrite.
emplace_back(std::make_pair(Sel, *Ops));
4927 for (
Use *U : AS.getDeadUsesIfPromotable()) {
4928 auto *OldInst = dyn_cast<Instruction>(
U->get());
4932 DeadInsts.push_back(OldInst);
4934 if (PHIUsers.empty() && SelectUsers.empty()) {
4936 PromotableAllocas.push_back(NewAI);
4941 for (
PHINode *PHIUser : PHIUsers)
4942 SpeculatablePHIs.insert(PHIUser);
4943 SelectsToRewrite.reserve(SelectsToRewrite.size() +
4944 NewSelectsToRewrite.
size());
4946 std::make_move_iterator(NewSelectsToRewrite.
begin()),
4947 std::make_move_iterator(NewSelectsToRewrite.
end())))
4948 SelectsToRewrite.insert(std::move(KV));
4949 Worklist.insert(NewAI);
4953 while (PostPromotionWorklist.size() > PPWOldSize)
4954 PostPromotionWorklist.pop_back();
4964 Worklist.insert(NewAI);
4974 if (
const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
4975 return DAI->getAddress();
4976 return cast<DbgDeclareInst>(DVI)->getAddress();
4980 assert(DVR->
getType() == DbgVariableRecord::LocationType::Declare ||
4981 DVR->
getType() == DbgVariableRecord::LocationType::Assign);
4986 if (
const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
4987 return DAI->isKillAddress();
4988 return cast<DbgDeclareInst>(DVI)->isKillLocation();
4992 assert(DVR->
getType() == DbgVariableRecord::LocationType::Declare ||
4993 DVR->
getType() == DbgVariableRecord::LocationType::Assign);
4994 if (DVR->
getType() == DbgVariableRecord::LocationType::Assign)
5000 if (
const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
5001 return DAI->getAddressExpression();
5002 return cast<DbgDeclareInst>(DVI)->getExpression();
5006 assert(DVR->
getType() == DbgVariableRecord::LocationType::Declare ||
5007 DVR->
getType() == DbgVariableRecord::LocationType::Assign);
5008 if (DVR->
getType() == DbgVariableRecord::LocationType::Assign)
5040 int64_t BitExtractOffset) {
5042 bool HasFragment =
false;
5043 bool HasBitExtract =
false;
5052 HasBitExtract =
true;
5053 int64_t ExtractOffsetInBits =
Op.getArg(0);
5054 int64_t ExtractSizeInBits =
Op.getArg(1);
5063 assert(BitExtractOffset <= 0);
5064 int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5070 if (AdjustedOffset < 0)
5074 Ops.
push_back(std::max<int64_t>(0, AdjustedOffset));
5078 Op.appendToVector(Ops);
5083 if (HasFragment && HasBitExtract)
5086 if (!HasBitExtract) {
5091 return DIExpression::get(Expr->
getContext(), Ops);
5104 std::optional<DIExpression::FragmentInfo> NewFragment,
5105 int64_t BitExtractAdjustment) {
5108 BitExtractAdjustment);
5112 DIB.insertDeclare(NewAddr, Orig->
getVariable(), NewAddrExpr,
5127 std::optional<DIExpression::FragmentInfo> NewFragment,
5128 int64_t BitExtractAdjustment) {
5137 BitExtractAdjustment);
5138 if (!NewFragmentExpr)
5142 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5149 NewFragmentExpr, NewAddr, NewAddrExpr,
5152 LLVM_DEBUG(
dbgs() <<
"Created new assign intrinsic: " << *NewAssign <<
"\n");
5167 std::optional<DIExpression::FragmentInfo> NewFragment,
5168 int64_t BitExtractAdjustment) {
5178 BitExtractAdjustment);
5179 if (!NewFragmentExpr)
5185 BeforeInst->
getParent()->insertDbgRecordBefore(DVR,
5191 if (!NewAddr->
hasMetadata(LLVMContext::MD_DIAssignID)) {
5199 LLVM_DEBUG(
dbgs() <<
"Created new DVRAssign: " << *NewAssign <<
"\n");
5205bool SROA::splitAlloca(
AllocaInst &AI, AllocaSlices &AS) {
5206 if (AS.begin() == AS.end())
5209 unsigned NumPartitions = 0;
5210 bool Changed =
false;
5214 Changed |= presplitLoadsAndStores(AI, AS);
5222 bool IsSorted =
true;
5226 const uint64_t MaxBitVectorSize = 1024;
5227 if (AllocaSize <= MaxBitVectorSize) {
5232 for (
unsigned O = S.beginOffset() + 1;
5233 O < S.endOffset() && O < AllocaSize; O++)
5234 SplittableOffset.reset(O);
5236 for (Slice &S : AS) {
5237 if (!S.isSplittable())
5240 if ((S.beginOffset() > AllocaSize || SplittableOffset[S.beginOffset()]) &&
5241 (S.endOffset() > AllocaSize || SplittableOffset[S.endOffset()]))
5244 if (isa<LoadInst>(S.getUse()->getUser()) ||
5245 isa<StoreInst>(S.getUse()->getUser())) {
5246 S.makeUnsplittable();
5253 for (Slice &S : AS) {
5254 if (!S.isSplittable())
5257 if (S.beginOffset() == 0 && S.endOffset() >= AllocaSize)
5260 if (isa<LoadInst>(S.getUse()->getUser()) ||
5261 isa<StoreInst>(S.getUse()->getUser())) {
5262 S.makeUnsplittable();
5283 for (
auto &
P : AS.partitions()) {
5284 if (
AllocaInst *NewAI = rewritePartition(AI, AS,
P)) {
5291 uint64_t Size = std::min(AllocaSize,
P.size() * SizeOfByte);
5293 Fragment(NewAI,
P.beginOffset() * SizeOfByte,
Size));
5299 NumAllocaPartitions += NumPartitions;
5300 MaxPartitionsPerAlloca.updateMax(NumPartitions);
5314 int64_t CurrentExprOffsetInBytes = 0;
5317 ->extractLeadingOffset(CurrentExprOffsetInBytes, PostOffsetOps))
5321 int64_t ExtractOffsetInBits = 0;
5325 ExtractOffsetInBits =
Op.getArg(0);
5331 for (
auto Fragment : Fragments) {
5332 int64_t OffsetFromLocationInBits;
5333 std::optional<DIExpression::FragmentInfo> NewDbgFragment;
5338 DL, &AI, Fragment.Offset, Fragment.Size, DbgPtr,
5339 CurrentExprOffsetInBytes * 8, ExtractOffsetInBits, VarFrag,
5340 NewDbgFragment, OffsetFromLocationInBits))
5346 if (NewDbgFragment && !NewDbgFragment->SizeInBits)
5351 if (!NewDbgFragment)
5356 int64_t OffestFromNewAllocaInBits =
5357 OffsetFromLocationInBits - ExtractOffsetInBits;
5360 int64_t BitExtractOffset =
5361 std::min<int64_t>(0, OffestFromNewAllocaInBits);
5366 OffestFromNewAllocaInBits =
5367 std::max(int64_t(0), OffestFromNewAllocaInBits);
5374 if (OffestFromNewAllocaInBits > 0) {
5375 int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7) / 8;
5382 auto SameVariableFragment = [](
const auto *
LHS,
const auto *
RHS) {
5383 return LHS->getVariable() ==
RHS->getVariable() &&
5384 LHS->getDebugLoc()->getInlinedAt() ==
5385 RHS->getDebugLoc()->getInlinedAt();
5388 OldDII->eraseFromParent();
5394 NewDbgFragment, BitExtractOffset);
5409void SROA::clobberUse(
Use &U) {
5417 if (
Instruction *OldI = dyn_cast<Instruction>(OldV))
5419 DeadInsts.push_back(OldI);
5428std::pair<
bool ,
bool >
5430 bool Changed =
false;
5431 bool CFGChanged =
false;
5434 ++NumAllocasAnalyzed;
5440 return {Changed, CFGChanged};
5448 Size.getFixedValue() == 0)
5449 return {Changed, CFGChanged};
5453 IRBuilderTy IRB(&AI);
5454 AggLoadStoreRewriter AggRewriter(
DL, IRB);
5455 Changed |= AggRewriter.rewrite(AI);
5458 AllocaSlices AS(
DL, AI);
5461 return {Changed, CFGChanged};
5466 for (
Use &DeadOp : DeadUser->operands())
5473 DeadInsts.push_back(DeadUser);
5476 for (
Use *DeadOp : AS.getDeadOperands()) {
5477 clobberUse(*DeadOp);
5482 if (AS.begin() == AS.end())
5483 return {Changed, CFGChanged};
5485 Changed |= splitAlloca(AI, AS);
5488 while (!SpeculatablePHIs.empty())
5492 auto RemainingSelectsToRewrite = SelectsToRewrite.takeVector();
5493 while (!RemainingSelectsToRewrite.empty()) {
5494 const auto [
K,
V] = RemainingSelectsToRewrite.pop_back_val();
5499 return {Changed, CFGChanged};
5511bool SROA::deleteDeadInstructions(
5513 bool Changed =
false;
5514 while (!DeadInsts.empty()) {
5515 Instruction *
I = dyn_cast_or_null<Instruction>(DeadInsts.pop_back_val());
5524 DeletedAllocas.
insert(AI);
5526 OldDII->eraseFromParent();
5528 OldDII->eraseFromParent();
5534 for (
Use &Operand :
I->operands())
5535 if (
Instruction *U = dyn_cast<Instruction>(Operand)) {
5539 DeadInsts.push_back(U);
5543 I->eraseFromParent();
5555 if (PromotableAllocas.empty())
5558 NumPromoted += PromotableAllocas.size();
5567 PromotableAllocas.clear();
5571std::pair<
bool ,
bool > SROA::runSROA(
Function &
F) {
5581 PromotableAllocas.push_back(AI);
5583 Worklist.insert(AI);
5587 bool Changed =
false;
5588 bool CFGChanged =
false;
5594 while (!Worklist.empty()) {
5595 auto [IterationChanged, IterationCFGChanged] =
5596 runOnAlloca(*Worklist.pop_back_val());
5597 Changed |= IterationChanged;
5598 CFGChanged |= IterationCFGChanged;
5600 Changed |= deleteDeadInstructions(DeletedAllocas);
5604 if (!DeletedAllocas.
empty()) {
5605 auto IsInSet = [&](
AllocaInst *AI) {
return DeletedAllocas.
count(AI); };
5606 Worklist.remove_if(IsInSet);
5607 PostPromotionWorklist.remove_if(IsInSet);
5609 DeletedAllocas.
clear();
5613 Changed |= promoteAllocas(
F);
5615 Worklist = PostPromotionWorklist;
5616 PostPromotionWorklist.clear();
5617 }
while (!Worklist.empty());
5619 assert((!CFGChanged || Changed) &&
"Can not only modify the CFG.");
5621 "Should not have modified the CFG when told to preserve it.");
5624 for (
auto &BB :
F) {
5629 return {Changed, CFGChanged};
5636 auto [Changed, CFGChanged] =
5650 OS, MapClassName2PassName);
5651 OS << (
PreserveCFG == SROAOptions::PreserveCFG ?
"<preserve-cfg>"
5672 if (skipFunction(
F))
5675 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
5677 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
5691 StringRef getPassName()
const override {
return "SROA"; }
5696char SROALegacyPass::ID = 0;
5704 "Scalar Replacement Of Aggregates",
false,
false)
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)
Rewrite Partial Register Uses
This is the interface for a simple mod/ref and alias analysis over globals.
This defines the Use class.
This file implements a map that provides insertion order iteration.
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
This header defines various interfaces for pass management in LLVM.
#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.
static bool rewrite(Function &F)
This file provides a collection of visitors which walk the (instruction) uses of a pointer.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
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 Align getAdjustedAlignment(Instruction *I, uint64_t Offset)
Compute the adjusted alignment for a load or store from an offset.
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.
DbgVariableRecord * UnwrapDbgInstPtr(DbgInstPtr P, DbgVariableRecord *Unused)
Helpers for handling new and old debug info modes in migrateDebugInfo.
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 bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy)
Test whether we can convert a value from the old to the new type.
static DebugVariable getAggregateVariable(DbgVariableIntrinsic *DVI)
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)
static FragCalcResult calculateFragment(DILocalVariable *Variable, uint64_t NewStorageSliceOffsetInBits, uint64_t NewStorageSliceSizeInBits, std::optional< DIExpression::FragmentInfo > StorageFragment, std::optional< DIExpression::FragmentInfo > CurrentFragment, DIExpression::FragmentInfo &Target)
const Value * getAddress(const DbgVariableIntrinsic *DVI)
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 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)
static bool checkVectorTypeForPromotion(Partition &P, VectorType *VTy, const DataLayout &DL)
Test whether a vector type is viable for promotion.
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)
bool isKillAddress(const DbgVariableIntrinsic *DVI)
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 bool isVectorPromotionViableForSlice(Partition &P, const Slice &S, VectorType *Ty, uint64_t ElementSize, const DataLayout &DL)
Test whether the given slice use can be promoted to a vector.
static void insertNewDbgInst(DIBuilder &DIB, DbgDeclareInst *Orig, AllocaInst *NewAddr, DIExpression *NewAddrExpr, Instruction *BeforeInst, std::optional< DIExpression::FragmentInfo > NewFragment, int64_t BitExtractAdjustment)
Insert a new dbg.declare.
const DIExpression * getAddressExpression(const DbgVariableIntrinsic *DVI)
static void speculateSelectInstLoads(SelectInst &SI, LoadInst &LI, IRBuilderTy &IRB)
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 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.
static VectorType * isVectorPromotionViable(Partition &P, const DataLayout &DL)
Test whether the given alloca partitioning and range of slices can be promoted to a vector.
static VectorType * checkVectorTypesForPromotion(Partition &P, const DataLayout &DL, SmallVectorImpl< VectorType * > &CandidateTys, bool HaveCommonEltTy, Type *CommonEltTy, bool HaveVecPtrTy, bool HaveCommonVecPtrTy, VectorType *CommonVecPtrTy)
Test whether any vector type in CandidateTys is viable for promotion.
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
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.
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.
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.
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 Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
static DIAssignID * getDistinct(LLVMContext &Context)
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
static 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 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 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 ...
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.
This represents the llvm.dbg.assign instruction.
This represents the llvm.dbg.declare instruction.
DebugLoc getDebugLoc() const
Value * getValue(unsigned OpIdx=0) const
This is the common base class for debug info intrinsics for variables.
DILocalVariable * getVariable() const
DIExpression * getExpression() const
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LocationType getType() const
bool isKillAddress() const
Check whether this kills the address component.
bool isKillLocation() const
Value * getValue(unsigned OpIdx=0) const
static DbgVariableRecord * createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
Value * getAddress() const
DIExpression * getExpression() const
DILocalVariable * getVariable() const
static 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.
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 FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
Represents flags for the getelementptr instruction/expression.
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
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.
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.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
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.
bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
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...
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.
bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
AAMDNodes getAAMetadata() const
Returns the AA metadata for this instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
@ MAX_INT_BITS
Maximum number of bits that can be specified.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void setAlignment(Align Align)
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Type * getPointerOperandType() const
static unsigned getPointerOperandIndex()
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
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 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
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
T get() const
Returns the value of the specified pointer type.
static 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.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
A base class for visitors over the uses of a pointer value.
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...
This class represents the LLVM 'select' instruction.
const Value * getFalseValue() const
const Value * getTrueValue() const
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
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
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 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...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
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.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
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.
static IntegerType * getInt8Ty(LLVMContext &C)
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.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
static 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()
const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr) const
Accumulate the constant offset this value has compared to a base pointer.
bool hasOneUse() const
Return true if there is exactly one use of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
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 void dropDroppableUse(Use &U)
Remove the droppable use U.
void dropDroppableUsesIn(User &Usr)
Remove every use of this value in User that can safely be removed.
LLVMContext & getContext() const
All values hold a context through their type.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
void setEscapedAndAborted(Instruction *I=nullptr)
Mark the pointer as escaped, and the visit as aborted.
void setAborted(Instruction *I=nullptr)
Mark the visit as aborted.
APInt Offset
The constant offset of the use if that is known.
void enqueueUsers(Instruction &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).
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.
friend const_iterator begin(StringRef path, Style style)
Get begin iterator over path.
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.
AssignmentMarkerRange getAssignmentMarkers(DIAssignID *ID)
Return a range of dbg.assign intrinsics which use \ID as an operand.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
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
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
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)
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.
TinyPtrVector< DbgDeclareInst * > findDbgDeclares(Value *V)
Finds dbg.declare intrinsics declaring local variables as living in the memory that 'V' points to.
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...
auto successors(const MachineBasicBlock *BB)
bool operator!=(uint64_t V1, const APInt &V2)
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.
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)
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.
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.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
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...
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
void initializeSROALegacyPassPass(PassRegistry &)
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...
TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
As above, for DVRDeclares.
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.
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 ...
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...
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.