18#include "llvm/Support/FormatVariadic.h"
24#define GEN_PASS_DEF_CONVERTMATHTOXEVM
25#include "mlir/Conversion/Passes.h.inc"
30#define DEBUG_TYPE "math-to-xevm"
33 auto vecType = dyn_cast<VectorType>(type);
34 return vecType && vecType.getShape().size() == 1 &&
35 vecType.getShape()[0] == 1 && vecType.getElementType().isFloat();
41 if (
auto vecType = dyn_cast<VectorType>(type)) {
42 if (!vecType.getElementType().isFloat())
47 if (
shape.size() != 1)
71 std::string mangledFuncName =
74 auto appendFloatToMangledFunc = [&mangledFuncName](
Type type) {
76 mangledFuncName +=
"f";
77 else if (type.isF16())
78 mangledFuncName +=
"Dh";
79 else if (type.isF64())
80 mangledFuncName +=
"d";
83 for (
auto type : operandTypes) {
84 if (
auto vecType = dyn_cast<VectorType>(type)) {
85 mangledFuncName +=
"Dv" + std::to_string(vecType.getShape()[0]) +
"_";
86 appendFloatToMangledFunc(vecType.getElementType());
88 appendFloatToMangledFunc(type);
91 return mangledFuncName;
96 ConversionPatternRewriter &rewriter)
const override {
100 arith::FastMathFlags fastFlags = op.getFastmath();
101 if (!arith::bitEnumContainsAll(fastFlags, arith::FastMathFlags::afn))
102 return rewriter.notifyMatchFailure(op,
"not a fastmath `afn` operation");
113 for (
Value &operand : operands) {
114 Type opTy = operand.getType();
119 return rewriter.notifyMatchFailure(
120 op, llvm::formatv(
"incompatible operand type: '{0}'", opTy));
121 if (unwrapSizeOneVec) {
123 "expected all operands to be size-1 vectors");
124 opTy = cast<VectorType>(opTy).getElementType();
125 operand = vector::ExtractOp::create(rewriter, loc, operand,
128 operandTypes.push_back(opTy);
131 Type resultType = unwrapSizeOneVec
132 ? cast<VectorType>(op.getType()).getElementType()
135 auto moduleOp = op->template getParentWithTrait<OpTrait::SymbolTable>();
138 operandTypes, resultType);
139 assert(!failed(funcOpRes));
140 LLVM::LLVMFuncOp funcOp = funcOpRes.value();
142 auto callOp = LLVM::CallOp::create(rewriter, loc, funcOp, operands);
149 if (attr.getName() == LLVM::CallOp::getFastmathAttrName()) {
150 callOp.setFastmathFlagsAttr(
151 cast<LLVM::FastmathFlagsAttr>(attr.getValue()));
154 discardableAttrs.push_back(attr);
156 callOp->setDiscardableAttrs(discardableAttrs);
158 if (unwrapSizeOneVec) {
160 rewriter.replaceOpWithNewOp<vector::BroadcastOp>(op, op.getType(),
163 rewriter.replaceOp(op, callOp);
171template <
typename OpTy>
176 std::string prefix =
"__spirv_ocl_";
177 std::string mangledName =
"_Z" +
178 std::to_string(prefix.size() + opName.size()) +
179 prefix + opName.str();
183 converter, mangledName +
"f", mangledName +
"d",
185 "", benefit, LLVM::cconv::CConv::SPIR_FUNC);
245 patterns.
getContext(),
"__spirv_ocl_native_exp", benefit);
247 patterns.
getContext(),
"__spirv_ocl_native_cos", benefit);
249 patterns.
getContext(),
"__spirv_ocl_native_exp2", benefit);
251 patterns.
getContext(),
"__spirv_ocl_native_log", benefit);
253 patterns.
getContext(),
"__spirv_ocl_native_log2", benefit);
255 patterns.
getContext(),
"__spirv_ocl_native_log10", benefit);
257 patterns.
getContext(),
"__spirv_ocl_native_powr", benefit);
259 patterns.
getContext(),
"__spirv_ocl_native_rsqrt", benefit);
261 patterns.
getContext(),
"__spirv_ocl_native_sin", benefit);
263 patterns.
getContext(),
"__spirv_ocl_native_sqrt", benefit);
265 patterns.
getContext(),
"__spirv_ocl_native_tan", benefit);
268 patterns.
getContext(),
"__spirv_ocl_native_divide", benefit);
272struct ConvertMathToXeVMPass
275 void runOnOperation()
override;
279void ConvertMathToXeVMPass::runOnOperation() {
280 Operation *op = getOperation();
283 const auto &dl = getAnalysis<DataLayoutAnalysis>();
286 LowerToLLVMOptions
options(ctx, dl.getAtOrAbove(op));
287 LLVMTypeConverter converter(ctx,
options);
297 .addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::LogOp,
298 LLVM::Log10Op, LLVM::Log2Op, LLVM::SinOp, LLVM::SqrtOp>();
300 target.addLegalDialect<BuiltinDialect, LLVM::LLVMDialect>();
304 target.addLegalOp<vector::ExtractOp, vector::BroadcastOp>();
306 applyPartialConversion(getOperation(),
target, std::move(patterns))))
static bool isSizeOneVector(Type type)
static bool isSPIRVCompatibleFloatOrVec(Type type)
static void populateOCLExtSetOpPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit, StringRef opName)
static llvm::ManagedStatic< PassManagerOptions > options
Conversion from types to the LLVM IR dialect.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
NamedAttribute represents a combination of a name and an Attribute value.
Location getLoc()
The source location the operation was defined or derived from.
This provides public APIs that all operations should have.
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...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isFloat() const
Return true if this is an float type (with the specified width).
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
ArrayRef< NamedAttribute > getAttrs() const
FailureOr< LLVM::LLVMFuncOp > lookupOrCreateFn(OpBuilder &b, Operation *moduleOp, StringRef name, ArrayRef< Type > paramTypes={}, Type resultType={}, bool isVarArg=false, bool isReserved=false, SymbolTableCollection *symbolTables=nullptr)
Create a FuncOp with signature resultType(paramTypes) and name name`.
Include the generated interface declarations.
void populateMathToScalarOCLExtSetConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Populate the given list with patterns that convert from Math to OCL LLVM-SPV builtin calls.
void populateMathToXeVMConversionPatterns(RewritePatternSet &patterns, bool convertArith, PatternBenefit benefit=1)
Populate the given list with patterns that convert from Math to XeVM calls.
Convert math ops marked with fast (afn) to native OpenCL intrinsics.
const StringRef nativeFunc
ConvertNativeFuncPattern(MLIRContext *context, StringRef nativeFunc, PatternBenefit benefit=1)
std::string getMangledNativeFuncName(const ArrayRef< Type > operandTypes) const
LogicalResult matchAndRewrite(Op op, typename Op::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override
Rewriting that replaces SourceOp with a CallOp to f32Func or f64Func or f32ApproxFunc or f16Func or i...
Unrolls SourceOp to array/vector elements.