aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp267
1 files changed, 182 insertions, 85 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index e03b7026f802..41bc65620ff6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -28,30 +28,42 @@ using namespace PatternMatch;
#define DEBUG_TYPE "instcombine"
-STATISTIC(NumDeadStore, "Number of dead stores eliminated");
+STATISTIC(NumDeadStore, "Number of dead stores eliminated");
STATISTIC(NumGlobalCopies, "Number of allocas copied from constant global");
-/// isOnlyCopiedFromConstantGlobal - Recursively walk the uses of a (derived)
+static cl::opt<unsigned> MaxCopiedFromConstantUsers(
+ "instcombine-max-copied-from-constant-users", cl::init(128),
+ cl::desc("Maximum users to visit in copy from constant transform"),
+ cl::Hidden);
+
+/// isOnlyCopiedFromConstantMemory - Recursively walk the uses of a (derived)
/// pointer to an alloca. Ignore any reads of the pointer, return false if we
/// see any stores or other unknown uses. If we see pointer arithmetic, keep
/// track of whether it moves the pointer (with IsOffset) but otherwise traverse
/// the uses. If we see a memcpy/memmove that targets an unoffseted pointer to
-/// the alloca, and if the source pointer is a pointer to a constant global, we
-/// can optimize this.
+/// the alloca, and if the source pointer is a pointer to a constant memory
+/// location, we can optimize this.
static bool
-isOnlyCopiedFromConstantMemory(AAResults *AA,
- Value *V, MemTransferInst *&TheCopy,
+isOnlyCopiedFromConstantMemory(AAResults *AA, AllocaInst *V,
+ MemTransferInst *&TheCopy,
SmallVectorImpl<Instruction *> &ToDelete) {
// We track lifetime intrinsics as we encounter them. If we decide to go
- // ahead and replace the value with the global, this lets the caller quickly
- // eliminate the markers.
+ // ahead and replace the value with the memory location, this lets the caller
+ // quickly eliminate the markers.
+
+ using ValueAndIsOffset = PointerIntPair<Value *, 1, bool>;
+ SmallVector<ValueAndIsOffset, 32> Worklist;
+ SmallPtrSet<ValueAndIsOffset, 32> Visited;
+ Worklist.emplace_back(V, false);
+ while (!Worklist.empty()) {
+ ValueAndIsOffset Elem = Worklist.pop_back_val();
+ if (!Visited.insert(Elem).second)
+ continue;
+ if (Visited.size() > MaxCopiedFromConstantUsers)
+ return false;
- SmallVector<std::pair<Value *, bool>, 35> ValuesToInspect;
- ValuesToInspect.emplace_back(V, false);
- while (!ValuesToInspect.empty()) {
- auto ValuePair = ValuesToInspect.pop_back_val();
- const bool IsOffset = ValuePair.second;
- for (auto &U : ValuePair.first->uses()) {
+ const auto [Value, IsOffset] = Elem;
+ for (auto &U : Value->uses()) {
auto *I = cast<Instruction>(U.getUser());
if (auto *LI = dyn_cast<LoadInst>(I)) {
@@ -60,15 +72,22 @@ isOnlyCopiedFromConstantMemory(AAResults *AA,
continue;
}
- if (isa<BitCastInst>(I) || isa<AddrSpaceCastInst>(I)) {
+ if (isa<PHINode, SelectInst>(I)) {
+ // We set IsOffset=true, to forbid the memcpy from occurring after the
+ // phi: If one of the phi operands is not based on the alloca, we
+ // would incorrectly omit a write.
+ Worklist.emplace_back(I, true);
+ continue;
+ }
+ if (isa<BitCastInst, AddrSpaceCastInst>(I)) {
// If uses of the bitcast are ok, we are ok.
- ValuesToInspect.emplace_back(I, IsOffset);
+ Worklist.emplace_back(I, IsOffset);
continue;
}
if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
// If the GEP has all zero indices, it doesn't offset the pointer. If it
// doesn't, it does.
- ValuesToInspect.emplace_back(I, IsOffset || !GEP->hasAllZeroIndices());
+ Worklist.emplace_back(I, IsOffset || !GEP->hasAllZeroIndices());
continue;
}
@@ -85,11 +104,12 @@ isOnlyCopiedFromConstantMemory(AAResults *AA,
if (IsArgOperand && Call->isInAllocaArgument(DataOpNo))
return false;
- // If this is a readonly/readnone call site, then we know it is just a
- // load (but one that potentially returns the value itself), so we can
+ // If this call site doesn't modify the memory, then we know it is just
+ // a load (but one that potentially returns the value itself), so we can
// ignore it if we know that the value isn't captured.
- if (Call->onlyReadsMemory() &&
- (Call->use_empty() || Call->doesNotCapture(DataOpNo)))
+ bool NoCapture = Call->doesNotCapture(DataOpNo);
+ if ((Call->onlyReadsMemory() && (Call->use_empty() || NoCapture)) ||
+ (Call->onlyReadsMemory(DataOpNo) && NoCapture))
continue;
// If this is being passed as a byval argument, the caller is making a
@@ -111,12 +131,14 @@ isOnlyCopiedFromConstantMemory(AAResults *AA,
if (!MI)
return false;
+ // If the transfer is volatile, reject it.
+ if (MI->isVolatile())
+ return false;
+
// If the transfer is using the alloca as a source of the transfer, then
// ignore it since it is a load (unless the transfer is volatile).
- if (U.getOperandNo() == 1) {
- if (MI->isVolatile()) return false;
+ if (U.getOperandNo() == 1)
continue;
- }
// If we already have seen a copy, reject the second one.
if (TheCopy) return false;
@@ -128,8 +150,8 @@ isOnlyCopiedFromConstantMemory(AAResults *AA,
// If the memintrinsic isn't using the alloca as the dest, reject it.
if (U.getOperandNo() != 0) return false;
- // If the source of the memcpy/move is not a constant global, reject it.
- if (!AA->pointsToConstantMemory(MI->getSource()))
+ // If the source of the memcpy/move is not constant, reject it.
+ if (isModSet(AA->getModRefInfoMask(MI->getSource())))
return false;
// Otherwise, the transform is safe. Remember the copy instruction.
@@ -139,9 +161,10 @@ isOnlyCopiedFromConstantMemory(AAResults *AA,
return true;
}
-/// isOnlyCopiedFromConstantGlobal - Return true if the specified alloca is only
-/// modified by a copy from a constant global. If we can prove this, we can
-/// replace any uses of the alloca with uses of the global directly.
+/// isOnlyCopiedFromConstantMemory - Return true if the specified alloca is only
+/// modified by a copy from a constant memory location. If we can prove this, we
+/// can replace any uses of the alloca with uses of the memory location
+/// directly.
static MemTransferInst *
isOnlyCopiedFromConstantMemory(AAResults *AA,
AllocaInst *AI,
@@ -165,7 +188,7 @@ static bool isDereferenceableForAllocaSize(const Value *V, const AllocaInst *AI,
}
static Instruction *simplifyAllocaArraySize(InstCombinerImpl &IC,
- AllocaInst &AI) {
+ AllocaInst &AI, DominatorTree &DT) {
// Check for array size of 1 (scalar allocation).
if (!AI.isArrayAllocation()) {
// i32 1 is the canonical array size for scalar allocations.
@@ -184,6 +207,8 @@ static Instruction *simplifyAllocaArraySize(InstCombinerImpl &IC,
nullptr, AI.getName());
New->setAlignment(AI.getAlign());
+ replaceAllDbgUsesWith(AI, *New, *New, DT);
+
// Scan to the end of the allocation instructions, to skip over a block of
// allocas if possible...also skip interleaved debug info
//
@@ -234,31 +259,83 @@ namespace {
// instruction.
class PointerReplacer {
public:
- PointerReplacer(InstCombinerImpl &IC) : IC(IC) {}
+ PointerReplacer(InstCombinerImpl &IC, Instruction &Root)
+ : IC(IC), Root(Root) {}
- bool collectUsers(Instruction &I);
- void replacePointer(Instruction &I, Value *V);
+ bool collectUsers();
+ void replacePointer(Value *V);
private:
+ bool collectUsersRecursive(Instruction &I);
void replace(Instruction *I);
Value *getReplacement(Value *I);
+ bool isAvailable(Instruction *I) const {
+ return I == &Root || Worklist.contains(I);
+ }
+ SmallPtrSet<Instruction *, 32> ValuesToRevisit;
SmallSetVector<Instruction *, 4> Worklist;
MapVector<Value *, Value *> WorkMap;
InstCombinerImpl &IC;
+ Instruction &Root;
};
} // end anonymous namespace
-bool PointerReplacer::collectUsers(Instruction &I) {
- for (auto U : I.users()) {
+bool PointerReplacer::collectUsers() {
+ if (!collectUsersRecursive(Root))
+ return false;
+
+ // Ensure that all outstanding (indirect) users of I
+ // are inserted into the Worklist. Return false
+ // otherwise.
+ for (auto *Inst : ValuesToRevisit)
+ if (!Worklist.contains(Inst))
+ return false;
+ return true;
+}
+
+bool PointerReplacer::collectUsersRecursive(Instruction &I) {
+ for (auto *U : I.users()) {
auto *Inst = cast<Instruction>(&*U);
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
if (Load->isVolatile())
return false;
Worklist.insert(Load);
- } else if (isa<GetElementPtrInst>(Inst) || isa<BitCastInst>(Inst)) {
+ } else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
+ // All incoming values must be instructions for replacability
+ if (any_of(PHI->incoming_values(),
+ [](Value *V) { return !isa<Instruction>(V); }))
+ return false;
+
+ // If at least one incoming value of the PHI is not in Worklist,
+ // store the PHI for revisiting and skip this iteration of the
+ // loop.
+ if (any_of(PHI->incoming_values(), [this](Value *V) {
+ return !isAvailable(cast<Instruction>(V));
+ })) {
+ ValuesToRevisit.insert(Inst);
+ continue;
+ }
+
+ Worklist.insert(PHI);
+ if (!collectUsersRecursive(*PHI))
+ return false;
+ } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
+ if (!isa<Instruction>(SI->getTrueValue()) ||
+ !isa<Instruction>(SI->getFalseValue()))
+ return false;
+
+ if (!isAvailable(cast<Instruction>(SI->getTrueValue())) ||
+ !isAvailable(cast<Instruction>(SI->getFalseValue()))) {
+ ValuesToRevisit.insert(Inst);
+ continue;
+ }
+ Worklist.insert(SI);
+ if (!collectUsersRecursive(*SI))
+ return false;
+ } else if (isa<GetElementPtrInst, BitCastInst>(Inst)) {
Worklist.insert(Inst);
- if (!collectUsers(*Inst))
+ if (!collectUsersRecursive(*Inst))
return false;
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
if (MI->isVolatile())
@@ -293,6 +370,14 @@ void PointerReplacer::replace(Instruction *I) {
IC.InsertNewInstWith(NewI, *LT);
IC.replaceInstUsesWith(*LT, NewI);
WorkMap[LT] = NewI;
+ } else if (auto *PHI = dyn_cast<PHINode>(I)) {
+ Type *NewTy = getReplacement(PHI->getIncomingValue(0))->getType();
+ auto *NewPHI = PHINode::Create(NewTy, PHI->getNumIncomingValues(),
+ PHI->getName(), PHI);
+ for (unsigned int I = 0; I < PHI->getNumIncomingValues(); ++I)
+ NewPHI->addIncoming(getReplacement(PHI->getIncomingValue(I)),
+ PHI->getIncomingBlock(I));
+ WorkMap[PHI] = NewPHI;
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
auto *V = getReplacement(GEP->getPointerOperand());
assert(V && "Operand not replaced");
@@ -313,6 +398,13 @@ void PointerReplacer::replace(Instruction *I) {
IC.InsertNewInstWith(NewI, *BC);
NewI->takeName(BC);
WorkMap[BC] = NewI;
+ } else if (auto *SI = dyn_cast<SelectInst>(I)) {
+ auto *NewSI = SelectInst::Create(
+ SI->getCondition(), getReplacement(SI->getTrueValue()),
+ getReplacement(SI->getFalseValue()), SI->getName(), nullptr, SI);
+ IC.InsertNewInstWith(NewSI, *SI);
+ NewSI->takeName(SI);
+ WorkMap[SI] = NewSI;
} else if (auto *MemCpy = dyn_cast<MemTransferInst>(I)) {
auto *SrcV = getReplacement(MemCpy->getRawSource());
// The pointer may appear in the destination of a copy, but we don't want to
@@ -339,27 +431,27 @@ void PointerReplacer::replace(Instruction *I) {
}
}
-void PointerReplacer::replacePointer(Instruction &I, Value *V) {
+void PointerReplacer::replacePointer(Value *V) {
#ifndef NDEBUG
- auto *PT = cast<PointerType>(I.getType());
+ auto *PT = cast<PointerType>(Root.getType());
auto *NT = cast<PointerType>(V->getType());
assert(PT != NT && PT->hasSameElementTypeAs(NT) && "Invalid usage");
#endif
- WorkMap[&I] = V;
+ WorkMap[&Root] = V;
for (Instruction *Workitem : Worklist)
replace(Workitem);
}
Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
- if (auto *I = simplifyAllocaArraySize(*this, AI))
+ if (auto *I = simplifyAllocaArraySize(*this, AI, DT))
return I;
if (AI.getAllocatedType()->isSized()) {
// Move all alloca's of zero byte objects to the entry block and merge them
// together. Note that we only do this for alloca's, because malloc should
// allocate and return a unique pointer, even for a zero byte allocation.
- if (DL.getTypeAllocSize(AI.getAllocatedType()).getKnownMinSize() == 0) {
+ if (DL.getTypeAllocSize(AI.getAllocatedType()).getKnownMinValue() == 0) {
// For a zero sized alloca there is no point in doing an array allocation.
// This is helpful if the array size is a complicated expression not used
// elsewhere.
@@ -377,7 +469,7 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
AllocaInst *EntryAI = dyn_cast<AllocaInst>(FirstInst);
if (!EntryAI || !EntryAI->getAllocatedType()->isSized() ||
DL.getTypeAllocSize(EntryAI->getAllocatedType())
- .getKnownMinSize() != 0) {
+ .getKnownMinValue() != 0) {
AI.moveBefore(FirstInst);
return &AI;
}
@@ -395,11 +487,11 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
}
// Check to see if this allocation is only modified by a memcpy/memmove from
- // a constant whose alignment is equal to or exceeds that of the allocation.
- // If this is the case, we can change all users to use the constant global
- // instead. This is commonly produced by the CFE by constructs like "void
- // foo() { int A[] = {1,2,3,4,5,6,7,8,9...}; }" if 'A' is only subsequently
- // read.
+ // a memory location whose alignment is equal to or exceeds that of the
+ // allocation. If this is the case, we can change all users to use the
+ // constant memory location instead. This is commonly produced by the CFE by
+ // constructs like "void foo() { int A[] = {1,2,3,4,5,6,7,8,9...}; }" if 'A'
+ // is only subsequently read.
SmallVector<Instruction *, 4> ToDelete;
if (MemTransferInst *Copy = isOnlyCopiedFromConstantMemory(AA, &AI, ToDelete)) {
Value *TheSrc = Copy->getSource();
@@ -415,7 +507,7 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
LLVM_DEBUG(dbgs() << " memcpy = " << *Copy << '\n');
unsigned SrcAddrSpace = TheSrc->getType()->getPointerAddressSpace();
auto *DestTy = PointerType::get(AI.getAllocatedType(), SrcAddrSpace);
- if (AI.getType()->getAddressSpace() == SrcAddrSpace) {
+ if (AI.getAddressSpace() == SrcAddrSpace) {
for (Instruction *Delete : ToDelete)
eraseInstFromFunction(*Delete);
@@ -426,13 +518,13 @@ Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
return NewI;
}
- PointerReplacer PtrReplacer(*this);
- if (PtrReplacer.collectUsers(AI)) {
+ PointerReplacer PtrReplacer(*this, AI);
+ if (PtrReplacer.collectUsers()) {
for (Instruction *Delete : ToDelete)
eraseInstFromFunction(*Delete);
Value *Cast = Builder.CreateBitCast(TheSrc, DestTy);
- PtrReplacer.replacePointer(AI, Cast);
+ PtrReplacer.replacePointer(Cast);
++NumGlobalCopies;
}
}
@@ -507,6 +599,7 @@ static StoreInst *combineStoreToNewValue(InstCombinerImpl &IC, StoreInst &SI,
// here.
switch (ID) {
case LLVMContext::MD_dbg:
+ case LLVMContext::MD_DIAssignID:
case LLVMContext::MD_tbaa:
case LLVMContext::MD_prof:
case LLVMContext::MD_fpmath:
@@ -575,43 +668,43 @@ static bool isMinMaxWithLoads(Value *V, Type *&LoadTy) {
/// later. However, it is risky in case some backend or other part of LLVM is
/// relying on the exact type loaded to select appropriate atomic operations.
static Instruction *combineLoadToOperationType(InstCombinerImpl &IC,
- LoadInst &LI) {
+ LoadInst &Load) {
// FIXME: We could probably with some care handle both volatile and ordered
// atomic loads here but it isn't clear that this is important.
- if (!LI.isUnordered())
+ if (!Load.isUnordered())
return nullptr;
- if (LI.use_empty())
+ if (Load.use_empty())
return nullptr;
// swifterror values can't be bitcasted.
- if (LI.getPointerOperand()->isSwiftError())
+ if (Load.getPointerOperand()->isSwiftError())
return nullptr;
- const DataLayout &DL = IC.getDataLayout();
-
// Fold away bit casts of the loaded value by loading the desired type.
// Note that we should not do this for pointer<->integer casts,
// because that would result in type punning.
- if (LI.hasOneUse()) {
+ if (Load.hasOneUse()) {
// Don't transform when the type is x86_amx, it makes the pass that lower
// x86_amx type happy.
- if (auto *BC = dyn_cast<BitCastInst>(LI.user_back())) {
- assert(!LI.getType()->isX86_AMXTy() &&
- "load from x86_amx* should not happen!");
+ Type *LoadTy = Load.getType();
+ if (auto *BC = dyn_cast<BitCastInst>(Load.user_back())) {
+ assert(!LoadTy->isX86_AMXTy() && "Load from x86_amx* should not happen!");
if (BC->getType()->isX86_AMXTy())
return nullptr;
}
- if (auto* CI = dyn_cast<CastInst>(LI.user_back()))
- if (CI->isNoopCast(DL) && LI.getType()->isPtrOrPtrVectorTy() ==
- CI->getDestTy()->isPtrOrPtrVectorTy())
- if (!LI.isAtomic() || isSupportedAtomicType(CI->getDestTy())) {
- LoadInst *NewLoad = IC.combineLoadToNewType(LI, CI->getDestTy());
- CI->replaceAllUsesWith(NewLoad);
- IC.eraseInstFromFunction(*CI);
- return &LI;
- }
+ if (auto *CastUser = dyn_cast<CastInst>(Load.user_back())) {
+ Type *DestTy = CastUser->getDestTy();
+ if (CastUser->isNoopCast(IC.getDataLayout()) &&
+ LoadTy->isPtrOrPtrVectorTy() == DestTy->isPtrOrPtrVectorTy() &&
+ (!Load.isAtomic() || isSupportedAtomicType(DestTy))) {
+ LoadInst *NewLoad = IC.combineLoadToNewType(Load, DestTy);
+ CastUser->replaceAllUsesWith(NewLoad);
+ IC.eraseInstFromFunction(*CastUser);
+ return &Load;
+ }
+ }
}
// FIXME: We should also canonicalize loads of vectors when their elements are
@@ -639,7 +732,7 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
".unpack");
NewLoad->setAAMetadata(LI.getAAMetadata());
return IC.replaceInstUsesWith(LI, IC.Builder.CreateInsertValue(
- UndefValue::get(T), NewLoad, 0, Name));
+ PoisonValue::get(T), NewLoad, 0, Name));
}
// We don't want to break loads with padding here as we'd loose
@@ -654,13 +747,13 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
auto *IdxType = Type::getInt32Ty(T->getContext());
auto *Zero = ConstantInt::get(IdxType, 0);
- Value *V = UndefValue::get(T);
+ Value *V = PoisonValue::get(T);
for (unsigned i = 0; i < NumElements; i++) {
Value *Indices[2] = {
Zero,
ConstantInt::get(IdxType, i),
};
- auto *Ptr = IC.Builder.CreateInBoundsGEP(ST, Addr, makeArrayRef(Indices),
+ auto *Ptr = IC.Builder.CreateInBoundsGEP(ST, Addr, ArrayRef(Indices),
Name + ".elt");
auto *L = IC.Builder.CreateAlignedLoad(
ST->getElementType(i), Ptr,
@@ -681,7 +774,7 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
LoadInst *NewLoad = IC.combineLoadToNewType(LI, ET, ".unpack");
NewLoad->setAAMetadata(LI.getAAMetadata());
return IC.replaceInstUsesWith(LI, IC.Builder.CreateInsertValue(
- UndefValue::get(T), NewLoad, 0, Name));
+ PoisonValue::get(T), NewLoad, 0, Name));
}
// Bail out if the array is too large. Ideally we would like to optimize
@@ -699,14 +792,14 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
auto *IdxType = Type::getInt64Ty(T->getContext());
auto *Zero = ConstantInt::get(IdxType, 0);
- Value *V = UndefValue::get(T);
+ Value *V = PoisonValue::get(T);
uint64_t Offset = 0;
for (uint64_t i = 0; i < NumElements; i++) {
Value *Indices[2] = {
Zero,
ConstantInt::get(IdxType, i),
};
- auto *Ptr = IC.Builder.CreateInBoundsGEP(AT, Addr, makeArrayRef(Indices),
+ auto *Ptr = IC.Builder.CreateInBoundsGEP(AT, Addr, ArrayRef(Indices),
Name + ".elt");
auto *L = IC.Builder.CreateAlignedLoad(AT->getElementType(), Ptr,
commonAlignment(Align, Offset),
@@ -769,10 +862,13 @@ static bool isObjectSizeLessThanOrEq(Value *V, uint64_t MaxSize,
if (!CS)
return false;
- uint64_t TypeSize = DL.getTypeAllocSize(AI->getAllocatedType());
+ TypeSize TS = DL.getTypeAllocSize(AI->getAllocatedType());
+ if (TS.isScalable())
+ return false;
// Make sure that, even if the multiplication below would wrap as an
// uint64_t, we still do the right thing.
- if ((CS->getValue().zext(128) * APInt(128, TypeSize)).ugt(MaxSize))
+ if ((CS->getValue().zext(128) * APInt(128, TS.getFixedValue()))
+ .ugt(MaxSize))
return false;
continue;
}
@@ -849,7 +945,7 @@ static bool canReplaceGEPIdxWithZero(InstCombinerImpl &IC,
if (!AllocTy || !AllocTy->isSized())
return false;
const DataLayout &DL = IC.getDataLayout();
- uint64_t TyAllocSize = DL.getTypeAllocSize(AllocTy).getFixedSize();
+ uint64_t TyAllocSize = DL.getTypeAllocSize(AllocTy).getFixedValue();
// If there are more indices after the one we might replace with a zero, make
// sure they're all non-negative. If any of them are negative, the overall
@@ -1183,8 +1279,8 @@ static bool unpackStoreToAggregate(InstCombinerImpl &IC, StoreInst &SI) {
Zero,
ConstantInt::get(IdxType, i),
};
- auto *Ptr = IC.Builder.CreateInBoundsGEP(ST, Addr, makeArrayRef(Indices),
- AddrName);
+ auto *Ptr =
+ IC.Builder.CreateInBoundsGEP(ST, Addr, ArrayRef(Indices), AddrName);
auto *Val = IC.Builder.CreateExtractValue(V, i, EltName);
auto EltAlign = commonAlignment(Align, SL->getElementOffset(i));
llvm::Instruction *NS = IC.Builder.CreateAlignedStore(Val, Ptr, EltAlign);
@@ -1229,8 +1325,8 @@ static bool unpackStoreToAggregate(InstCombinerImpl &IC, StoreInst &SI) {
Zero,
ConstantInt::get(IdxType, i),
};
- auto *Ptr = IC.Builder.CreateInBoundsGEP(AT, Addr, makeArrayRef(Indices),
- AddrName);
+ auto *Ptr =
+ IC.Builder.CreateInBoundsGEP(AT, Addr, ArrayRef(Indices), AddrName);
auto *Val = IC.Builder.CreateExtractValue(V, i, EltName);
auto EltAlign = commonAlignment(Align, Offset);
Instruction *NS = IC.Builder.CreateAlignedStore(Val, Ptr, EltAlign);
@@ -1372,7 +1468,7 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) {
// If we have a store to a location which is known constant, we can conclude
// that the store must be storing the constant value (else the memory
// wouldn't be constant), and this must be a noop.
- if (AA->pointsToConstantMemory(Ptr))
+ if (!isModSet(AA->getModRefInfoMask(Ptr)))
return eraseInstFromFunction(SI);
// Do really simple DSE, to catch cases where there are several consecutive
@@ -1547,6 +1643,7 @@ bool InstCombinerImpl::mergeStoreIntoSuccessor(StoreInst &SI) {
SI.getOrdering(), SI.getSyncScopeID());
InsertNewInstBefore(NewSI, *BBI);
NewSI->setDebugLoc(MergedLoc);
+ NewSI->mergeDIAssignID({&SI, OtherStore});
// If the two stores had AA tags, merge them.
AAMDNodes AATags = SI.getAAMetadata();