diff --git a/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp b/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp --- a/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp +++ b/mlir/lib/Conversion/MathToLibm/MathToLibm.cpp @@ -11,6 +11,7 @@ #include "../PassDetail.h" #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" #include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Math/IR/Math.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" @@ -129,6 +130,14 @@ opFunc = rewriter.create(rewriter.getUnknownLoc(), name, opFunctionTy); opFunc.setPrivate(); + + // By definition Math dialect operations imply LLVM's "readnone" + // function attribute, so we can set it here to provide more + // optimization opportunities (e.g. LICM) for backends targeting LLVM IR. + // This will have to be changed, when strict FP behavior is supported + // by Math dialect. + opFunc->setAttr(LLVM::LLVMDialect::getReadnoneAttrName(), + UnitAttr::get(rewriter.getContext())); } assert(isa(SymbolTable::lookupSymbolIn(module, name))); diff --git a/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir b/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir --- a/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir +++ b/mlir/test/Conversion/MathToLibm/convert-to-libm.mlir @@ -1,29 +1,29 @@ // RUN: mlir-opt %s -convert-math-to-libm -canonicalize | FileCheck %s -// CHECK-DAG: @atan(f64) -> f64 -// CHECK-DAG: @atanf(f32) -> f32 -// CHECK-DAG: @erf(f64) -> f64 -// CHECK-DAG: @erff(f32) -> f32 -// CHECK-DAG: @expm1(f64) -> f64 -// CHECK-DAG: @expm1f(f32) -> f32 -// CHECK-DAG: @atan2(f64, f64) -> f64 -// CHECK-DAG: @atan2f(f32, f32) -> f32 -// CHECK-DAG: @tan(f64) -> f64 -// CHECK-DAG: @tanf(f32) -> f32 -// CHECK-DAG: @tanh(f64) -> f64 -// CHECK-DAG: @tanhf(f32) -> f32 -// CHECK-DAG: @round(f64) -> f64 -// CHECK-DAG: @roundf(f32) -> f32 -// CHECK-DAG: @roundeven(f64) -> f64 -// CHECK-DAG: @roundevenf(f32) -> f32 -// CHECK-DAG: @cos(f64) -> f64 -// CHECK-DAG: @cosf(f32) -> f32 -// CHECK-DAG: @sin(f64) -> f64 -// CHECK-DAG: @sinf(f32) -> f32 -// CHECK-DAG: @floor(f64) -> f64 -// CHECK-DAG: @floorf(f32) -> f32 -// CHECK-DAG: @ceil(f64) -> f64 -// CHECK-DAG: @ceilf(f32) -> f32 +// CHECK-DAG: @atan(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @atanf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @erf(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @erff(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @expm1(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @expm1f(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @atan2(f64, f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @atan2f(f32, f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @tan(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @tanf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @tanh(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @tanhf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @round(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @roundf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @roundeven(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @roundevenf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @cos(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @cosf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @sin(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @sinf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @floor(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @floorf(f32) -> f32 attributes {llvm.readnone} +// CHECK-DAG: @ceil(f64) -> f64 attributes {llvm.readnone} +// CHECK-DAG: @ceilf(f32) -> f32 attributes {llvm.readnone} // CHECK-LABEL: func @atan_caller // CHECK-SAME: %[[FLOAT:.*]]: f32