23#define GEN_PASS_DEF_CONVERTMATHTONVVM
24#include "mlir/Conversion/Passes.h.inc"
29#define DEBUG_TYPE "math-to-nvvm"
31template <
typename OpTy>
35 StringRef f64Func, StringRef f32ApproxFunc =
"",
36 StringRef f16Func =
"") {
39 f32ApproxFunc, f16Func,
43template <
typename OpTy>
57 return type && type.getWidth() <= 32;
61struct FPowIScalarizeLowering
63 using ScalarizeVectorOpLowering::ScalarizeVectorOpLowering;
66 matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
67 ConversionPatternRewriter &rewriter)
const override {
69 return rewriter.notifyMatchFailure(op,
"exponent does not fit in i32");
78 matchAndRewrite(math::FPowIOp op, OpAdaptor adaptor,
79 ConversionPatternRewriter &rewriter)
const override {
81 return rewriter.notifyMatchFailure(op,
"exponent does not fit in i32");
84 if (!op->getParentOfType<FunctionOpInterface>() ||
85 !isa<Float16Type, BFloat16Type, Float32Type, Float64Type>(
86 adaptor.getLhs().getType()))
87 return rewriter.notifyMatchFailure(op,
"cannot be lowered to libdevice");
89 Value exponent = adaptor.getRhs();
91 exponent = LLVM::SExtOp::create(rewriter, op.getLoc(),
92 rewriter.getI32Type(), exponent);
93 Value operands[] = {adaptor.getLhs(), exponent};
95 op, OpAdaptor(
ValueRange(operands), op), rewriter);
106 ConversionPatternRewriter &rewriter)
const override {
108 Value input = adaptor.getOperand();
110 auto convertedInput = maybeExt(input, rewriter);
111 auto computeType = convertedInput.getType();
113 StringRef sincosFunc;
114 if (isa<Float32Type>(computeType)) {
115 const arith::FastMathFlags flag = op.getFastmath();
116 const bool useApprox =
117 mlir::arith::bitEnumContainsAny(flag, arith::FastMathFlags::afn);
118 sincosFunc = useApprox ?
"__nv_fast_sincosf" :
"__nv_sincosf";
119 }
else if (isa<Float64Type>(computeType)) {
120 sincosFunc =
"__nv_sincos";
122 return rewriter.notifyMatchFailure(op,
123 "unsupported operand type for sincos");
126 auto ptrType = LLVM::LLVMPointerType::get(rewriter.getContext());
128 Value sinPtr, cosPtr;
133 assert(scope &&
"Expected op to be inside automatic allocation scope");
134 rewriter.setInsertionPointToStart(&scope->getRegion(0).front());
135 auto one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(),
136 rewriter.getI32IntegerAttr(1));
138 LLVM::AllocaOp::create(rewriter, loc, ptrType, computeType, one, 0);
140 LLVM::AllocaOp::create(rewriter, loc, ptrType, computeType, one, 0);
143 createSincosCall(rewriter, loc, sincosFunc, convertedInput, sinPtr, cosPtr,
146 auto sinResult = LLVM::LoadOp::create(rewriter, loc, computeType, sinPtr);
147 auto cosResult = LLVM::LoadOp::create(rewriter, loc, computeType, cosPtr);
149 rewriter.replaceOp(op, {maybeTrunc(sinResult, inputType, rewriter),
150 maybeTrunc(cosResult, inputType, rewriter)});
156 if (isa<Float16Type, BFloat16Type>(operand.
getType()))
157 return LLVM::FPExtOp::create(rewriter, operand.
getLoc(),
163 Value maybeTrunc(Value operand, Type type, PatternRewriter &rewriter)
const {
165 return LLVM::FPTruncOp::create(rewriter, operand.
getLoc(), type, operand);
169 void createSincosCall(ConversionPatternRewriter &rewriter, Location loc,
170 StringRef funcName, Value input, Value sinPtr,
171 Value cosPtr, Operation *op)
const {
172 auto voidType = LLVM::LLVMVoidType::get(rewriter.getContext());
173 auto ptrType = sinPtr.
getType();
175 SmallVector<Type> operandTypes = {input.
getType(), ptrType, ptrType};
176 auto funcType = LLVM::LLVMFunctionType::get(voidType, operandTypes);
178 auto funcAttr = StringAttr::get(op->
getContext(), funcName);
184 assert(parentFunc &&
"expected there to be a parent function");
185 OpBuilder
b(parentFunc);
188 funcOp = LLVM::LLVMFuncOp::create(
b, globalloc, funcName, funcType);
191 SmallVector<Value> callOperands = {input, sinPtr, cosPtr};
192 LLVM::CallOp::create(rewriter, loc, funcOp, callOperands);
202 "__nv_fmaxf",
"__nv_fmax");
204 "__nv_fminf",
"__nv_fmin");
228 "__nv_copysignf",
"__nv_copysign");
230 "__nv_cos",
"__nv_fast_cosf");
238 "__nv_exp",
"__nv_fast_expf");
249 "__nv_finitef",
"__nv_isfinited");
255 "__nv_log",
"__nv_fast_logf");
257 "__nv_log10",
"__nv_fast_log10f");
261 "__nv_log2",
"__nv_fast_log2f");
263 "__nv_pow",
"__nv_fast_powf");
264 patterns.
add<FPowIScalarizeLowering>(converter, benefit);
265 patterns.
add<FPowIOpLowering>(converter,
"__nv_powif",
"__nv_powi",
"",
"",
270 "__nv_rintf",
"__nv_rint");
274 "__nv_sin",
"__nv_fast_sinf");
280 "__nv_tan",
"__nv_fast_tanf");
289struct ConvertMathToNVVMPass final
292 ConvertMathToNVVMPass>::ConvertMathToNVVMBase;
294 void runOnOperation()
override;
298void ConvertMathToNVVMPass::runOnOperation() {
299 auto m = getOperation();
300 MLIRContext *ctx = m.getContext();
303 LowerToLLVMOptions
options(ctx, DataLayout(m));
304 LLVMTypeConverter converter(ctx,
options);
310 .addLegalDialect<BuiltinDialect, func::FuncDialect, vector::VectorDialect,
311 LLVM::LLVMDialect, NVVM::NVVMDialect>();
312 target.addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::FAbsOp,
313 LLVM::FCeilOp, LLVM::FFloorOp, LLVM::FRemOp, LLVM::LogOp,
314 LLVM::Log10Op, LLVM::Log2Op, LLVM::PowOp, LLVM::SinOp,
316 if (
failed(applyPartialConversion(m,
target, std::move(patterns))))
static bool exponentFitsInI32(math::FPowIOp op)
libdevice's __nv_powi and __nv_powif take an i32 exponent, so math.fpowi with a wider or index expone...
static void populateOpPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit, StringRef f32Func, StringRef f64Func, StringRef f32ApproxFunc="", StringRef f16Func="")
static void populateIntOpPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit, StringRef i32Func)
static llvm::ManagedStatic< PassManagerOptions > options
MLIRContext * getContext() const
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
typename math::SincosOp::Adaptor OpAdaptor
Conversion from types to the LLVM IR dialect.
LocationAttr findInstanceOfOrUnknown()
Return an instance of the given location type if one is nested under the current location else return...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
RAII guard to reset the insertion point of the builder when destroyed.
A trait of region holding operations that define a new scope for automatic allocations,...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
MLIRContext * getContext()
Return the context this operation is associated with.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isInteger() const
Return true if this is an integer type (with the specified width).
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Location getLoc() const
Return the location of this value.
Include the generated interface declarations.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
void populateLibDeviceConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Populate the given list with patterns that convert from Math to NVVM libdevice calls.
LogicalResult matchAndRewrite(math::SincosOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
Rewriting that replaces SourceOp with a CallOp to f32Func or f64Func or f32ApproxFunc or f16Func or i...
OpToFuncCallLowering(const LLVMTypeConverter &lowering, StringRef f32Func, StringRef f64Func, StringRef f32ApproxFunc, StringRef f16Func, StringRef i32Func="", PatternBenefit benefit=1, LLVM::cconv::CConv cconv=LLVM::cconv::CConv::C)
LogicalResult matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override
Methods that operate on the SourceOp type.
Unrolls SourceOp to array/vector elements.
LogicalResult matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override
Methods that operate on the SourceOp type.