diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 01d476f530b1c..ad67fba5a81cf 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:$vscale_range, OptionalAttr:$frame_pointer, OptionalAttr:$target_cpu, - OptionalAttr:$target_features + OptionalAttr:$target_features, + OptionalAttr:$unsafe_fp_math, + OptionalAttr:$no_infs_fp_math, + OptionalAttr:$no_nans_fp_math, + OptionalAttr:$approx_func_fp_math, + OptionalAttr:$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 928d8077175cc..5ca4a9fd68d65 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 69a1cbe5969e8..6364cacbd1924 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 9dc1bc57034e0..006f2f64a2727 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 af2ef9db96ae3..c46db5e346434 100644 --- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll +++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll @@ -272,3 +272,63 @@ 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_true +; CHECK-SAME: attributes {unsafe_fp_math = true} +declare void @func_attr_unsafe_fp_math_true() "unsafe-fp-math"="true" + +; // ----- + +; 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_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_true +; CHECK-SAME: attributes {no_nans_fp_math = true} +declare void @func_attr_no_nans_fp_math_true() "no-nans-fp-math"="true" + +; // ----- + +; 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_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_true +; CHECK-SAME: attributes {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 new file mode 100644 index 0000000000000..4877c1137e3cd --- /dev/null +++ b/mlir/test/Target/LLVMIR/fp-math-function-attributes.mlir @@ -0,0 +1,89 @@ +// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s + +// CHECK-LABEL: define void @unsafe_fp_math_func_true() +// CHECK-SAME: #[[ATTRS:[0-9]+]] +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 @unsafe_fp_math_func_false() +// CHECK-SAME: #[[ATTRS:[0-9]+]] +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_infs_fp_math_func_false() +// CHECK-SAME: #[[ATTRS:[0-9]+]] +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 @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_true() 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_true() +// CHECK-SAME: #[[ATTRS:[0-9]+]] +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" }