[SPIR-V] Parse parameterized Memory Access operands with a shared helper#209262
[SPIR-V] Parse parameterized Memory Access operands with a shared helper#209262aobolensk wants to merge 7 commits into
Conversation
Copy printing only special cased Aligned, so alias list and scope IDs were then misread as additional masks
|
@llvm/pr-subscribers-backend-spir-v Author: Arseniy Obolenskiy (aobolensk) ChangesCopy printing only special cased Aligned, so alias list and scope IDs were then misread as additional masks Full diff: https://github.com/llvm/llvm-project/pull/209262.diff 3 Files Affected:
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 }>
+@src2 = external dso_local addrspace(1) global %struct.T, align 4
+@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"}
+
|
| @@ -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 | |||
There was a problem hiding this comment.
Should be a separate test
| ++NextOp; | ||
| } | ||
| return NextOp; | ||
| } |
There was a problem hiding this comment.
Iterating in one place and incrementing iterator in another is looking very fragile.
Lets imagine in the future in SPIR-V spec will be added another memory operand mask which makes an instruction accepting yet another literal operand. This memory operand was implemented with a bug and somehow we made it this far. In such case the loop block on L289 will be executed once more time re-processing all of the already processed masks, duplicating printed operands and making the iterator be out of bound.
There was a problem hiding this comment.
Left only one place with the increment, unified handling for all cases
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
Copy printing only special cased Aligned, so alias list and scope IDs were then misread as additional masks