Revert "[SROA] Optimize reloaded values in allocas that escape into readonly nocapture calls. (#116645)"
Causing buffer overflow: SUMMARY: AddressSanitizer: heap-buffer-overflow llvm/lib/Transforms/Scalar/SROA.cpp:5552:35 This reverts commit 5e247d726d7a54cf0acc997bc17b50e7494e6fa3.
This commit is contained in:
parent
7071cd3885
commit
e3676aa21f
@ -64,9 +64,6 @@ public:
|
||||
/// Is the pointer escaped at some point?
|
||||
bool isEscaped() const { return EscapedInfo != nullptr; }
|
||||
|
||||
/// Is the pointer escaped into a read-only nocapture call at some point?
|
||||
bool isEscapedReadOnly() const { return EscapedReadOnly != nullptr; }
|
||||
|
||||
/// Get the instruction causing the visit to abort.
|
||||
/// \returns a pointer to the instruction causing the abort if one is
|
||||
/// available; otherwise returns null.
|
||||
@ -77,10 +74,6 @@ public:
|
||||
/// is available; otherwise returns null.
|
||||
Instruction *getEscapingInst() const { return EscapedInfo; }
|
||||
|
||||
/// Get the instruction causing the pointer to escape which is a read-only
|
||||
/// nocapture call.
|
||||
Instruction *getEscapedReadOnlyInst() const { return EscapedReadOnly; }
|
||||
|
||||
/// Mark the visit as aborted. Intended for use in a void return.
|
||||
/// \param I The instruction which caused the visit to abort, if available.
|
||||
void setAborted(Instruction *I) {
|
||||
@ -95,12 +88,6 @@ public:
|
||||
EscapedInfo = I;
|
||||
}
|
||||
|
||||
/// Mark the pointer as escaped into a readonly-nocapture call.
|
||||
void setEscapedReadOnly(Instruction *I) {
|
||||
assert(I && "Expected a valid pointer in setEscapedReadOnly");
|
||||
EscapedReadOnly = I;
|
||||
}
|
||||
|
||||
/// Mark the pointer as escaped, and the visit as aborted. Intended
|
||||
/// for use in a void return.
|
||||
/// \param I The instruction which both escapes the pointer and aborts the
|
||||
@ -113,7 +100,6 @@ public:
|
||||
private:
|
||||
Instruction *AbortedInfo = nullptr;
|
||||
Instruction *EscapedInfo = nullptr;
|
||||
Instruction *EscapedReadOnly = nullptr;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
@ -188,13 +188,6 @@ public:
|
||||
/// Return false if a sub-class wants to keep one of the loads/stores
|
||||
/// after the SSA construction.
|
||||
virtual bool shouldDelete(Instruction *I) const { return true; }
|
||||
|
||||
/// Return the value to use for the point in the code that the alloca is
|
||||
/// positioned. This will only be used if an Alloca is included in Insts,
|
||||
/// otherwise the value of a uninitialized load will be assumed to be poison.
|
||||
virtual Value *getValueToUseForAlloca(Instruction *AI) const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/Loads.h"
|
||||
#include "llvm/Analysis/PtrUseVisitor.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
@ -84,7 +83,6 @@
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
|
||||
#include "llvm/Transforms/Utils/SSAUpdater.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
@ -248,7 +246,6 @@ private:
|
||||
bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
|
||||
AllocaInst *rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &P);
|
||||
bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
|
||||
bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
|
||||
std::pair<bool /*Changed*/, bool /*CFGChanged*/> runOnAlloca(AllocaInst &AI);
|
||||
void clobberUse(Use &U);
|
||||
bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
|
||||
@ -601,7 +598,6 @@ public:
|
||||
/// If this is true, the slices are never fully built and should be
|
||||
/// ignored.
|
||||
bool isEscaped() const { return PointerEscapingInstr; }
|
||||
bool isEscapedReadOnly() const { return PointerEscapingInstrReadOnly; }
|
||||
|
||||
/// Support for iterating over the slices.
|
||||
/// @{
|
||||
@ -684,7 +680,6 @@ private:
|
||||
/// store a pointer to that here and abort trying to form slices of the
|
||||
/// alloca. This will be null if the alloca slices are analyzed successfully.
|
||||
Instruction *PointerEscapingInstr;
|
||||
Instruction *PointerEscapingInstrReadOnly;
|
||||
|
||||
/// The slices of the alloca.
|
||||
///
|
||||
@ -1395,18 +1390,6 @@ private:
|
||||
|
||||
/// Disable SROA entirely if there are unhandled users of the alloca.
|
||||
void visitInstruction(Instruction &I) { PI.setAborted(&I); }
|
||||
|
||||
void visitCallBase(CallBase &CB) {
|
||||
// If the call operand is NoCapture ReadOnly, then we mark it as
|
||||
// EscapedReadOnly.
|
||||
if (CB.doesNotCapture(U->getOperandNo()) &&
|
||||
CB.onlyReadsMemory(U->getOperandNo())) {
|
||||
PI.setEscapedReadOnly(&CB);
|
||||
return;
|
||||
}
|
||||
|
||||
Base::visitCallBase(CB);
|
||||
}
|
||||
};
|
||||
|
||||
AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI)
|
||||
@ -1414,7 +1397,7 @@ AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI)
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
AI(AI),
|
||||
#endif
|
||||
PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
|
||||
PointerEscapingInstr(nullptr) {
|
||||
SliceBuilder PB(DL, AI, *this);
|
||||
SliceBuilder::PtrInfo PtrI = PB.visitPtr(AI);
|
||||
if (PtrI.isEscaped() || PtrI.isAborted()) {
|
||||
@ -1425,7 +1408,6 @@ AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI)
|
||||
assert(PointerEscapingInstr && "Did not track a bad instruction");
|
||||
return;
|
||||
}
|
||||
PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
|
||||
|
||||
llvm::erase_if(Slices, [](const Slice &S) { return S.isDead(); });
|
||||
|
||||
@ -1463,9 +1445,6 @@ void AllocaSlices::print(raw_ostream &OS) const {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PointerEscapingInstrReadOnly)
|
||||
OS << "Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly << "\n";
|
||||
|
||||
OS << "Slices of alloca: " << AI << "\n";
|
||||
for (const_iterator I = begin(), E = end(); I != E; ++I)
|
||||
print(OS, I);
|
||||
@ -5475,86 +5454,6 @@ void SROA::clobberUse(Use &U) {
|
||||
}
|
||||
}
|
||||
|
||||
/// A basic LoadAndStorePromoter that does not remove store nodes.
|
||||
class BasicLoadAndStorePromoter : public LoadAndStorePromoter {
|
||||
public:
|
||||
BasicLoadAndStorePromoter(ArrayRef<const Instruction *> Insts, SSAUpdater &S,
|
||||
Type *ZeroType)
|
||||
: LoadAndStorePromoter(Insts, S), ZeroType(ZeroType) {}
|
||||
bool shouldDelete(Instruction *I) const override {
|
||||
return !isa<StoreInst>(I) && !isa<AllocaInst>(I);
|
||||
}
|
||||
|
||||
Value *getValueToUseForAlloca(Instruction *I) const override {
|
||||
return UndefValue::get(ZeroType);
|
||||
}
|
||||
|
||||
private:
|
||||
Type *ZeroType;
|
||||
};
|
||||
|
||||
bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
|
||||
// Look through each "partition", looking for slices with the same start/end
|
||||
// that do not overlap with any before them. The slices are sorted by
|
||||
// increasing beginOffset. We don't use AS.partitions(), as it will use a more
|
||||
// sophisticated algorithm that takes splittable slices into account.
|
||||
auto PartitionBegin = AS.begin();
|
||||
auto PartitionEnd = PartitionBegin;
|
||||
uint64_t BeginOffset = PartitionBegin->beginOffset();
|
||||
uint64_t EndOffset = PartitionBegin->endOffset();
|
||||
while (PartitionBegin != AS.end()) {
|
||||
bool AllSameAndValid = true;
|
||||
SmallVector<Instruction *> Insts;
|
||||
Type *PartitionType = nullptr;
|
||||
while (PartitionEnd != AS.end() &&
|
||||
(PartitionEnd->beginOffset() < EndOffset ||
|
||||
PartitionEnd->endOffset() <= EndOffset)) {
|
||||
if (AllSameAndValid) {
|
||||
AllSameAndValid &= PartitionEnd->beginOffset() == BeginOffset &&
|
||||
PartitionEnd->endOffset() == EndOffset;
|
||||
Instruction *User =
|
||||
cast<Instruction>(PartitionEnd->getUse()->getUser());
|
||||
if (auto *LI = dyn_cast<LoadInst>(User)) {
|
||||
Type *UserTy = LI->getType();
|
||||
// LoadAndStorePromoter requires all the types to be the same.
|
||||
if (!LI->isSimple() || (PartitionType && UserTy != PartitionType))
|
||||
AllSameAndValid = false;
|
||||
PartitionType = UserTy;
|
||||
Insts.push_back(User);
|
||||
} else if (auto *SI = dyn_cast<StoreInst>(User)) {
|
||||
Type *UserTy = SI->getValueOperand()->getType();
|
||||
if (!SI->isSimple() || PartitionType && UserTy != PartitionType)
|
||||
AllSameAndValid = false;
|
||||
PartitionType = UserTy;
|
||||
Insts.push_back(User);
|
||||
} else if (!isAssumeLikeIntrinsic(User)) {
|
||||
AllSameAndValid = false;
|
||||
}
|
||||
}
|
||||
EndOffset = std::max(EndOffset, PartitionEnd->endOffset());
|
||||
++PartitionEnd;
|
||||
}
|
||||
|
||||
// So long as all the slices start and end offsets matched, update loads to
|
||||
// the values stored in the partition.
|
||||
if (AllSameAndValid && !Insts.empty()) {
|
||||
LLVM_DEBUG(dbgs() << "Propagate values on slice [" << BeginOffset << ", "
|
||||
<< EndOffset << ")\n");
|
||||
SmallVector<PHINode *, 4> NewPHIs;
|
||||
SSAUpdater SSA(&NewPHIs);
|
||||
Insts.push_back(&AI);
|
||||
BasicLoadAndStorePromoter Promoter(Insts, SSA, PartitionType);
|
||||
Promoter.run(Insts);
|
||||
}
|
||||
|
||||
// Step on to the next partition.
|
||||
PartitionBegin = PartitionEnd;
|
||||
BeginOffset = PartitionBegin->beginOffset();
|
||||
EndOffset = PartitionBegin->endOffset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Analyze an alloca for SROA.
|
||||
///
|
||||
/// This analyzes the alloca to ensure we can reason about it, builds
|
||||
@ -5595,11 +5494,6 @@ SROA::runOnAlloca(AllocaInst &AI) {
|
||||
if (AS.isEscaped())
|
||||
return {Changed, CFGChanged};
|
||||
|
||||
if (AS.isEscapedReadOnly()) {
|
||||
Changed |= propagateStoredValuesToLoads(AI, AS);
|
||||
return {Changed, CFGChanged};
|
||||
}
|
||||
|
||||
// Delete all the dead users of this alloca before splitting and rewriting it.
|
||||
for (Instruction *DeadUser : AS.getDeadUsers()) {
|
||||
// Free up everything used by this instruction.
|
||||
|
||||
@ -412,13 +412,9 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
|
||||
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
|
||||
updateDebugInfo(SI);
|
||||
SSA.AddAvailableValue(BB, SI->getOperand(0));
|
||||
} else if (auto *AI = dyn_cast<AllocaInst>(User)) {
|
||||
// We treat AllocaInst as a store of an getValueToUseForAlloca value.
|
||||
SSA.AddAvailableValue(BB, getValueToUseForAlloca(AI));
|
||||
} else {
|
||||
} else
|
||||
// Otherwise it is a load, queue it to rewrite as a live-in load.
|
||||
LiveInLoads.push_back(cast<LoadInst>(User));
|
||||
}
|
||||
BlockUses.clear();
|
||||
continue;
|
||||
}
|
||||
@ -426,7 +422,7 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
|
||||
// Otherwise, check to see if this block is all loads.
|
||||
bool HasStore = false;
|
||||
for (Instruction *I : BlockUses) {
|
||||
if (isa<StoreInst>(I) || isa<AllocaInst>(I)) {
|
||||
if (isa<StoreInst>(I)) {
|
||||
HasStore = true;
|
||||
break;
|
||||
}
|
||||
@ -472,12 +468,6 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
|
||||
|
||||
// Remember that this is the active value in the block.
|
||||
StoredValue = SI->getOperand(0);
|
||||
} else if (auto *AI = dyn_cast<AllocaInst>(&I)) {
|
||||
// Check if this an alloca, in which case we treat it as a store of
|
||||
// getValueToUseForAlloca.
|
||||
if (!isInstInList(AI, Insts))
|
||||
continue;
|
||||
StoredValue = getValueToUseForAlloca(AI);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,18 +9,19 @@ define i32 @alloca_used_in_call(ptr %data, i64 %n) {
|
||||
; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[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(ptr [[RETVAL]])
|
||||
; CHECK-NEXT: ret i32 [[RDX_INC]]
|
||||
; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: ret i32 [[I1]]
|
||||
;
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
@ -137,18 +138,19 @@ define i32 @alloca_not_captured_and_readonly_as_per_operand_attr(ptr %data, i64
|
||||
; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[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(ptr nocapture readonly [[RETVAL]])
|
||||
; CHECK-NEXT: ret i32 [[RDX_INC]]
|
||||
; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: ret i32 [[I1]]
|
||||
;
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
@ -265,18 +267,19 @@ define i32 @alloca_with_gep_used_in_call(ptr %data, i64 %n) {
|
||||
; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[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(ptr [[RETVAL]])
|
||||
; CHECK-NEXT: ret i32 [[RDX_INC]]
|
||||
; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: ret i32 [[I1]]
|
||||
;
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
@ -350,11 +353,11 @@ define i32 @alloca_used_in_maybe_throwing_call(ptr %data, i64 %n) personality pt
|
||||
; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
|
||||
@ -369,7 +372,8 @@ define i32 @alloca_used_in_maybe_throwing_call(ptr %data, i64 %n) personality pt
|
||||
; CHECK-NEXT: catch ptr null
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret i32 [[RDX_INC]]
|
||||
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: ret i32 [[I2]]
|
||||
;
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
@ -409,11 +413,11 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(ptr %data, i64 %n
|
||||
; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
|
||||
@ -426,7 +430,8 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(ptr %data, i64 %n
|
||||
; CHECK-NEXT: catch ptr null
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret i32 [[RDX_INC]]
|
||||
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: ret i32 [[I2]]
|
||||
;
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
@ -467,11 +472,11 @@ define [2 x i32] @part_of_alloca_used_in_call(ptr %data, i64 %n) {
|
||||
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
|
||||
@ -479,9 +484,11 @@ define [2 x i32] @part_of_alloca_used_in_call(ptr %data, i64 %n) {
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr [[RETVAL]])
|
||||
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
|
||||
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
|
||||
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[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], ptr [[RETVAL_FULL]], i32 0, i32 1
|
||||
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
|
||||
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[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]]
|
||||
;
|
||||
entry:
|
||||
@ -518,11 +525,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(ptr %data,
|
||||
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
|
||||
@ -530,9 +537,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(ptr %data,
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL_FULL]])
|
||||
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
|
||||
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
|
||||
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[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], ptr [[RETVAL_FULL]], i32 0, i32 1
|
||||
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
|
||||
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[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]]
|
||||
;
|
||||
entry:
|
||||
@ -679,11 +688,11 @@ define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(ptr %data, i64
|
||||
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
|
||||
@ -691,9 +700,11 @@ define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(ptr %data, i64
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL]], ptr [[RETVAL]])
|
||||
; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
|
||||
; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
|
||||
; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[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], ptr [[RETVAL_FULL]], i32 0, i32 1
|
||||
; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[RDX_INC]], 1
|
||||
; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[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]]
|
||||
;
|
||||
entry:
|
||||
@ -731,11 +742,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(ptr %data
|
||||
; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[RDX:%.*]] = 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, ptr [[DATA:%.*]], i64 [[INDVARS_IV]]
|
||||
; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]]
|
||||
; CHECK-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]]
|
||||
@ -745,9 +756,11 @@ define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(ptr %data
|
||||
; CHECK-NEXT: [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr [[RETVAL_FULL]], ptr [[RETVAL]])
|
||||
; CHECK-NEXT: [[I2:%.*]] = call i32 @capture_of_alloca(ptr [[SOME_ANOTHER_ALLOCA_FULL]])
|
||||
; CHECK-NEXT: [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0
|
||||
; CHECK-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] poison, i32 0, 0
|
||||
; CHECK-NEXT: [[I3_FCA_0_LOAD:%.*]] = load i32, ptr [[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], ptr [[RETVAL_FULL]], i32 0, i32 1
|
||||
; CHECK-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[RDX_INC]], 1
|
||||
; CHECK-NEXT: [[I3_FCA_1_LOAD:%.*]] = load i32, ptr [[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]]
|
||||
;
|
||||
entry:
|
||||
@ -838,7 +851,8 @@ define i8 @dont_transform_load_only() {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
|
||||
; CHECK-NEXT: call void @byte_user_of_alloca(ptr [[A]])
|
||||
; CHECK-NEXT: ret i8 undef
|
||||
; CHECK-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
|
||||
; CHECK-NEXT: ret i8 [[R]]
|
||||
;
|
||||
entry:
|
||||
%a = alloca i8
|
||||
@ -852,7 +866,8 @@ define i8 @transform_load_and_store() {
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
|
||||
; CHECK-NEXT: store i8 0, ptr [[A]], align 1
|
||||
; CHECK-NEXT: call void @byte_user_of_alloca(ptr [[A]])
|
||||
; CHECK-NEXT: ret i8 0
|
||||
; CHECK-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
|
||||
; CHECK-NEXT: ret i8 [[R]]
|
||||
;
|
||||
entry:
|
||||
%a = alloca i8
|
||||
|
||||
@ -8,7 +8,8 @@ define i32 @simple() {
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: ret i32 0
|
||||
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
|
||||
; CHECK-NEXT: ret i32 [[L1]]
|
||||
;
|
||||
%a = alloca i32
|
||||
store i32 0, ptr %a
|
||||
@ -39,7 +40,9 @@ define i32 @twoalloc() {
|
||||
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
|
||||
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 0, 1
|
||||
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
|
||||
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = alloca {i32, i32}
|
||||
@ -59,7 +62,8 @@ define i32 @twostore() {
|
||||
; CHECK-NEXT: store i32 1, ptr [[A]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: store i32 2, ptr [[A]], align 4
|
||||
; CHECK-NEXT: ret i32 2
|
||||
; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4
|
||||
; CHECK-NEXT: ret i32 [[L]]
|
||||
;
|
||||
%a = alloca i32
|
||||
store i32 1, ptr %a
|
||||
@ -112,8 +116,10 @@ define i32 @twocalls() {
|
||||
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
|
||||
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 0, 1
|
||||
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = alloca {i32, i32}
|
||||
@ -159,7 +165,8 @@ define i32 @atomic() {
|
||||
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: [[L1:%.*]] = load atomic i32, ptr [[A]] seq_cst, align 4
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], 1
|
||||
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = alloca {i32, i32}
|
||||
@ -177,10 +184,12 @@ define i32 @notdominating() {
|
||||
; CHECK-LABEL: @notdominating(
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca { i32, i32 }, align 8
|
||||
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
|
||||
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
|
||||
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
|
||||
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
|
||||
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
|
||||
; CHECK-NEXT: call void @callee(ptr [[A]])
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 undef, undef
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = alloca {i32, i32}
|
||||
@ -226,7 +235,9 @@ define i32 @multiuse() {
|
||||
; CHECK-NEXT: [[B:%.*]] = getelementptr i32, ptr [[A]], i32 1
|
||||
; CHECK-NEXT: store i32 1, ptr [[B]], align 4
|
||||
; CHECK-NEXT: call void @callee_multiuse(ptr [[A]], ptr [[A]])
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 0, 1
|
||||
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[A]], align 4
|
||||
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[B]], align 4
|
||||
; CHECK-NEXT: [[R:%.*]] = add i32 [[L1]], [[L2]]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = alloca {i32, i32}
|
||||
@ -285,7 +296,8 @@ define void @incompletestruct(i1 %b, i1 %c) {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[LII:%.*]] = alloca [[STRUCT_LOADIMMEDIATEINFO:%.*]], align 4
|
||||
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[LII]])
|
||||
; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 undef, -262144
|
||||
; CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[LII]], align 4
|
||||
; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 [[BF_LOAD]], -262144
|
||||
; CHECK-NEXT: [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072
|
||||
; CHECK-NEXT: [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]]
|
||||
; CHECK-NEXT: store i32 [[BF_SET12]], ptr [[LII]], align 4
|
||||
@ -313,7 +325,8 @@ define void @incompletestruct_bb(i1 %b, i1 %c) {
|
||||
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
||||
; CHECK: if.then:
|
||||
; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[LII]])
|
||||
; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 undef, -262144
|
||||
; CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[LII]], align 4
|
||||
; CHECK-NEXT: [[BF_CLEAR4:%.*]] = and i32 [[BF_LOAD]], -262144
|
||||
; CHECK-NEXT: [[BF_SET5:%.*]] = select i1 [[B:%.*]], i32 196608, i32 131072
|
||||
; CHECK-NEXT: [[BF_SET12:%.*]] = or disjoint i32 [[BF_SET5]], [[BF_CLEAR4]]
|
||||
; CHECK-NEXT: store i32 [[BF_SET12]], ptr [[LII]], align 4
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user