Revert "Reland [SROA] Maintain shadow/backing alloca when some slices are noncapturnig read-only calls to allow alloca partitioning/promotion"

There seems to be one more uncaught problem, SROA may now end up trying
to re-re-repromote the just-promoted shadow alloca, and do that endlessly.

This reverts commit adc0984d81.
This commit is contained in:
Roman Lebedev 2022-03-05 01:08:11 +03:00
parent acf603b947
commit e47257e251
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
2 changed files with 183 additions and 273 deletions

View File

@ -167,7 +167,6 @@ public:
void makeUnsplittable() { UseAndIsSplittable.setInt(false); }
Use *getUse() const { return UseAndIsSplittable.getPointer(); }
void setUse(Use *U) { UseAndIsSplittable.setPointer(U); }
bool isDead() const { return getUse() == nullptr; }
void kill() { UseAndIsSplittable.setPointer(nullptr); }
@ -219,7 +218,7 @@ public:
class llvm::sroa::AllocaSlices {
public:
/// Construct the slices of a particular alloca.
AllocaSlices(const DataLayout &DL, AllocaInst &AI, bool &Changed);
AllocaSlices(const DataLayout &DL, AllocaInst &AI);
/// Test whether a pointer to the allocation escapes our analysis.
///
@ -271,12 +270,6 @@ public:
return DeadUseIfPromotable;
}
void forgetTheDead() {
DeadUsers.clear();
DeadUseIfPromotable.clear();
DeadOperands.clear();
};
/// Access the dead operands referring to this alloca.
///
/// These are operands which have cannot actually be used to refer to the
@ -302,21 +295,11 @@ private:
friend class AllocaSlices::SliceBuilder;
void formBackingAlloca(AllocaInst *AI, bool &Changed);
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Handle to alloca instruction to simplify method interfaces.
AllocaInst &AI;
#endif
/// Certain escaping uses of an alloca (non-capturing-ones)
/// do not prevent promotion, but force retention of the alloca.
/// This records if there are any such uses.
bool NeedsBackingAlloca = false;
/// Track if there are any `select`s/PHI's involving the alloca pointers.
bool HavePHINodesOrSelectInstrs = false;
/// The instruction responsible for this alloca not having a known set
/// of slices.
///
@ -1072,10 +1055,6 @@ private:
return;
}
AS.HavePHINodesOrSelectInstrs = true;
if (AS.NeedsBackingAlloca && AS.HavePHINodesOrSelectInstrs)
return PI.setAborted(&I);
insertUse(I, Offset, Size);
}
@ -1083,24 +1062,11 @@ private:
void visitSelectInst(SelectInst &SI) { visitPHINodeOrSelectInst(SI); }
void visitCallBase(CallBase &CB) {
if (!IsOffsetKnown || !CB.doesNotCapture(U->getOperandNo()))
return PI.setAborted(&CB);
// If we know that the callee does not retain the pointer,
// then it does not prevent SROA, although we have to workaround this.
// However, for now, only allow uses, that, at most, read from said memory.
if (!CB.onlyReadsMemory() && !CB.onlyReadsMemory(U->getOperandNo()))
return PI.setAborted(&CB);
AS.NeedsBackingAlloca = true;
if (AS.NeedsBackingAlloca && AS.HavePHINodesOrSelectInstrs)
return PI.setAborted(&CB);
}
/// Disable SROA entirely if there are unhandled users of the alloca.
void visitInstruction(Instruction &I) { PI.setAborted(&I); }
};
AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI, bool &Changed)
AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI)
:
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
AI(AI),
@ -1117,10 +1083,6 @@ AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI, bool &Changed)
return;
}
// We may have found that the pointer to the AI escapes, but isn't captured.
if (NeedsBackingAlloca)
formBackingAlloca(&AI, Changed);
llvm::erase_if(Slices, [](const Slice &S) { return S.isDead(); });
// Sort the uses. This arranges for the offsets to be in ascending order,
@ -3625,122 +3587,6 @@ private:
} // end anonymous namespace
/// Apparently, we can promote the alloca, but some uses of the alloca
/// are calls (that don't capture it's address), which require for the
/// trace alloca to remain. To do so, we must form a new "backing" alloca,
/// which will be kept as an up-to-date backup of the to-be-promoted-alloca's
/// content, and used in it's place in these non-capturing calls.
/// FIXME: support non-readonly non-capturing calls.
void AllocaSlices::formBackingAlloca(AllocaInst *AllocaToPromote,
bool &Changed) {
assert(NeedsBackingAlloca &&
"Should not be called if there is no need to rewrite.");
// We are going to preserve all of the original instructions that were
// operating on the original alloca, so we must forget any instructions
// that were deemed as dead-to-be-deleted during normal promotion.
forgetTheDead();
Changed = true;
// Now, we want to retain all of the instructions operating on the original
// alloca, so to avoid much hassle, create a new alloca, and swap (RAUW) them.
AllocaInst *ShadowAlloca = cast<AllocaInst>(AllocaToPromote->clone());
ShadowAlloca->takeName(AllocaToPromote);
AllocaToPromote->setName(ShadowAlloca->getName() + ".prom");
ShadowAlloca->insertBefore(AllocaToPromote);
AllocaToPromote->replaceAllUsesWith(ShadowAlloca);
// Avoid recomputing the same pointer over and over again, cache it.
SmallDenseMap<std::pair<uint64_t, Type *>, Value *> RebasedPtrsCSE;
// Don't do anything fancy, just put new insts "right after" the alloca.
IRBuilderTy Builder(AllocaToPromote->getContext());
BasicBlock *AllocaToPromoteBB = AllocaToPromote->getParent();
Builder.SetInsertPoint(AllocaToPromoteBB,
AllocaToPromoteBB->getFirstInsertionPt());
// Give a pointer `Offset` bytes into the `AllocaToPromote` with `PtrTy` type.
auto getRebasedPtr = [&RebasedPtrsCSE, &Builder, AllocaToPromote,
DL = AllocaToPromote->getModule()->getDataLayout()](
PointerType *PtrTy, const uint64_t Offset) {
// Look it up in a cache first.
auto It = RebasedPtrsCSE.find({Offset, PtrTy});
if (It != RebasedPtrsCSE.end())
return It->second;
// Otherwise, create a new pointer, and cache it for the future.
Value *NewPtr = getAdjustedPtr(
Builder, DL, AllocaToPromote,
APInt(DL.getIndexSizeInBits(PtrTy->getAddressSpace()), Offset), PtrTy,
"");
RebasedPtrsCSE[{Offset, PtrTy}] = NewPtr;
return NewPtr;
};
// Some instructions may have several uses of an alloca, and there's
// a separate slice for each use, so we must cache each instruction
// we clone, so that we only clone it once,
// not for each slice that references it.
SmallDenseMap<Instruction *, Instruction *> InstrCloneMap;
// Now, let's just deal with each slice. Roughly, we need to clone each
// instruction that is referenced by a slice (once per instruction!),
// and change the appropriate pointer from pointing at the shadow alloca
// into pointing into the alloca we are going to promote.
//
// NOTE: the original instruction is generally preserved,
// because we need to maintain the content parity between the two allocas!
for (Slice &S : Slices) {
// Just completely ignore dead slices.
if (S.isDead())
continue;
// Which instruction does this slice represent?
Use *OrigUse = S.getUse();
auto *OrigInstr = cast<Instruction>(OrigUse->getUser());
// Now, we need to make a clone of this instruction, but operating on
// the alloca-to-be-promoted instead.
Instruction *ClonedInstr;
// Only clone instruction once! See if we already did that for this instr.
auto It = InstrCloneMap.find(OrigInstr);
if (It != InstrCloneMap.end())
ClonedInstr = It->second;
else {
// This is the first time this instruction is seen.
// Clone it next to the original instruction, and cache it.
ClonedInstr = OrigInstr->clone();
ClonedInstr->insertBefore(OrigInstr);
InstrCloneMap.insert({OrigInstr, ClonedInstr});
// Also, if the instruction was returning anything, we do that instead.
if (!ClonedInstr->getType()->isVoidTy()) {
assert(isa<LoadInst>(OrigInstr) &&
"Not expecting to encounter here anything other than a `load`.");
ClonedInstr->setName(OrigInstr->getName() + ".prom");
OrigInstr->replaceAllUsesWith(ClonedInstr);
}
if (isa<LoadInst>(OrigInstr))
// We know that all the offending (non-capturing) calls do not modify
// the content of the shadow alloca, so we do not need to propagate
// the content of the shadow alloca to the alloca-to-be-promoted.
DeadUsers.push_back(OrigInstr);
}
// Final touch: the slice should refer to the
// use of the alloca-to-be-promoted, while it currently refers to
// use of the shadow alloca, so rectify that.
Value *NewPtr = getRebasedPtr(cast<PointerType>(OrigUse->get()->getType()),
S.beginOffset());
Use &ClonedUse = ClonedInstr->getOperandUse(OrigUse->getOperandNo());
ClonedUse.set(NewPtr);
S.setUse(&ClonedUse);
}
}
/// Strip aggregate type wrapping.
///
/// This removes no-op aggregate types wrapping an underlying type. It will
@ -4766,7 +4612,7 @@ bool SROAPass::runOnAlloca(AllocaInst &AI) {
Changed |= AggRewriter.rewrite(AI);
// Build the slices using a recursive instruction-visiting builder.
AllocaSlices AS(DL, AI, Changed);
AllocaSlices AS(DL, AI);
LLVM_DEBUG(AS.print(dbgs()));
if (AS.isEscaped())
return Changed;

View File

@ -9,18 +9,19 @@ define i32 @alloca_used_in_call(i32* %data, i64 %n) {
; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(i32* [[RETVAL]])
; CHECK-NEXT: ret i32 [[RDX_INC]]
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: ret i32 [[I1]]
;
; CHECK-OPAQUE-LABEL: @alloca_used_in_call(
; CHECK-OPAQUE-NEXT: entry:
@ -28,18 +29,19 @@ define i32 @alloca_used_in_call(i32* %data, i64 %n) {
; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
; CHECK-OPAQUE-NEXT: ret i32 [[RDX_INC]]
; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: ret i32 [[I1]]
;
entry:
%retval = alloca i32, align 4
@ -196,18 +198,19 @@ define i32 @alloca_not_captured_and_readonly_as_per_operand_attr(i32* %data, i64
; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(i32* nocapture readonly [[RETVAL]])
; CHECK-NEXT: ret i32 [[RDX_INC]]
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: ret i32 [[I1]]
;
; CHECK-OPAQUE-LABEL: @alloca_not_captured_and_readonly_as_per_operand_attr(
; CHECK-OPAQUE-NEXT: entry:
@ -215,18 +218,19 @@ define i32 @alloca_not_captured_and_readonly_as_per_operand_attr(i32* %data, i64
; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr nocapture readonly [[RETVAL]])
; CHECK-OPAQUE-NEXT: ret i32 [[RDX_INC]]
; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: ret i32 [[I1]]
;
entry:
%retval = alloca i32, align 4
@ -257,18 +261,19 @@ define i32 @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase
; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(i32* nocapture [[RETVAL]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: ret i32 [[RDX_INC]]
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: ret i32 [[I1]]
;
; CHECK-OPAQUE-LABEL: @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase_attr(
; CHECK-OPAQUE-NEXT: entry:
@ -276,18 +281,19 @@ define i32 @alloca_not_captured_as_per_operand_attr_and_readonly_as_per_callbase
; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr nocapture [[RETVAL]]) #[[ATTR2:[0-9]+]]
; CHECK-OPAQUE-NEXT: ret i32 [[RDX_INC]]
; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: ret i32 [[I1]]
;
entry:
%retval = alloca i32, align 4
@ -381,11 +387,11 @@ define i32 @alloca_with_gep_used_in_call(i32* %data, i64 %n) {
; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -393,7 +399,8 @@ define i32 @alloca_with_gep_used_in_call(i32* %data, i64 %n) {
; CHECK: exit:
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[RETVAL]], i32 0
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(i32* [[GEP]])
; CHECK-NEXT: ret i32 [[RDX_INC]]
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: ret i32 [[I1]]
;
; CHECK-OPAQUE-LABEL: @alloca_with_gep_used_in_call(
; CHECK-OPAQUE-NEXT: entry:
@ -401,11 +408,11 @@ define i32 @alloca_with_gep_used_in_call(i32* %data, i64 %n) {
; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -413,7 +420,8 @@ define i32 @alloca_with_gep_used_in_call(i32* %data, i64 %n) {
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[RETVAL]], i32 0
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[GEP]])
; CHECK-OPAQUE-NEXT: ret i32 [[RDX_INC]]
; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: ret i32 [[I1]]
;
entry:
%retval = alloca i32, align 4
@ -508,11 +516,11 @@ define i32 @alloca_used_in_maybe_throwing_call(i32* %data, i64 %n) personality i
; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -527,7 +535,8 @@ define i32 @alloca_used_in_maybe_throwing_call(i32* %data, i64 %n) personality i
; CHECK-NEXT: catch i8* null
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: ret i32 [[RDX_INC]]
; CHECK-NEXT: [[I2:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: ret i32 [[I2]]
;
; CHECK-OPAQUE-LABEL: @alloca_used_in_maybe_throwing_call(
; CHECK-OPAQUE-NEXT: entry:
@ -535,11 +544,11 @@ define i32 @alloca_used_in_maybe_throwing_call(i32* %data, i64 %n) personality i
; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -554,7 +563,8 @@ define i32 @alloca_used_in_maybe_throwing_call(i32* %data, i64 %n) personality i
; CHECK-OPAQUE-NEXT: catch ptr null
; CHECK-OPAQUE-NEXT: br label [[END]]
; CHECK-OPAQUE: end:
; CHECK-OPAQUE-NEXT: ret i32 [[RDX_INC]]
; CHECK-OPAQUE-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: ret i32 [[I2]]
;
entry:
%retval = alloca i32, align 4
@ -594,11 +604,11 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(i32* %data, i64 %
; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -611,7 +621,8 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(i32* %data, i64 %
; CHECK-NEXT: catch i8* null
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: ret i32 [[RDX_INC]]
; CHECK-NEXT: [[I2:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: ret i32 [[I2]]
;
; CHECK-OPAQUE-LABEL: @alloca_used_in_maybe_throwing_call_with_same_dests(
; CHECK-OPAQUE-NEXT: entry:
@ -619,11 +630,11 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(i32* %data, i64 %
; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_PROM_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -636,7 +647,8 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(i32* %data, i64 %
; CHECK-OPAQUE-NEXT: catch ptr null
; CHECK-OPAQUE-NEXT: br label [[END]]
; CHECK-OPAQUE: end:
; CHECK-OPAQUE-NEXT: ret i32 [[RDX_INC]]
; CHECK-OPAQUE-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: ret i32 [[I2]]
;
entry:
%retval = alloca i32, align 4
@ -677,19 +689,23 @@ define [2 x i32] @part_of_alloca_used_in_call(i32* %data, i64 %n) {
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(i32* [[RETVAL]])
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
; CHECK-OPAQUE-LABEL: @part_of_alloca_used_in_call(
@ -702,19 +718,23 @@ define [2 x i32] @part_of_alloca_used_in_call(i32* %data, i64 %n) {
; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
entry:
@ -752,19 +772,23 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(i32* %data
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* [[RETVAL]], i32* [[RETVAL_BASE]])
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
; CHECK-OPAQUE-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args(
@ -778,19 +802,23 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(i32* %data
; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_BASE]])
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
entry:
@ -829,11 +857,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_FULL_PROM_SROA_3_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_3_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -841,8 +869,12 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK: exit:
; CHECK-NEXT: call void @llvm.memcpy.p0i32.p0i32.i32(i32* [[RETVAL_BASE]], i32* [[RETVAL]], i32 4, i1 false)
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* [[RETVAL]], i32* [[RETVAL_BASE]])
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[RDX_INC]], 0
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
; CHECK-OPAQUE-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_before_call(
@ -856,11 +888,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_FULL_PROM_SROA_3_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_3_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -868,8 +900,12 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[RETVAL_BASE]], ptr [[RETVAL]], i32 4, i1 false)
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_BASE]])
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[RDX_INC]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
entry:
@ -909,11 +945,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_FULL_PROM_SROA_3_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_3_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -921,8 +957,12 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* [[RETVAL]], i32* [[RETVAL_BASE]])
; CHECK-NEXT: call void @llvm.memcpy.p0i32.p0i32.i32(i32* [[RETVAL_BASE]], i32* [[RETVAL]], i32 4, i1 false)
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[RDX_INC]], 0
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
; CHECK-OPAQUE-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcpy_after_call(
@ -936,11 +976,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_FULL_PROM_SROA_3_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_3_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -948,8 +988,12 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args_with_memcp
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_BASE]])
; CHECK-OPAQUE-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[RETVAL_BASE]], ptr [[RETVAL]], i32 4, i1 false)
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[RDX_INC]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
entry:
@ -988,19 +1032,23 @@ define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(i32* %data, i64
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* [[RETVAL]], i32* [[RETVAL]])
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
; CHECK-OPAQUE-LABEL: @part_of_alloca_used_in_call_with_multiple_args(
@ -1013,19 +1061,23 @@ define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(i32* %data, i64
; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK-OPAQUE: exit:
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL]])
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I1_FCA_0_LOAD]], 0
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1
; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]]
;
entry:
@ -1065,11 +1117,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(i32* %dat
; CHECK-NEXT: [[SOME_ANOTHER_ALLOCA:%.*]] = getelementptr inbounds [42 x i32], [42 x i32]* [[SOME_ANOTHER_ALLOCA_FULL]], i64 0, i64 0
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -1078,8 +1130,12 @@ define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(i32* %dat
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* [[RETVAL]], i32* [[RETVAL_BASE]])
; CHECK-NEXT: [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* [[RETVAL_BASE]], i32* [[RETVAL]])
; CHECK-NEXT: [[I2:%.*]] = call i32 @capture_of_alloca(i32* [[SOME_ANOTHER_ALLOCA]])
; CHECK-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-NEXT: [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0
; CHECK-NEXT: [[I3_FCA_0_LOAD:%.*]] = load i32, i32* [[I3_FCA_0_GEP]], align 4
; CHECK-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I3_FCA_0_LOAD]], 0
; CHECK-NEXT: [[I3_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1
; CHECK-NEXT: [[I3_FCA_1_LOAD:%.*]] = load i32, i32* [[I3_FCA_1_GEP]], align 4
; CHECK-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[I3_FCA_1_LOAD]], 1
; CHECK-NEXT: ret [2 x i32] [[I3_FCA_1_INSERT]]
;
; CHECK-OPAQUE-LABEL: @all_parts_of_alloca_used_in_calls_with_multiple_args(
@ -1095,11 +1151,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(i32* %dat
; CHECK-OPAQUE-NEXT: [[SOME_ANOTHER_ALLOCA:%.*]] = getelementptr inbounds [42 x i32], ptr [[SOME_ANOTHER_ALLOCA_FULL]], i64 0, i64 0
; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]]
; CHECK-OPAQUE: loop:
; CHECK-OPAQUE-NEXT: [[RETVAL_FULL_PROM_SROA_2_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RDX_INC:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC]] = add nsw i32 [[RETVAL_FULL_PROM_SROA_2_0]], [[LD]]
; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
@ -1108,8 +1164,12 @@ define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(i32* %dat
; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_BASE]])
; CHECK-OPAQUE-NEXT: [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL_BASE]], ptr [[RETVAL]])
; CHECK-OPAQUE-NEXT: [[I2:%.*]] = call i32 @capture_of_alloca(ptr [[SOME_ANOTHER_ALLOCA]])
; CHECK-OPAQUE-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
; CHECK-OPAQUE-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[RDX_INC]], 1
; CHECK-OPAQUE-NEXT: [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
; CHECK-OPAQUE-NEXT: [[I3_FCA_0_LOAD:%.*]] = load i32, ptr [[I3_FCA_0_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 [[I3_FCA_0_LOAD]], 0
; CHECK-OPAQUE-NEXT: [[I3_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1
; CHECK-OPAQUE-NEXT: [[I3_FCA_1_LOAD:%.*]] = load i32, ptr [[I3_FCA_1_GEP]], align 4
; CHECK-OPAQUE-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[I3_FCA_1_LOAD]], 1
; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I3_FCA_1_INSERT]]
;
entry:
@ -1144,7 +1204,6 @@ define i32 @all_uses_of_alloca_are_calls(i32* %data, i64 %n) {
; CHECK-LABEL: @all_uses_of_alloca_are_calls(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[RETVAL_PROM:%.*]] = alloca i32, align 4
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(i32* [[RETVAL]])
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @user_of_alloca(i32* [[RETVAL]])
; CHECK-NEXT: ret i32 0
@ -1152,7 +1211,6 @@ define i32 @all_uses_of_alloca_are_calls(i32* %data, i64 %n) {
; CHECK-OPAQUE-LABEL: @all_uses_of_alloca_are_calls(
; CHECK-OPAQUE-NEXT: entry:
; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
; CHECK-OPAQUE-NEXT: [[RETVAL_PROM:%.*]] = alloca i32, align 4
; CHECK-OPAQUE-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
; CHECK-OPAQUE-NEXT: [[TMP1:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
; CHECK-OPAQUE-NEXT: ret i32 0
@ -1178,7 +1236,8 @@ define i64 @do_schedule_instrs_for_dce_after_fixups() {
; CHECK: if.end:
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAYDECAY]], i64 1
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @user_of_alloca(i32* [[ADD_PTR]])
; CHECK-NEXT: ret i64 0
; CHECK-NEXT: [[LD:%.*]] = load i64, i64* [[C]], align 4
; CHECK-NEXT: ret i64 [[LD]]
;
; CHECK-OPAQUE-LABEL: @do_schedule_instrs_for_dce_after_fixups(
; CHECK-OPAQUE-NEXT: entry:
@ -1191,7 +1250,8 @@ define i64 @do_schedule_instrs_for_dce_after_fixups() {
; CHECK-OPAQUE: if.end:
; CHECK-OPAQUE-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAYDECAY]], i64 1
; CHECK-OPAQUE-NEXT: [[TMP1:%.*]] = call i32 @user_of_alloca(ptr [[ADD_PTR]])
; CHECK-OPAQUE-NEXT: ret i64 0
; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i64, ptr [[C]], align 4
; CHECK-OPAQUE-NEXT: ret i64 [[LD]]
;
entry:
%c = alloca i64, align 2
@ -1234,13 +1294,15 @@ define i8 @dont_transform_load_only() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
; CHECK-NEXT: call void @byte_user_of_alloca(i8* [[A]])
; CHECK-NEXT: ret i8 undef
; CHECK-NEXT: [[R:%.*]] = load i8, i8* [[A]], align 1
; CHECK-NEXT: ret i8 [[R]]
;
; CHECK-OPAQUE-LABEL: @dont_transform_load_only(
; CHECK-OPAQUE-NEXT: entry:
; CHECK-OPAQUE-NEXT: [[A:%.*]] = alloca i8, align 1
; CHECK-OPAQUE-NEXT: call void @byte_user_of_alloca(ptr [[A]])
; CHECK-OPAQUE-NEXT: ret i8 undef
; CHECK-OPAQUE-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
; CHECK-OPAQUE-NEXT: ret i8 [[R]]
;
entry:
%a = alloca i8
@ -1254,14 +1316,16 @@ define i8 @transform_load_and_store() {
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
; CHECK-NEXT: store i8 0, i8* [[A]], align 1
; CHECK-NEXT: call void @byte_user_of_alloca(i8* [[A]])
; CHECK-NEXT: ret i8 0
; CHECK-NEXT: [[R:%.*]] = load i8, i8* [[A]], align 1
; CHECK-NEXT: ret i8 [[R]]
;
; CHECK-OPAQUE-LABEL: @transform_load_and_store(
; CHECK-OPAQUE-NEXT: entry:
; CHECK-OPAQUE-NEXT: [[A:%.*]] = alloca i8, align 1
; CHECK-OPAQUE-NEXT: store i8 0, ptr [[A]], align 1
; CHECK-OPAQUE-NEXT: call void @byte_user_of_alloca(ptr [[A]])
; CHECK-OPAQUE-NEXT: ret i8 0
; CHECK-OPAQUE-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
; CHECK-OPAQUE-NEXT: ret i8 [[R]]
;
entry:
%a = alloca i8