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 @@ -129,6 +129,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("passthrough", rewriter.getArrayAttr(StringAttr::get( + rewriter.getContext(), "readnone"))); } 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,23 +1,23 @@ // 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: @cos(f64) -> f64 -// CHECK-DAG: @cosf(f32) -> f32 -// CHECK-DAG: @sin(f64) -> f64 -// CHECK-DAG: @sinf(f32) -> f32 +// CHECK-DAG: @atan(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @atanf(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @erf(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @erff(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @expm1(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @expm1f(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @atan2(f64, f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @atan2f(f32, f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @tan(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @tanf(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @tanh(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @tanhf(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @round(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @roundf(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @cos(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @cosf(f32) -> f32 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @sin(f64) -> f64 attributes {passthrough = ["readnone"]} +// CHECK-DAG: @sinf(f32) -> f32 attributes {passthrough = ["readnone"]} // CHECK-LABEL: func @atan_caller // CHECK-SAME: %[[FLOAT:.*]]: f32