[llvm] [SPIR-V] Parse parameterized Memory Access operands with a shared helper (PR #209262)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 14 06:22:08 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/209262
>From bbfe9a6bc2a34aa2f81530e4bb97c042df156f5c Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 13 Jul 2026 20:16:17 +0200
Subject: [PATCH 1/2] [SPIR-V] Parse parameterized Memory Access operands with
a shared helper
Copy printing only special cased Aligned, so alias list and scope IDs were then misread as additional masks
---
.../SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp | 63 ++++++++++++-------
.../SPIRV/MCTargetDesc/SPIRVInstPrinter.h | 1 +
.../SPIRV/llvm-intrinsics/logical-memcpy.ll | 28 ++++++++-
3 files changed, 68 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
index b7dcd10bac809..4454921753da7 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -113,6 +113,42 @@ void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI,
O << Imm;
}
+unsigned SPIRVInstPrinter::printMemoryOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ O << ' ';
+ if (OpNo >= MI->getNumOperands())
+ return OpNo;
+ const uint64_t Mask = MI->getOperand(OpNo).getImm();
+ printSymbolicOperand<OperandCategory::MemoryOperandOperand>(MI, OpNo, O);
+ unsigned NextOp = OpNo + 1;
+ if (Mask & SPIRV::MemoryOperand::Aligned) {
+ O << ' ';
+ printOperand(MI, NextOp, O);
+ ++NextOp;
+ }
+ if (Mask & SPIRV::MemoryOperand::MakePointerAvailableKHR) {
+ O << ' ';
+ printOperand(MI, NextOp, O);
+ ++NextOp;
+ }
+ if (Mask & SPIRV::MemoryOperand::MakePointerVisibleKHR) {
+ O << ' ';
+ printOperand(MI, NextOp, O);
+ ++NextOp;
+ }
+ if (Mask & SPIRV::MemoryOperand::AliasScopeINTELMask) {
+ O << ' ';
+ printOperand(MI, NextOp, O);
+ ++NextOp;
+ }
+ if (Mask & SPIRV::MemoryOperand::NoAliasINTELMask) {
+ O << ' ';
+ printOperand(MI, NextOp, O);
+ ++NextOp;
+ }
+ return NextOp;
+}
+
void SPIRVInstPrinter::recordIntType(const MCInst *MI) {
MCRegister IntTypeReg = MI->getOperand(0).getReg();
unsigned Bitwidth = MI->getOperand(1).getImm();
@@ -192,10 +228,7 @@ void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
switch (OpCode) {
case SPIRV::OpLoad:
case SPIRV::OpStore:
- OS << ' ';
- printSymbolicOperand<OperandCategory::MemoryOperandOperand>(
- MI, FirstVariableIndex, OS);
- printRemainingVariableOps(MI, FirstVariableIndex + 1, OS);
+ printMemoryOperand(MI, FirstVariableIndex, OS);
break;
case SPIRV::OpSwitch:
if (MI->getFlags() & SPIRV::INST_PRINTER_WIDTH64) {
@@ -253,17 +286,8 @@ void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
case SPIRV::OpCopyMemory:
case SPIRV::OpCopyMemorySized: {
const unsigned NumOps = MI->getNumOperands();
- for (unsigned i = NumFixedOps; i < NumOps; ++i) {
- OS << ' ';
- printSymbolicOperand<OperandCategory::MemoryOperandOperand>(MI, i,
- OS);
- if (MI->getOperand(i).getImm() & MemoryOperand::Aligned) {
- assert(i + 1 < NumOps && "Missing alignment operand");
- OS << ' ';
- printOperand(MI, i + 1, OS);
- i += 1;
- }
- }
+ for (unsigned i = NumFixedOps; i < NumOps;)
+ i = printMemoryOperand(MI, i, OS);
break;
}
case SPIRV::OpConstantI:
@@ -346,13 +370,8 @@ void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
}
case SPIRV::OpPredicatedLoadINTEL:
case SPIRV::OpPredicatedStoreINTEL: {
- const unsigned NumOps = MI->getNumOperands();
- if (NumOps > NumFixedOps) {
- OS << ' ';
- printSymbolicOperand<OperandCategory::MemoryOperandOperand>(
- MI, NumOps - 1, OS);
- break;
- }
+ if (MI->getNumOperands() > NumFixedOps)
+ printMemoryOperand(MI, NumFixedOps, OS);
break;
}
default:
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
index b195c3de1801d..4d9450376a0a4 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.h
@@ -43,6 +43,7 @@ class SPIRVInstPrinter : public MCInstPrinter {
bool SkipImmediates = false);
void printOpConstantVarOps(const MCInst *MI, unsigned StartIndex,
raw_ostream &O);
+ unsigned printMemoryOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printExtension(const MCInst *MI, unsigned OpNo, raw_ostream &O);
template <SPIRV::OperandCategory::OperandCategory category>
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll
index b8fe49a1ee481..007a32e244ac3 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll
@@ -1,9 +1,11 @@
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown --spirv-ext=+SPV_INTEL_memory_access_aliasing %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown --spirv-ext=+SPV_INTEL_memory_access_aliasing %s -o - -filetype=obj | spirv-val %}
; CHECK: OpName %[[dst_var:[0-9]+]] "dst"
; CHECK: OpName %[[src_var:[0-9]+]] "src"
+; CHECK: %[[#List:]] = OpAliasScopeListDeclINTEL
+
; CHECK: %[[f32:[0-9]+]] = OpTypeFloat 32
; CHECK: %[[structS:[0-9]+]] = OpTypeStruct %[[f32]] %[[f32]] %[[f32]] %[[f32]] %[[f32]]
; CHECK: %[[ptr_crosswkgrp_structS:[0-9]+]] = OpTypePointer CrossWorkgroup %[[structS]]
@@ -27,6 +29,28 @@ entry:
; CHECK: OpFunctionEnd
}
+; Aliasing metadata on an OpCopyMemory pointer adds parameterized operands (an
+; alignment literal plus an alias-list ID) after the memory access mask; the
+; printer must consume exactly those operands rather than the fixed one it
+; previously special-cased for Aligned only.
+%struct.T = type <{ float, float, float, float, float }>
+ at src2 = external dso_local addrspace(1) global %struct.T, align 4
+ at dst2 = external dso_local addrspace(1) global %struct.T, align 4
+
+; CHECK: %[[#]] = OpFunction
+define void @copy_aliased() {
+entry:
+; CHECK: OpCopyMemory %[[#]] %[[#]] AliasScopeINTELMask %[[#List]]
+ call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) align 4 @dst2, ptr addrspace(1) align 4 @src2, i64 20, i1 false), !alias.scope !1
+ ret void
+}
+
+declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1), ptr addrspace(1), i64, i1)
+
attributes #0 = { "hlsl.numthreads"="8,1,1" "hlsl.shader"="compute" }
+!1 = !{!2}
+!2 = distinct !{!2, !3, !"copy_aliased: %this"}
+!3 = distinct !{!3, !"copy_aliased"}
+
>From 535199afbb79e4f6e2c79197d7bc0b0f6dc52a16 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Tue, 14 Jul 2026 15:21:57 +0200
Subject: [PATCH 2/2] Address comments
---
.../SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp | 31 ++++++-------------
.../alias-copy-memory.ll | 25 +++++++++++++++
.../SPIRV/llvm-intrinsics/logical-memcpy.ll | 28 ++---------------
3 files changed, 37 insertions(+), 47 deletions(-)
create mode 100644 llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_memory_access_aliasing/alias-copy-memory.ll
diff --git a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
index 4454921753da7..1a05aea432bee 100644
--- a/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVInstPrinter.cpp
@@ -121,27 +121,16 @@ unsigned SPIRVInstPrinter::printMemoryOperand(const MCInst *MI, unsigned OpNo,
const uint64_t Mask = MI->getOperand(OpNo).getImm();
printSymbolicOperand<OperandCategory::MemoryOperandOperand>(MI, OpNo, O);
unsigned NextOp = OpNo + 1;
- if (Mask & SPIRV::MemoryOperand::Aligned) {
- O << ' ';
- printOperand(MI, NextOp, O);
- ++NextOp;
- }
- if (Mask & SPIRV::MemoryOperand::MakePointerAvailableKHR) {
- O << ' ';
- printOperand(MI, NextOp, O);
- ++NextOp;
- }
- if (Mask & SPIRV::MemoryOperand::MakePointerVisibleKHR) {
- O << ' ';
- printOperand(MI, NextOp, O);
- ++NextOp;
- }
- if (Mask & SPIRV::MemoryOperand::AliasScopeINTELMask) {
- O << ' ';
- printOperand(MI, NextOp, O);
- ++NextOp;
- }
- if (Mask & SPIRV::MemoryOperand::NoAliasINTELMask) {
+ static constexpr uint64_t ParameterizedMasks[] = {
+ SPIRV::MemoryOperand::Aligned,
+ SPIRV::MemoryOperand::MakePointerAvailableKHR,
+ SPIRV::MemoryOperand::MakePointerVisibleKHR,
+ SPIRV::MemoryOperand::AliasScopeINTELMask,
+ SPIRV::MemoryOperand::NoAliasINTELMask,
+ };
+ for (uint64_t ParamMask : ParameterizedMasks) {
+ if (!(Mask & ParamMask))
+ continue;
O << ' ';
printOperand(MI, NextOp, O);
++NextOp;
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
new file mode 100644
index 0000000000000..89bdfbc2bd96d
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_memory_access_aliasing/alias-copy-memory.ll
@@ -0,0 +1,25 @@
+; Aliasing metadata on OpCopyMemory adds an alignment literal and an
+; alias-list ID after the memory access mask.
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown --spirv-ext=+SPV_INTEL_memory_access_aliasing %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown --spirv-ext=+SPV_INTEL_memory_access_aliasing %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: %[[#List:]] = OpAliasScopeListDeclINTEL
+
+; CHECK: %[[#]] = OpFunction
+define void @copy_aliased() {
+entry:
+; 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
+ ret void
+}
+
+%struct.T = type <{ float, float, float, float, float }>
+ at src = external dso_local addrspace(1) global %struct.T, align 4
+ at dst = external dso_local addrspace(1) global %struct.T, align 4
+
+declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1), ptr addrspace(1), i64, i1)
+
+!1 = !{!2}
+!2 = distinct !{!2, !3, !"copy_aliased: %this"}
+!3 = distinct !{!3, !"copy_aliased"}
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll
index 007a32e244ac3..b8fe49a1ee481 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/logical-memcpy.ll
@@ -1,11 +1,9 @@
-; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown --spirv-ext=+SPV_INTEL_memory_access_aliasing %s -o - | FileCheck %s
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown --spirv-ext=+SPV_INTEL_memory_access_aliasing %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; CHECK: OpName %[[dst_var:[0-9]+]] "dst"
; CHECK: OpName %[[src_var:[0-9]+]] "src"
-; CHECK: %[[#List:]] = OpAliasScopeListDeclINTEL
-
; CHECK: %[[f32:[0-9]+]] = OpTypeFloat 32
; CHECK: %[[structS:[0-9]+]] = OpTypeStruct %[[f32]] %[[f32]] %[[f32]] %[[f32]] %[[f32]]
; CHECK: %[[ptr_crosswkgrp_structS:[0-9]+]] = OpTypePointer CrossWorkgroup %[[structS]]
@@ -29,28 +27,6 @@ entry:
; CHECK: OpFunctionEnd
}
-; Aliasing metadata on an OpCopyMemory pointer adds parameterized operands (an
-; alignment literal plus an alias-list ID) after the memory access mask; the
-; printer must consume exactly those operands rather than the fixed one it
-; previously special-cased for Aligned only.
-%struct.T = type <{ float, float, float, float, float }>
- at src2 = external dso_local addrspace(1) global %struct.T, align 4
- at dst2 = external dso_local addrspace(1) global %struct.T, align 4
-
-; CHECK: %[[#]] = OpFunction
-define void @copy_aliased() {
-entry:
-; CHECK: OpCopyMemory %[[#]] %[[#]] AliasScopeINTELMask %[[#List]]
- call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) align 4 @dst2, ptr addrspace(1) align 4 @src2, i64 20, i1 false), !alias.scope !1
- ret void
-}
-
-declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1), ptr addrspace(1), i64, i1)
-
attributes #0 = { "hlsl.numthreads"="8,1,1" "hlsl.shader"="compute" }
-!1 = !{!2}
-!2 = distinct !{!2, !3, !"copy_aliased: %this"}
-!3 = distinct !{!3, !"copy_aliased"}
-
More information about the llvm-commits
mailing list