Skip to content

Conversation

@s-perron
Copy link
Contributor

This change sets the hasSideEffects flag to false on type and constant opcodes
so that they can be considered trivially dead if their result is unused. This
means that instruction selection will now be able to remove them.

This change sets the hasSideEffects flag to false on type and constant opcodes
so that they can be considered trivially dead if their result is unused. This
means that instruction selection will now be able to remove them.
@llvmbot
Copy link
Member

llvmbot commented Oct 23, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Steven Perron (s-perron)

Changes

This change sets the hasSideEffects flag to false on type and constant opcodes
so that they can be considered trivially dead if their result is unused. This
means that instruction selection will now be able to remove them.


Full diff: https://github.com/llvm/llvm-project/pull/164868.diff

4 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVInstrFormats.td (+5)
  • (modified) llvm/lib/Target/SPIRV/SPIRVInstrInfo.td (+108-71)
  • (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/AddUint64.ll (+1-1)
  • (modified) llvm/test/CodeGen/SPIRV/pointers/resource-vector-load-store.ll (+16-11)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrFormats.td b/llvm/lib/Target/SPIRV/SPIRVInstrFormats.td
index 2fde2b0bc0b1f..f93240dc35993 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrFormats.td
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrFormats.td
@@ -25,6 +25,11 @@ class Op<bits<16> Opcode, dag outs, dag ins, string asmstr, list<dag> pattern =
   let Pattern = pattern;
 }
 
+class PureOp<bits<16> Opcode, dag outs, dag ins, string asmstr,
+             list<dag> pattern = []> : Op<Opcode, outs, ins, asmstr, pattern> {
+  let hasSideEffects = 0;
+}
+
 class UnknownOp<dag outs, dag ins, string asmstr, list<dag> pattern = []>
     : Op<0, outs, ins, asmstr, pattern> {
   let isPseudo = 1;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
index a61351eba03f8..799a82c96b0f0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
@@ -163,52 +163,74 @@ def OpExecutionModeId: Op<331, (outs), (ins ID:$entry, ExecutionMode:$mode, vari
 
 // 3.42.6 Type-Declaration Instructions
 
-def OpTypeVoid: Op<19, (outs TYPE:$type), (ins), "$type = OpTypeVoid">;
-def OpTypeBool: Op<20, (outs TYPE:$type), (ins), "$type = OpTypeBool">;
-def OpTypeInt: Op<21, (outs TYPE:$type), (ins i32imm:$width, i32imm:$signedness),
-                  "$type = OpTypeInt $width $signedness">;
-def OpTypeFloat: Op<22, (outs TYPE:$type), (ins i32imm:$width, variable_ops),
-                  "$type = OpTypeFloat $width">;
-def OpTypeVector: Op<23, (outs TYPE:$type), (ins TYPE:$compType, i32imm:$compCount),
-                  "$type = OpTypeVector $compType $compCount">;
-def OpTypeMatrix: Op<24, (outs TYPE:$type), (ins TYPE:$colType, i32imm:$colCount),
-                  "$type = OpTypeMatrix $colType $colCount">;
-def OpTypeImage: Op<25, (outs TYPE:$res), (ins TYPE:$sampTy, Dim:$dim, i32imm:$depth,
-      i32imm:$arrayed, i32imm:$MS, i32imm:$sampled, ImageFormat:$imFormat, variable_ops),
-                  "$res = OpTypeImage $sampTy $dim $depth $arrayed $MS $sampled $imFormat">;
-def OpTypeSampler: Op<26, (outs TYPE:$res), (ins), "$res = OpTypeSampler">;
-def OpTypeSampledImage: Op<27, (outs TYPE:$res), (ins TYPE:$imageType),
-                  "$res = OpTypeSampledImage $imageType">;
-def OpTypeArray: Op<28, (outs TYPE:$type), (ins TYPE:$elementType, ID:$length),
-                  "$type = OpTypeArray $elementType $length">;
-def OpTypeRuntimeArray: Op<29, (outs TYPE:$type), (ins TYPE:$elementType),
-                  "$type = OpTypeRuntimeArray $elementType">;
-def OpTypeStruct: Op<30, (outs TYPE:$res), (ins variable_ops), "$res = OpTypeStruct">;
-def OpTypeStructContinuedINTEL: Op<6090, (outs), (ins variable_ops),
-                  "OpTypeStructContinuedINTEL">;
-def OpTypeOpaque: Op<31, (outs TYPE:$res), (ins StringImm:$name, variable_ops),
-                  "$res = OpTypeOpaque $name">;
-def OpTypePointer: Op<32, (outs TYPE:$res), (ins StorageClass:$storage, TYPE:$type),
-                  "$res = OpTypePointer $storage $type">;
-def OpTypeFunction: Op<33, (outs TYPE:$funcType), (ins TYPE:$returnType, variable_ops),
-                  "$funcType = OpTypeFunction $returnType">;
-def OpTypeEvent: Op<34, (outs TYPE:$res), (ins), "$res = OpTypeEvent">;
-def OpTypeDeviceEvent: Op<35, (outs TYPE:$res), (ins), "$res = OpTypeDeviceEvent">;
-def OpTypeReserveId: Op<36, (outs TYPE:$res), (ins), "$res = OpTypeReserveId">;
-def OpTypeQueue: Op<37, (outs TYPE:$res), (ins), "$res = OpTypeQueue">;
-def OpTypePipe: Op<38, (outs TYPE:$res), (ins AccessQualifier:$a), "$res = OpTypePipe $a">;
-def OpTypeForwardPointer: Op<39, (outs), (ins TYPE:$ptrType, StorageClass:$storageClass),
-                  "OpTypeForwardPointer $ptrType $storageClass">;
-def OpTypePipeStorage: Op<322, (outs TYPE:$res), (ins), "$res = OpTypePipeStorage">;
-def OpTypeNamedBarrier: Op<327, (outs TYPE:$res), (ins), "$res = OpTypeNamedBarrier">;
-def OpTypeAccelerationStructureNV: Op<5341, (outs TYPE:$res), (ins),
-                  "$res = OpTypeAccelerationStructureNV">;
-def OpTypeCooperativeMatrixNV: Op<5358, (outs TYPE:$res),
-                  (ins TYPE:$compType, ID:$scope, ID:$rows, ID:$cols),
-                  "$res = OpTypeCooperativeMatrixNV $compType $scope $rows $cols">;
-def OpTypeCooperativeMatrixKHR: Op<4456, (outs TYPE:$res),
-                  (ins TYPE:$compType, ID:$scope, ID:$rows, ID:$cols, ID:$use),
-                  "$res = OpTypeCooperativeMatrixKHR $compType $scope $rows $cols $use">;
+def OpTypeVoid : PureOp<19, (outs TYPE:$type), (ins), "$type = OpTypeVoid">;
+def OpTypeBool : PureOp<20, (outs TYPE:$type), (ins), "$type = OpTypeBool">;
+def OpTypeInt
+    : PureOp<21, (outs TYPE:$type), (ins i32imm:$width, i32imm:$signedness),
+             "$type = OpTypeInt $width $signedness">;
+def OpTypeFloat
+    : PureOp<22, (outs TYPE:$type), (ins i32imm:$width, variable_ops),
+             "$type = OpTypeFloat $width">;
+def OpTypeVector
+    : PureOp<23, (outs TYPE:$type), (ins TYPE:$compType, i32imm:$compCount),
+             "$type = OpTypeVector $compType $compCount">;
+def OpTypeMatrix
+    : PureOp<24, (outs TYPE:$type), (ins TYPE:$colType, i32imm:$colCount),
+             "$type = OpTypeMatrix $colType $colCount">;
+def OpTypeImage : PureOp<25, (outs TYPE:$res),
+                         (ins TYPE:$sampTy, Dim:$dim, i32imm:$depth,
+                             i32imm:$arrayed, i32imm:$MS, i32imm:$sampled,
+                             ImageFormat:$imFormat, variable_ops),
+                         "$res = OpTypeImage $sampTy $dim $depth $arrayed $MS "
+                         "$sampled $imFormat">;
+def OpTypeSampler : PureOp<26, (outs TYPE:$res), (ins), "$res = OpTypeSampler">;
+def OpTypeSampledImage : PureOp<27, (outs TYPE:$res), (ins TYPE:$imageType),
+                                "$res = OpTypeSampledImage $imageType">;
+def OpTypeArray
+    : PureOp<28, (outs TYPE:$type), (ins TYPE:$elementType, ID:$length),
+             "$type = OpTypeArray $elementType $length">;
+def OpTypeRuntimeArray : PureOp<29, (outs TYPE:$type), (ins TYPE:$elementType),
+                                "$type = OpTypeRuntimeArray $elementType">;
+def OpTypeStruct
+    : PureOp<30, (outs TYPE:$res), (ins variable_ops), "$res = OpTypeStruct">;
+def OpTypeStructContinuedINTEL
+    : PureOp<6090, (outs), (ins variable_ops), "OpTypeStructContinuedINTEL">;
+def OpTypeOpaque
+    : PureOp<31, (outs TYPE:$res), (ins StringImm:$name, variable_ops),
+             "$res = OpTypeOpaque $name">;
+def OpTypePointer
+    : PureOp<32, (outs TYPE:$res), (ins StorageClass:$storage, TYPE:$type),
+             "$res = OpTypePointer $storage $type">;
+def OpTypeFunction
+    : PureOp<33, (outs TYPE:$funcType), (ins TYPE:$returnType, variable_ops),
+             "$funcType = OpTypeFunction $returnType">;
+def OpTypeEvent : PureOp<34, (outs TYPE:$res), (ins), "$res = OpTypeEvent">;
+def OpTypeDeviceEvent
+    : PureOp<35, (outs TYPE:$res), (ins), "$res = OpTypeDeviceEvent">;
+def OpTypeReserveId
+    : PureOp<36, (outs TYPE:$res), (ins), "$res = OpTypeReserveId">;
+def OpTypeQueue : PureOp<37, (outs TYPE:$res), (ins), "$res = OpTypeQueue">;
+def OpTypePipe : PureOp<38, (outs TYPE:$res), (ins AccessQualifier:$a),
+                        "$res = OpTypePipe $a">;
+def OpTypeForwardPointer
+    : PureOp<39, (outs), (ins TYPE:$ptrType, StorageClass:$storageClass),
+             "OpTypeForwardPointer $ptrType $storageClass">;
+def OpTypePipeStorage
+    : PureOp<322, (outs TYPE:$res), (ins), "$res = OpTypePipeStorage">;
+def OpTypeNamedBarrier
+    : PureOp<327, (outs TYPE:$res), (ins), "$res = OpTypeNamedBarrier">;
+def OpTypeAccelerationStructureNV
+    : PureOp<5341, (outs TYPE:$res), (ins),
+             "$res = OpTypeAccelerationStructureNV">;
+def OpTypeCooperativeMatrixNV
+    : PureOp<5358, (outs TYPE:$res),
+             (ins TYPE:$compType, ID:$scope, ID:$rows, ID:$cols),
+             "$res = OpTypeCooperativeMatrixNV $compType $scope $rows $cols">;
+def OpTypeCooperativeMatrixKHR
+    : PureOp<4456, (outs TYPE:$res),
+             (ins TYPE:$compType, ID:$scope, ID:$rows, ID:$cols, ID:$use),
+             "$res = OpTypeCooperativeMatrixKHR $compType $scope $rows $cols "
+             "$use">;
 
 // 3.42.7 Constant-Creation Instructions
 
@@ -222,31 +244,46 @@ defm OpConstant: IntFPImm<43, "OpConstant">;
 
 def ConstPseudoTrue: IntImmLeaf<i64, [{ return Imm.getBitWidth() == 1 && Imm.getZExtValue() == 1; }]>;
 def ConstPseudoFalse: IntImmLeaf<i64, [{ return Imm.getBitWidth() == 1 && Imm.getZExtValue() == 0; }]>;
-def OpConstantTrue: Op<41, (outs iID:$dst), (ins TYPE:$src_ty), "$dst = OpConstantTrue $src_ty",
-                      [(set iID:$dst, (assigntype ConstPseudoTrue, TYPE:$src_ty))]>;
-def OpConstantFalse: Op<42, (outs iID:$dst), (ins TYPE:$src_ty), "$dst = OpConstantFalse $src_ty",
-                      [(set iID:$dst, (assigntype ConstPseudoFalse, TYPE:$src_ty))]>;
-
-def OpConstantComposite: Op<44, (outs ID:$res), (ins TYPE:$type, variable_ops),
-                  "$res = OpConstantComposite $type">;
-def OpConstantCompositeContinuedINTEL: Op<6091, (outs), (ins variable_ops),
-                  "OpConstantCompositeContinuedINTEL">;
-
-def OpConstantSampler: Op<45, (outs ID:$res),
-                  (ins TYPE:$t, SamplerAddressingMode:$s, i32imm:$p, SamplerFilterMode:$f),
-                  "$res = OpConstantSampler $t $s $p $f">;
-def OpConstantNull: Op<46, (outs ID:$dst), (ins TYPE:$src_ty), "$dst = OpConstantNull $src_ty">;
-
-def OpSpecConstantTrue: Op<48, (outs ID:$r), (ins TYPE:$t), "$r = OpSpecConstantTrue $t">;
-def OpSpecConstantFalse: Op<49, (outs ID:$r), (ins TYPE:$t), "$r = OpSpecConstantFalse $t">;
-def OpSpecConstant: Op<50, (outs ID:$res), (ins TYPE:$type, i32imm:$imm, variable_ops),
-                  "$res = OpSpecConstant $type $imm">;
-def OpSpecConstantComposite: Op<51, (outs ID:$res), (ins TYPE:$type, variable_ops),
-                  "$res = OpSpecConstantComposite $type">;
-def OpSpecConstantCompositeContinuedINTEL: Op<6092, (outs), (ins variable_ops),
-                  "OpSpecConstantCompositeContinuedINTEL">;
-def OpSpecConstantOp: Op<52, (outs ID:$res), (ins TYPE:$t, SpecConstantOpOperands:$c, ID:$o, variable_ops),
-                  "$res = OpSpecConstantOp $t $c $o">;
+def OpConstantTrue
+    : PureOp<41, (outs iID:$dst), (ins TYPE:$src_ty),
+             "$dst = OpConstantTrue $src_ty",
+             [(set iID:$dst, (assigntype ConstPseudoTrue, TYPE:$src_ty))]>;
+def OpConstantFalse
+    : PureOp<42, (outs iID:$dst), (ins TYPE:$src_ty),
+             "$dst = OpConstantFalse $src_ty",
+             [(set iID:$dst, (assigntype ConstPseudoFalse, TYPE:$src_ty))]>;
+
+def OpConstantComposite
+    : PureOp<44, (outs ID:$res), (ins TYPE:$type, variable_ops),
+             "$res = OpConstantComposite $type">;
+def OpConstantCompositeContinuedINTEL
+    : PureOp<6091, (outs), (ins variable_ops),
+             "OpConstantCompositeContinuedINTEL">;
+
+def OpConstantSampler : PureOp<45, (outs ID:$res),
+                               (ins TYPE:$t, SamplerAddressingMode:$s,
+                                   i32imm:$p, SamplerFilterMode:$f),
+                               "$res = OpConstantSampler $t $s $p $f">;
+def OpConstantNull : PureOp<46, (outs ID:$dst), (ins TYPE:$src_ty),
+                            "$dst = OpConstantNull $src_ty">;
+
+def OpSpecConstantTrue
+    : PureOp<48, (outs ID:$r), (ins TYPE:$t), "$r = OpSpecConstantTrue $t">;
+def OpSpecConstantFalse
+    : PureOp<49, (outs ID:$r), (ins TYPE:$t), "$r = OpSpecConstantFalse $t">;
+def OpSpecConstant
+    : PureOp<50, (outs ID:$res), (ins TYPE:$type, i32imm:$imm, variable_ops),
+             "$res = OpSpecConstant $type $imm">;
+def OpSpecConstantComposite
+    : PureOp<51, (outs ID:$res), (ins TYPE:$type, variable_ops),
+             "$res = OpSpecConstantComposite $type">;
+def OpSpecConstantCompositeContinuedINTEL
+    : PureOp<6092, (outs), (ins variable_ops),
+             "OpSpecConstantCompositeContinuedINTEL">;
+def OpSpecConstantOp
+    : PureOp<52, (outs ID:$res),
+             (ins TYPE:$t, SpecConstantOpOperands:$c, ID:$o, variable_ops),
+             "$res = OpSpecConstantOp $t $c $o">;
 
 // 3.42.8 Memory Instructions
 
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/AddUint64.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/AddUint64.ll
index a97492b8453ea..a15d628cc3614 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/AddUint64.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/AddUint64.ll
@@ -63,7 +63,7 @@ entry:
 ; CHECK: %[[#a_high:]] = OpVectorShuffle %[[#vec2_int_32]] %[[#a]] %[[#undef_v4i32]] 1 3
 ; CHECK: %[[#b_low:]] = OpVectorShuffle %[[#vec2_int_32]] %[[#b]] %[[#undef_v4i32]] 0 2
 ; CHECK: %[[#b_high:]] = OpVectorShuffle %[[#vec2_int_32]] %[[#b]] %[[#undef_v4i32]] 1 3
-; CHECK: %[[#iaddcarry:]] = OpIAddCarry %[[#struct_v2i32_v2i32]] %[[#a_low]] %[[#vec2_int_32]]
+; CHECK: %[[#iaddcarry:]] = OpIAddCarry %[[#struct_v2i32_v2i32]] %[[#a_low]] %[[#b_low]]
 ; CHECK: %[[#lowsum:]] = OpCompositeExtract %[[#vec2_int_32]] %[[#iaddcarry]] 0
 ; CHECK: %[[#carry:]] = OpCompositeExtract %[[#vec2_int_32]] %[[#iaddcarry]] 1
 ; CHECK: %[[#carry_ne0:]] = OpINotEqual %[[#vec2_bool]] %[[#carry]] %[[#const_v2i32_0_0]]
diff --git a/llvm/test/CodeGen/SPIRV/pointers/resource-vector-load-store.ll b/llvm/test/CodeGen/SPIRV/pointers/resource-vector-load-store.ll
index 7548f4757dbe6..6fc03a386d14d 100644
--- a/llvm/test/CodeGen/SPIRV/pointers/resource-vector-load-store.ll
+++ b/llvm/test/CodeGen/SPIRV/pointers/resource-vector-load-store.ll
@@ -4,18 +4,23 @@
 
 @.str = private unnamed_addr constant [7 x i8] c"buffer\00", align 1
 
+; The i64 values in the extracts will be turned
+; into immidiate values. There should be no 64-bit
+; integers in the module.
+; CHECK-NOT:  OpTypeInt 64 0
+
 define void @main() "hlsl.shader"="pixel"  {
-; CHECK:         %24 = OpFunction %2 None %3 ; -- Begin function main
-; CHECK-NEXT:     %1 = OpLabel
-; CHECK-NEXT:    %25 = OpVariable %13 Function %22
-; CHECK-NEXT:    %26 = OpLoad %7 %23
-; CHECK-NEXT:    %27 = OpImageRead %5 %26 %15
-; CHECK-NEXT:    %28 = OpCompositeExtract %4 %27 0
-; CHECK-NEXT:    %29 = OpCompositeExtract %4 %27 1
-; CHECK-NEXT:    %30 = OpFAdd %4 %29 %28
-; CHECK-NEXT:    %31 = OpCompositeInsert %5 %30 %27 0
-; CHECK-NEXT:    %32 = OpLoad %7 %23
-; CHECK-NEXT:          OpImageWrite %32 %15 %31
+; CHECK:         %[[FUNC:[0-9]+]] = OpFunction %[[VOID:[0-9]+]] None %[[FNTYPE:[0-9]+]] ; -- Begin function main
+; CHECK-NEXT:     %[[LABEL:[0-9]+]] = OpLabel
+; CHECK-NEXT:    %[[VAR:[0-9]+]] = OpVariable %[[PTR_FN:[a-zA-Z0-9_]+]] Function %[[INIT:[a-zA-Z0-9_]+]]
+; CHECK-NEXT:    %[[LOAD1:[0-9]+]] = OpLoad %[[IMG_TYPE:[a-zA-Z0-9_]+]] %[[IMG_VAR:[a-zA-Z0-9_]+]]
+; CHECK-NEXT:    %[[READ:[0-9]+]] = OpImageRead %[[VEC4:[a-zA-Z0-9_]+]] %[[LOAD1]] %[[COORD:[a-zA-Z0-9_]+]]
+; CHECK-NEXT:    %[[EXTRACT1:[0-9]+]] = OpCompositeExtract %[[FLOAT:[a-zA-Z0-9_]+]] %[[READ]] 0
+; CHECK-NEXT:    %[[EXTRACT2:[0-9]+]] = OpCompositeExtract %[[FLOAT]] %[[READ]] 1
+; CHECK-NEXT:    %[[ADD:[0-9]+]] = OpFAdd %[[FLOAT]] %[[EXTRACT2]] %[[EXTRACT1]]
+; CHECK-NEXT:    %[[INSERT:[0-9]+]] = OpCompositeInsert %[[VEC4]] %[[ADD]] %[[READ]] 0
+; CHECK-NEXT:    %[[LOAD2:[0-9]+]] = OpLoad %[[IMG_TYPE]] %[[IMG_VAR]]
+; CHECK-NEXT:          OpImageWrite %[[LOAD2]] %[[COORD]] %[[INSERT]]
 ; CHECK-NEXT:          OpReturn
 ; CHECK-NEXT:          OpFunctionEnd
 entry:

@s-perron
Copy link
Contributor Author

The concern with this change is the global registry. If we delete the type instruction, could we be left with a dangling pointer in the Global Registry that will be needed later?

Copy link
Contributor

@Keenuts Keenuts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but yes the GlobalRegistry keeping references might be an issue.
IIRC there was some work to make this an analysis or something like this no? @michalpaszkowski

@s-perron
Copy link
Contributor Author

@michalpaszkowski Would it be possible to get your thoughts on this? If we are unsure could we get a run of the OpenCL tests to make sure there are no problems? I'd like to know if I need to remove the unused types in a different way or not.

@MrSidims
Copy link
Contributor

MrSidims commented Oct 31, 2025

I will run SYCL E2E tests with it, though currently my local nightly CI seem to be broken after some change in LLVM, probably some new SPIR-V extension got enabled by default.

@s-perron
Copy link
Contributor Author

s-perron commented Nov 5, 2025

@MrSidims Any word on the E2E tests?

@MrSidims
Copy link
Contributor

MrSidims commented Nov 5, 2025

@MrSidims Any word on the E2E tests?

They are broken on my end (not by your change), with the only way to resolve it by reverting few patches, which is a bit tricky. In the end of the day - it's our problem, that we can't test in timely manner, so I don't want to block your PR with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants