[llvm] [SPIR-V] Fix invalid OpIMul emitted for i1 multiplication (PR #207388)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 01:16:01 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/207388
>From 34781be3f936ac24f25e5e5ec0cf5ebb8fe1215b Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 3 Jul 2026 14:54:58 +0200
Subject: [PATCH 1/2] [SPIR-V] Fix invalid OpIMul emitted for i1 multiplication
OpIMul requires integer scalar/vector operands
OpTypeBool is not considered an integer type and causes spirv-val failure
---
llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp | 7 +++++++
.../instructions/scalar-integer-arithmetic.ll | 14 ++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index eb16c9a314a23..ef85c62547d81 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -512,6 +512,13 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const {
SPIRV::OpTypeBool))
MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
break;
+ // multiplication of bool operands is equivalent to a logical AND
+ case SPIRV::OpIMulS:
+ case SPIRV::OpIMulV:
+ if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(),
+ SPIRV::OpTypeBool))
+ MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalAnd));
+ break;
// ensure that LLVM IR bitwise instructions result in logical SPIR-V
// instructions when applied to bool type
diff --git a/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll b/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll
index 649c146f68993..e62ba39132db4 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll
@@ -8,6 +8,7 @@
; CHECK-DAG: OpName [[BOOL_SUB:%.+]] "bool_sub"
; CHECK-DAG: OpName [[SCALAR_ADD:%.+]] "scalar_add"
; CHECK-DAG: OpName [[SCALAR_SUB:%.+]] "scalar_sub"
+; CHECK-DAG: OpName [[BOOL_MUL:%.+]] "bool_mul"
; CHECK-DAG: OpName [[SCALAR_MUL:%.+]] "scalar_mul"
; CHECK-DAG: OpName [[SCALAR_UDIV:%.+]] "scalar_udiv"
; CHECK-DAG: OpName [[SCALAR_SDIV:%.+]] "scalar_sdiv"
@@ -84,6 +85,19 @@ define i32 @scalar_sub(i32 %a, i32 %b) {
;; Test mul on scalar:
+define i1 @bool_mul(i1 %a, i1 %b) {
+ %c = mul i1 %a, %b
+ ret i1 %c
+}
+
+; CHECK: [[BOOL_MUL]] = OpFunction [[BOOL]] None [[BOOL_FN]]
+; CHECK-NEXT: [[A:%.+]] = OpFunctionParameter [[BOOL]]
+; CHECK-NEXT: [[B:%.+]] = OpFunctionParameter [[BOOL]]
+; CHECK: OpLabel
+; CHECK: [[C:%.+]] = OpLogicalAnd [[BOOL]] [[A]] [[B]]
+; CHECK: OpReturnValue [[C]]
+; CHECK-NEXT: OpFunctionEnd
+
define i32 @scalar_mul(i32 %a, i32 %b) {
%c = mul i32 %a, %b
ret i32 %c
>From f49bf80b1a1c17ead140f9ee4cd150883a2965aa Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 6 Jul 2026 10:15:51 +0200
Subject: [PATCH 2/2] Address comment
---
.../instructions/scalar-integer-arithmetic.ll | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll b/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll
index e62ba39132db4..222f128acac0d 100644
--- a/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll
+++ b/llvm/test/CodeGen/SPIRV/instructions/scalar-integer-arithmetic.ll
@@ -9,6 +9,8 @@
; CHECK-DAG: OpName [[SCALAR_ADD:%.+]] "scalar_add"
; CHECK-DAG: OpName [[SCALAR_SUB:%.+]] "scalar_sub"
; CHECK-DAG: OpName [[BOOL_MUL:%.+]] "bool_mul"
+; CHECK-DAG: OpName [[BOOL_MUL_NSW:%.+]] "bool_mul_nsw"
+; CHECK-DAG: OpName [[BOOL_MUL_NUW:%.+]] "bool_mul_nuw"
; CHECK-DAG: OpName [[SCALAR_MUL:%.+]] "scalar_mul"
; CHECK-DAG: OpName [[SCALAR_UDIV:%.+]] "scalar_udiv"
; CHECK-DAG: OpName [[SCALAR_SDIV:%.+]] "scalar_sdiv"
@@ -98,6 +100,32 @@ define i1 @bool_mul(i1 %a, i1 %b) {
; CHECK: OpReturnValue [[C]]
; CHECK-NEXT: OpFunctionEnd
+define i1 @bool_mul_nsw(i1 %a, i1 %b) {
+ %c = mul nsw i1 %a, %b
+ ret i1 %c
+}
+
+; CHECK: [[BOOL_MUL_NSW]] = OpFunction [[BOOL]] None [[BOOL_FN]]
+; CHECK-NEXT: [[A:%.+]] = OpFunctionParameter [[BOOL]]
+; CHECK-NEXT: [[B:%.+]] = OpFunctionParameter [[BOOL]]
+; CHECK: OpLabel
+; CHECK: [[C:%.+]] = OpLogicalAnd [[BOOL]] [[A]] [[B]]
+; CHECK: OpReturnValue [[C]]
+; CHECK-NEXT: OpFunctionEnd
+
+define i1 @bool_mul_nuw(i1 %a, i1 %b) {
+ %c = mul nuw i1 %a, %b
+ ret i1 %c
+}
+
+; CHECK: [[BOOL_MUL_NUW]] = OpFunction [[BOOL]] None [[BOOL_FN]]
+; CHECK-NEXT: [[A:%.+]] = OpFunctionParameter [[BOOL]]
+; CHECK-NEXT: [[B:%.+]] = OpFunctionParameter [[BOOL]]
+; CHECK: OpLabel
+; CHECK: [[C:%.+]] = OpLogicalAnd [[BOOL]] [[A]] [[B]]
+; CHECK: OpReturnValue [[C]]
+; CHECK-NEXT: OpFunctionEnd
+
define i32 @scalar_mul(i32 %a, i32 %b) {
%c = mul i32 %a, %b
ret i32 %c
More information about the llvm-commits
mailing list