[llvm] [SPIR-V] Lower G_SADDO and G_SSUBO instead of using generic selection (PR #189031)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 27 08:53:58 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>



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


3 Files Affected:

- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (-3) 
- (modified) llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (+3-2) 
- (modified) llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll (+24-8) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index df2ddea2228b2..c61a3ac4b85a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -906,9 +906,6 @@ static bool mayApplyGenericSelection(unsigned Opcode) {
   case TargetOpcode::G_CONSTANT:
   case TargetOpcode::G_FCONSTANT:
     return false;
-  case TargetOpcode::G_SADDO:
-  case TargetOpcode::G_SSUBO:
-    return true;
   }
   return isTypeFoldingSupported(Opcode);
 }
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 92b900be17642..afc97869a9c0f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -428,10 +428,11 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
   // TODO: add proper legalization rules.
   getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG).alwaysLegal();
 
-  getActionDefinitionsBuilder(
-      {G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO})
+  getActionDefinitionsBuilder({G_UADDO, G_USUBO, G_UMULO, G_SMULO})
       .alwaysLegal();
 
+  getActionDefinitionsBuilder({G_SADDO, G_SSUBO}).lower();
+
   getActionDefinitionsBuilder({G_LROUND, G_LLROUND})
       .legalForCartesianProduct(allFloatScalarsAndVectors,
                                 allIntScalarsAndVectors);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll
index 52f939faf0a9f..d977347529010 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/signed_arithmetic_overflow.ll
@@ -1,8 +1,20 @@
-; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -filetype=obj -o - | spirv-val %}
-; XFAIL: *
-;@llvm.sadd.with.overflow and @llvm.ssub.with.overflow has not been implemented.
+; RUN: llc -verify-machineinstrs -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 %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
+; CHECK-DAG: %[[Int:.*]] = OpTypeInt 32 0
+; CHECK-DAG: %[[Bool:.*]] = OpTypeBool
+; CHECK-DAG: %[[NullInt:.*]] = OpConstantNull %[[Int]]
+
+; CHECK: OpFunction
+; CHECK: %[[A:.*]] = OpFunctionParameter %[[Int]]
+; CHECK: %[[B:.*]] = OpFunctionParameter %[[Int]]
+; CHECK: %[[Res:.*]] = OpIAdd %[[Int]] %[[A]] %[[B]]
+; CHECK: %[[ResLtA:.*]] = OpSLessThan %[[Bool]] %[[Res]] %[[A]]
+; CHECK: %[[BLt0:.*]] = OpSLessThan %[[Bool]] %[[B]] %[[NullInt]]
+; CHECK: %[[Overflow:.*]] = OpLogicalNotEqual %[[Bool]] %[[BLt0]] %[[ResLtA]]
+; CHECK: OpReturn
 define spir_func void @test_sadd_overflow(ptr %out_result, ptr %out_overflow, i32 %a, i32 %b) {
 entry:
   %res = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
@@ -14,8 +26,14 @@ entry:
   ret void
 }
 
-declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32)
-
+; CHECK: OpFunction
+; CHECK: %[[A2:.*]] = OpFunctionParameter %[[Int]]
+; CHECK: %[[B2:.*]] = OpFunctionParameter %[[Int]]
+; CHECK: %[[Res2:.*]] = OpISub %[[Int]] %[[A2]] %[[B2]]
+; CHECK: %[[ResLtA2:.*]] = OpSLessThan %[[Bool]] %[[Res2]] %[[A2]]
+; CHECK: %[[BGt0:.*]] = OpSGreaterThan %[[Bool]] %[[B2]] %[[NullInt]]
+; CHECK: %[[Overflow2:.*]] = OpLogicalNotEqual %[[Bool]] %[[BGt0]] %[[ResLtA2]]
+; CHECK: OpReturn
 define spir_func void @test_ssub_overflow(ptr %out_result, ptr %out_overflow, i32 %a, i32 %b) {
 entry:
   %res = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
@@ -26,5 +44,3 @@ entry:
   store i8 %zext_ofl, ptr %out_overflow
   ret void
 }
-
-declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32)

``````````

</details>


https://github.com/llvm/llvm-project/pull/189031


More information about the llvm-commits mailing list