[Mlir-commits] [mlir] ed2fda6 - [mlir][spirv] Convert arith.subui_extended to spirv.ISubBorrow (#197736)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri May 15 05:43:34 PDT 2026


Author: Arseniy Obolenskiy
Date: 2026-05-15T14:43:30+02:00
New Revision: ed2fda64ac2246968ab21fdab4d795fe25e276cd

URL: https://github.com/llvm/llvm-project/commit/ed2fda64ac2246968ab21fdab4d795fe25e276cd
DIFF: https://github.com/llvm/llvm-project/commit/ed2fda64ac2246968ab21fdab4d795fe25e276cd.diff

LOG: [mlir][spirv] Convert arith.subui_extended to spirv.ISubBorrow (#197736)

Added: 
    

Modified: 
    mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
    mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
    mlir/test/Target/SPIRV/arithmetic-ops.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
index 1b5a8728dd3f8..63f84bc1ceb60 100644
--- a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
+++ b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp
@@ -1318,32 +1318,34 @@ class CmpFOpNanNonePattern final : public OpConversionPattern<arith::CmpFOp> {
 };
 
 //===----------------------------------------------------------------------===//
-// AddUIExtendedOp
+// AddUIExtendedOp/SubUIExtendedOp
 //===----------------------------------------------------------------------===//
 
-/// Converts arith.addui_extended to spirv.IAddCarry.
-class AddUIExtendedOpPattern final
-    : public OpConversionPattern<arith::AddUIExtendedOp> {
+/// Converts arith.addui_extended/arith.subui_extended to spirv.IAddCarry/
+/// spirv.ISubBorrow.
+template <typename ArithExtendedOp, typename SPIRVExtendedOp>
+class BinaryExtendedOpPattern final
+    : public OpConversionPattern<ArithExtendedOp> {
 public:
-  using Base::Base;
+  using OpConversionPattern<ArithExtendedOp>::OpConversionPattern;
   LogicalResult
-  matchAndRewrite(arith::AddUIExtendedOp op, OpAdaptor adaptor,
+  matchAndRewrite(ArithExtendedOp op, typename ArithExtendedOp::Adaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
     Type dstElemTy = adaptor.getLhs().getType();
     Location loc = op->getLoc();
-    Value result = spirv::IAddCarryOp::create(rewriter, loc, adaptor.getLhs(),
-                                              adaptor.getRhs());
+    Value result = SPIRVExtendedOp::create(rewriter, loc, adaptor.getLhs(),
+                                           adaptor.getRhs());
 
-    Value sumResult = spirv::CompositeExtractOp::create(rewriter, loc, result,
-                                                        llvm::ArrayRef(0));
-    Value carryValue = spirv::CompositeExtractOp::create(rewriter, loc, result,
-                                                         llvm::ArrayRef(1));
+    Value valueResult = spirv::CompositeExtractOp::create(rewriter, loc, result,
+                                                          llvm::ArrayRef(0));
+    Value flagValue = spirv::CompositeExtractOp::create(rewriter, loc, result,
+                                                        llvm::ArrayRef(1));
 
-    // Convert the carry value to boolean.
+    // Convert the carry/borrow value to boolean.
     Value one = spirv::ConstantOp::getOne(dstElemTy, loc, rewriter);
-    Value carryResult = spirv::IEqualOp::create(rewriter, loc, carryValue, one);
+    Value flagResult = spirv::IEqualOp::create(rewriter, loc, flagValue, one);
 
-    rewriter.replaceOp(op, {sumResult, carryResult});
+    rewriter.replaceOp(op, {valueResult, flagResult});
     return success();
   }
 };
@@ -1552,7 +1554,8 @@ void mlir::arith::populateArithToSPIRVPatterns(
     TypeCastingOpPattern<arith::BitcastOp, spirv::BitcastOp>,
     CmpIOpBooleanPattern, CmpIOpPattern,
     CmpFOpNanNonePattern, CmpFOpPattern,
-    AddUIExtendedOpPattern,
+    BinaryExtendedOpPattern<arith::AddUIExtendedOp, spirv::IAddCarryOp>,
+    BinaryExtendedOpPattern<arith::SubUIExtendedOp, spirv::ISubBorrowOp>,
     MulIExtendedOpPattern<arith::MulSIExtendedOp, spirv::SMulExtendedOp>,
     MulIExtendedOpPattern<arith::MulUIExtendedOp, spirv::UMulExtendedOp>,
     SelectOpPattern,

diff  --git a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
index 31b70177a0d19..b6a488f0dad73 100644
--- a/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
+++ b/mlir/test/Conversion/ArithToSPIRV/arith-to-spirv.mlir
@@ -99,6 +99,33 @@ func.func @int32_vector_addui_extended(%lhs: vector<4xi32>, %rhs: vector<4xi32>)
   return %sum, %overflow : vector<4xi32>, vector<4xi1>
 }
 
+// Check integer subtract-with-borrow conversions.
+// CHECK-LABEL: @int32_scalar_subui_extended
+// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)
+func.func @int32_scalar_subui_extended(%lhs: i32, %rhs: i32) -> (i32, i1) {
+  // CHECK-NEXT: %[[ISB:.+]] = spirv.ISubBorrow %[[LHS]], %[[RHS]] : !spirv.struct<(i32, i32)>
+  // CHECK-DAG:  %[[DIFF:.+]] = spirv.CompositeExtract %[[ISB]][0 : i32] : !spirv.struct<(i32, i32)>
+  // CHECK-DAG:  %[[B0:.+]]   = spirv.CompositeExtract %[[ISB]][1 : i32] : !spirv.struct<(i32, i32)>
+  // CHECK-DAG:  %[[ONE:.+]]  = spirv.Constant 1 : i32
+  // CHECK-NEXT: %[[B1:.+]]   = spirv.IEqual %[[B0]], %[[ONE]] : i32
+  // CHECK-NEXT: return %[[DIFF]], %[[B1]] : i32, i1
+  %
diff , %borrow = arith.subui_extended %lhs, %rhs: i32, i1
+  return %
diff , %borrow : i32, i1
+}
+
+// CHECK-LABEL: @int32_vector_subui_extended
+// CHECK-SAME: (%[[LHS:.+]]: vector<4xi32>, %[[RHS:.+]]: vector<4xi32>)
+func.func @int32_vector_subui_extended(%lhs: vector<4xi32>, %rhs: vector<4xi32>) -> (vector<4xi32>, vector<4xi1>) {
+  // CHECK-NEXT: %[[ISB:.+]] = spirv.ISubBorrow %[[LHS]], %[[RHS]] : !spirv.struct<(vector<4xi32>, vector<4xi32>)>
+  // CHECK-DAG:  %[[DIFF:.+]] = spirv.CompositeExtract %[[ISB]][0 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)>
+  // CHECK-DAG:  %[[B0:.+]]   = spirv.CompositeExtract %[[ISB]][1 : i32] : !spirv.struct<(vector<4xi32>, vector<4xi32>)>
+  // CHECK-DAG:  %[[ONE:.+]]  = spirv.Constant dense<1> : vector<4xi32>
+  // CHECK-NEXT: %[[B1:.+]]   = spirv.IEqual %[[B0]], %[[ONE]] : vector<4xi32>
+  // CHECK-NEXT: return %[[DIFF]], %[[B1]] : vector<4xi32>, vector<4xi1>
+  %
diff , %borrow = arith.subui_extended %lhs, %rhs: vector<4xi32>, vector<4xi1>
+  return %
diff , %borrow : vector<4xi32>, vector<4xi1>
+}
+
 // Check extended signed integer multiplication conversions.
 // CHECK-LABEL: @int32_scalar_mulsi_extended
 // CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32)

diff  --git a/mlir/test/Target/SPIRV/arithmetic-ops.mlir b/mlir/test/Target/SPIRV/arithmetic-ops.mlir
index ec47035d088b7..3b4c48f8b7b98 100644
--- a/mlir/test/Target/SPIRV/arithmetic-ops.mlir
+++ b/mlir/test/Target/SPIRV/arithmetic-ops.mlir
@@ -56,6 +56,16 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, BFloat1
     %0 = spirv.IMul %arg0, %arg1 : vector<4xi32>
     spirv.Return
   }
+  spirv.func @isub_borrow(%arg0 : i32, %arg1 : i32) "None" {
+    // CHECK: {{%.*}} = spirv.ISubBorrow {{%.*}}, {{%.*}} : !spirv.struct<(i32, i32)>
+    %0 = spirv.ISubBorrow %arg0, %arg1 : !spirv.struct<(i32, i32)>
+    spirv.Return
+  }
+  spirv.func @isub_borrow_vector(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) "None" {
+    // CHECK: {{%.*}} = spirv.ISubBorrow {{%.*}}, {{%.*}} : !spirv.struct<(vector<4xi32>, vector<4xi32>)>
+    %0 = spirv.ISubBorrow %arg0, %arg1 : !spirv.struct<(vector<4xi32>, vector<4xi32>)>
+    spirv.Return
+  }
   spirv.func @udiv(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) "None" {
     // CHECK: {{%.*}} = spirv.UDiv {{%.*}}, {{%.*}} : vector<4xi32>
     %0 = spirv.UDiv %arg0, %arg1 : vector<4xi32>


        


More information about the Mlir-commits mailing list