[llvm] [Mem2Reg] Remove extraneous getAllocatedType() check (PR #177438)
Jameson Nash via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 26 21:01:26 PST 2026
https://github.com/vtjnash updated https://github.com/llvm/llvm-project/pull/177438
>From 2c596c4ffb399107e6e3a02e8b7714207c465cde Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash+github at gmail.com>
Date: Wed, 21 Jan 2026 18:54:41 +0000
Subject: [PATCH 1/3] [Mem2Reg] Remove extraneous getAllocatedType() check
Replace uses of getAllocatedType() in PromoteMemoryToRegister.cpp with
type tracking from actual loads and stores. This makes the promotion
logic more semantic - it now checks that all loads/stores use a
consistent type rather than requiring them to match the alloca's
declared type.
Changes:
- isAllocaPromotable() now tracks the first load/store type seen and
ensures all subsequent accesses use the same type
- AllocaInfo gains a ValueType field populated during AnalyzeAlloca()
- PromoteMem2Reg tracks AllocaValueTypes alongside other per-alloca info
- PHI nodes and UndefValues are created using the tracked type
This is semantically more permissive - an alloca declared as i64 but
only accessed as i32 is now promotable. This is correct because the
alloca is just a blob of memory; what matters is consistent access
patterns.
Test fixes:
- asan-stack-safety.ll: Changed loads/stores to volatile to prevent
promotion while preserving ASAN stack safety analysis behavior
- SPIRV pointer tests (array-skips-gep.ll, load-struct.ll,
store-struct.ll, store-to-array-first-element.ll): Added escape
calls to prevent alloca promotion, as these tests verify SPIRV
backend handling of Function-storage-class pointers
Co-Authored-By: Claude Opus 4.5 <noreply at anthropic.com>
---
.../Utils/PromoteMemoryToRegister.cpp | 38 +++++++++++++++----
.../CodeGen/SPIRV/pointers/array-skips-gep.ll | 3 ++
.../CodeGen/SPIRV/pointers/load-struct.ll | 5 +++
.../CodeGen/SPIRV/pointers/store-struct.ll | 8 ++++
.../pointers/store-to-array-first-element.ll | 3 ++
.../AddressSanitizer/asan-stack-safety.ll | 4 +-
6 files changed, 52 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index d93a4d87f30f4..223f94f2037ee 100644
--- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -65,20 +65,31 @@ STATISTIC(NumPHIInsert, "Number of PHI nodes inserted");
bool llvm::isAllocaPromotable(const AllocaInst *AI) {
// Only allow direct and non-volatile loads and stores...
+ // All loads and stores must use the same type (determined by the first one
+ // seen). We don't require the type to match the alloca's declared type.
+ Type *ExpectedType = nullptr;
for (const User *U : AI->users()) {
if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
// Note that atomic loads can be transformed; atomic semantics do
// not have any meaning for a local alloca.
- if (LI->isVolatile() || LI->getType() != AI->getAllocatedType())
+ if (LI->isVolatile())
+ return false;
+ if (!ExpectedType)
+ ExpectedType = LI->getType();
+ else if (LI->getType() != ExpectedType)
return false;
} else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
- if (SI->getValueOperand() == AI ||
- SI->getValueOperand()->getType() != AI->getAllocatedType())
+ if (SI->getValueOperand() == AI)
return false; // Don't allow a store OF the AI, only INTO the AI.
// Note that atomic stores can be transformed; atomic semantics do
// not have any meaning for a local alloca.
if (SI->isVolatile())
return false;
+ Type *StoreType = SI->getValueOperand()->getType();
+ if (!ExpectedType)
+ ExpectedType = StoreType;
+ else if (StoreType != ExpectedType)
+ return false;
} else if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
if (!II->isLifetimeStartOrEnd() && !II->isDroppable() &&
II->getIntrinsicID() != Intrinsic::fake_use)
@@ -199,6 +210,10 @@ struct AllocaInfo {
BasicBlock *OnlyBlock;
bool OnlyUsedInOneBlock;
+ /// The type used by all loads/stores of this alloca. This may differ from
+ /// the alloca's declared type if all accesses use a different type.
+ Type *ValueType;
+
/// Debug users of the alloca - does not include dbg.assign intrinsics.
DPUserVec DPUsers;
/// Helper to update assignment tracking debug info.
@@ -210,6 +225,7 @@ struct AllocaInfo {
OnlyStore = nullptr;
OnlyBlock = nullptr;
OnlyUsedInOneBlock = true;
+ ValueType = nullptr;
DPUsers.clear();
AssignmentTracking.clear();
}
@@ -229,11 +245,15 @@ struct AllocaInfo {
// Remember the basic blocks which define new values for the alloca
DefiningBlocks.push_back(SI->getParent());
OnlyStore = SI;
+ if (!ValueType)
+ ValueType = SI->getValueOperand()->getType();
} else {
LoadInst *LI = cast<LoadInst>(User);
// Otherwise it must be a load instruction, keep track of variable
// reads.
UsingBlocks.push_back(LI->getParent());
+ if (!ValueType)
+ ValueType = LI->getType();
}
if (OnlyUsedInOneBlock) {
@@ -380,6 +400,8 @@ struct PromoteMem2Reg {
/// For each alloca, keep an instance of a helper class that gives us an easy
/// way to update assignment tracking debug info if the alloca is promoted.
SmallVector<AssignmentTrackingInfo, 8> AllocaATInfo;
+ /// For each alloca, the type used by all loads/stores of this alloca.
+ SmallVector<Type *, 8> AllocaValueTypes;
/// A set of dbg.assigns to delete because they've been demoted to
/// dbg.values. Call cleanUpDbgAssigns to delete them.
SmallPtrSet<DbgVariableRecord *, 8> DVRAssignsToDelete;
@@ -745,6 +767,7 @@ void PromoteMem2Reg::run() {
AllocaATInfo.resize(Allocas.size());
AllocaDPUsers.resize(Allocas.size());
+ AllocaValueTypes.resize(Allocas.size());
AllocaInfo Info;
LargeBlockInfo LBI;
@@ -806,6 +829,7 @@ void PromoteMem2Reg::run() {
AllocaATInfo[AllocaNum] = Info.AssignmentTracking;
if (!Info.DPUsers.empty())
AllocaDPUsers[AllocaNum] = Info.DPUsers;
+ AllocaValueTypes[AllocaNum] = Info.ValueType;
// Keep the reverse mapping of the 'Allocas' array for the rename pass.
AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
@@ -847,7 +871,7 @@ void PromoteMem2Reg::run() {
// been stored yet. In this case, it will get this null value.
IncomingVals.resize(Allocas.size());
for (unsigned i = 0, e = Allocas.size(); i != e; ++i)
- IncomingVals.init(i, UndefValue::get(Allocas[i]->getAllocatedType()));
+ IncomingVals.init(i, UndefValue::get(AllocaValueTypes[i]));
// When handling debug info, treat all incoming values as if they have
// compiler-generated (empty) locations, representing the uninitialized
@@ -1061,9 +1085,9 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo,
if (PN)
return false;
- // Create a PhiNode using the dereferenced type... and add the phi-node to the
- // BasicBlock.
- PN = PHINode::Create(Allocas[AllocaNo]->getAllocatedType(), getNumPreds(BB),
+ // Create a PhiNode using the type from loads/stores... and add the phi-node
+ // to the BasicBlock.
+ PN = PHINode::Create(AllocaValueTypes[AllocaNo], getNumPreds(BB),
Allocas[AllocaNo]->getName() + "." + Twine(Version++));
PN->insertBefore(BB->begin());
++NumPHIInsert;
diff --git a/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll b/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll
index 3bc07bc137ac6..b2b83f650ecf9 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll
@@ -16,6 +16,7 @@
define internal spir_func i32 @foo() {
%array = alloca [10 x i32], align 4
; CHECK: %[[#array:]] = OpVariable %[[#array_fp:]] Function
+ call void @escape(ptr %array)
; Direct load from the pointer index. This requires an OpAccessChain
%1 = load i32, ptr %array, align 4
@@ -26,6 +27,8 @@ define internal spir_func i32 @foo() {
; CHECK: OpReturnValue %[[#val]]
}
+declare void @escape(ptr)
+
define internal spir_func i32 @bar() {
; Direct load from the pointer index. This requires an OpAccessChain
%1 = load i32, ptr addrspace(10) @gv
diff --git a/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll
index 280a7e4f9053b..226a80e23f333 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll
@@ -25,6 +25,7 @@
define internal spir_func float @foo() {
%1 = alloca %struct.SF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sf_fp]] Function
+ call void @escape(ptr %1)
%2 = load float, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -36,6 +37,7 @@ define internal spir_func float @foo() {
define internal spir_func i32 @bar() {
%1 = alloca %struct.SU, align 4
; CHECK: %[[#var:]] = OpVariable %[[#su_fp]] Function
+ call void @escape(ptr %1)
%2 = load i32, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]]
@@ -47,6 +49,7 @@ define internal spir_func i32 @bar() {
define internal spir_func float @baz() {
%1 = alloca %struct.SFUF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sfuf_fp]] Function
+ call void @escape(ptr %1)
%2 = load float, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -62,3 +65,5 @@ define internal spir_func float @biz() {
ret float %2
}
+
+declare void @escape(ptr)
diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll
index 1ff53614990d5..effe372b93f83 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll
@@ -42,6 +42,7 @@
define internal spir_func void @foo() {
%1 = alloca %struct.SF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sf_fp]] Function
+ call void @escape(ptr %1)
store float 0.0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -53,6 +54,7 @@ define internal spir_func void @foo() {
define internal spir_func void @bar() {
%1 = alloca %struct.SU, align 4
; CHECK: %[[#var:]] = OpVariable %[[#su_fp]] Function
+ call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]]
@@ -64,6 +66,7 @@ define internal spir_func void @bar() {
define internal spir_func void @baz() {
%1 = alloca %struct.SFUF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sfuf_fp]] Function
+ call void @escape(ptr %1)
store float 0.0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -83,6 +86,7 @@ define internal spir_func void @biz() {
define internal spir_func void @nested_store() {
%1 = alloca %struct.SSU, align 4
; CHECK: %[[#var:]] = OpVariable %[[#ssu_fp]] Function
+ call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]] %[[#uint_0]]
@@ -94,6 +98,7 @@ define internal spir_func void @nested_store() {
define internal spir_func void @nested_store_vector() {
%1 = alloca %struct.SSV, align 4
; CHECK: %[[#var:]] = OpVariable %[[#ssv_fp]] Function
+ call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]]
@@ -105,6 +110,7 @@ define internal spir_func void @nested_store_vector() {
define internal spir_func void @nested_array_vector() {
%1 = alloca %struct.SSASSV, align 4
; CHECK: %[[#var:]] = OpVariable %[[#ssassv_fp]] Function
+ call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]]
@@ -112,3 +118,5 @@ define internal spir_func void @nested_array_vector() {
ret void
}
+
+declare void @escape(ptr)
diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll b/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll
index 2369c51799993..8ec7fa9c94da7 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll
@@ -15,6 +15,9 @@
define spir_func void @test_array_store() {
entry:
%var = alloca [4 x i32]
+ call void @escape(ptr %var)
store i32 123, ptr %var
ret void
}
+
+declare void @escape(ptr)
diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll
index 8210970aaaeb4..f94f3d4e6fb4e 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/asan-stack-safety.ll
@@ -7,7 +7,7 @@
define i32 @load() sanitize_address {
%buf = alloca [10 x i8], align 1
; NOSAFETY: call i64 @__asan_stack_malloc
- %1 = load i8, ptr %buf, align 1
+ %1 = load volatile i8, ptr %buf, align 1
; NOSAFETY: call void @__asan_load1
ret i32 0
}
@@ -16,7 +16,7 @@ define i32 @load() sanitize_address {
define i32 @store() sanitize_address {
%buf = alloca [10 x i8], align 1
; NOSAFETY: call i64 @__asan_stack_malloc
- store i8 0, ptr %buf
+ store volatile i8 0, ptr %buf
; NOSAFETY: call void @__asan_store1
ret i32 0
}
>From e3a0be371d02b7fd2f84286627e6745a87a037e2 Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash+github at gmail.com>
Date: Tue, 27 Jan 2026 03:58:18 +0000
Subject: [PATCH 2/3] reviewer feedback
---
llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
index 223f94f2037ee..ef668e575f3ea 100644
--- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
+++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
@@ -247,6 +247,9 @@ struct AllocaInfo {
OnlyStore = SI;
if (!ValueType)
ValueType = SI->getValueOperand()->getType();
+ else
+ assert(ValueType == SI->getValueOperand()->getType() &&
+ "All stores were checked to have used the same type");
} else {
LoadInst *LI = cast<LoadInst>(User);
// Otherwise it must be a load instruction, keep track of variable
@@ -254,6 +257,9 @@ struct AllocaInfo {
UsingBlocks.push_back(LI->getParent());
if (!ValueType)
ValueType = LI->getType();
+ else
+ assert(ValueType == LI->getType() &&
+ "All loads where checked to have used the same type");
}
if (OnlyUsedInOneBlock) {
>From 57347fff16eb10de8979652bb2c903d954863912 Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Tue, 27 Jan 2026 04:55:52 +0000
Subject: [PATCH 3/3] SPIRV test fixup
Since these SPIRV tests rely upon the alloca not getting optimized away
at O0, even though mem2reg is the only pass that would apply here and
the SPIRV test does not want it to run. So explicitly disable
optimization passes for these functions.
---
.../CodeGen/SPIRV/pointers/array-skips-gep.ll | 5 ++---
.../CodeGen/SPIRV/pointers/load-struct.ll | 13 +++++------
.../CodeGen/SPIRV/pointers/store-struct.ll | 22 +++++++------------
.../pointers/store-to-array-first-element.ll | 5 ++---
4 files changed, 17 insertions(+), 28 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll b/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll
index b2b83f650ecf9..57534bdf01c93 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/array-skips-gep.ll
@@ -13,10 +13,9 @@
@gv = external addrspace(10) global [10 x i32]
; CHECK: %[[#gv:]] = OpVariable %[[#array_pp]] Private
-define internal spir_func i32 @foo() {
+define internal spir_func i32 @foo() #0 {
%array = alloca [10 x i32], align 4
; CHECK: %[[#array:]] = OpVariable %[[#array_fp:]] Function
- call void @escape(ptr %array)
; Direct load from the pointer index. This requires an OpAccessChain
%1 = load i32, ptr %array, align 4
@@ -27,7 +26,7 @@ define internal spir_func i32 @foo() {
; CHECK: OpReturnValue %[[#val]]
}
-declare void @escape(ptr)
+attributes #0 = { optnone noinline }
define internal spir_func i32 @bar() {
; Direct load from the pointer index. This requires an OpAccessChain
diff --git a/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll
index 226a80e23f333..64e9ecdf96632 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/load-struct.ll
@@ -22,10 +22,9 @@
@gsfuf = external addrspace(10) global %struct.SFUF
; CHECK: %[[#gsfuf:]] = OpVariable %[[#sfuf_pp]] Private
-define internal spir_func float @foo() {
+define internal spir_func float @foo() #0 {
%1 = alloca %struct.SF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sf_fp]] Function
- call void @escape(ptr %1)
%2 = load float, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -34,10 +33,9 @@ define internal spir_func float @foo() {
ret float %2
}
-define internal spir_func i32 @bar() {
+define internal spir_func i32 @bar() #0 {
%1 = alloca %struct.SU, align 4
; CHECK: %[[#var:]] = OpVariable %[[#su_fp]] Function
- call void @escape(ptr %1)
%2 = load i32, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]]
@@ -46,10 +44,9 @@ define internal spir_func i32 @bar() {
ret i32 %2
}
-define internal spir_func float @baz() {
+define internal spir_func float @baz() #0 {
%1 = alloca %struct.SFUF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sfuf_fp]] Function
- call void @escape(ptr %1)
%2 = load float, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -58,7 +55,7 @@ define internal spir_func float @baz() {
ret float %2
}
-define internal spir_func float @biz() {
+define internal spir_func float @biz() #0 {
%2 = load float, ptr addrspace(10) @gsfuf, align 4
; CHECK: %[[#tmp:]] = OpAccessChain %[[#float_pp]] %[[#gsfuf]] %[[#uint_0]]
; CHECK: %[[#val:]] = OpLoad %[[#float]] %[[#tmp]] Aligned 4
@@ -66,4 +63,4 @@ define internal spir_func float @biz() {
ret float %2
}
-declare void @escape(ptr)
+attributes #0 = { optnone noinline }
diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll
index effe372b93f83..a352bf24ec3dd 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/store-struct.ll
@@ -39,10 +39,9 @@
@gsfuf = external addrspace(10) global %struct.SFUF
; CHECK-DAG: %[[#gsfuf:]] = OpVariable %[[#sfuf_pp]] Private
-define internal spir_func void @foo() {
+define internal spir_func void @foo() #0 {
%1 = alloca %struct.SF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sf_fp]] Function
- call void @escape(ptr %1)
store float 0.0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -51,10 +50,9 @@ define internal spir_func void @foo() {
ret void
}
-define internal spir_func void @bar() {
+define internal spir_func void @bar() #0 {
%1 = alloca %struct.SU, align 4
; CHECK: %[[#var:]] = OpVariable %[[#su_fp]] Function
- call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]]
@@ -63,10 +61,9 @@ define internal spir_func void @bar() {
ret void
}
-define internal spir_func void @baz() {
+define internal spir_func void @baz() #0 {
%1 = alloca %struct.SFUF, align 4
; CHECK: %[[#var:]] = OpVariable %[[#sfuf_fp]] Function
- call void @escape(ptr %1)
store float 0.0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#float_fp]] %[[#var]] %[[#uint_0]]
@@ -75,7 +72,7 @@ define internal spir_func void @baz() {
ret void
}
-define internal spir_func void @biz() {
+define internal spir_func void @biz() #0 {
store float 0.0, ptr addrspace(10) @gsfuf, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#float_pp]] %[[#gsfuf]] %[[#uint_0]]
; CHECK: OpStore %[[#tmp]] %[[#float_0]] Aligned 4
@@ -83,10 +80,9 @@ define internal spir_func void @biz() {
ret void
}
-define internal spir_func void @nested_store() {
+define internal spir_func void @nested_store() #0 {
%1 = alloca %struct.SSU, align 4
; CHECK: %[[#var:]] = OpVariable %[[#ssu_fp]] Function
- call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]] %[[#uint_0]]
@@ -95,10 +91,9 @@ define internal spir_func void @nested_store() {
ret void
}
-define internal spir_func void @nested_store_vector() {
+define internal spir_func void @nested_store_vector() #0 {
%1 = alloca %struct.SSV, align 4
; CHECK: %[[#var:]] = OpVariable %[[#ssv_fp]] Function
- call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]]
@@ -107,10 +102,9 @@ define internal spir_func void @nested_store_vector() {
ret void
}
-define internal spir_func void @nested_array_vector() {
+define internal spir_func void @nested_array_vector() #0 {
%1 = alloca %struct.SSASSV, align 4
; CHECK: %[[#var:]] = OpVariable %[[#ssassv_fp]] Function
- call void @escape(ptr %1)
store i32 0, ptr %1, align 4
; CHECK: %[[#tmp:]] = OpInBoundsAccessChain %[[#uint_fp]] %[[#var]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]] %[[#uint_0]]
@@ -119,4 +113,4 @@ define internal spir_func void @nested_array_vector() {
ret void
}
-declare void @escape(ptr)
+attributes #0 = { optnone noinline }
diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll b/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll
index 8ec7fa9c94da7..c41724cfaf72f 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/store-to-array-first-element.ll
@@ -12,12 +12,11 @@
; CHECK: %[[#GEP:]] = OpInBoundsAccessChain %[[#IntPtr]] %[[#Var]] %[[#Zero]]
; CHECK: OpStore %[[#GEP]] %[[#Const]]
-define spir_func void @test_array_store() {
+define spir_func void @test_array_store() #0 {
entry:
%var = alloca [4 x i32]
- call void @escape(ptr %var)
store i32 123, ptr %var
ret void
}
-declare void @escape(ptr)
+attributes #0 = { optnone noinline }
More information about the llvm-commits
mailing list