[Mlir-commits] [mlir] [mlir][LLVM] Add nneg flag (PR #115498)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Nov 8 07:18:38 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-llvm

Author: None (lfrenot)

<details>
<summary>Changes</summary>

This implementation is based on the existing one for the exact flag.

If the nneg flag is set and the argument is negative, the result is a poison value.

@<!-- -->zero9178, @<!-- -->gysit and @<!-- -->Dinistro, could you take a look?

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


8 Files Affected:

- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td (+27) 
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td (+19-2) 
- (modified) mlir/include/mlir/Target/LLVMIR/ModuleImport.h (+5) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp (+3) 
- (modified) mlir/lib/Target/LLVMIR/ModuleImport.cpp (+6) 
- (modified) mlir/test/Dialect/LLVMIR/roundtrip.mlir (+13) 
- (added) mlir/test/Target/LLVMIR/Import/nneg.ll (+10) 
- (added) mlir/test/Target/LLVMIR/nneg.mlir (+10) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 12c430df208925..352e2ec91bdbea 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -114,6 +114,33 @@ def ExactFlagInterface : OpInterface<"ExactFlagInterface"> {
   ];
 }
 
+def NonNegFlagInterface : OpInterface<"NonNegFlagInterface"> {
+  let description = [{
+    This interface defines an LLVM operation with an nneg flag and
+    provides a uniform API for accessing it.
+  }];
+
+  let cppNamespace = "::mlir::LLVM";
+
+  let methods = [
+    InterfaceMethod<[{
+      Get the nneg flag for the operation.
+    }], "bool", "getNonNeg", (ins), [{}], [{
+      return $_op.getProperties().nonNeg;
+    }]>,
+    InterfaceMethod<[{
+      Set the nneg flag for the operation.
+    }], "void", "setNonNeg", (ins "bool":$nonNeg), [{}], [{
+      $_op.getProperties().nonNeg = nonNeg;
+    }]>,
+    StaticInterfaceMethod<[{
+      Get the attribute name of the nonNeg property.
+    }], "StringRef", "getNonNegName", (ins), [{}], [{
+      return "nonNeg";
+    }]>,
+  ];
+}
+
 def BranchWeightOpInterface : OpInterface<"BranchWeightOpInterface"> {
   let description = [{
     An interface for operations that can carry branch weights metadata. It
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 315af2594047a5..afdba9b9a16b5f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -508,6 +508,23 @@ class LLVM_CastOp<string mnemonic, string instName, Type type,
       $_location, $_resultType, $arg);
   }];
 }
+class LLVM_CastOpWithNNegFlag<string mnemonic, string instName, Type type,
+                  Type resultType, list<Trait> traits = []> :
+    LLVM_Op<mnemonic, !listconcat([Pure], [DeclareOpInterfaceMethods<NonNegFlagInterface>], traits)>,
+    LLVM_Builder<"$res = builder.Create" # instName # "($arg, $_resultType, /*Name=*/\"\", op.getNonNeg());"> {
+  let arguments = (ins type:$arg,  UnitAttr:$nonNeg);
+  let results = (outs resultType:$res);
+  let builders = [LLVM_OneResultOpBuilder];
+  let assemblyFormat = "(`nneg` $nonNeg^)? $arg attr-dict `:` type($arg) `to` type($res)";
+  string llvmInstName = instName;
+  string mlirBuilder = [{
+    auto op = $_builder.create<$_qualCppClassName>(
+      $_location, $_resultType, $arg);
+    moduleImport.setNonNegFlag(inst, op);
+    $res = op;
+  }];
+}
+
 def LLVM_BitcastOp : LLVM_CastOp<"bitcast", "BitCast", LLVM_AnyNonAggregate,
     LLVM_AnyNonAggregate, [DeclareOpInterfaceMethods<PromotableOpInterface>]> {
   let hasFolder = 1;
@@ -531,7 +548,7 @@ def LLVM_SExtOp : LLVM_CastOp<"sext", "SExt",
                               LLVM_ScalarOrVectorOf<AnySignlessInteger>> {
   let hasVerifier = 1;
 }
-def LLVM_ZExtOp : LLVM_CastOp<"zext", "ZExt",
+def LLVM_ZExtOp : LLVM_CastOpWithNNegFlag<"zext", "ZExt",
                               LLVM_ScalarOrVectorOf<AnySignlessInteger>,
                               LLVM_ScalarOrVectorOf<AnySignlessInteger>> {
   let hasFolder = 1;
@@ -543,7 +560,7 @@ def LLVM_TruncOp : LLVM_CastOp<"trunc", "Trunc",
 def LLVM_SIToFPOp : LLVM_CastOp<"sitofp", "SIToFP",
                                 LLVM_ScalarOrVectorOf<AnySignlessInteger>,
                                 LLVM_ScalarOrVectorOf<LLVM_AnyFloat>>;
-def LLVM_UIToFPOp : LLVM_CastOp<"uitofp", "UIToFP",
+def LLVM_UIToFPOp : LLVM_CastOpWithNNegFlag<"uitofp", "UIToFP",
                                 LLVM_ScalarOrVectorOf<AnySignlessInteger>,
                                 LLVM_ScalarOrVectorOf<LLVM_AnyFloat>>;
 def LLVM_FPToSIOp : LLVM_CastOp<"fptosi", "FPToSI",
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 6c3a500f20e3a9..30164843f63675 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -192,6 +192,11 @@ class ModuleImport {
   /// implement the exact flag interface.
   void setExactFlag(llvm::Instruction *inst, Operation *op) const;
 
+  /// Sets the nneg flag attribute for the imported operation `op` given
+  /// the original instruction `inst`. Asserts if the operation does not
+  /// implement the nneg flag interface.
+  void setNonNegFlag(llvm::Instruction *inst, Operation *op) const;
+
   /// Sets the fastmath flags attribute for the imported operation `op` given
   /// the original instruction `inst`. Asserts if the operation does not
   /// implement the fastmath interface.
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 6b2d8943bf4885..d39edb8020ccb6 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -146,6 +146,9 @@ static void printLLVMOpAttrs(OpAsmPrinter &printer, Operation *op,
   } else if (auto iface = dyn_cast<ExactFlagInterface>(op)) {
     printer.printOptionalAttrDict(filteredAttrs,
                                   /*elidedAttrs=*/{iface.getIsExactName()});
+  } else if (auto iface = dyn_cast<NonNegFlagInterface>(op)) {
+    printer.printOptionalAttrDict(filteredAttrs,
+                                  /*elidedAttrs=*/{iface.getNonNegName()});
   } else {
     printer.printOptionalAttrDict(filteredAttrs);
   }
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 12145f7a2217df..71d88d3a62f2b9 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -689,6 +689,12 @@ void ModuleImport::setExactFlag(llvm::Instruction *inst, Operation *op) const {
   iface.setIsExact(inst->isExact());
 }
 
+void ModuleImport::setNonNegFlag(llvm::Instruction *inst, Operation *op) const {
+  auto iface = cast<NonNegFlagInterface>(op);
+
+  iface.setNonNeg(inst->hasNonNeg());
+}
+
 void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst,
                                         Operation *op) const {
   auto iface = cast<FastmathFlagsInterface>(op);
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 682780c5f0a7df..f96f7d7fecae5a 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -325,6 +325,19 @@ func.func @casts(%arg0: i32, %arg1: i64, %arg2: vector<4xi32>,
   llvm.return
 }
 
+// CHECK-LABEL: @nneg_casts
+// CHECK-SAME: (%[[I32:.*]]: i32, %[[I64:.*]]: i64, %[[V4I32:.*]]: vector<4xi32>, %[[V4I64:.*]]: vector<4xi64>, %[[PTR:.*]]: !llvm.ptr)
+func.func @nneg_casts(%arg0: i32, %arg1: i64, %arg2: vector<4xi32>,
+                %arg3: vector<4xi64>, %arg4: !llvm.ptr) {
+// CHECK:  = llvm.zext nneg %[[I32]] : i32 to i64
+  %0 = llvm.zext nneg %arg0 : i32 to i64
+// CHECK:  = llvm.zext nneg %[[V4I32]] : vector<4xi32> to vector<4xi64>
+  %4 = llvm.zext nneg %arg2 : vector<4xi32> to vector<4xi64>
+// CHECK: %[[FLOAT:.*]] = llvm.uitofp nneg %[[I32]] : i32 to f32
+  %7 = llvm.uitofp nneg %arg0 : i32 to f32
+  llvm.return
+}
+
 // CHECK-LABEL: @vect
 func.func @vect(%arg0: vector<4xf32>, %arg1: i32, %arg2: f32, %arg3: !llvm.vec<2 x ptr>) {
 // CHECK:  = llvm.extractelement {{.*}} : vector<4xf32>
diff --git a/mlir/test/Target/LLVMIR/Import/nneg.ll b/mlir/test/Target/LLVMIR/Import/nneg.ll
new file mode 100644
index 00000000000000..07756b9f706bdb
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/nneg.ll
@@ -0,0 +1,10 @@
+; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+
+; CHECK-LABEL: @nnegflag_inst
+define void @nnegflag_inst(i32 %arg1) {
+  ; CHECK: llvm.zext nneg %{{.*}} : i32 to i64
+  %1 = zext nneg i32 %arg1 to i64
+  ; CHECK: llvm.uitofp nneg %{{.*}} : i32 to f32
+  %2 = uitofp nneg i32 %arg1 to float
+  ret void
+}
diff --git a/mlir/test/Target/LLVMIR/nneg.mlir b/mlir/test/Target/LLVMIR/nneg.mlir
new file mode 100644
index 00000000000000..8afa765a510e24
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/nneg.mlir
@@ -0,0 +1,10 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK-LABEL: define void @nnegflag_func
+llvm.func @nnegflag_func(%arg0: i32) {
+  // CHECK: %{{.*}} = zext nneg i32 %{{.*}} to i64
+  %0 = llvm.zext nneg %arg0 : i32 to i64
+  // CHECK: %{{.*}} = uitofp nneg i32 %{{.*}} to float
+  %1 = llvm.uitofp nneg %arg0 : i32 to f32
+  llvm.return
+}

``````````

</details>


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


More information about the Mlir-commits mailing list