[llvm] [SPIRV] Respect source alignment when lowering memory copies (PR #228859)
Alexander Shaposhnikov via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 4 15:50:28 PDT 2026
https://github.com/alexander-shaposhnikov updated https://github.com/llvm/llvm-project/pull/228859
>From 013c293632cfe3278646c107687b01da02af72d5 Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 4 Oct 2026 11:33:28 -0700
Subject: [PATCH 1/4] [SPIRV] Respect source alignment when lowering memory
copies
Lowering memcpy, memcpy.inline, and memmove to OpCopyMemory or
OpCopyMemorySized only considers the destination alignment. A single
Aligned memory operand applies to both pointers, so a destination
alignment greater than the source alignment overstates the latter.
For SPIR-V 1.4 and later, emit separate destination and source alignments
when they differ. For earlier versions, use their minimum in the single
permitted memory operand mask. Keep one mask when the alignments match.
Consolidate both copy selectors in selectCopyMemory so they share the
alignment handling. Allow the memory operand helper to take an explicit
alignment while preserving the existing flags and alias metadata on both
accesses.
Cover equal and unequal alignments in SPIR-V 1.3 and 1.4, and add an
OpCopyMemory regression case with unequal alignments, volatility, and
alias-scope metadata.
---
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 93 ++++++++++---------
.../alias-copy-memory.ll | 6 +-
.../SPIRV/llvm-intrinsics/memcpy.align.ll | 16 ++--
3 files changed, 63 insertions(+), 52 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 143e1c0e3ef2a..9cf72523b45a1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -168,7 +168,6 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectMemOperation(Register ResVReg, MachineInstr &I) const;
Register getOrCreateMemSetGlobal(MachineInstr &I) const;
bool selectCopyMemory(MachineInstr &I, Register SrcReg) const;
- bool selectCopyMemorySized(MachineInstr &I, Register SrcReg) const;
bool selectAtomicRMW(Register ResVReg, SPIRVTypeInst ResType, MachineInstr &I,
unsigned NewOpcode, unsigned NegateOpcode = 0) const;
@@ -1969,10 +1968,10 @@ bool SPIRVInstructionSelector::selectBitcast(Register ResVReg,
return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast);
}
-static void addMemoryOperands(MachineMemOperand *MemOp,
- MachineInstrBuilder &MIB,
- MachineIRBuilder &MIRBuilder,
- SPIRVGlobalRegistry &GR) {
+static void
+addMemoryOperands(const MachineMemOperand *MemOp, MachineInstrBuilder &MIB,
+ MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry &GR,
+ std::optional<Align> Align = std::nullopt) {
const SPIRVSubtarget *ST =
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
@@ -2004,7 +2003,7 @@ static void addMemoryOperands(MachineMemOperand *MemOp,
if (SpvMemOp != static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
MIB.addImm(SpvMemOp);
if (SpvMemOp & static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
- MIB.addImm(MemOp->getAlign().value());
+ MIB.addImm(Align.value_or(MemOp->getAlign()).value());
if (AliasList)
MIB.addUse(AliasList->getOperand(0).getReg());
if (NoAliasList)
@@ -2535,42 +2534,53 @@ bool SPIRVInstructionSelector::selectCopyMemory(MachineInstr &I,
Register SrcReg) const {
MachineBasicBlock &BB = *I.getParent();
Register DstReg = I.getOperand(0).getReg();
- SPIRVTypeInst DstTy = GR.getSPIRVTypeForVReg(DstReg);
- SPIRVTypeInst SrcTy = GR.getSPIRVTypeForVReg(SrcReg);
- if (GR.getPointeeType(DstTy) != GR.getPointeeType(SrcTy))
- return diagnoseUnsupported(
- I, "OpCopyMemory requires operands to have the same type");
- uint64_t CopySize = getIConstVal(I.getOperand(2).getReg(), MRI);
- SPIRVTypeInst PointeeTy = GR.getPointeeType(DstTy);
- const Type *LLVMPointeeTy = GR.getTypeForSPIRVType(PointeeTy);
- if (!LLVMPointeeTy)
- return diagnoseUnsupported(
- I, "Unable to determine pointee type size for OpCopyMemory");
- const DataLayout &DL = I.getMF()->getFunction().getDataLayout();
- if (CopySize != DL.getTypeStoreSize(const_cast<Type *>(LLVMPointeeTy)))
- return diagnoseUnsupported(
- I, "OpCopyMemory requires the size to match the pointee type size");
- auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCopyMemory))
+ const bool IsLogical = STI.isLogicalSPIRV();
+ if (IsLogical) {
+ SPIRVTypeInst DstTy = GR.getSPIRVTypeForVReg(DstReg);
+ SPIRVTypeInst SrcTy = GR.getSPIRVTypeForVReg(SrcReg);
+ if (GR.getPointeeType(DstTy) != GR.getPointeeType(SrcTy))
+ return diagnoseUnsupported(
+ I, "OpCopyMemory requires operands to have the same type");
+ uint64_t CopySize = getIConstVal(I.getOperand(2).getReg(), MRI);
+ SPIRVTypeInst PointeeTy = GR.getPointeeType(DstTy);
+ const Type *LLVMPointeeTy = GR.getTypeForSPIRVType(PointeeTy);
+ if (!LLVMPointeeTy)
+ return diagnoseUnsupported(
+ I, "Unable to determine pointee type size for OpCopyMemory");
+ const DataLayout &DL = I.getMF()->getFunction().getDataLayout();
+ if (CopySize != DL.getTypeStoreSize(const_cast<Type *>(LLVMPointeeTy)))
+ return diagnoseUnsupported(
+ I, "OpCopyMemory requires the size to match the pointee type size");
+ }
+
+ const unsigned Opcode =
+ IsLogical ? SPIRV::OpCopyMemory : SPIRV::OpCopyMemorySized;
+ auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
.addUse(DstReg)
.addUse(SrcReg);
- if (I.getNumMemOperands()) {
- MachineIRBuilder MIRBuilder(I);
- addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder, GR);
- }
- MIB.constrainAllUses(TII, TRI, RBI);
- return true;
-}
+ if (!IsLogical)
+ MIB.addUse(I.getOperand(2).getReg());
-bool SPIRVInstructionSelector::selectCopyMemorySized(MachineInstr &I,
- Register SrcReg) const {
- MachineBasicBlock &BB = *I.getParent();
- auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCopyMemorySized))
- .addUse(I.getOperand(0).getReg())
- .addUse(SrcReg)
- .addUse(I.getOperand(2).getReg());
if (I.getNumMemOperands()) {
MachineIRBuilder MIRBuilder(I);
- addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder, GR);
+ const MachineMemOperand *DstMemOp = *I.memoperands_begin();
+ const Align DstAlign = DstMemOp->getAlign();
+ Align SrcAlign = DstAlign;
+ // Copies carry destination and source MMOs; memset carries only the
+ // destination. Shader memory operands do not include alignment.
+ if (I.getNumMemOperands() > 1 && !STI.isShader())
+ SrcAlign = (*std::next(I.memoperands_begin()))->getAlign();
+
+ // A single mask applies to both pointers. SPIR-V 1.4 allows separate
+ // destination and source masks, preserving their individual alignments.
+ if (DstAlign != SrcAlign && STI.isAtLeastSPIRVVer(VersionTuple(1, 4))) {
+ // Preserve the existing flags and metadata on both accesses.
+ addMemoryOperands(DstMemOp, MIB, MIRBuilder, GR);
+ addMemoryOperands(DstMemOp, MIB, MIRBuilder, GR, SrcAlign);
+ } else {
+ addMemoryOperands(DstMemOp, MIB, MIRBuilder, GR,
+ std::min(DstAlign, SrcAlign));
+ }
}
MIB.constrainAllUses(TII, TRI, RBI);
return true;
@@ -2598,13 +2608,8 @@ bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg,
if (!selectOpWithSrcs(SrcReg, SourceTy, I, {VarReg}, SPIRV::OpBitcast))
return false;
}
- if (STI.isLogicalSPIRV()) {
- if (!selectCopyMemory(I, SrcReg))
- return false;
- } else {
- if (!selectCopyMemorySized(I, SrcReg))
- return false;
- }
+ if (!selectCopyMemory(I, SrcReg))
+ return false;
if (ResVReg.isValid() && ResVReg != I.getOperand(0).getReg())
if (!BuildCOPY(ResVReg, I.getOperand(0).getReg(), I))
return false;
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_memory_access_aliasing/alias-copy-memory.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_memory_access_aliasing/alias-copy-memory.ll
index ddd61bd9e0bbb..6ceddae59ba0d 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_memory_access_aliasing/alias-copy-memory.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_memory_access_aliasing/alias-copy-memory.ll
@@ -9,14 +9,16 @@
; CHECK: %[[#]] = OpFunction
define void @copy_aliased() {
entry:
-; CHECK: OpCopyMemory %[[#]] %[[#]] Aligned|AliasScopeINTELMask 4 %[[#List]]
+; CHECK: OpCopyMemory %[[#]] %[[#]] Aligned|AliasScopeINTELMask 4 %[[#List]]{{$}}
call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) align 4 @dst, ptr addrspace(1) align 4 @src, i64 20, i1 false), !alias.scope !1
+; CHECK: OpCopyMemory %[[#]] %[[#]] Volatile|Aligned|AliasScopeINTELMask 8 %[[#List]] Volatile|Aligned|AliasScopeINTELMask 4 %[[#List]]{{$}}
+ call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) align 8 @dst, ptr addrspace(1) align 4 @src, i64 20, i1 true), !alias.scope !1
ret void
}
%struct.T = type <{ float, float, float, float, float }>
@src = external dso_local addrspace(1) global %struct.T, align 4
- at dst = external dso_local addrspace(1) global %struct.T, align 4
+ at dst = external dso_local addrspace(1) global %struct.T, align 8
declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1), ptr addrspace(1), i64, i1)
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll
index b4100019a8a0c..03f20f0176d2b 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll
@@ -1,5 +1,7 @@
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPV13
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPV14
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - -filetype=obj | spirv-val %}
%struct.B = type { [2 x i32] }
%struct.A = type { i64, %struct.B }
@@ -14,13 +16,14 @@ entry:
call void @llvm.lifetime.start.p0(i64 8, ptr %0)
%1 = bitcast ptr %b to ptr
call void @llvm.memcpy.p0.p2.i32(ptr align 4 %1, ptr addrspace(2) align 4 @__const.foo.b, i32 8, i1 false)
-; CHECK: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 4
+; CHECK: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 4{{$}}
%b1 = getelementptr inbounds %struct.A, ptr %agg.result, i32 0, i32 1
%2 = bitcast ptr %b1 to ptr
%3 = bitcast ptr %b to ptr
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %2, ptr align 4 %3, i32 8, i1 false)
; CHECK: %[[#PTR1:]] = OpInBoundsPtrAccessChain %[[#]] %[[#]] %[[#]] %[[#]]
-; CHECK: OpCopyMemorySized %[[#PTR1]] %[[#]] %[[#]] Aligned 8
+; SPV13: OpCopyMemorySized %[[#PTR1]] %[[#]] %[[#]] Aligned 4{{$}}
+; SPV14: OpCopyMemorySized %[[#PTR1]] %[[#]] %[[#]] Aligned 8 Aligned 4{{$}}
%4 = bitcast ptr %b to ptr
call void @llvm.lifetime.end.p0(i64 8, ptr %4)
ret void
@@ -41,13 +44,14 @@ entry:
call void @llvm.lifetime.start.p0(i64 16, ptr %0)
%1 = bitcast ptr %a to ptr
call void @llvm.memcpy.p0.p2.i32(ptr align 8 %1, ptr addrspace(2) align 8 @__const.bar.a, i32 16, i1 false)
-; CHECK: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 8
+; CHECK: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 8{{$}}
%b = getelementptr inbounds %struct.A, ptr %a, i32 0, i32 1
%2 = bitcast ptr %agg.result to ptr
%3 = bitcast ptr %b to ptr
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %2, ptr align 8 %3, i32 8, i1 false)
; CHECK: %[[#PTR2:]] = OpInBoundsPtrAccessChain %[[#]] %[[#]] %[[#]] %[[#]]
-; CHECK: OpCopyMemorySized %[[#]] %[[#PTR2]] %[[#]] Aligned 4
+; SPV13: OpCopyMemorySized %[[#]] %[[#PTR2]] %[[#]] Aligned 4{{$}}
+; SPV14: OpCopyMemorySized %[[#]] %[[#PTR2]] %[[#]] Aligned 4 Aligned 8{{$}}
%4 = bitcast ptr %a to ptr
call void @llvm.lifetime.end.p0(i64 16, ptr %4)
ret void
>From 69e229f125504b41d08f889e7e6deb80fee9ba21 Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 4 Oct 2026 15:41:47 -0700
Subject: [PATCH 2/4] Address comments
---
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 9 ++---
.../llvm-intrinsics/logical-memcpy.align.ll | 36 +++++++++++++++++++
.../SPIRV/llvm-intrinsics/memcpy.align.ll | 14 ++++++++
3 files changed, 55 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.align.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 9cf72523b45a1..ffc7523955457 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1968,10 +1968,11 @@ bool SPIRVInstructionSelector::selectBitcast(Register ResVReg,
return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast);
}
-static void
-addMemoryOperands(const MachineMemOperand *MemOp, MachineInstrBuilder &MIB,
- MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry &GR,
- std::optional<Align> Align = std::nullopt) {
+static void addMemoryOperands(const MachineMemOperand *MemOp,
+ MachineInstrBuilder &MIB,
+ MachineIRBuilder &MIRBuilder,
+ SPIRVGlobalRegistry &GR,
+ std::optional<Align> Align = std::nullopt) {
const SPIRVSubtarget *ST =
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.align.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.align.ll
new file mode 100644
index 0000000000000..19f20c46df6cc
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.align.ll
@@ -0,0 +1,36 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s --implicit-check-not=Aligned --implicit-check-not=OpCopyMemorySized
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan %s -o - -filetype=obj | spirv-val %}
+
+; Shader copies omit alignment operands, including when the source and
+; destination alignments differ. Volatile still applies to both accesses.
+; CHECK: OpCapability Shader
+; CHECK: OpMemoryModel Logical GLSL450
+; CHECK: OpEntryPoint GLCompute %[[#Main:]] "main"
+; CHECK-DAG: OpName %[[#Dst:]] "dst"
+; CHECK-DAG: OpName %[[#Src:]] "src"
+
+%struct.S = type { i32, i32 }
+ at dst = internal addrspace(3) global %struct.S undef, align 8
+ at src = internal addrspace(3) global %struct.S undef, align 8
+
+; CHECK: %[[#Main]] = OpFunction
+define void @main() #0 {
+entry:
+; CHECK: OpCopyMemory %[[#Dst]] %[[#Src]]{{$}}
+ call void @llvm.memcpy.p3.p3.i32(ptr addrspace(3) align 4 @dst, ptr addrspace(3) align 4 @src, i32 8, i1 false)
+; CHECK: OpCopyMemory %[[#Dst]] %[[#Src]]{{$}}
+ call void @llvm.memcpy.p3.p3.i32(ptr addrspace(3) align 8 @dst, ptr addrspace(3) align 4 @src, i32 8, i1 false)
+; CHECK: OpCopyMemory %[[#Dst]] %[[#Src]]{{$}}
+ call void @llvm.memcpy.p3.p3.i32(ptr addrspace(3) align 4 @dst, ptr addrspace(3) align 8 @src, i32 8, i1 false)
+; CHECK: OpCopyMemory %[[#Dst]] %[[#Src]]{{$}}
+ call void @llvm.memcpy.p3.p3.i32(ptr addrspace(3) align 4 @dst, ptr addrspace(3) @src, i32 8, i1 false)
+; CHECK: OpCopyMemory %[[#Dst]] %[[#Src]] Volatile{{$}}
+ call void @llvm.memcpy.p3.p3.i32(ptr addrspace(3) align 8 @dst, ptr addrspace(3) align 4 @src, i32 8, i1 true)
+ ret void
+; CHECK: OpReturn
+; CHECK: OpFunctionEnd
+}
+
+declare void @llvm.memcpy.p3.p3.i32(ptr addrspace(3), ptr addrspace(3), i32, i1 immarg)
+
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll
index 03f20f0176d2b..3425ebd6ed106 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.ll
@@ -15,6 +15,8 @@ entry:
%0 = bitcast ptr %b to ptr
call void @llvm.lifetime.start.p0(i64 8, ptr %0)
%1 = bitcast ptr %b to ptr
+; Both pointers explicitly have alignment 4, so one mask applies to both
+; in every SPIR-V version.
call void @llvm.memcpy.p0.p2.i32(ptr align 4 %1, ptr addrspace(2) align 4 @__const.foo.b, i32 8, i1 false)
; CHECK: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 4{{$}}
%b1 = getelementptr inbounds %struct.A, ptr %agg.result, i32 0, i32 1
@@ -57,6 +59,18 @@ entry:
ret void
}
+; An unspecified source alignment defaults to 1. Before SPIR-V 1.4 the
+; shared alignment must therefore be 1, even when the destination is aligned.
+; CHECK: %[[#]] = OpFunction
+; SPV13: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 1{{$}}
+; SPV14: OpCopyMemorySized %[[#]] %[[#]] %[[#]] Aligned 4 Aligned 1{{$}}
+; CHECK: OpFunctionEnd
+define spir_func void @unspecified_source_alignment(ptr %dst, ptr addrspace(2) %src) {
+entry:
+ call void @llvm.memcpy.p0.p2.i32(ptr align 4 %dst, ptr addrspace(2) %src, i32 8, i1 false)
+ ret void
+}
+
; CHECK: OpFunction
; CHECK-NOT: OpCopyMemorySized
; CHECK: OpFunctionEnd
>From c573a8c23ecfa9ac81750818848b7e581b09664b Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 4 Oct 2026 15:47:51 -0700
Subject: [PATCH 3/4] Rename test
---
.../{logical-memcpy.align.ll => memcpy.align.shader.ll} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename llvm/test/CodeGen/SPIRV/llvm-intrinsics/{logical-memcpy.align.ll => memcpy.align.shader.ll} (100%)
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.align.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll
similarity index 100%
rename from llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.align.ll
rename to llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll
>From a2f3f5a42065e7c5f2a0345863f19c5d35f4ff24 Mon Sep 17 00:00:00 2001
From: Alexander Shaposhnikov <alexander.v.shaposhnikov at gmail.com>
Date: Sun, 4 Oct 2026 15:49:56 -0700
Subject: [PATCH 4/4] Fix test
---
.../test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll
index 19f20c46df6cc..caae9dba6c9c5 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/memcpy.align.shader.ll
@@ -10,8 +10,8 @@
; CHECK-DAG: OpName %[[#Src:]] "src"
%struct.S = type { i32, i32 }
- at dst = internal addrspace(3) global %struct.S undef, align 8
- at src = internal addrspace(3) global %struct.S undef, align 8
+ at dst = internal addrspace(3) global %struct.S poison, align 8
+ at src = internal addrspace(3) global %struct.S poison, align 8
; CHECK: %[[#Main]] = OpFunction
define void @main() #0 {
More information about the llvm-commits
mailing list