60 #if __cplusplus >= 201103L && !defined(NDEBUG)
67 #define DEBUG_TYPE "sroa"
69 STATISTIC(NumAllocasAnalyzed,
"Number of allocas analyzed for replacement");
70 STATISTIC(NumAllocaPartitions,
"Number of alloca partitions formed");
71 STATISTIC(MaxPartitionsPerAlloca,
"Maximum number of partitions per alloca");
72 STATISTIC(NumAllocaPartitionUses,
"Number of alloca partition uses rewritten");
73 STATISTIC(MaxUsesPerAllocaPartition,
"Maximum number of uses of a partition");
74 STATISTIC(NumNewAllocas,
"Number of new, smaller allocas introduced");
75 STATISTIC(NumPromoted,
"Number of allocas promoted to SSA values");
76 STATISTIC(NumLoadsSpeculated,
"Number of loads speculated to allow promotion");
77 STATISTIC(NumDeleted,
"Number of instructions deleted");
78 STATISTIC(NumVectorized,
"Number of vectorized aggregates");
98 template <
bool preserveNames = true>
99 class IRBuilderPrefixedInserter
116 class IRBuilderPrefixedInserter<
false>
119 void SetNamePrefix(
const Twine &P) {}
141 uint64_t BeginOffset;
151 Slice() : BeginOffset(), EndOffset() {}
152 Slice(uint64_t BeginOffset, uint64_t EndOffset,
Use *U,
bool IsSplittable)
153 : BeginOffset(BeginOffset), EndOffset(EndOffset),
154 UseAndIsSplittable(U, IsSplittable) {}
156 uint64_t beginOffset()
const {
return BeginOffset; }
157 uint64_t endOffset()
const {
return EndOffset; }
159 bool isSplittable()
const {
return UseAndIsSplittable.getInt(); }
160 void makeUnsplittable() { UseAndIsSplittable.setInt(
false); }
162 Use *getUse()
const {
return UseAndIsSplittable.getPointer(); }
164 bool isDead()
const {
return getUse() ==
nullptr; }
165 void kill() { UseAndIsSplittable.setPointer(
nullptr); }
174 if (beginOffset() < RHS.beginOffset())
176 if (beginOffset() > RHS.beginOffset())
178 if (isSplittable() != RHS.isSplittable())
179 return !isSplittable();
180 if (endOffset() > RHS.endOffset())
187 uint64_t RHSOffset) {
188 return LHS.beginOffset() < RHSOffset;
192 return LHSOffset < RHS.beginOffset();
196 return isSplittable() == RHS.isSplittable() &&
197 beginOffset() == RHS.beginOffset() && endOffset() == RHS.endOffset();
225 bool isEscaped()
const {
return PointerEscapingInstr; }
232 iterator
end() {
return Slices.
end(); }
236 const_iterator
begin()
const {
return Slices.
begin(); }
237 const_iterator
end()
const {
return Slices.
end(); }
241 void erase(iterator Start, iterator Stop) { Slices.erase(Start, Stop); }
249 int OldSize = Slices.size();
250 Slices.append(NewSlices.
begin(), NewSlices.
end());
251 auto SliceI = Slices.
begin() + OldSize;
252 std::sort(SliceI, Slices.end());
253 std::inplace_merge(Slices.begin(), SliceI, Slices.end());
257 class partition_iterator;
270 friend class AllocaSlices;
271 friend class AllocaSlices::partition_iterator;
274 uint64_t BeginOffset, EndOffset;
284 Partition(iterator
SI) : SI(SI), SJ(SI) {}
290 uint64_t beginOffset()
const {
return BeginOffset; }
295 uint64_t endOffset()
const {
return EndOffset; }
300 uint64_t
size()
const {
301 assert(BeginOffset < EndOffset &&
"Partitions must span some bytes!");
302 return EndOffset - BeginOffset;
307 bool empty()
const {
return SI == SJ; }
318 iterator
begin()
const {
return SI; }
319 iterator
end()
const {
return SJ; }
339 class partition_iterator
341 std::forward_iterator_tag, Partition> {
342 friend class AllocaSlices;
353 uint64_t MaxSplitSliceEndOffset;
358 :
P(SI), SE(SE), MaxSplitSliceEndOffset(0) {
369 assert((
P.SI != SE || !
P.SplitTails.empty()) &&
370 "Cannot advance past the end of the slices!");
373 if (!
P.SplitTails.empty()) {
374 if (
P.EndOffset >= MaxSplitSliceEndOffset) {
376 P.SplitTails.clear();
377 MaxSplitSliceEndOffset = 0;
384 P.SplitTails.begin(),
P.SplitTails.end(),
385 [&](Slice *S) {
return S->endOffset() <=
P.EndOffset; }),
387 assert(std::any_of(
P.SplitTails.begin(),
P.SplitTails.end(),
389 return S->endOffset() == MaxSplitSliceEndOffset;
391 "Could not find the current max split slice offset!");
394 return S->endOffset() <= MaxSplitSliceEndOffset;
396 "Max split slice end offset is not actually the max!");
403 assert(
P.SplitTails.empty() &&
"Failed to clear the split slices!");
413 if (S.isSplittable() && S.endOffset() > P.EndOffset) {
414 P.SplitTails.push_back(&S);
415 MaxSplitSliceEndOffset =
416 std::max(S.endOffset(), MaxSplitSliceEndOffset);
424 P.BeginOffset = P.EndOffset;
425 P.EndOffset = MaxSplitSliceEndOffset;
432 if (!P.SplitTails.empty() && P.SI->beginOffset() != P.EndOffset &&
433 !P.SI->isSplittable()) {
434 P.BeginOffset = P.EndOffset;
435 P.EndOffset = P.SI->beginOffset();
445 P.BeginOffset = P.SplitTails.empty() ? P.SI->beginOffset() : P.EndOffset;
446 P.EndOffset = P.SI->endOffset();
451 if (!P.SI->isSplittable()) {
454 assert(P.BeginOffset == P.SI->beginOffset());
458 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
459 if (!P.SJ->isSplittable())
460 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
472 assert(P.SI->isSplittable() &&
"Forming a splittable partition!");
475 while (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset &&
476 P.SJ->isSplittable()) {
477 P.EndOffset = std::max(P.EndOffset, P.SJ->endOffset());
484 if (P.SJ != SE && P.SJ->beginOffset() < P.EndOffset) {
485 assert(!P.SJ->isSplittable());
486 P.EndOffset = P.SJ->beginOffset();
491 bool operator==(
const partition_iterator &RHS)
const {
492 assert(SE == RHS.SE &&
493 "End iterators don't match between compared partition iterators!");
500 if (P.SI == RHS.P.SI &&
501 P.SplitTails.empty() == RHS.P.SplitTails.empty()) {
502 assert(P.SJ == RHS.P.SJ &&
503 "Same set of slices formed two different sized partitions!");
504 assert(P.SplitTails.size() == RHS.P.SplitTails.size() &&
505 "Same slice position with differently sized non-empty split "
512 partition_iterator &operator++() {
529 partition_iterator(
end(),
end()));
543 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
550 void dump(const_iterator
I)
const;
555 template <
typename DerivedT,
typename RetT =
void>
class BuilderBase;
559 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
614 if (
PHINode *PN = dyn_cast<PHINode>(&I)) {
616 return PN->hasConstantValue();
630 const uint64_t AllocSize;
642 AllocSize(DL.getTypeAllocSize(AI.getAllocatedType())), AS(AS) {}
646 if (VisitedDeadInsts.insert(&I).second)
647 AS.DeadUsers.push_back(&I);
651 bool IsSplittable =
false) {
654 if (Size == 0 || Offset.
uge(AllocSize)) {
655 DEBUG(
dbgs() <<
"WARNING: Ignoring " << Size <<
" byte use @" << Offset
656 <<
" which has zero size or starts outside of the "
657 << AllocSize <<
" byte alloca:\n"
658 <<
" alloca: " << AS.AI <<
"\n"
659 <<
" use: " << I <<
"\n");
660 return markAsDead(I);
664 uint64_t EndOffset = BeginOffset + Size;
672 assert(AllocSize >= BeginOffset);
673 if (Size > AllocSize - BeginOffset) {
674 DEBUG(
dbgs() <<
"WARNING: Clamping a " << Size <<
" byte use @" << Offset
675 <<
" to remain within the " << AllocSize <<
" byte alloca:\n"
676 <<
" alloca: " << AS.AI <<
"\n"
677 <<
" use: " << I <<
"\n");
678 EndOffset = AllocSize;
681 AS.Slices.push_back(Slice(BeginOffset, EndOffset, U, IsSplittable));
686 return markAsDead(BC);
688 return Base::visitBitCastInst(BC);
693 return markAsDead(GEPI);
703 APInt GEPOffset = Offset;
713 if (
StructType *STy = dyn_cast<StructType>(*GTI)) {
729 if (GEPOffset.
ugt(AllocSize))
730 return markAsDead(GEPI);
734 return Base::visitGetElementPtrInst(GEPI);
738 uint64_t Size,
bool IsVolatile) {
742 bool IsSplittable = Ty->
isIntegerTy() && !IsVolatile;
744 insertUse(I, Offset, Size, IsSplittable);
749 "All simple FCA loads should have been pre-split");
752 return PI.setAborted(&LI);
762 return PI.setEscapedAndAborted(&SI);
764 return PI.setAborted(&SI);
776 if (Size > AllocSize || Offset.ugt(AllocSize - Size)) {
777 DEBUG(
dbgs() <<
"WARNING: Ignoring " << Size <<
" byte store @" << Offset
778 <<
" which extends past the end of the " << AllocSize
780 <<
" alloca: " << AS.AI <<
"\n"
781 <<
" use: " << SI <<
"\n");
782 return markAsDead(SI);
786 "All simple FCA stores should have been pre-split");
791 assert(II.
getRawDest() == *U &&
"Pointer use is not the destination?");
793 if ((Length && Length->getValue() == 0) ||
794 (IsOffsetKnown && Offset.uge(AllocSize)))
796 return markAsDead(II);
799 return PI.setAborted(&II);
801 insertUse(II, Offset, Length ? Length->getLimitedValue()
802 : AllocSize - Offset.getLimitedValue(),
808 if (Length && Length->
getValue() == 0)
810 return markAsDead(II);
814 if (VisitedDeadInsts.count(&II))
818 return PI.setAborted(&II);
825 if (Offset.uge(AllocSize)) {
827 MemTransferSliceMap.
find(&II);
828 if (MTPI != MemTransferSliceMap.
end())
829 AS.Slices[MTPI->second].kill();
830 return markAsDead(II);
833 uint64_t RawOffset = Offset.getLimitedValue();
834 uint64_t Size = Length ? Length->
getLimitedValue() : AllocSize - RawOffset;
841 return markAsDead(II);
843 return insertUse(II, Offset, Size,
false);
850 std::tie(MTPI, Inserted) =
851 MemTransferSliceMap.
insert(std::make_pair(&II, AS.Slices.size()));
852 unsigned PrevIdx = MTPI->second;
854 Slice &PrevP = AS.Slices[PrevIdx];
858 if (!II.
isVolatile() && PrevP.beginOffset() == RawOffset) {
860 return markAsDead(II);
865 PrevP.makeUnsplittable();
869 insertUse(II, Offset, Size, Inserted && Length);
872 assert(AS.Slices[PrevIdx].getUse()->getUser() == &II &&
873 "Map index doesn't point back to a slice with this user.");
881 return PI.setAborted(&II);
886 uint64_t Size =
std::min(AllocSize - Offset.getLimitedValue(),
888 insertUse(II, Offset, Size,
true);
892 Base::visitIntrinsicInst(II);
903 Uses.
push_back(std::make_pair(cast<Instruction>(*U), Root));
912 if (
LoadInst *LI = dyn_cast<LoadInst>(I)) {
916 if (
StoreInst *SI = dyn_cast<StoreInst>(I)) {
925 if (!
GEP->hasAllZeroIndices())
927 }
else if (!isa<BitCastInst>(I) && !isa<PHINode>(
I) &&
928 !isa<SelectInst>(I)) {
933 if (Visited.
insert(cast<Instruction>(U)).second)
934 Uses.
push_back(std::make_pair(I, cast<Instruction>(U)));
935 }
while (!Uses.
empty());
941 assert(isa<PHINode>(I) || isa<SelectInst>(I));
943 return markAsDead(I);
961 AS.DeadOperands.push_back(U);
967 return PI.setAborted(&I);
970 uint64_t &Size = PHIOrSelectSizes[&
I];
973 if (
Instruction *UnsafeI = hasUnsafePHIOrSelectUse(&I, Size))
974 return PI.setAborted(UnsafeI);
983 if (Offset.uge(AllocSize)) {
984 AS.DeadOperands.push_back(U);
988 insertUse(I, Offset, Size);
991 void visitPHINode(
PHINode &PN) { visitPHINodeOrSelectInst(PN); }
993 void visitSelectInst(
SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
996 void visitInstruction(
Instruction &I) { PI.setAborted(&I); }
1001 #
if !defined(
NDEBUG) || defined(LLVM_ENABLE_DUMP)
1004 PointerEscapingInstr(nullptr) {
1006 SliceBuilder::PtrInfo PtrI = PB.visitPtr(AI);
1007 if (PtrI.isEscaped() || PtrI.isAborted()) {
1010 PointerEscapingInstr = PtrI.getEscapingInst() ? PtrI.getEscapingInst()
1011 : PtrI.getAbortingInst();
1012 assert(PointerEscapingInstr &&
"Did not track a bad instruction");
1016 Slices.erase(std::remove_if(Slices.begin(), Slices.end(),
1017 [](
const Slice &S) {
1022 #if __cplusplus >= 201103L && !defined(NDEBUG)
1025 std::shuffle(Slices.begin(), Slices.end(), MT);
1031 std::sort(Slices.begin(), Slices.end());
1034 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1036 void AllocaSlices::print(
raw_ostream &OS, const_iterator I,
1038 printSlice(OS, I, Indent);
1040 printUse(OS, I, Indent);
1043 void AllocaSlices::printSlice(
raw_ostream &OS, const_iterator I,
1045 OS << Indent <<
"[" << I->beginOffset() <<
"," << I->endOffset() <<
")"
1046 <<
" slice #" << (I -
begin())
1047 << (I->isSplittable() ?
" (splittable)" :
"");
1050 void AllocaSlices::printUse(
raw_ostream &OS, const_iterator I,
1052 OS << Indent <<
" used by: " << *I->getUse()->getUser() <<
"\n";
1056 if (PointerEscapingInstr) {
1057 OS <<
"Can't analyze slices for alloca: " << AI <<
"\n"
1058 <<
" A pointer to this alloca escaped by:\n"
1059 <<
" " << *PointerEscapingInstr <<
"\n";
1063 OS <<
"Slices of alloca: " << AI <<
"\n";
1064 for (const_iterator I =
begin(), E =
end(); I != E; ++
I)
1073 #endif // !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1099 if (
auto *L = LocalAsMetadata::getIfExists(&AI)) {
1100 if (
auto *
DINode = MetadataAsValue::getIfExists(AI.getContext(), L)) {
1103 DDIs.push_back(DDI);
1104 else if (
DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
1105 DVIs.push_back(DVI);
1109 LoadAndStorePromoter::run(Insts);
1113 while (!DDIs.empty())
1114 DDIs.pop_back_val()->eraseFromParent();
1115 while (!DVIs.empty())
1116 DVIs.pop_back_val()->eraseFromParent();
1123 if (
LoadInst *LI = dyn_cast<LoadInst>(I))
1136 if (
BitCastInst *BCI = dyn_cast<BitCastInst>(Ptr))
1137 Ptr = BCI->getOperand(0);
1143 }
while (Visited.
insert(Ptr).second);
1148 void updateDebugInfo(
Instruction *Inst)
const override {
1150 if (
StoreInst *SI = dyn_cast<StoreInst>(Inst))
1152 else if (
LoadInst *LI = dyn_cast<LoadInst>(Inst))
1155 Value *Arg =
nullptr;
1156 if (
StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
1165 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
1170 DIB.insertDbgValueIntrinsic(Arg, 0, DVI->getVariable(),
1171 DVI->getExpression(), DVI->getDebugLoc(),
1198 const bool RequiresDomTree;
1229 std::vector<AllocaInst *> PromotableAllocas;
1247 SROA(
bool RequiresDomTree =
true)
1252 bool runOnFunction(
Function &
F)
override;
1255 const char *getPassName()
const override {
return "SROA"; }
1259 friend class PHIOrSelectSpeculator;
1260 friend class AllocaSliceRewriter;
1262 bool presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS);
1264 AllocaSlices::Partition &P);
1265 bool splitAlloca(
AllocaInst &AI, AllocaSlices &AS);
1267 void clobberUse(
Use &U);
1276 return new SROA(RequiresDomTree);
1289 AllocaSlices::const_iterator E,
1290 uint64_t EndOffset) {
1292 bool TyIsCommon =
true;
1297 for (AllocaSlices::const_iterator I = B; I != E; ++
I) {
1298 Use *U = I->getUse();
1299 if (isa<IntrinsicInst>(*U->getUser()))
1301 if (I->beginOffset() != B->beginOffset() || I->endOffset() != EndOffset)
1304 Type *UserTy =
nullptr;
1305 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
1307 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
1311 if (
IntegerType *UserITy = dyn_cast_or_null<IntegerType>(UserTy)) {
1316 if (UserITy->getBitWidth() % 8 != 0 ||
1317 UserITy->getBitWidth() / 8 > (EndOffset - B->beginOffset()))
1322 if (!ITy || ITy->
getBitWidth() < UserITy->getBitWidth())
1328 if (!UserTy || (Ty && Ty != UserTy))
1334 return TyIsCommon ? Ty : ITy;
1361 unsigned MaxAlign = 0;
1362 bool HaveLoad =
false;
1377 if (BBI->mayWriteToMemory())
1421 DEBUG(
dbgs() <<
" original: " << PN <<
"\n");
1423 Type *LoadTy = cast<PointerType>(PN.
getType())->getElementType();
1424 IRBuilderTy PHIBuilder(&PN);
1426 PN.
getName() +
".sroa.speculated");
1448 IRBuilderTy PredBuilder(TI);
1451 InVal, (PN.
getName() +
".sroa.speculate.load." + Pred->
getName()));
1452 ++NumLoadsSpeculated;
1459 DEBUG(
dbgs() <<
" speculated to: " << *NewPN <<
"\n");
1503 DEBUG(
dbgs() <<
" original: " << SI <<
"\n");
1505 IRBuilderTy IRB(&SI);
1511 assert(LI->
isSimple() &&
"We only speculate simple loads");
1513 IRB.SetInsertPoint(LI);
1515 IRB.CreateLoad(TV, LI->
getName() +
".sroa.speculate.load.true");
1517 IRB.CreateLoad(FV, LI->
getName() +
".sroa.speculate.load.false");
1518 NumLoadsSpeculated += 2;
1532 LI->
getName() +
".sroa.speculated");
1534 DEBUG(
dbgs() <<
" speculated to: " << *V <<
"\n");
1547 if (Indices.
empty())
1552 if (Indices.
size() == 1 && cast<ConstantInt>(Indices.
back())->
isZero())
1555 return IRB.CreateInBoundsGEP(
nullptr, BasePtr, Indices,
1556 NamePrefix +
"sroa_idx");
1573 return buildGEP(IRB, BasePtr, Indices, NamePrefix);
1580 unsigned NumLayers = 0;
1581 Type *ElementTy = Ty;
1586 if (
ArrayType *ArrayTy = dyn_cast<ArrayType>(ElementTy)) {
1587 ElementTy = ArrayTy->getElementType();
1588 Indices.
push_back(IRB.getIntN(PtrSize, 0));
1589 }
else if (
VectorType *VectorTy = dyn_cast<VectorType>(ElementTy)) {
1590 ElementTy = VectorTy->getElementType();
1592 }
else if (
StructType *STy = dyn_cast<StructType>(ElementTy)) {
1593 if (STy->element_begin() == STy->element_end())
1595 ElementTy = *STy->element_begin();
1601 }
while (ElementTy != TargetTy);
1602 if (ElementTy != TargetTy)
1603 Indices.
erase(Indices.
end() - NumLayers, Indices.
end());
1605 return buildGEP(IRB, BasePtr, Indices, NamePrefix);
1628 if (
VectorType *VecTy = dyn_cast<VectorType>(Ty)) {
1630 if (ElementSizeInBits % 8 != 0) {
1635 APInt NumSkippedElements = Offset.
sdiv(ElementSize);
1636 if (NumSkippedElements.ugt(VecTy->getNumElements()))
1638 Offset -= NumSkippedElements * ElementSize;
1639 Indices.
push_back(IRB.getInt(NumSkippedElements));
1641 Offset, TargetTy, Indices, NamePrefix);
1644 if (
ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
1645 Type *ElementTy = ArrTy->getElementType();
1647 APInt NumSkippedElements = Offset.
sdiv(ElementSize);
1648 if (NumSkippedElements.ugt(ArrTy->getNumElements()))
1651 Offset -= NumSkippedElements * ElementSize;
1652 Indices.
push_back(IRB.getInt(NumSkippedElements));
1654 Indices, NamePrefix);
1673 Indices, NamePrefix);
1701 if (ElementSize == 0)
1703 APInt NumSkippedElements = Offset.
sdiv(ElementSize);
1705 Offset -= NumSkippedElements * ElementSize;
1706 Indices.
push_back(IRB.getInt(NumSkippedElements));
1708 Indices, NamePrefix);
1737 Value *OffsetPtr =
nullptr;
1738 Value *OffsetBasePtr;
1742 Value *Int8Ptr =
nullptr;
1751 if (!
GEP->accumulateConstantOffset(DL, GEPOffset))
1753 Offset += GEPOffset;
1754 Ptr =
GEP->getPointerOperand();
1755 if (!Visited.
insert(Ptr).second)
1762 Indices, NamePrefix)) {
1766 if (OffsetPtr && OffsetPtr != OffsetBasePtr)
1767 if (
Instruction *I = dyn_cast<Instruction>(OffsetPtr)) {
1768 assert(I->
use_empty() &&
"Built a GEP with uses some how!");
1772 OffsetBasePtr = Ptr;
1781 Int8PtrOffset = Offset;
1785 if (Operator::getOpcode(Ptr) == Instruction::BitCast) {
1786 Ptr = cast<Operator>(Ptr)->getOperand(0);
1787 }
else if (
GlobalAlias *GA = dyn_cast<GlobalAlias>(Ptr)) {
1788 if (GA->mayBeOverridden())
1790 Ptr = GA->getAliasee();
1795 }
while (Visited.
insert(Ptr).second);
1799 Int8Ptr = IRB.CreateBitCast(
1801 NamePrefix +
"sroa_raw_cast");
1802 Int8PtrOffset = Offset;
1805 OffsetPtr = Int8PtrOffset == 0
1807 : IRB.CreateInBoundsGEP(IRB.getInt8Ty(), Int8Ptr,
1808 IRB.getInt(Int8PtrOffset),
1809 NamePrefix +
"sroa_raw_idx");
1815 Ptr = IRB.CreateBitCast(Ptr, PointerTy, NamePrefix +
"sroa_cast");
1825 if (
auto *LI = dyn_cast<LoadInst>(I)) {
1828 }
else if (
auto *SI = dyn_cast<StoreInst>(I)) {
1838 return MinAlign(Alignment, Offset);
1854 if (isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) {
1857 "We can't have the same bitwidth for different int types");
1890 assert(
canConvertValue(DL, OldTy, NewTy) &&
"Value not convertable to type");
1895 assert(!(isa<IntegerType>(OldTy) && isa<IntegerType>(NewTy)) &&
1896 "Integer types must be the exact same to convert.");
1904 return IRB.CreateIntToPtr(IRB.CreateBitCast(V, DL.
getIntPtrType(NewTy)),
1909 return IRB.CreateIntToPtr(IRB.CreateBitCast(V, DL.
getIntPtrType(NewTy)),
1912 return IRB.CreateIntToPtr(V, NewTy);
1921 return IRB.CreateBitCast(IRB.CreatePtrToInt(V, DL.
getIntPtrType(OldTy)),
1926 return IRB.CreateBitCast(IRB.CreatePtrToInt(V, DL.
getIntPtrType(OldTy)),
1929 return IRB.CreatePtrToInt(V, NewTy);
1932 return IRB.CreateBitCast(V, NewTy);
1941 uint64_t ElementSize,
1944 uint64_t BeginOffset =
1945 std::max(S.beginOffset(), P.beginOffset()) - P.beginOffset();
1946 uint64_t BeginIndex = BeginOffset / ElementSize;
1947 if (BeginIndex * ElementSize != BeginOffset ||
1950 uint64_t EndOffset =
1951 std::min(S.endOffset(), P.endOffset()) - P.beginOffset();
1952 uint64_t EndIndex = EndOffset / ElementSize;
1953 if (EndIndex * ElementSize != EndOffset || EndIndex > Ty->
getNumElements())
1956 assert(EndIndex > BeginIndex &&
"Empty vector!");
1957 uint64_t NumElements = EndIndex - BeginIndex;
1958 Type *SliceTy = (NumElements == 1)
1963 Type::getIntNTy(Ty->
getContext(), NumElements * ElementSize * 8);
1965 Use *U = S.getUse();
1968 if (
MI->isVolatile())
1970 if (!S.isSplittable())
1972 }
else if (
IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
1976 }
else if (U->get()->getType()->getPointerElementType()->isStructTy()) {
1979 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
1983 if (P.beginOffset() > S.beginOffset() || P.endOffset() < S.endOffset()) {
1989 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
1993 if (P.beginOffset() > S.beginOffset() || P.endOffset() < S.endOffset()) {
2020 Type *CommonEltTy =
nullptr;
2021 bool HaveCommonEltTy =
true;
2022 auto CheckCandidateType = [&](
Type *Ty) {
2023 if (
auto *VTy = dyn_cast<VectorType>(Ty)) {
2026 CommonEltTy = VTy->getElementType();
2027 else if (CommonEltTy != VTy->getElementType())
2028 HaveCommonEltTy =
false;
2032 for (
const Slice &S : P)
2033 if (S.beginOffset() == P.beginOffset() &&
2034 S.endOffset() == P.endOffset()) {
2035 if (
auto *LI = dyn_cast<LoadInst>(S.getUse()->getUser()))
2036 CheckCandidateType(LI->
getType());
2037 else if (
auto *SI = dyn_cast<StoreInst>(S.getUse()->getUser()))
2042 if (CandidateTys.
empty())
2049 if (!HaveCommonEltTy) {
2050 CandidateTys.
erase(std::remove_if(CandidateTys.
begin(), CandidateTys.
end(),
2052 return !VTy->getElementType()->isIntegerTy();
2054 CandidateTys.
end());
2057 if (CandidateTys.
empty())
2064 "Cannot have vector types of different sizes!");
2066 "All non-integer types eliminated!");
2067 assert(LHSTy->getElementType()->isIntegerTy() &&
2068 "All non-integer types eliminated!");
2071 std::sort(CandidateTys.
begin(), CandidateTys.
end(), RankVectorTypes);
2073 std::unique(CandidateTys.
begin(), CandidateTys.
end(), RankVectorTypes),
2074 CandidateTys.
end());
2080 assert(VTy->getElementType() == CommonEltTy &&
2081 "Unaccounted for element type!");
2082 assert(VTy == CandidateTys[0] &&
2083 "Different vector types with the same element type!");
2086 CandidateTys.resize(1);
2090 auto CheckVectorTypeForPromotion = [&](
VectorType *VTy) {
2095 if (ElementSize % 8)
2098 "vector size not a multiple of element size?");
2101 for (
const Slice &S : P)
2105 for (
const Slice *S : P.splitSliceTails())
2112 if (CheckVectorTypeForPromotion(VTy))
2123 uint64_t AllocBeginOffset,
2126 bool &WholeAllocaOp) {
2129 uint64_t RelBegin = S.beginOffset() - AllocBeginOffset;
2130 uint64_t RelEnd = S.endOffset() - AllocBeginOffset;
2137 Use *U = S.getUse();
2139 if (
LoadInst *LI = dyn_cast<LoadInst>(U->getUser())) {
2148 if (!isa<VectorType>(LI->
getType()) && RelBegin == 0 && RelEnd == Size)
2149 WholeAllocaOp =
true;
2153 }
else if (RelBegin != 0 || RelEnd != Size ||
2159 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(U->getUser())) {
2169 if (!isa<VectorType>(ValueTy) && RelBegin == 0 && RelEnd == Size)
2170 WholeAllocaOp =
true;
2171 if (
IntegerType *ITy = dyn_cast<IntegerType>(ValueTy)) {
2174 }
else if (RelBegin != 0 || RelEnd != Size ||
2180 }
else if (
MemIntrinsic *
MI = dyn_cast<MemIntrinsic>(U->getUser())) {
2181 if (
MI->isVolatile() || !isa<Constant>(
MI->getLength()))
2183 if (!S.isSplittable())
2185 }
else if (
IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
2206 if (SizeInBits > IntegerType::MAX_INT_BITS)
2216 Type *IntTy = Type::getIntNTy(AllocaTy->
getContext(), SizeInBits);
2228 bool WholeAllocaOp =
2231 for (
const Slice &S : P)
2236 for (
const Slice *S : P.splitSliceTails())
2241 return WholeAllocaOp;
2247 DEBUG(
dbgs() <<
" start: " << *V <<
"\n");
2250 "Element extends past full value");
2251 uint64_t ShAmt = 8 * Offset;
2255 V = IRB.CreateLShr(V, ShAmt, Name +
".shift");
2256 DEBUG(
dbgs() <<
" shifted: " << *V <<
"\n");
2259 "Cannot extract to a larger integer!");
2261 V = IRB.CreateTrunc(V, Ty, Name +
".trunc");
2262 DEBUG(
dbgs() <<
" trunced: " << *V <<
"\n");
2271 assert(Ty->getBitWidth() <= IntTy->
getBitWidth() &&
2272 "Cannot insert a larger integer!");
2273 DEBUG(
dbgs() <<
" start: " << *V <<
"\n");
2275 V = IRB.CreateZExt(V, IntTy, Name +
".ext");
2276 DEBUG(
dbgs() <<
" extended: " << *V <<
"\n");
2279 "Element store outside of alloca store");
2280 uint64_t ShAmt = 8 * Offset;
2284 V = IRB.CreateShl(V, ShAmt, Name +
".shift");
2285 DEBUG(
dbgs() <<
" shifted: " << *V <<
"\n");
2288 if (ShAmt || Ty->getBitWidth() < IntTy->
getBitWidth()) {
2290 Old = IRB.CreateAnd(Old, Mask, Name +
".mask");
2291 DEBUG(
dbgs() <<
" masked: " << *Old <<
"\n");
2292 V = IRB.CreateOr(Old, V, Name +
".insert");
2293 DEBUG(
dbgs() <<
" inserted: " << *V <<
"\n");
2301 unsigned NumElements = EndIndex - BeginIndex;
2302 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2307 if (NumElements == 1) {
2308 V = IRB.CreateExtractElement(V, IRB.getInt32(BeginIndex),
2310 DEBUG(
dbgs() <<
" extract: " << *V <<
"\n");
2316 for (
unsigned i = BeginIndex; i != EndIndex; ++i)
2318 V = IRB.CreateShuffleVector(V, UndefValue::get(V->
getType()),
2319 ConstantVector::get(Mask), Name +
".extract");
2320 DEBUG(
dbgs() <<
" shuffle: " << *V <<
"\n");
2325 unsigned BeginIndex,
const Twine &
Name) {
2327 assert(VecTy &&
"Can only insert a vector into a vector");
2332 V = IRB.CreateInsertElement(Old, V, IRB.getInt32(BeginIndex),
2334 DEBUG(
dbgs() <<
" insert: " << *V <<
"\n");
2339 "Too many elements!");
2341 assert(V->
getType() == VecTy &&
"Vector type mismatch");
2353 if (i >= BeginIndex && i < EndIndex)
2354 Mask.
push_back(IRB.getInt32(i - BeginIndex));
2356 Mask.
push_back(UndefValue::get(IRB.getInt32Ty()));
2357 V = IRB.CreateShuffleVector(V, UndefValue::get(V->
getType()),
2358 ConstantVector::get(Mask), Name +
".expand");
2359 DEBUG(
dbgs() <<
" shuffle: " << *V <<
"\n");
2363 Mask.
push_back(IRB.getInt1(i >= BeginIndex && i < EndIndex));
2365 V = IRB.CreateSelect(ConstantVector::get(Mask), V, Old, Name +
"blend");
2367 DEBUG(
dbgs() <<
" blend: " << *V <<
"\n");
2378 class AllocaSliceRewriter :
public InstVisitor<AllocaSliceRewriter, bool> {
2387 const uint64_t NewAllocaBeginOffset, NewAllocaEndOffset;
2407 uint64_t ElementSize;
2411 uint64_t BeginOffset, EndOffset;
2414 uint64_t NewBeginOffset, NewEndOffset;
2431 AllocaSliceRewriter(
const DataLayout &DL, AllocaSlices &AS, SROA &
Pass,
2433 uint64_t NewAllocaBeginOffset,
2434 uint64_t NewAllocaEndOffset,
bool IsIntegerPromotable,
2438 : DL(DL), AS(AS), Pass(Pass), OldAI(OldAI), NewAI(NewAI),
2439 NewAllocaBeginOffset(NewAllocaBeginOffset),
2440 NewAllocaEndOffset(NewAllocaEndOffset),
2441 NewAllocaTy(NewAI.getAllocatedType()),
2442 IntTy(IsIntegerPromotable
2445 DL.getTypeSizeInBits(NewAI.getAllocatedType()))
2447 VecTy(PromotableVecTy),
2448 ElementTy(VecTy ? VecTy->getElementType() : nullptr),
2449 ElementSize(VecTy ? DL.getTypeSizeInBits(ElementTy) / 8 : 0),
2450 BeginOffset(), EndOffset(), IsSplittable(), IsSplit(), OldUse(),
2451 OldPtr(), PHIUsers(PHIUsers), SelectUsers(SelectUsers),
2455 "Only multiple-of-8 sized vector elements are viable");
2458 assert((!IntTy && !VecTy) || (IntTy && !VecTy) || (!IntTy && VecTy));
2461 bool visit(AllocaSlices::const_iterator I) {
2462 bool CanSROA =
true;
2463 BeginOffset = I->beginOffset();
2464 EndOffset = I->endOffset();
2465 IsSplittable = I->isSplittable();
2467 BeginOffset < NewAllocaBeginOffset || EndOffset > NewAllocaEndOffset;
2468 DEBUG(
dbgs() <<
" rewriting " << (IsSplit ?
"split " :
""));
2473 assert(BeginOffset < NewAllocaEndOffset);
2474 assert(EndOffset > NewAllocaBeginOffset);
2475 NewBeginOffset = std::max(BeginOffset, NewAllocaBeginOffset);
2476 NewEndOffset =
std::min(EndOffset, NewAllocaEndOffset);
2478 SliceSize = NewEndOffset - NewBeginOffset;
2480 OldUse = I->getUse();
2481 OldPtr = cast<Instruction>(OldUse->get());
2483 Instruction *OldUserI = cast<Instruction>(OldUse->getUser());
2484 IRB.SetInsertPoint(OldUserI);
2485 IRB.SetCurrentDebugLocation(OldUserI->getDebugLoc());
2488 CanSROA &=
visit(cast<Instruction>(OldUse->getUser()));
2500 DEBUG(
dbgs() <<
" !!!! Cannot rewrite: " << I <<
"\n");
2507 assert(IsSplit || BeginOffset == NewBeginOffset);
2508 uint64_t Offset = NewBeginOffset - NewAllocaBeginOffset;
2513 size_t LastSROAPrefix = OldName.
rfind(
".sroa.");
2515 OldName = OldName.
substr(LastSROAPrefix + strlen(
".sroa."));
2520 OldName = OldName.
substr(IndexEnd + 1);
2524 OldName = OldName.
substr(OffsetEnd + 1);
2528 OldName = OldName.
substr(0, OldName.
find(
".sroa_"));
2534 Twine(OldName) +
"."
2546 unsigned getSliceAlign(
Type *Ty =
nullptr) {
2551 MinAlign(NewAIAlign, NewBeginOffset - NewAllocaBeginOffset);
2555 unsigned getIndex(uint64_t Offset) {
2556 assert(VecTy &&
"Can only call getIndex when rewriting a vector");
2557 uint64_t RelOffset = Offset - NewAllocaBeginOffset;
2558 assert(RelOffset / ElementSize < UINT32_MAX &&
"Index out of bounds");
2559 uint32_t Index = RelOffset / ElementSize;
2560 assert(Index * ElementSize == RelOffset);
2564 void deleteIfTriviallyDead(
Value *V) {
2567 Pass.DeadInsts.insert(I);
2570 Value *rewriteVectorizedLoadInst() {
2571 unsigned BeginIndex = getIndex(NewBeginOffset);
2572 unsigned EndIndex = getIndex(NewEndOffset);
2573 assert(EndIndex > BeginIndex &&
"Empty vector!");
2580 assert(IntTy &&
"We cannot insert an integer to the alloca");
2584 assert(NewBeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
2585 uint64_t Offset = NewBeginOffset - NewAllocaBeginOffset;
2586 if (Offset > 0 || NewEndOffset < NewAllocaEndOffset)
2593 DEBUG(
dbgs() <<
" original: " << LI <<
"\n");
2595 assert(OldOp == OldPtr);
2600 bool IsPtrAdjusted =
false;
2603 V = rewriteVectorizedLoadInst();
2605 V = rewriteIntegerLoad(LI);
2606 }
else if (NewBeginOffset == NewAllocaBeginOffset &&
2607 NewEndOffset == NewAllocaEndOffset &&
2609 (IsLoadPastEnd && NewAllocaTy->isIntegerTy() &&
2620 if (
auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
2621 if (
auto *TITy = dyn_cast<IntegerType>(TargetTy))
2622 if (AITy->getBitWidth() < TITy->getBitWidth()) {
2623 V = IRB.CreateZExt(V, TITy,
"load.ext");
2625 V = IRB.CreateShl(V, TITy->getBitWidth() - AITy->getBitWidth(),
2630 LoadInst *NewLI = IRB.CreateAlignedLoad(getNewAllocaSlicePtr(IRB, LTy),
2631 getSliceAlign(TargetTy),
2637 IsPtrAdjusted =
true;
2644 "Only integer type loads and stores are split");
2646 "Split load isn't smaller than original load");
2649 "Non-byte-multiple bit width");
2656 Value *Placeholder =
2658 V =
insertInteger(DL, IRB, Placeholder, V, NewBeginOffset - BeginOffset,
2667 Pass.DeadInsts.insert(&LI);
2668 deleteIfTriviallyDead(OldOp);
2675 unsigned BeginIndex = getIndex(NewBeginOffset);
2676 unsigned EndIndex = getIndex(NewEndOffset);
2677 assert(EndIndex > BeginIndex &&
"Empty vector!");
2678 unsigned NumElements = EndIndex - BeginIndex;
2679 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2680 Type *SliceTy = (NumElements == 1)
2691 Pass.DeadInsts.insert(&SI);
2694 DEBUG(
dbgs() <<
" to: " << *Store <<
"\n");
2699 assert(IntTy &&
"We cannot extract an integer from the alloca");
2703 IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"oldload");
2705 assert(BeginOffset >= NewAllocaBeginOffset &&
"Out of bounds offset");
2706 uint64_t Offset = BeginOffset - NewAllocaBeginOffset;
2711 Pass.DeadInsts.insert(&SI);
2713 DEBUG(
dbgs() <<
" to: " << *Store <<
"\n");
2718 DEBUG(
dbgs() <<
" original: " << SI <<
"\n");
2720 assert(OldOp == OldPtr);
2728 Pass.PostPromotionWorklist.insert(AI);
2733 "Only integer type loads and stores are split");
2736 "Non-byte-multiple bit width");
2738 V =
extractInteger(DL, IRB, V, NarrowTy, NewBeginOffset - BeginOffset,
2743 return rewriteVectorizedStoreInst(V, SI, OldOp);
2745 return rewriteIntegerStore(V, SI);
2749 if (NewBeginOffset == NewAllocaBeginOffset &&
2750 NewEndOffset == NewAllocaEndOffset &&
2752 (IsStorePastEnd && NewAllocaTy->isIntegerTy() &&
2757 if (
auto *VITy = dyn_cast<IntegerType>(V->
getType()))
2758 if (
auto *AITy = dyn_cast<IntegerType>(NewAllocaTy))
2759 if (VITy->getBitWidth() > AITy->getBitWidth()) {
2761 V = IRB.CreateLShr(V, VITy->getBitWidth() - AITy->getBitWidth(),
2763 V = IRB.CreateTrunc(V, AITy,
"load.trunc");
2767 NewSI = IRB.CreateAlignedStore(V, &NewAI, NewAI.
getAlignment(),
2771 NewSI = IRB.CreateAlignedStore(V, NewPtr, getSliceAlign(V->
getType()),
2776 Pass.DeadInsts.insert(&SI);
2777 deleteIfTriviallyDead(OldOp);
2779 DEBUG(
dbgs() <<
" to: " << *NewSI <<
"\n");
2780 return NewSI->getPointerOperand() == &NewAI && !SI.
isVolatile();
2792 Value *getIntegerSplat(
Value *V,
unsigned Size) {
2793 assert(Size > 0 &&
"Expected a positive number of bytes.");
2795 assert(VTy->
getBitWidth() == 8 &&
"Expected an i8 value for the byte");
2801 IRB.CreateZExt(V, SplatIntTy,
"zext"),
2811 Value *getVectorSplat(
Value *V,
unsigned NumElements) {
2812 V = IRB.CreateVectorSplat(NumElements, V,
"vsplat");
2813 DEBUG(
dbgs() <<
" splat: " << *V <<
"\n");
2818 DEBUG(
dbgs() <<
" original: " << II <<
"\n");
2825 assert(NewBeginOffset == BeginOffset);
2826 II.
setDest(getNewAllocaSlicePtr(IRB, OldPtr->getType()));
2830 deleteIfTriviallyDead(OldPtr);
2835 Pass.DeadInsts.insert(&II);
2842 if (!VecTy && !IntTy &&
2843 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
2851 getNewAllocaSlicePtr(IRB, OldPtr->getType()), II.
getValue(), Size,
2854 DEBUG(
dbgs() <<
" to: " << *New <<
"\n");
2867 assert(ElementTy == ScalarTy);
2869 unsigned BeginIndex = getIndex(NewBeginOffset);
2870 unsigned EndIndex = getIndex(NewEndOffset);
2871 assert(EndIndex > BeginIndex &&
"Empty vector!");
2872 unsigned NumElements = EndIndex - BeginIndex;
2873 assert(NumElements <= VecTy->getNumElements() &&
"Too many elements!");
2878 if (NumElements > 1)
2879 Splat = getVectorSplat(Splat, NumElements);
2882 IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"oldload");
2889 uint64_t Size = NewEndOffset - NewBeginOffset;
2890 V = getIntegerSplat(II.
getValue(), Size);
2892 if (IntTy && (BeginOffset != NewAllocaBeginOffset ||
2893 EndOffset != NewAllocaBeginOffset)) {
2895 IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"oldload");
2897 uint64_t Offset = NewBeginOffset - NewAllocaBeginOffset;
2900 assert(V->
getType() == IntTy &&
2901 "Wrong type for an alloca wide integer!");
2906 assert(NewBeginOffset == NewAllocaBeginOffset);
2907 assert(NewEndOffset == NewAllocaEndOffset);
2910 if (
VectorType *AllocaVecTy = dyn_cast<VectorType>(AllocaTy))
2911 V = getVectorSplat(V, AllocaVecTy->getNumElements());
2919 DEBUG(
dbgs() <<
" to: " << *New <<
"\n");
2927 DEBUG(
dbgs() <<
" original: " << II <<
"\n");
2930 assert((IsDest && II.
getRawDest() == OldPtr) ||
2933 unsigned SliceAlign = getSliceAlign();
2942 if (!IsSplittable) {
2943 Value *AdjustedPtr = getNewAllocaSlicePtr(IRB, OldPtr->getType());
2956 deleteIfTriviallyDead(OldPtr);
2969 (BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
2976 if (EmitMemCpy && &OldAI == &NewAI) {
2978 assert(NewBeginOffset == BeginOffset);
2981 if (NewEndOffset != EndOffset)
2983 NewEndOffset - NewBeginOffset));
2987 Pass.DeadInsts.insert(&II);
2994 assert(AI != &OldAI && AI != &NewAI &&
2995 "Splittable transfers cannot reach the same alloca on both ends.");
2996 Pass.Worklist.insert(AI);
3004 APInt OtherOffset(IntPtrWidth, NewBeginOffset - BeginOffset);
3006 OtherOffset.zextOrTrunc(64).getZExtValue());
3011 OtherPtr =
getAdjustedPtr(IRB, DL, OtherPtr, OtherOffset, OtherPtrTy,
3014 Value *OurPtr = getNewAllocaSlicePtr(IRB, OldPtr->getType());
3019 IsDest ? OurPtr : OtherPtr, IsDest ? OtherPtr : OurPtr, Size,
3022 DEBUG(
dbgs() <<
" to: " << *New <<
"\n");
3026 bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset &&
3027 NewEndOffset == NewAllocaEndOffset;
3028 uint64_t Size = NewEndOffset - NewBeginOffset;
3029 unsigned BeginIndex = VecTy ? getIndex(NewBeginOffset) : 0;
3030 unsigned EndIndex = VecTy ? getIndex(NewEndOffset) : 0;
3031 unsigned NumElements = EndIndex - BeginIndex;
3037 if (VecTy && !IsWholeAlloca) {
3038 if (NumElements == 1)
3039 OtherPtrTy = VecTy->getElementType();
3044 }
else if (IntTy && !IsWholeAlloca) {
3051 OtherPtr->getName() +
".");
3052 unsigned SrcAlign = OtherAlign;
3053 Value *DstPtr = &NewAI;
3054 unsigned DstAlign = SliceAlign;
3061 if (VecTy && !IsWholeAlloca && !IsDest) {
3062 Src = IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"load");
3064 }
else if (IntTy && !IsWholeAlloca && !IsDest) {
3065 Src = IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"load");
3067 uint64_t Offset = NewBeginOffset - NewAllocaBeginOffset;
3071 IRB.CreateAlignedLoad(SrcPtr, SrcAlign, II.
isVolatile(),
"copyload");
3074 if (VecTy && !IsWholeAlloca && IsDest) {
3076 IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"oldload");
3078 }
else if (IntTy && !IsWholeAlloca && IsDest) {
3080 IRB.CreateAlignedLoad(&NewAI, NewAI.
getAlignment(),
"oldload");
3082 uint64_t Offset = NewBeginOffset - NewAllocaBeginOffset;
3088 IRB.CreateAlignedStore(Src, DstPtr, DstAlign, II.
isVolatile()));
3090 DEBUG(
dbgs() <<
" to: " << *Store <<
"\n");
3097 DEBUG(
dbgs() <<
" original: " << II <<
"\n");
3101 Pass.DeadInsts.insert(&II);
3105 NewEndOffset - NewBeginOffset);
3106 Value *Ptr = getNewAllocaSlicePtr(IRB, OldPtr->getType());
3109 New = IRB.CreateLifetimeStart(Ptr, Size);
3111 New = IRB.CreateLifetimeEnd(Ptr, Size);
3114 DEBUG(
dbgs() <<
" to: " << *New <<
"\n");
3119 DEBUG(
dbgs() <<
" original: " << PN <<
"\n");
3120 assert(BeginOffset >= NewAllocaBeginOffset &&
"PHIs are unsplittable");
3121 assert(EndOffset <= NewAllocaEndOffset &&
"PHIs are unsplittable");
3127 IRBuilderTy PtrBuilder(IRB);
3128 if (isa<PHINode>(OldPtr))
3129 PtrBuilder.SetInsertPoint(OldPtr->getParent()->getFirstInsertionPt());
3131 PtrBuilder.SetInsertPoint(OldPtr);
3132 PtrBuilder.SetCurrentDebugLocation(OldPtr->getDebugLoc());
3134 Value *NewPtr = getNewAllocaSlicePtr(PtrBuilder, OldPtr->getType());
3136 std::replace(PN.
op_begin(), PN.
op_end(), cast<Value>(OldPtr), NewPtr);
3139 deleteIfTriviallyDead(OldPtr);
3149 DEBUG(
dbgs() <<
" original: " << SI <<
"\n");
3151 "Pointer isn't an operand!");
3152 assert(BeginOffset >= NewAllocaBeginOffset &&
"Selects are unsplittable");
3153 assert(EndOffset <= NewAllocaEndOffset &&
"Selects are unsplittable");
3155 Value *NewPtr = getNewAllocaSlicePtr(IRB, OldPtr->getType());
3163 deleteIfTriviallyDead(OldPtr);
3180 class AggLoadStoreRewriter :
public InstVisitor<AggLoadStoreRewriter, bool> {
3197 AggLoadStoreRewriter(
const DataLayout &DL) : DL(DL) {}
3202 DEBUG(
dbgs() <<
" Rewriting FCA loads and stores...\n");
3204 bool Changed =
false;
3205 while (!Queue.empty()) {
3206 U = Queue.pop_back_val();
3207 Changed |=
visit(cast<Instruction>(U->getUser()));
3217 if (Visited.
insert(U.getUser()).second)
3218 Queue.push_back(&U);
3225 template <
typename Derived>
class OpSplitter {
3242 : IRB(InsertionPoint), GEPIndices(1, IRB.getInt32(0)), Ptr(Ptr) {}
3260 return static_cast<Derived *>(
this)->emitFunc(Ty, Agg, Name);
3262 if (
ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
3263 unsigned OldSize = Indices.size();
3265 for (
unsigned Idx = 0, Size = ATy->getNumElements(); Idx != Size;
3267 assert(Indices.size() == OldSize &&
"Did not return to the old size");
3268 Indices.push_back(Idx);
3269 GEPIndices.push_back(IRB.getInt32(Idx));
3270 emitSplitOps(ATy->getElementType(), Agg, Name +
"." +
Twine(Idx));
3271 GEPIndices.pop_back();
3277 if (
StructType *STy = dyn_cast<StructType>(Ty)) {
3278 unsigned OldSize = Indices.size();
3280 for (
unsigned Idx = 0, Size = STy->getNumElements(); Idx != Size;
3282 assert(Indices.size() == OldSize &&
"Did not return to the old size");
3283 Indices.push_back(Idx);
3284 GEPIndices.push_back(IRB.getInt32(Idx));
3285 emitSplitOps(STy->getElementType(Idx), Agg, Name +
"." +
Twine(Idx));
3286 GEPIndices.pop_back();
3296 struct LoadOpSplitter :
public OpSplitter<LoadOpSplitter> {
3298 : OpSplitter<LoadOpSplitter>(InsertionPoint, Ptr) {}
3306 IRB.CreateInBoundsGEP(
nullptr, Ptr, GEPIndices, Name +
".gep");
3307 Value *
Load = IRB.CreateLoad(GEP, Name +
".load");
3308 Agg = IRB.CreateInsertValue(Agg, Load, Indices, Name +
".insert");
3309 DEBUG(
dbgs() <<
" to: " << *Load <<
"\n");
3319 DEBUG(
dbgs() <<
" original: " << LI <<
"\n");
3320 LoadOpSplitter Splitter(&LI, *U);
3328 struct StoreOpSplitter :
public OpSplitter<StoreOpSplitter> {
3330 : OpSplitter<StoreOpSplitter>(InsertionPoint, Ptr) {}
3337 Value *Store = IRB.CreateStore(
3338 IRB.CreateExtractValue(Agg, Indices, Name +
".extract"),
3339 IRB.CreateInBoundsGEP(
nullptr, Ptr, GEPIndices, Name +
".gep"));
3341 DEBUG(
dbgs() <<
" to: " << *Store <<
"\n");
3353 DEBUG(
dbgs() <<
" original: " << SI <<
"\n");
3354 StoreOpSplitter Splitter(&SI, *U);
3370 bool visitPHINode(
PHINode &PN) {
3395 if (
ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) {
3396 InnerTy = ArrTy->getElementType();
3397 }
else if (
StructType *STy = dyn_cast<StructType>(Ty)) {
3400 InnerTy = STy->getElementType(Index);
3435 if (SeqTy->isPointerTy())
3438 Type *ElementTy = SeqTy->getElementType();
3440 uint64_t NumSkippedElements = Offset / ElementSize;
3441 if (
ArrayType *ArrTy = dyn_cast<ArrayType>(SeqTy)) {
3442 if (NumSkippedElements >= ArrTy->getNumElements())
3444 }
else if (
VectorType *VecTy = dyn_cast<VectorType>(SeqTy)) {
3445 if (NumSkippedElements >= VecTy->getNumElements())
3448 Offset -= NumSkippedElements * ElementSize;
3451 if (Offset > 0 || Size < ElementSize) {
3453 if ((Offset + Size) > ElementSize)
3458 assert(Offset == 0);
3460 if (Size == ElementSize)
3462 assert(Size > ElementSize);
3463 uint64_t NumElements = Size / ElementSize;
3464 if (NumElements * ElementSize != Size)
3466 return ArrayType::get(ElementTy, NumElements);
3476 uint64_t EndOffset = Offset + Size;
3485 if (Offset >= ElementSize)
3489 if (Offset > 0 || Size < ElementSize) {
3490 if ((Offset + Size) > ElementSize)
3494 assert(Offset == 0);
3496 if (Size == ElementSize)
3501 if (EndOffset < SL->getSizeInBytes()) {
3503 if (Index == EndIndex)
3513 assert(Index < EndIndex);
3521 if (Size != SubSL->getSizeInBytes())
3557 bool SROA::presplitLoadsAndStores(
AllocaInst &AI, AllocaSlices &AS) {
3558 DEBUG(
dbgs() <<
"Pre-splitting loads and stores\n");
3571 struct SplitOffsets {
3573 std::vector<uint64_t> Splits;
3590 DEBUG(
dbgs() <<
" Searching for candidate loads and stores\n");
3591 for (
auto &P : AS.partitions()) {
3592 for (Slice &S : P) {
3593 Instruction *I = cast<Instruction>(S.getUse()->getUser());
3594 if (!S.isSplittable() ||S.endOffset() <= P.endOffset()) {
3597 if (
auto *LI = dyn_cast<LoadInst>(I))
3598 UnsplittableLoads.
insert(LI);
3601 assert(P.endOffset() > S.beginOffset() &&
3602 "Empty or backwards partition!");
3605 if (
auto *LI = dyn_cast<LoadInst>(I)) {
3606 assert(!LI->
isVolatile() &&
"Cannot split volatile loads!");
3611 auto IsLoadSimplyStored = [](
LoadInst *LI) {
3619 if (!IsLoadSimplyStored(LI)) {
3620 UnsplittableLoads.
insert(LI);
3625 }
else if (
auto *SI = dyn_cast<StoreInst>(S.getUse()->getUser())) {
3630 if (!StoredLoad || !StoredLoad->isSimple())
3632 assert(!SI->
isVolatile() &&
"Cannot split volatile stores!");
3641 DEBUG(
dbgs() <<
" Candidate: " << *I <<
"\n");
3642 auto &
Offsets = SplitOffsetsMap[
I];
3643 assert(
Offsets.Splits.empty() &&
3644 "Should not have splits the first time we see an instruction!");
3646 Offsets.Splits.push_back(P.endOffset() - S.beginOffset());
3651 for (Slice *S : P.splitSliceTails()) {
3652 auto SplitOffsetsMapI =
3653 SplitOffsetsMap.
find(cast<Instruction>(S->getUse()->getUser()));
3654 if (SplitOffsetsMapI == SplitOffsetsMap.
end())
3656 auto &
Offsets = SplitOffsetsMapI->second;
3658 assert(
Offsets.S == S &&
"Found a mismatched slice!");
3659 assert(!
Offsets.Splits.empty() &&
3660 "Cannot have an empty set of splits on the second partition!");
3661 assert(
Offsets.Splits.back() ==
3662 P.beginOffset() -
Offsets.S->beginOffset() &&
3663 "Previous split does not end where this one begins!");
3667 if (S->endOffset() > P.endOffset())
3668 Offsets.Splits.push_back(P.endOffset() -
Offsets.S->beginOffset());
3677 std::remove_if(Stores.
begin(), Stores.
end(),
3678 [&UnsplittableLoads, &SplitOffsetsMap](
StoreInst *
SI) {
3684 if (UnsplittableLoads.
count(LI))
3687 auto LoadOffsetsI = SplitOffsetsMap.
find(LI);
3688 if (LoadOffsetsI == SplitOffsetsMap.
end())
3690 auto &LoadOffsets = LoadOffsetsI->second;
3693 auto &StoreOffsets = SplitOffsetsMap[
SI];
3698 if (LoadOffsets.Splits == StoreOffsets.Splits)
3702 <<
" Mismatched splits for load and store:\n"
3703 <<
" " << *LI <<
"\n"
3704 <<
" " << *SI <<
"\n");
3710 UnsplittableLoads.
insert(LI);
3722 return UnsplittableLoads.
count(LI);
3728 [&UnsplittableLoads](
LoadInst *LI) {
3729 return UnsplittableLoads.
count(LI);
3741 IRBuilderTy IRB(&AI);
3759 std::vector<LoadInst *> SplitLoads;
3766 assert(LoadSize > 0 &&
"Cannot have a zero-sized integer load!");
3768 auto &
Offsets = SplitOffsetsMap[LI];
3769 assert(LoadSize ==
Offsets.S->endOffset() -
Offsets.S->beginOffset() &&
3770 "Slice size should always match load size exactly!");
3771 uint64_t BaseOffset =
Offsets.S->beginOffset();
3772 assert(BaseOffset + LoadSize > BaseOffset &&
3773 "Cannot represent alloca access size using 64-bit integers!");
3778 DEBUG(
dbgs() <<
" Splitting load: " << *LI <<
"\n");
3780 uint64_t PartOffset = 0, PartSize =
Offsets.Splits.front();
3781 int Idx = 0, Size =
Offsets.Splits.size();
3783 auto *PartTy = Type::getIntNTy(Ty->
getContext(), PartSize * 8);
3785 LoadInst *PLoad = IRB.CreateAlignedLoad(
3788 PartPtrTy, BasePtr->
getName() +
"."),
3794 SplitLoads.push_back(PLoad);
3798 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
3801 DEBUG(
dbgs() <<
" new slice [" << NewSlices.
back().beginOffset()
3802 <<
", " << NewSlices.
back().endOffset() <<
"): " << *PLoad
3810 PartOffset =
Offsets.Splits[Idx];
3812 PartSize = (Idx < Size ?
Offsets.Splits[Idx] : LoadSize) - PartOffset;
3818 bool DeferredStores =
false;
3821 if (!Stores.
empty() && SplitOffsetsMap.
count(SI)) {
3822 DeferredStores =
true;
3823 DEBUG(
dbgs() <<
" Deferred splitting of store: " << *SI <<
"\n");
3830 DEBUG(
dbgs() <<
" Splitting store of load: " << *SI <<
"\n");
3832 for (
int Idx = 0, Size = SplitLoads.size(); Idx < Size; ++Idx) {
3834 uint64_t PartOffset = Idx == 0 ? 0 :
Offsets.Splits[Idx - 1];
3838 StoreInst *PStore = IRB.CreateAlignedStore(
3841 PartPtrTy, StoreBasePtr->
getName() +
"."),
3844 DEBUG(
dbgs() <<
" +" << PartOffset <<
":" << *PStore <<
"\n");
3851 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(StoreBasePtr)) {
3852 ResplitPromotableAllocas.
insert(OtherAI);
3853 Worklist.insert(OtherAI);
3854 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
3856 Worklist.insert(OtherAI);
3860 DeadInsts.insert(SI);
3865 SplitLoadsMap.
insert(std::make_pair(LI, std::move(SplitLoads)));
3868 DeadInsts.insert(LI);
3881 assert(StoreSize > 0 &&
"Cannot have a zero-sized integer store!");
3884 assert(StoreSize ==
Offsets.S->endOffset() -
Offsets.S->beginOffset() &&
3885 "Slice size should always match load size exactly!");
3886 uint64_t BaseOffset =
Offsets.S->beginOffset();
3887 assert(BaseOffset + StoreSize > BaseOffset &&
3888 "Cannot represent alloca access size using 64-bit integers!");
3893 DEBUG(
dbgs() <<
" Splitting store: " << *SI <<
"\n");
3896 auto SplitLoadsMapI = SplitLoadsMap.
find(LI);
3897 std::vector<LoadInst *> *SplitLoads =
nullptr;
3898 if (SplitLoadsMapI != SplitLoadsMap.
end()) {
3899 SplitLoads = &SplitLoadsMapI->second;
3900 assert(SplitLoads->size() ==
Offsets.Splits.size() + 1 &&
3901 "Too few split loads for the number of splits in the store!");
3903 DEBUG(
dbgs() <<
" of load: " << *LI <<
"\n");
3906 uint64_t PartOffset = 0, PartSize =
Offsets.Splits.front();
3907 int Idx = 0, Size =
Offsets.Splits.size();
3909 auto *PartTy = Type::getIntNTy(Ty->getContext(), PartSize * 8);
3915 PLoad = (*SplitLoads)[Idx];
3918 PLoad = IRB.CreateAlignedLoad(
3921 PartPtrTy, LoadBasePtr->
getName() +
"."),
3928 StoreInst *PStore = IRB.CreateAlignedStore(
3931 PartPtrTy, StoreBasePtr->
getName() +
"."),
3936 Slice(BaseOffset + PartOffset, BaseOffset + PartOffset + PartSize,
3939 DEBUG(
dbgs() <<
" new slice [" << NewSlices.
back().beginOffset()
3940 <<
", " << NewSlices.
back().endOffset() <<
"): " << *PStore
3943 DEBUG(
dbgs() <<
" of split load: " << *PLoad <<
"\n");
3951 PartOffset =
Offsets.Splits[Idx];
3953 PartSize = (Idx < Size ?
Offsets.Splits[Idx] : StoreSize) - PartOffset;
3962 if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(LoadBasePtr)) {
3963 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
3964 ResplitPromotableAllocas.
insert(OtherAI);
3965 Worklist.insert(OtherAI);
3966 }
else if (
AllocaInst *OtherAI = dyn_cast<AllocaInst>(
3968 assert(OtherAI != &AI &&
"We can't re-split our own alloca!");
3969 Worklist.insert(OtherAI);
3983 assert(*LI->
user_begin() == SI &&
"Single use isn't this store!");
3984 DeadInsts.insert(LI);
3986 DeadInsts.insert(SI);
3991 AS.erase(std::remove_if(AS.begin(), AS.end(), [](
const Slice &S) {
3997 AS.insert(NewSlices);
3999 DEBUG(
dbgs() <<
" Pre-split slices:\n");
4001 for (
auto I = AS.begin(), E = AS.end(); I != E; ++
I)
4007 PromotableAllocas.erase(
4009 PromotableAllocas.begin(), PromotableAllocas.end(),
4011 PromotableAllocas.end());
4027 AllocaSlices::Partition &P) {
4031 Type *SliceTy =
nullptr;
4035 SliceTy = CommonUseTy;
4038 P.beginOffset(), P.size()))
4039 SliceTy = TypePartitionTy;
4040 if ((!SliceTy || (SliceTy->
isArrayTy() &&
4043 SliceTy = Type::getIntNTy(*
C, P.size() * 8);
4045 SliceTy = ArrayType::get(Type::getInt8Ty(*
C), P.size());
4061 assert(P.beginOffset() == 0 &&
4062 "Non-zero begin offset but same alloca type");
4075 Alignment =
MinAlign(Alignment, P.beginOffset());
4081 SliceTy,
nullptr, Alignment,
4082 AI.
getName() +
".sroa." +
Twine(P.begin() - AS.begin()), &AI);
4086 DEBUG(
dbgs() <<
"Rewriting alloca partition "
4087 <<
"[" << P.beginOffset() <<
"," << P.endOffset()
4088 <<
") to: " << *NewAI <<
"\n");
4093 unsigned PPWOldSize = PostPromotionWorklist.size();
4094 unsigned NumUses = 0;
4098 AllocaSliceRewriter
Rewriter(DL, AS, *
this, AI, *NewAI, P.beginOffset(),
4099 P.endOffset(), IsIntegerPromotable, VecTy,
4100 PHIUsers, SelectUsers);
4101 bool Promotable =
true;
4102 for (Slice *S : P.splitSliceTails()) {
4106 for (Slice &S : P) {
4111 NumAllocaPartitionUses += NumUses;
4112 MaxUsesPerAllocaPartition =
4113 std::max<unsigned>(NumUses, MaxUsesPerAllocaPartition);
4123 SelectUsers.
clear();
4127 E = SelectUsers.
end();
4132 SelectUsers.
clear();
4137 if (PHIUsers.empty() && SelectUsers.
empty()) {
4139 PromotableAllocas.push_back(NewAI);
4144 for (
PHINode *PHIUser : PHIUsers)
4145 SpeculatablePHIs.insert(PHIUser);
4147 SpeculatableSelects.insert(SelectUser);
4148 Worklist.insert(NewAI);
4155 Worklist.insert(NewAI);
4158 while (PostPromotionWorklist.size() > PPWOldSize)
4159 PostPromotionWorklist.pop_back();
4167 bool SROA::splitAlloca(
AllocaInst &AI, AllocaSlices &AS) {
4168 if (AS.begin() == AS.end())
4171 unsigned NumPartitions = 0;
4172 bool Changed =
false;
4176 Changed |= presplitLoadsAndStores(AI, AS);
4182 bool IsSorted =
true;
4183 for (Slice &S : AS) {
4184 if (!S.isSplittable())
4190 if (S.beginOffset() == 0 &&
4193 if (isa<LoadInst>(S.getUse()->getUser()) ||
4194 isa<StoreInst>(S.getUse()->getUser())) {
4195 S.makeUnsplittable();
4200 std::sort(AS.begin(), AS.end());
4208 Piece(
AllocaInst *AI, uint64_t O, uint64_t S)
4209 : Alloca(AI), Offset(O), Size(S) {}
4214 for (
auto &P : AS.partitions()) {
4215 if (
AllocaInst *NewAI = rewritePartition(AI, AS, P)) {
4218 uint64_t SizeOfByte = 8;
4221 uint64_t Size =
std::min(AllocaSize, P.size() * SizeOfByte);
4222 Pieces.
push_back(Piece(NewAI, P.beginOffset() * SizeOfByte, Size));
4228 NumAllocaPartitions += NumPartitions;
4229 MaxPartitionsPerAlloca =
4230 std::max<unsigned>(NumPartitions, MaxPartitionsPerAlloca);
4235 auto *Var = DbgDecl->getVariable();
4236 auto *Expr = DbgDecl->getExpression();
4239 bool IsSplit = Pieces.
size() > 1;
4240 for (
auto Piece : Pieces) {
4243 auto *PieceExpr = Expr;
4244 if (IsSplit || Expr->isBitPiece()) {
4247 uint64_t Offset = Expr->isBitPiece() ? Expr->getBitPieceOffset() : 0;
4248 uint64_t Start = Offset + Piece.Offset;
4249 uint64_t Size = Piece.Size;
4250 if (Expr->isBitPiece()) {
4251 uint64_t AbsEnd = Expr->getBitPieceOffset() + Expr->getBitPieceSize();
4252 if (Start >= AbsEnd)
4255 Size =
std::min(Size, AbsEnd - Start);
4257 PieceExpr = DIB.createBitPieceExpression(Start, Size);
4262 OldDDI->eraseFromParent();
4264 DIB.insertDeclare(Piece.Alloca, Var, PieceExpr, DbgDecl->getDebugLoc(),
4272 void SROA::clobberUse(
Use &U) {
4275 U = UndefValue::get(OldV->
getType());
4280 if (
Instruction *OldI = dyn_cast<Instruction>(OldV))
4282 DeadInsts.insert(OldI);
4292 DEBUG(
dbgs() <<
"SROA alloca: " << AI <<
"\n");
4293 ++NumAllocasAnalyzed;
4307 bool Changed =
false;
4311 AggLoadStoreRewriter AggRewriter(DL);
4312 Changed |= AggRewriter.rewrite(AI);
4315 AllocaSlices AS(DL, AI);
4323 for (
Use &DeadOp : DeadUser->operands())
4327 DeadUser->replaceAllUsesWith(UndefValue::get(DeadUser->getType()));
4330 DeadInsts.insert(DeadUser);
4333 for (
Use *DeadOp : AS.getDeadOperands()) {
4334 clobberUse(*DeadOp);
4339 if (AS.begin() == AS.end())
4342 Changed |= splitAlloca(AI, AS);
4345 while (!SpeculatablePHIs.empty())
4348 DEBUG(
dbgs() <<
" Speculating Selects\n");
4349 while (!SpeculatableSelects.empty())
4364 void SROA::deleteDeadInstructions(
4366 while (!DeadInsts.empty()) {
4368 DEBUG(
dbgs() <<
"Deleting dead instruction: " << *I <<
"\n");
4373 if (
Instruction *U = dyn_cast<Instruction>(Operand)) {
4377 DeadInsts.insert(U);
4380 if (
AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
4381 DeletedAllocas.
insert(AI);
4383 DbgDecl->eraseFromParent();
4395 if (Visited.
insert(cast<Instruction>(U)).second)
4396 Worklist.
push_back(cast<Instruction>(U));
4407 bool SROA::promoteAllocas(
Function &
F) {
4408 if (PromotableAllocas.empty())
4411 NumPromoted += PromotableAllocas.size();
4414 DEBUG(
dbgs() <<
"Promoting allocas with mem2reg...\n");
4416 PromotableAllocas.clear();
4420 DEBUG(
dbgs() <<
"Promoting allocas with SSAUpdater...\n");
4430 for (
unsigned Idx = 0, Size = PromotableAllocas.size(); Idx != Size; ++Idx) {
4438 while (!Worklist.
empty()) {
4455 if (
LoadInst *LI = dyn_cast<LoadInst>(I)) {
4460 if (
StoreInst *SI = dyn_cast<StoreInst>(I)) {
4462 Insts.push_back(SI);
4472 AllocaPromoter(Insts, SSA, *AI, DIB).run(Insts);
4473 while (!DeadInsts.
empty())
4478 PromotableAllocas.
clear();
4482 bool SROA::runOnFunction(
Function &F) {
4483 if (skipOptnoneFunction(F))
4489 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
4491 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
4496 if (
AllocaInst *AI = dyn_cast<AllocaInst>(I))
4500 bool Changed =
false;
4506 while (!Worklist.
empty()) {
4508 deleteDeadInstructions(DeletedAllocas);
4512 if (!DeletedAllocas.
empty()) {
4513 auto IsInSet = [&](
AllocaInst *AI) {
return DeletedAllocas.
count(AI); };
4514 Worklist.remove_if(IsInSet);
4515 PostPromotionWorklist.remove_if(IsInSet);
4516 PromotableAllocas.
erase(std::remove_if(PromotableAllocas.begin(),
4517 PromotableAllocas.end(),
4519 PromotableAllocas.end());
4520 DeletedAllocas.
clear();
4524 Changed |= promoteAllocas(F);
4526 Worklist = PostPromotionWorklist;
4527 PostPromotionWorklist.
clear();
4528 }
while (!Worklist.
empty());
4535 if (RequiresDomTree)
unsigned getAlignment() const
Scalar Replacement Of static false Type * 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 Value * getAdjustedPtr(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, APInt Offset, Type *PointerTy, Twine NamePrefix)
Compute an adjusted pointer from Ptr by Offset bytes where the resulting pointer has PointerTy...
RetTy visitSelectInst(SelectInst &I)
static bool isDereferenceablePointer(const Value *V, const DataLayout &DL, const Instruction *CtxI, const DominatorTree *DT, const TargetLibraryInfo *TLI, SmallPtrSetImpl< const Value * > &Visited)
Return true if Value is always a dereferenceable pointer.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type (if unknown returns 0).
Pass interface - Implemented by all 'passes'.
const Use & getOperandUse(unsigned i) const
Value * getValueOperand()
iplist< Instruction >::iterator eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing basic block and deletes it...
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
const_iterator end(StringRef path)
Get end iterator over path.
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
Value * getPointerOperand()
RetTy visitMemSetInst(MemSetInst &I)
iterator_range< use_iterator > uses()
Helper class for SSA formation on a set of values defined in multiple blocks.
void addIncoming(Value *V, BasicBlock *BB)
addIncoming - Add an incoming value to the end of the PHI list
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
LLVM Argument representation.
Base class for instruction visitors.
uint64_t getZExtValue() const
Get zero extended value.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
STATISTIC(NumFunctions,"Total number of functions")
bool isVolatile() const
isVolatile - Return true if this is a store to a volatile memory location.
SynchronizationScope getSynchScope() const
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
DbgDeclareInst * FindAllocaDbgDeclare(Value *V)
FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
Intrinsic::ID getIntrinsicID() const
getIntrinsicID - Return the intrinsic ID of this intrinsic.
static Value * getNaturalGEPWithOffset(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, APInt Offset, Type *TargetTy, SmallVectorImpl< Value * > &Indices, Twine NamePrefix)
Get a natural GEP from a base pointer to a particular offset and resulting in a particular type...
ConstantInt * getAlignmentCst() const
Value * getValue() const
get* - Return the arguments to the instruction.
This class represents zero extension of integer types.
unsigned getPointerTypeSizeInBits(Type *) const
Layout pointer size, in bits, based on the type.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
CallInst - This class represents a function call, abstracting a target machine's calling convention...
static Value * extractInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *V, IntegerType *Ty, uint64_t Offset, const Twine &Name)
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
An immutable pass that tracks lazily created AssumptionCache objects.
gep_type_iterator gep_type_end(const User *GEP)
bool mayHaveSideEffects() const
mayHaveSideEffects - Return true if the instruction may have side effects.
A cache of .assume calls within a function.
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
static cl::opt< bool > ForceSSAUpdater("force-ssa-updater", cl::init(false), cl::Hidden)
Hidden option to force the pass to not use DomTree and mem2reg, instead forming SSA values through th...
const_iterator begin(StringRef path)
Get begin iterator over path.
MemSetInst - This class wraps the llvm.memset intrinsic.
Scalar Replacement Of Aggregates
const Function * getParent() const
Return the enclosing method, or null if none.
This class represents a sign extension of integer types.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
LoadInst - an instruction for reading from memory.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
RetTy visitPHINode(PHINode &I)
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
void reserve(size_type N)
void setDest(Value *Ptr)
set* - Set the specified arguments of the instruction.
void setAlignment(Constant *A)
Tagged DWARF-like metadata node.
static unsigned getAdjustedAlignment(Instruction *I, uint64_t Offset, const DataLayout &DL)
Compute the adjusted alignment for a load or store from an offset.
Builder for the alloca slices.
Type * getPointerElementType() const
StringRef getName() const
Return a constant reference to the value's name.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
iterator begin()
Instruction iterator methods.
bool isSingleValueType() const
isSingleValueType - Return true if the type is a valid type for a register in codegen.
static Value * getNaturalGEPWithType(IRBuilderTy &IRB, const DataLayout &DL, Value *BasePtr, Type *Ty, Type *TargetTy, SmallVectorImpl< Value * > &Indices, Twine NamePrefix)
Get a natural GEP off of the BasePtr walking through Ty toward TargetTy without changing the offset o...
element_iterator element_end() const
static Value * buildGEP(IRBuilderTy &IRB, Value *BasePtr, SmallVectorImpl< Value * > &Indices, Twine NamePrefix)
Build a GEP out of a base pointer and indices.
bool isArrayAllocation() const
isArrayAllocation - Return true if there is an allocation size parameter to the allocation instructio...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
AnalysisUsage & addRequired()
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
#define INITIALIZE_PASS_DEPENDENCY(depName)
std::string str() const
Return the twine contents as a std::string.
void push_back(NodeTy *val)
static Value * getPointerOperand(Instruction &Inst)
SelectInst - This class represents the LLVM 'select' instruction.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Type::subtype_iterator element_iterator
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
RetTy visitIntrinsicInst(IntrinsicInst &I)
const APInt & getValue() const
Return the constant as an APInt value reference.
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
StructType - Class to represent struct types.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type * getArrayElementType() const
A Use represents the edge between a Value definition and its users.
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 void advance(T &it, size_t Val)
FunctionPass * createSROAPass(bool RequiresDomTree=true)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
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.
bool isSized(SmallPtrSetImpl< const Type * > *Visited=nullptr) const
isSized - Return true if it makes sense to take the size of this type.
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
DominatorTree & getDomTree()
element_iterator element_begin() const
This file provides a collection of visitors which walk the (instruction) uses of a pointer...
SynchronizationScope getSynchScope() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
void visit(Iterator Start, Iterator End)
void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AliasSetTracker *AST=nullptr, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
load Combine Adjacent Loads
static Constant * getZExt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
A base class for visitors over the uses of a pointer value.
LLVMContext & getContext() const
getContext - Return the LLVMContext in which this type was uniqued.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
ArrayType - Class to represent array types.
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
getLimitedValue - If the value is smaller than the specified limit, return it, otherwise return the l...
This class represents a no-op cast from one type to another.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
ConstantFolder - Create constants with minimum, target independent, folding.
StoreInst - an instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
bool isArrayTy() const
isArrayTy - True if this is an instance of ArrayType.
static Constant * getUDiv(Constant *C1, Constant *C2, bool isExact=false)
unsigned getNumElements() const
Return the number of elements in the Vector type.
RetTy visitMemTransferInst(MemTransferInst &I)
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Type * getElementType() const
static bool canConvertValue(const DataLayout &DL, Type *OldTy, Type *NewTy)
Test whether we can convert a value from the old to the new type.
bool isInBounds() const
isInBounds - Determine whether the GEP has the inbounds flag.
PointerType - Class to represent pointers.
unsigned getNumIncomingValues() const
getNumIncomingValues - Return the number of incoming edges
uint64_t getElementOffset(unsigned Idx) const
unsigned getNumSuccessors() const
Return the number of successors that this terminator has.
GetElementPtrInst - an instruction for type-safe pointer arithmetic to access elements of arrays and ...
Scalar Replacement Of false
initializer< Ty > init(const Ty &Val)
friend const_iterator end(StringRef path)
Get end iterator over path.
unsigned getAlignment() const
getAlignment - Return the alignment of the access that is being performed
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Subclasses of this class are all able to terminate a basic block.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void setAAMetadata(const AAMDNodes &N)
setAAMetadata - Sets the metadata on this instruction from the AAMDNodes structure.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
static unsigned getPointerOperandIndex()
This is an important class for using LLVM in a threaded context.
uint64_t getTypeStoreSizeInBits(Type *Ty) const
Returns the maximum number of bits that may be overwritten by storing the specified type; always a mu...
bool isVectorTy() const
isVectorTy - True if this is an instance of VectorType.
Type * getElementType(unsigned N) const
This is an important base class in LLVM.
const Value * getCondition() const
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool isSafeSelectToSpeculate(SelectInst &SI)
Select instructions that use an alloca and are subsequently loaded can be rewritten to load both inpu...
static VectorType * isVectorPromotionViable(AllocaSlices::Partition &P, const DataLayout &DL)
Test whether the given alloca partitioning and range of slices can be promoted to a vector...
unsigned getAlignment() const
getAlignment - Return the alignment of the memory that is being allocated by the instruction.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Value * getRawDest() const
Value * stripInBoundsOffsets()
Strip off pointer casts and inbounds GEPs.
Represent the analysis usage information of a pass.
static cl::opt< bool > SROAStrictInbounds("sroa-strict-inbounds", cl::init(false), cl::Hidden)
Hidden option to experiment with completely strict handling of inbounds GEPs.
BasicBlock * getIncomingBlock(unsigned i) const
getIncomingBlock - Return incoming basic block number i.
#define LLVM_ATTRIBUTE_UNUSED
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
FunctionPass class - This class is used to implement most global optimizations.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const
Signed division function for APInt.
Value * getOperand(unsigned i) const
Value * getPointerOperand()
Class to represent integer types.
static bool isIntegerWideningViable(AllocaSlices::Partition &P, Type *AllocaTy, const DataLayout &DL)
Test whether the given alloca partition's integer operations can be widened to promotable ones...
RetTy visitLoadInst(LoadInst &I)
void setAlignment(unsigned Align)
static Constant * getAllOnesValue(Type *Ty)
Get the all ones value.
bool isPointerTy() const
isPointerTy - True if this is an instance of PointerType.
static UndefValue * get(Type *T)
get() - Static factory methods - Return an 'undef' object of the specified type.
iterator erase(iterator I)
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.
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
LLVMContext & getContext() const
All values hold a context through their type.
PointerType * getPointerTo(unsigned AddrSpace=0)
getPointerTo - Return a pointer to the current type.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
const Value * getTrueValue() const
static Type * stripAggregateTypeWrapping(const DataLayout &DL, Type *Ty)
Strip aggregate type wrapping.
bool ugt(const APInt &RHS) const
Unsigned greather than comparison.
SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
This provides the default implementation of the IRBuilder 'InsertHelper' method that is called whenev...
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
SequentialType - This is the superclass of the array, pointer and vector type classes.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getABITypeAlignment(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
isPodLike - This is a type trait that is used to determine whether a given type can be copied around ...
MemIntrinsic - This is the common base class for memset/memcpy/memmove.
AtomicOrdering getOrdering() const
Returns the ordering effect of this store.
unsigned getIntegerBitWidth() const
This is the shared class of boolean and integer constants.
Value * getIncomingValue(unsigned i) const
getIncomingValue - Return incoming value number x
BlockMass operator*(const BlockMass &L, const BranchProbability &R)
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
friend const_iterator begin(StringRef path)
Get begin iterator over path.
bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst *SI, DIBuilder &Builder)
===---------------------------------------------------------------——===// Dbg Intrinsic utilities ...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Type * getType() const
All values are typed, get the type of this value.
Instruction * user_back()
user_back - Specialize the methods defined in Value, as we know that an instruction can only be used ...
static Value * insertVector(IRBuilderTy &IRB, Value *Old, Value *V, unsigned BeginIndex, const Twine &Name)
static void enqueueUsersInWorklist(Instruction &I, SmallVectorImpl< Instruction * > &Worklist, SmallPtrSetImpl< Instruction * > &Visited)
bool isVolatile() const
isVolatile - Return true if this is a load from a volatile memory location.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Value * getLength() const
uint64_t getSizeInBytes() const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
unsigned getElementContainingOffset(uint64_t Offset) const
Given a valid byte offset into the structure, returns the structure index that contains it...
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
AtomicOrdering getOrdering() const
Returns the ordering effect of this fence.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const BasicBlock & getEntryBlock() const
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
static bool isVectorPromotionViableForSlice(AllocaSlices::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.
void setOperand(unsigned i, Value *Val)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
A range adaptor for a pair of iterators.
VectorType - Class to represent vector types.
Class for arbitrary precision integers.
bool isIntegerTy() const
isIntegerTy - True if this is an instance of IntegerType.
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.
iterator_range< user_iterator > users()
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void initializeSROAPass(PassRegistry &)
RetTy visitStoreInst(StoreInst &I)
iterator insert(iterator I, T &&Elt)
void InsertHelper(Instruction *I, const Twine &Name, BasicBlock *BB, BasicBlock::iterator InsertPt) const
static Value * insertInteger(const DataLayout &DL, IRBuilderTy &IRB, Value *Old, Value *V, uint64_t Offset, const Twine &Name)
const Type * getScalarType() const LLVM_READONLY
getScalarType - If this is a vector type, return the element type, otherwise return 'this'...
static Value * foldPHINodeOrSelectInst(Instruction &I)
A helper that folds a PHI node or a select.
Virtual Register Rewriter
bool operator!=(uint64_t V1, const APInt &V2)
uint64_t MinAlign(uint64_t A, uint64_t B)
MinAlign - A and B are either alignments or offsets.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
bool isLegalInteger(unsigned Width) const
Returns true if the specified type is known to be a native integer type supported by the CPU...
INITIALIZE_PASS_BEGIN(SROA,"sroa","Scalar Replacement Of Aggregates", false, false) INITIALIZE_PASS_END(SROA
DbgValueInst - This represents the llvm.dbg.value instruction.
unsigned getAlignment() const
getAlignment - Return the alignment of the access that is being performed
void getAAMetadata(AAMDNodes &N, bool Merge=false) const
getAAMetadata - Fills the AAMDNodes structure with AA metadata from this instruction.
static void speculateSelectInstLoads(SelectInst &SI)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
bool hasOneUse() const
Return true if there is exactly one user of this value.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
void setSource(Value *Ptr)
iterator find(const KeyT &Val)
static Value * extractVector(IRBuilderTy &IRB, Value *V, unsigned BeginIndex, unsigned EndIndex, const Twine &Name)
uint64_t getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
static Value * getNaturalGEPRecursively(IRBuilderTy &IRB, const DataLayout &DL, Value *Ptr, Type *Ty, APInt &Offset, Type *TargetTy, SmallVectorImpl< Value * > &Indices, Twine NamePrefix)
Recursively compute indices for a natural GEP.
bool all_of(R &&Range, UnaryPredicate &&P)
Provide wrappers to std::all_of which take ranges instead of having to pass being/end explicitly...
Value * getRawSource() const
get* - Return the arguments to the instruction.
static unsigned getPointerOperandIndex()
user_iterator user_begin()
bool operator<(int64_t V1, const APSInt &V2)
Module * getParent()
Get the module that this global value is contained inside of...
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
isInstructionTriviallyDead - Return true if the result produced by the instruction is not used...
LLVM Value Representation.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
A vector that has set insertion semantics.
static bool isSafePHIToSpeculate(PHINode &PN)
PHI instructions that use an alloca and are subsequently loaded can be rewritten to load both input p...
static VectorType * get(Type *ElementType, unsigned NumElements)
VectorType::get - This static method is the primary way to construct an VectorType.
APInt shl(const APInt &LHS, unsigned shiftAmt)
Left-shift function.
bool isTriviallyEmpty() const
Check if this twine is trivially empty; a false return value does not necessarily mean the twine is e...
static void speculatePHINodeLoads(PHINode &PN)
uint64_t getTypeSizeInBits(Type *Ty) const
Size examples:
This class implements an extremely fast bulk output stream that can only output to a stream...
bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, unsigned Align)
isSafeToLoadUnconditionally - Return true if we know that executing a load from this value cannot tra...
static cl::opt< bool > SROARandomShuffleSlices("sroa-random-shuffle-slices", cl::init(false), cl::Hidden)
Hidden option to enable randomly shuffling the slices to help uncover instability in their order...
C - The default llvm calling convention, compatible with C.
const Value * getFalseValue() const
StringRef - Represent a constant reference to a string, i.e.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const
Zero extend to a new width.
Legacy analysis pass which computes a DominatorTree.
bool operator==(uint64_t V1, const APInt &V2)
void visitInstruction(Instruction &I)
Type * getAllocatedType() const
getAllocatedType - Return the type that is being allocated by the instruction.
const Use & getRawDestUse() const
DbgDeclareInst - This represents the llvm.dbg.declare instruction.
Value * getPointerOperand()
const BasicBlock * getParent() const
static sys::TimeValue now(bool Deterministic)
IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic functions.
AllocaInst - an instruction to allocate memory on the stack.
gep_type_iterator gep_type_begin(const User *GEP)
static Value * foldSelectInst(SelectInst &SI)