[Mlir-commits] [mlir] [MLIR][LLVM] Add fast-math related function attribute support (PR #79812)

Alex Bradbury llvmlistbot at llvm.org
Mon Jan 29 07:14:41 PST 2024


https://github.com/asb updated https://github.com/llvm/llvm-project/pull/79812

>From 1e2881bb92f34d80c1c2d132eacf3a8b416d8b84 Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Sun, 28 Jan 2024 14:40:49 +0000
Subject: [PATCH 1/3] [MLIR][LLVM] Add fast-math related function attribute
 support

Adds unsafe-fp-math, no-infs-fp-math, no-nans-fp-math,
approx-func-fp-math, and no-signed-zeros-fp-math function attributes.
---
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   |  7 ++-
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       | 25 +++++++++++
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  | 18 ++++++++
 mlir/test/Dialect/LLVMIR/func.mlir            | 30 +++++++++++++
 .../LLVMIR/Import/function-attributes.ll      | 30 +++++++++++++
 .../LLVMIR/fp-math-function-attributes.mlir   | 44 +++++++++++++++++++
 6 files changed, 153 insertions(+), 1 deletion(-)
 create mode 100644 mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 01d476f530b1c57..ad67fba5a81cf8b 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1428,7 +1428,12 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
     OptionalAttr<LLVM_VScaleRangeAttr>:$vscale_range,
     OptionalAttr<FramePointerKindAttr>:$frame_pointer,
     OptionalAttr<StrAttr>:$target_cpu,
-    OptionalAttr<LLVM_TargetFeaturesAttr>:$target_features
+    OptionalAttr<LLVM_TargetFeaturesAttr>:$target_features,
+    OptionalAttr<BoolAttr>:$unsafe_fp_math,
+    OptionalAttr<BoolAttr>:$no_infs_fp_math,
+    OptionalAttr<BoolAttr>:$no_nans_fp_math,
+    OptionalAttr<BoolAttr>:$approx_func_fp_math,
+    OptionalAttr<BoolAttr>:$no_signed_zeros_fp_math
   );
 
   let regions = (region AnyRegion:$body);
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 928d8077175ccf5..5ca4a9fd68d650d 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1646,6 +1646,11 @@ static constexpr std::array ExplicitAttributes{
     StringLiteral("vscale_range"),
     StringLiteral("frame-pointer"),
     StringLiteral("target-features"),
+    StringLiteral("unsafe-fp-math"),
+    StringLiteral("no-infs-fp-math"),
+    StringLiteral("no-nans-fp-math"),
+    StringLiteral("approx-func-fp-math"),
+    StringLiteral("no-signed-zeros-fp-math"),
 };
 
 static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
@@ -1752,6 +1757,26 @@ void ModuleImport::processFunctionAttributes(llvm::Function *func,
       attr.isStringAttribute())
     funcOp.setTargetFeaturesAttr(
         LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
+
+  if (llvm::Attribute attr = func->getFnAttribute("unsafe-fp-math");
+      attr.isStringAttribute())
+    funcOp.setUnsafeFpMath(attr.getValueAsBool());
+
+  if (llvm::Attribute attr = func->getFnAttribute("no-infs-fp-math");
+      attr.isStringAttribute())
+    funcOp.setNoInfsFpMath(attr.getValueAsBool());
+
+  if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math");
+      attr.isStringAttribute())
+    funcOp.setNoNansFpMath(attr.getValueAsBool());
+
+  if (llvm::Attribute attr = func->getFnAttribute("approx-func-fp-math");
+      attr.isStringAttribute())
+    funcOp.setApproxFuncFpMath(attr.getValueAsBool());
+
+  if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");
+      attr.isStringAttribute())
+    funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
 }
 
 DictionaryAttr
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 69a1cbe5969e859..6364cacbd19245f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -37,6 +37,7 @@
 
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/IR/BasicBlock.h"
@@ -1214,6 +1215,23 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
         getLLVMContext(), attr->getMinRange().getInt(),
         attr->getMaxRange().getInt()));
 
+  if (auto unsafeFpMath = func.getUnsafeFpMath())
+    llvmFunc->addFnAttr("unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
+
+  if (auto noInfsFpMath = func.getNoInfsFpMath())
+    llvmFunc->addFnAttr("no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
+
+  if (auto noNansFpMath = func.getNoNansFpMath())
+    llvmFunc->addFnAttr("no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
+
+  if (auto approxFuncFpMath = func.getApproxFuncFpMath())
+    llvmFunc->addFnAttr("approx-func-fp-math",
+                        llvm::toStringRef(*approxFuncFpMath));
+
+  if (auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
+    llvmFunc->addFnAttr("no-signed-zeros-fp-math",
+                        llvm::toStringRef(*noSignedZerosFpMath));
+
   // Add function attribute frame-pointer, if found.
   if (FramePointerKindAttr attr = func.getFramePointerAttr())
     llvmFunc->addFnAttr("frame-pointer",
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index 9dc1bc57034e02f..006f2f64a27277c 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -257,6 +257,36 @@ module {
   llvm.func @frame_pointer_roundtrip() attributes {frame_pointer = #llvm.framePointerKind<"non-leaf">} {
     llvm.return
   }
+
+  llvm.func @unsafe_fp_math_roundtrip() attributes {unsafe_fp_math = true} {
+    // CHECK: @unsafe_fp_math_roundtrip
+    // CHECK-SAME: attributes {unsafe_fp_math = true}
+    llvm.return
+  }
+
+  llvm.func @no_infs_fp_math_roundtrip() attributes {no_infs_fp_math = true} {
+    // CHECK: @no_infs_fp_math_roundtrip
+    // CHECK-SAME: attributes {no_infs_fp_math = true}
+    llvm.return
+  }
+
+  llvm.func @no_nans_fp_math_roundtrip() attributes {no_nans_fp_math = true} {
+    // CHECK: @no_nans_fp_math_roundtrip
+    // CHECK-SAME: attributes {no_nans_fp_math = true}
+    llvm.return
+  }
+
+  llvm.func @approx_func_fp_math_roundtrip() attributes {approx_func_fp_math = true} {
+    // CHECK: @approx_func_fp_math_roundtrip
+    // CHECK-SAME: attributes {approx_func_fp_math = true}
+    llvm.return
+  }
+
+  llvm.func @no_signed_zeros_fp_math_roundtrip() attributes {no_signed_zeros_fp_math = true} {
+    // CHECK: @no_signed_zeros_fp_math_roundtrip
+    // CHECK-SAME: attributes {no_signed_zeros_fp_math = true}
+    llvm.return
+  }
 }
 
 // -----
diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
index af2ef9db96ae333..70387789aa97e4a 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -272,3 +272,33 @@ define void @align_func() align 2 {
 ; CHECK-LABEL: @align_decl
 ; CHECK-SAME: attributes {alignment = 64 : i64}
 declare void @align_decl() align 64
+
+; // -----
+
+; CHECK-LABEL: @func_attr_unsafe_fp_math
+; CHECK-SAME: attributes {unsafe_fp_math = true}
+declare void @func_attr_unsafe_fp_math() "unsafe-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_no_infs_fp_math
+; CHECK-SAME: attributes {no_infs_fp_math = true}
+declare void @func_attr_no_infs_fp_math() "no-infs-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_no_nans_fp_math
+; CHECK-SAME: attributes {no_nans_fp_math = true}
+declare void @func_attr_no_nans_fp_math() "no-nans-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_approx_func_fp_math
+; CHECK-SAME: attributes {approx_func_fp_math = true}
+declare void @func_attr_approx_func_fp_math() "approx-func-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_no_signed_zeros_fp_math
+; CHECK-SAME: attributes {no_signed_zeros_fp_math = true}
+declare void @func_attr_no_signed_zeros_fp_math() "no-signed-zeros-fp-math"="true"
diff --git a/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
new file mode 100644
index 000000000000000..ccae06cc3dd76d6
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
@@ -0,0 +1,44 @@
+// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
+
+// CHECK-LABEL: define void @unsafe_fp_math_func()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @unsafe_fp_math_func() attributes {unsafe_fp_math = true}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "unsafe-fp-math"="true" }
+
+// -----
+
+// CHECK-LABEL: define void @no_infs_fp_math_func()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_infs_fp_math_func() attributes {no_infs_fp_math = true}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "no-infs-fp-math"="true" }
+
+// -----
+
+// CHECK-LABEL: define void @no_nans_fp_math_func()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_nans_fp_math_func() attributes {no_nans_fp_math = true}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "no-nans-fp-math"="true" }
+
+// -----
+
+// CHECK-LABEL: define void @approx_func_fp_math_func()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @approx_func_fp_math_func() attributes {approx_func_fp_math = true}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "approx-func-fp-math"="true" }
+
+// -----
+
+// CHECK-LABEL: define void @no_signed_zeros_fp_math_func()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_signed_zeros_fp_math_func() attributes {no_signed_zeros_fp_math = true}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "no-signed-zeros-fp-math"="true" }

>From 8f67309e8a548454ee1e883be60f3bb4f2c5111e Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Mon, 29 Jan 2024 15:04:02 +0000
Subject: [PATCH 2/3] Add tests for fast math attributes set to false

---
 .../LLVMIR/Import/function-attributes.ll      | 50 ++++++++++++---
 .../LLVMIR/fp-math-function-attributes.mlir   | 63 ++++++++++++++++---
 2 files changed, 94 insertions(+), 19 deletions(-)

diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
index 70387789aa97e4a..c46db5e34643466 100644
--- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll
+++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll
@@ -275,30 +275,60 @@ declare void @align_decl() align 64
 
 ; // -----
 
-; CHECK-LABEL: @func_attr_unsafe_fp_math
+; CHECK-LABEL: @func_attr_unsafe_fp_math_true
 ; CHECK-SAME: attributes {unsafe_fp_math = true}
-declare void @func_attr_unsafe_fp_math() "unsafe-fp-math"="true"
+declare void @func_attr_unsafe_fp_math_true() "unsafe-fp-math"="true"
 
 ; // -----
 
-; CHECK-LABEL: @func_attr_no_infs_fp_math
+; CHECK-LABEL: @func_attr_unsafe_fp_math_false
+; CHECK-SAME: attributes {unsafe_fp_math = false}
+declare void @func_attr_unsafe_fp_math_false() "unsafe-fp-math"="false"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_no_infs_fp_math_true
 ; CHECK-SAME: attributes {no_infs_fp_math = true}
-declare void @func_attr_no_infs_fp_math() "no-infs-fp-math"="true"
+declare void @func_attr_no_infs_fp_math_true() "no-infs-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_no_infs_fp_math_false
+; CHECK-SAME: attributes {no_infs_fp_math = false}
+declare void @func_attr_no_infs_fp_math_false() "no-infs-fp-math"="false"
 
 ; // -----
 
-; CHECK-LABEL: @func_attr_no_nans_fp_math
+; CHECK-LABEL: @func_attr_no_nans_fp_math_true
 ; CHECK-SAME: attributes {no_nans_fp_math = true}
-declare void @func_attr_no_nans_fp_math() "no-nans-fp-math"="true"
+declare void @func_attr_no_nans_fp_math_true() "no-nans-fp-math"="true"
 
 ; // -----
 
-; CHECK-LABEL: @func_attr_approx_func_fp_math
+; CHECK-LABEL: @func_attr_no_nans_fp_math_false
+; CHECK-SAME: attributes {no_nans_fp_math = false}
+declare void @func_attr_no_nans_fp_math_false() "no-nans-fp-math"="false"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_approx_func_fp_math_true
 ; CHECK-SAME: attributes {approx_func_fp_math = true}
-declare void @func_attr_approx_func_fp_math() "approx-func-fp-math"="true"
+declare void @func_attr_approx_func_fp_math_true() "approx-func-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_approx_func_fp_math_false
+; CHECK-SAME: attributes {approx_func_fp_math = false}
+declare void @func_attr_approx_func_fp_math_false() "approx-func-fp-math"="false"
 
 ; // -----
 
-; CHECK-LABEL: @func_attr_no_signed_zeros_fp_math
+; CHECK-LABEL: @func_attr_no_signed_zeros_fp_math_true
 ; CHECK-SAME: attributes {no_signed_zeros_fp_math = true}
-declare void @func_attr_no_signed_zeros_fp_math() "no-signed-zeros-fp-math"="true"
+declare void @func_attr_no_signed_zeros_fp_math_true() "no-signed-zeros-fp-math"="true"
+
+; // -----
+
+; CHECK-LABEL: @func_attr_no_signed_zeros_fp_math_false
+; CHECK-SAME: attributes {no_signed_zeros_fp_math = false}
+declare void @func_attr_no_signed_zeros_fp_math_false() "no-signed-zeros-fp-math"="false"
diff --git a/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
index ccae06cc3dd76d6..cb0ec44b0793348 100644
--- a/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
+++ b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
@@ -1,44 +1,89 @@
 // RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
 
-// CHECK-LABEL: define void @unsafe_fp_math_func()
+// CHECK-LABEL: define void @unsafe_fp_math_func_true()
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
-llvm.func @unsafe_fp_math_func() attributes {unsafe_fp_math = true}  {
+llvm.func @unsafe_fp_math_func_true() attributes {unsafe_fp_math = true}  {
   llvm.return
 }
 // CHECK: attributes #[[ATTRS]] = { "unsafe-fp-math"="true" }
 
 // -----
 
-// CHECK-LABEL: define void @no_infs_fp_math_func()
+// CHECK-LABEL: define void @unsafe_fp_math_func_false()
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
-llvm.func @no_infs_fp_math_func() attributes {no_infs_fp_math = true}  {
+llvm.func @unsafe_fp_math_func_false() attributes {unsafe_fp_math = false}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "unsafe-fp-math"="false" }
+
+// -----
+
+// CHECK-LABEL: define void @no_infs_fp_math_func_true()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_infs_fp_math_func_true() attributes {no_infs_fp_math = true}  {
   llvm.return
 }
 // CHECK: attributes #[[ATTRS]] = { "no-infs-fp-math"="true" }
 
 // -----
 
-// CHECK-LABEL: define void @no_nans_fp_math_func()
+// CHECK-LABEL: define void @no_infs_fp_math_func_false()
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
-llvm.func @no_nans_fp_math_func() attributes {no_nans_fp_math = true}  {
+llvm.func @no_infs_fp_math_func_false() attributes {no_infs_fp_math = false}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "no-infs-fp-math"="false" }
+
+// -----
+
+// CHECK-LABEL: define void @no_nans_fp_math_func_true()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_nans_fp_math_func_true() attributes {no_nans_fp_math = true}  {
   llvm.return
 }
 // CHECK: attributes #[[ATTRS]] = { "no-nans-fp-math"="true" }
 
 // -----
 
-// CHECK-LABEL: define void @approx_func_fp_math_func()
+// CHECK-LABEL: define void @no_nans_fp_math_func_false()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_nans_fp_math_func_false() attributes {no_nans_fp_math = false}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "no-nans-fp-math"="false" }
+
+// -----
+
+// CHECK-LABEL: define void @approx_func_fp_math_func_true()
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
 llvm.func @approx_func_fp_math_func() attributes {approx_func_fp_math = true}  {
   llvm.return
 }
 // CHECK: attributes #[[ATTRS]] = { "approx-func-fp-math"="true" }
 
+// -----
+//
+// CHECK-LABEL: define void @approx_func_fp_math_func_false()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @approx_func_fp_math_func_false() attributes {approx_func_fp_math = false}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "approx-func-fp-math"="false" }
+
 // -----
 
-// CHECK-LABEL: define void @no_signed_zeros_fp_math_func()
+// CHECK-LABEL: define void @no_signed_zeros_fp_math_func_true()
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
-llvm.func @no_signed_zeros_fp_math_func() attributes {no_signed_zeros_fp_math = true}  {
+llvm.func @no_signed_zeros_fp_math_func_true() attributes {no_signed_zeros_fp_math = true}  {
   llvm.return
 }
 // CHECK: attributes #[[ATTRS]] = { "no-signed-zeros-fp-math"="true" }
+
+// -----
+
+// CHECK-LABEL: define void @no_signed_zeros_fp_math_func_false()
+// CHECK-SAME: #[[ATTRS:[0-9]+]]
+llvm.func @no_signed_zeros_fp_math_func_false() attributes {no_signed_zeros_fp_math = false}  {
+  llvm.return
+}
+// CHECK: attributes #[[ATTRS]] = { "no-signed-zeros-fp-math"="false" }

>From 5418474a4e1fa62220f328d1ea1683e00946f291 Mon Sep 17 00:00:00 2001
From: Alex Bradbury <asb at igalia.com>
Date: Mon, 29 Jan 2024 15:14:22 +0000
Subject: [PATCH 3/3] Fix copy/paste error in fp-math-function-attributes.mlir

---
 mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
index cb0ec44b0793348..4877c1137e3cd78 100644
--- a/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
+++ b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir
@@ -56,7 +56,7 @@ llvm.func @no_nans_fp_math_func_false() attributes {no_nans_fp_math = false}  {
 
 // CHECK-LABEL: define void @approx_func_fp_math_func_true()
 // CHECK-SAME: #[[ATTRS:[0-9]+]]
-llvm.func @approx_func_fp_math_func() attributes {approx_func_fp_math = true}  {
+llvm.func @approx_func_fp_math_func_true() attributes {approx_func_fp_math = true}  {
   llvm.return
 }
 // CHECK: attributes #[[ATTRS]] = { "approx-func-fp-math"="true" }



More information about the Mlir-commits mailing list