MLIR 23.0.0git
IndexIntrinsicsOpLowering.h
Go to the documentation of this file.
1//===- IndexIntrinsicsOpLowering.h - GPU Index Op Lowering ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#ifndef MLIR_CONVERSION_GPUCOMMON_INDEXINTRINSICSOPLOWERING_H_
9#define MLIR_CONVERSION_GPUCOMMON_INDEXINTRINSICSOPLOWERING_H_
10
15
16namespace mlir {
17namespace gpu {
18namespace index_lowering {
19// Alias so existing call sites don't need updating.
20using IndexKind = gpu::DimensionKind;
21
22enum class IntrType : uint32_t {
23 None = 0,
24 Id = 1,
25 Dim = 2,
26};
27
28/// Returns a ConstantRangeAttr for a GPU index op, or nullptr if no bounds
29/// are found. `bitWidth` controls the width of the returned range.
30/// Checks the provided upper_bound from the op (highest priority), inherent
31/// attrs on enclosing `gpu.func`s, and discardable attributes on other
32/// enclosing function ops (lowest priority). However, in the case where
33/// a dimension is known to have a constant value, returns a range indicating
34/// that value.
35LLVM::ConstantRangeAttr getIndexOpRange(Operation *op, gpu::Dimension dim,
36 std::optional<uint32_t> opUpperBound,
37 IndexKind indexKind, IntrType intrType,
38 unsigned bitWidth);
39
40// Rewriting that replaces Op with XOp, YOp, or ZOp depending on the dimension
41// that Op operates on. Op is assumed to return an `index` value and
42// XOp, YOp and ZOp are assumed to return an `llvm.i32` value. Depending on
43// `indexBitwidth`, sign-extend or truncate the resulting value to match the
44// bitwidth expected by the consumers of the value.
45template <typename Op, typename XOp, typename YOp, typename ZOp>
47private:
48 unsigned indexBitwidth;
49 IndexKind indexKind;
50 IntrType intrType;
51
52public:
53 explicit OpLowering(const LLVMTypeConverter &typeConverter,
54 PatternBenefit benefit = 1)
55 : ConvertOpToLLVMPattern<Op>(typeConverter, benefit),
56 indexBitwidth(typeConverter.getIndexTypeBitwidth()),
57 indexKind(IndexKind::Other), intrType(IntrType::None) {}
58
59 explicit OpLowering(const LLVMTypeConverter &typeConverter,
60 IndexKind indexKind, IntrType intrType,
61 PatternBenefit benefit = 1)
62 : ConvertOpToLLVMPattern<Op>(typeConverter, benefit),
63 indexBitwidth(typeConverter.getIndexTypeBitwidth()),
64 indexKind(indexKind), intrType(intrType) {}
65
66 // Convert the kernel arguments to an LLVM type, preserve the rest.
67 LogicalResult
68 matchAndRewrite(Op op, typename Op::Adaptor adaptor,
69 ConversionPatternRewriter &rewriter) const override {
70 Location loc = op->getLoc();
71 MLIRContext *context = rewriter.getContext();
72 Operation *newOp;
73 switch (op.getDimension()) {
74 case gpu::Dimension::x:
75 newOp = XOp::create(rewriter, loc, IntegerType::get(context, 32));
76 break;
77 case gpu::Dimension::y:
78 newOp = YOp::create(rewriter, loc, IntegerType::get(context, 32));
79 break;
80 case gpu::Dimension::z:
81 newOp = ZOp::create(rewriter, loc, IntegerType::get(context, 32));
82 break;
83 }
84
85 std::optional<uint32_t> opBound;
86 if (auto bound = op.getUpperBound())
87 opBound = static_cast<uint32_t>(bound->getZExtValue());
88 if (auto range = getIndexOpRange(op, op.getDimension(), opBound, indexKind,
89 intrType, /*bitWidth=*/32))
90 newOp->setAttr("range", range);
91
92 if (indexBitwidth > 32) {
93 newOp = LLVM::SExtOp::create(rewriter, loc,
94 IntegerType::get(context, indexBitwidth),
95 newOp->getResult(0));
96 } else if (indexBitwidth < 32) {
97 newOp = LLVM::TruncOp::create(rewriter, loc,
98 IntegerType::get(context, indexBitwidth),
99 newOp->getResult(0));
100 }
101
102 rewriter.replaceOp(op, newOp->getResults());
103 return success();
104 }
105};
106} // namespace index_lowering
107} // namespace gpu
108} // namespace mlir
109
110#endif // MLIR_CONVERSION_GPUCOMMON_INDEXINTRINSICSOPLOWERING_H_
return success()
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
Definition Pattern.h:233
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...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
Location getLoc()
The source location the operation was defined or derived from.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:433
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
Definition Operation.h:608
result_range getResults()
Definition Operation.h:441
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
LLVM::ConstantRangeAttr getIndexOpRange(Operation *op, gpu::Dimension dim, std::optional< uint32_t > opUpperBound, IndexKind indexKind, IntrType intrType, unsigned bitWidth)
Returns a ConstantRangeAttr for a GPU index op, or nullptr if no bounds are found.
Include the generated interface declarations.
OpLowering(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
LogicalResult matchAndRewrite(Op op, typename Op::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override
OpLowering(const LLVMTypeConverter &typeConverter, IndexKind indexKind, IntrType intrType, PatternBenefit benefit=1)