[mlir][math] Add `math.absi` op
authorJeff Niu <jeff@modular.com>
Sat, 6 Aug 2022 16:09:57 +0000 (12:09 -0400)
committerJeff Niu <jeff@modular.com>
Mon, 8 Aug 2022 15:05:01 +0000 (11:05 -0400)
Adds an integer absolute value op to the math dialect.

When converting to LLVM, this op is lowered to the LLVM `abs` intrinsic.
When converting to SPIRV, this op is lowered to `spv.GL.SAbs`.

Depends on D131325

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D131327

mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
mlir/include/mlir/Dialect/Math/IR/MathOps.td
mlir/lib/Conversion/MathToLLVM/MathToLLVM.cpp
mlir/lib/Conversion/MathToSPIRV/MathToSPIRV.cpp
mlir/lib/Dialect/Math/IR/MathOps.cpp
mlir/test/Conversion/MathToLLVM/math-to-llvm.mlir
mlir/test/Conversion/MathToSPIRV/math-to-gl-spirv.mlir

index c7e947b622fb42753f8303cbfc94b721b8eaccbc..937a2fa65ff5f12a5bb49f13d48e6dce31661bb2 100644 (file)
@@ -40,6 +40,7 @@ class LLVM_CountZerosIntrinsicOp<string func, list<Trait> traits = []> :
   let arguments = (ins LLVM_Type:$in, I<1>:$zero_undefined);
 }
 
+def LLVM_AbsOp : LLVM_UnaryIntrinsicOp<"abs">;
 def LLVM_CopySignOp : LLVM_BinarySameArgsIntrinsicOp<"copysign">;
 def LLVM_CosOp : LLVM_UnaryIntrinsicOp<"cos">;
 def LLVM_ExpOp : LLVM_UnaryIntrinsicOp<"exp">;
index 27ab3a3b4656dd124601896f73eea8aeb4759eff..966a9a1241b130ab0ff74add7fc1a69bfe5fa3c7 100644 (file)
@@ -86,6 +86,27 @@ def Math_AbsFOp : Math_FloatUnaryOp<"absf"> {
   let hasFolder = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// AbsIOp
+//===----------------------------------------------------------------------===//
+
+def Math_AbsIOp : Math_IntegerUnaryOp<"absi"> {
+  let summary = "integer absolute-value operation";
+  let description = [{
+    The `absi` operation computes the absolute value. It takes one operand of
+    integer type (i.e., scalar, tensor or vector) and returns one result of the
+    same type.
+
+    Example:
+
+    ```mlir
+    // Scalar absolute value.
+    %a = math.absi %b : i64
+    ```
+  }];
+  let hasFolder = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // AtanOp
 //===----------------------------------------------------------------------===//
index 1ac4bbd7492e823bd76f1484fb5fb8d40b8ad9d3..77fc91d3085273dfaabe6d6b2870f27cc9ac6c2e 100644 (file)
@@ -19,6 +19,7 @@ using namespace mlir;
 
 namespace {
 using AbsFOpLowering = VectorConvertToLLVMPattern<math::AbsFOp, LLVM::FAbsOp>;
+using AbsIOpLowering = VectorConvertToLLVMPattern<math::AbsIOp, LLVM::AbsOp>;
 using CeilOpLowering = VectorConvertToLLVMPattern<math::CeilOp, LLVM::FCeilOp>;
 using CopySignOpLowering =
     VectorConvertToLLVMPattern<math::CopySignOp, LLVM::CopySignOp>;
@@ -269,6 +270,7 @@ void mlir::populateMathToLLVMConversionPatterns(LLVMTypeConverter &converter,
   // clang-format off
   patterns.add<
     AbsFOpLowering,
+    AbsIOpLowering,
     CeilOpLowering,
     CopySignOpLowering,
     CosOpLowering,
index e53bd2b9549473eea698ccb84a4f88915313883b..55a242991bbcff2ac4ee311363c1c21447e36c14 100644 (file)
@@ -288,6 +288,7 @@ void populateMathToSPIRVPatterns(SPIRVTypeConverter &typeConverter,
       .add<CountLeadingZerosPattern, Log1pOpPattern<spirv::GLLogOp>,
            ExpM1OpPattern<spirv::GLExpOp>, PowFOpPattern, RoundOpPattern,
            spirv::ElementwiseOpPattern<math::AbsFOp, spirv::GLFAbsOp>,
+           spirv::ElementwiseOpPattern<math::AbsIOp, spirv::GLSAbsOp>,
            spirv::ElementwiseOpPattern<math::CeilOp, spirv::GLCeilOp>,
            spirv::ElementwiseOpPattern<math::CosOp, spirv::GLCosOp>,
            spirv::ElementwiseOpPattern<math::ExpOp, spirv::GLExpOp>,
index 50d65127cd45ae326db66a5193669807f5ded984..e128435cefdc2613b2530c11bddd200628d11a43 100644 (file)
@@ -30,6 +30,15 @@ OpFoldResult math::AbsFOp::fold(ArrayRef<Attribute> operands) {
                                      [](const APFloat &a) { return abs(a); });
 }
 
+//===----------------------------------------------------------------------===//
+// AbsIOp folder
+//===----------------------------------------------------------------------===//
+
+OpFoldResult math::AbsIOp::fold(ArrayRef<Attribute> operands) {
+  return constFoldUnaryOp<IntegerAttr>(operands,
+                                       [](const APInt &a) { return a.abs(); });
+}
+
 //===----------------------------------------------------------------------===//
 // AtanOp folder
 //===----------------------------------------------------------------------===//
index 6378ea6475f2554430cf2552cf077941570c49a2..fc91a55f4264b9c58cf389bb5ad76fdd04b6f4c4 100644 (file)
@@ -2,14 +2,16 @@
 
 // CHECK-LABEL: @ops
 func.func @ops(%arg0: f32, %arg1: f32, %arg2: i32, %arg3: i32, %arg4: f64) {
-// CHECK: = "llvm.intr.exp"(%{{.*}}) : (f32) -> f32
-  %13 = math.exp %arg0 : f32
-// CHECK: = "llvm.intr.exp2"(%{{.*}}) : (f32) -> f32
-  %14 = math.exp2 %arg0 : f32
-// CHECK: = "llvm.intr.sqrt"(%{{.*}}) : (f32) -> f32
-  %19 = math.sqrt %arg0 : f32
-// CHECK: = "llvm.intr.sqrt"(%{{.*}}) : (f64) -> f64
-  %20 = math.sqrt %arg4 : f64
+  // CHECK: = "llvm.intr.exp"(%{{.*}}) : (f32) -> f32
+  %0 = math.exp %arg0 : f32
+  // CHECK: = "llvm.intr.exp2"(%{{.*}}) : (f32) -> f32
+  %1 = math.exp2 %arg0 : f32
+  // CHECK: = "llvm.intr.sqrt"(%{{.*}}) : (f32) -> f32
+  %2 = math.sqrt %arg0 : f32
+  // CHECK: = "llvm.intr.sqrt"(%{{.*}}) : (f64) -> f64
+  %3 = math.sqrt %arg4 : f64
+  // CHECK: = "llvm.intr.abs"(%{{.*}}) : (i32) -> i32
+  %4 = math.absi %arg2 : i32
   func.return
 }
 
index 1302b47182ce15e9cb9ff67c0776623a90f76475..662478aa30db68318d7ba1f114ad9ded78129530 100644 (file)
@@ -79,6 +79,13 @@ func.func @float32_ternary_vector(%a: vector<4xf32>, %b: vector<4xf32>,
   return
 }
 
+// CHECK-LABEL: @int_unary
+func.func @int_unary(%arg0: i32) {
+  // CHECK: spv.GL.SAbs %{{.*}}
+  %0 = math.absi %arg0 : i32
+  return
+}
+
 // CHECK-LABEL: @ctlz_scalar
 //  CHECK-SAME: (%[[VAL:.+]]: i32)
 func.func @ctlz_scalar(%val: i32) -> i32 {