[llvm] [SPIR-V] Fix incorrect bitwise instructions applied to the bool type (PR #85929)

Vyacheslav Levytskyy via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 20 06:30:59 PDT 2024


https://github.com/VyacheslavLevytskyy created https://github.com/llvm/llvm-project/pull/85929

This PR ensures that LLVM IR bitwise instructions result in logical SPIR-V instructions when applied to i1 type.

>From 87bf3a8397341766283a7924d9b72ec061924d30 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Wed, 20 Mar 2024 06:29:11 -0700
Subject: [PATCH] ensure that LLVM IR bitwise instructions result in logical
 SPIR-V instructions when applied to i1 type

---
 llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp   | 20 ++++++
 .../CodeGen/SPIRV/instructions/bitwise-i1.ll  | 69 +++++++++++++++++++
 2 files changed, 89 insertions(+)
 create mode 100644 llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index e6e9131d8dc28f..55b4c47c197dab 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -145,6 +145,26 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const {
         validatePtrTypes(STI, MRI, GR, MI,
                          GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg()), 0);
         break;
+      // ensure that LLVM IR bitwise instructions result in logical SPIR-V
+      // instructions when applied to bool type
+      case SPIRV::OpBitwiseOrS:
+      case SPIRV::OpBitwiseOrV:
+        if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(),
+                                      SPIRV::OpTypeBool))
+          MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalOr));
+        break;
+      case SPIRV::OpBitwiseAndS:
+      case SPIRV::OpBitwiseAndV:
+        if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(),
+                                      SPIRV::OpTypeBool))
+          MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalAnd));
+        break;
+      case SPIRV::OpBitwiseXorS:
+      case SPIRV::OpBitwiseXorV:
+        if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(),
+                                      SPIRV::OpTypeBool))
+          MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
+        break;
       }
     }
   }
diff --git a/llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll b/llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll
new file mode 100644
index 00000000000000..8d3657b36454bf
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll
@@ -0,0 +1,69 @@
+; This test ensures that LLVM IR bitwise instructions result in logical SPIR-V instructions
+; when applied to i1 type
+
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#Vec2Char:]] = OpTypeVector %[[#Char]] 2
+; CHECK-DAG: %[[#Bool:]] = OpTypeBool
+; CHECK-DAG: %[[#Vec2Bool:]] = OpTypeVector %[[#Bool]] 2
+
+; CHECK: OpBitwiseAnd %[[#Char]]
+; CHECK: OpBitwiseOr %[[#Char]]
+; CHECK: OpBitwiseXor %[[#Char]]
+; CHECK: OpBitwiseAnd %[[#Vec2Char]]
+; CHECK: OpBitwiseOr %[[#Vec2Char]]
+; CHECK: OpBitwiseXor %[[#Vec2Char]]
+
+; CHECK: OpLogicalAnd %[[#Bool]]
+
+; CHECK: OpLogicalAnd %[[#Bool]]
+; CHECK: OpLogicalOr %[[#Bool]]
+; CHECK: OpLogicalNotEqual %[[#Bool]]
+; CHECK: OpLogicalAnd %[[#Vec2Bool]]
+; CHECK: OpLogicalOr %[[#Vec2Bool]]
+; CHECK: OpLogicalNotEqual %[[#Vec2Bool]]
+
+define void @test1(i8 noundef %arg1, i8 noundef %arg2) {
+  %cond1 = and i8 %arg1, %arg2
+  %cond2 = or i8 %arg1, %arg2
+  %cond3 = xor i8 %arg1, %arg2
+  ret void
+}
+
+define void @test1v(<2 x i8> noundef %arg1, <2 x i8> noundef %arg2) {
+  %cond1 = and <2 x i8> %arg1, %arg2
+  %cond2 = or <2 x i8> %arg1, %arg2
+  %cond3 = xor <2 x i8> %arg1, %arg2
+  ret void
+}
+
+define void @test2(float noundef %real, float noundef %imag) {
+entry:
+  %realabs = tail call spir_func noundef float @_Z16__spirv_ocl_fabsf(float noundef %real)
+  %cond1 = fcmp oeq float %realabs, 1.000000e+00
+  %cond2 = fcmp oeq float %imag, 0.000000e+00
+  %cond3 = and i1 %cond1, %cond2
+  br i1 %cond3, label %midlbl, label %cleanup
+midlbl:
+  br label %cleanup
+cleanup:
+  ret void
+}
+
+define void @test3(i1 noundef %arg1, i1 noundef %arg2) {
+  %cond1 = and i1 %arg1, %arg2
+  %cond2 = or i1 %arg1, %arg2
+  %cond3 = xor i1 %arg1, %arg2
+  ret void
+}
+
+define void @test3v(<2 x i1> noundef %arg1, <2 x i1> noundef %arg2) {
+  %cond1 = and <2 x i1> %arg1, %arg2
+  %cond2 = or <2 x i1> %arg1, %arg2
+  %cond3 = xor <2 x i1> %arg1, %arg2
+  ret void
+}
+
+declare dso_local spir_func noundef float @_Z16__spirv_ocl_fabsf(float noundef)



More information about the llvm-commits mailing list