27#define GEN_PASS_DEF_ARITHTOAMDGPUCONVERSIONPASS
28#include "mlir/Conversion/Passes.h.inc"
35struct ArithToAMDGPUConversionPass final
37 using impl::ArithToAMDGPUConversionPassBase<
38 ArithToAMDGPUConversionPass>::ArithToAMDGPUConversionPassBase;
40 void runOnOperation()
override;
46 ROCDL::TargetInfo target;
47 ExtFOnFloat8RewritePattern(MLIRContext *ctx,
const ROCDL::TargetInfo &target,
48 PatternBenefit benefit)
49 : OpRewritePattern::OpRewritePattern(ctx, benefit), target(target) {}
51 LogicalResult matchAndRewrite(arith::ExtFOp op,
52 PatternRewriter &rewriter)
const override;
55struct TruncFToFloat8RewritePattern final :
OpRewritePattern<arith::TruncFOp> {
56 bool saturateFP8 =
false;
57 TruncFToFloat8RewritePattern(MLIRContext *ctx,
bool saturateFP8,
58 const ROCDL::TargetInfo &target,
59 PatternBenefit benefit)
60 : OpRewritePattern::OpRewritePattern(ctx, benefit),
61 saturateFP8(saturateFP8), target(target) {}
62 ROCDL::TargetInfo target;
64 LogicalResult matchAndRewrite(arith::TruncFOp op,
65 PatternRewriter &rewriter)
const override;
68struct TruncfToFloat16RewritePattern final
73 LogicalResult matchAndRewrite(arith::TruncFOp op,
74 PatternRewriter &rewriter)
const override;
77struct ScalingExtFRewritePattern final
81 LogicalResult matchAndRewrite(arith::ScalingExtFOp op,
82 PatternRewriter &rewriter)
const override;
85struct ScalingTruncFRewritePattern final
89 LogicalResult matchAndRewrite(arith::ScalingTruncFOp op,
90 PatternRewriter &rewriter)
const override;
96 return isa<Float8E4M3FNUZType, Float8E5M2FNUZType>(elementType);
98 return isa<Float8E4M3FNType, Float8E5M2Type>(elementType);
105 if (elementType.
isF32())
108 return arith::TruncFOp::create(rewriter, loc, desType, f32);
110 return arith::ExtFOp::create(rewriter, loc,
TypeRange{desType},
111 ValueRange{f32}, arith::ExtFOp::Properties{});
112 llvm_unreachable(
"The only 32-bit float type is f32");
116ExtFOnFloat8RewritePattern::matchAndRewrite(arith::ExtFOp op,
118 Type inType = op.getIn().getType();
119 auto inVecType = dyn_cast<VectorType>(inType);
121 if (inVecType.isScalable())
123 inType = inVecType.getElementType();
131 VectorType extResType = VectorType::get(2, rewriter.
getF32Type());
133 Value asFloat = amdgpu::ExtPackedFp8Op::create(
139 int64_t numElements = inVecType.getNumElements();
141 Value zero = arith::ConstantOp::create(
143 VectorType outType = cast<VectorType>(op.getOut().getType());
145 if (inVecType.getShape().empty()) {
147 rewriter.
createOrFold<vector::BroadcastOp>(loc, outType, zero);
150 Value scalarExt = arith::ExtFOp::create(
152 arith::ExtFOp::Properties{});
153 Value result = vector::InsertOp::create(rewriter, loc, scalarExt,
160 outType.getElementType());
163 if (inVecType.getRank() > 1) {
165 inVecType.getElementType());
166 in = vector::ShapeCastOp::create(rewriter, loc, inVecType, in);
169 for (
int64_t i = 0; i < numElements; i += 4) {
170 int64_t elemsThisOp = std::min(numElements, i + 4) - i;
171 Value inSlice = vector::ExtractStridedSliceOp::create(rewriter, loc, in, i,
173 for (
int64_t j = 0;
j < elemsThisOp;
j += 2) {
174 if (i +
j + 1 < numElements) {
175 Value asFloats = amdgpu::ExtPackedFp8Op::create(
176 rewriter, loc, extResType, inSlice,
j / 2);
177 Type desType = VectorType::get(2, outElemType);
179 result = vector::InsertStridedSliceOp::create(rewriter, loc, asType,
182 Value asFloat = amdgpu::ExtPackedFp8Op::create(
183 rewriter, loc, rewriter.
getF32Type(), inSlice,
j / 2 * 2);
185 result = vector::InsertOp::create(rewriter, loc, asType,
result, i +
j);
190 if (inVecType.getRank() != outType.getRank()) {
191 result = vector::ShapeCastOp::create(rewriter, loc, outType,
result);
203 return arith::ExtFOp::create(
205 arith::ExtFOp::Properties{});
207 return arith::TruncFOp::create(rewriter, loc, rewriter.
getF32Type(), value);
208 llvm_unreachable(
"The only 32-bit float type is f32");
219 const llvm::fltSemantics &sourceSem =
221 const llvm::fltSemantics &targetSem =
222 cast<FloatType>(outElemType).getFloatSemantics();
224 APFloat
min = APFloat::getLargest(targetSem,
true);
225 APFloat
max = APFloat::getLargest(targetSem,
false);
226 bool ignoredLosesInfo =
false;
230 (
void)
min.convert(sourceSem, APFloat::rmNearestTiesToEven, &ignoredLosesInfo);
231 (
void)
max.convert(sourceSem, APFloat::rmNearestTiesToEven, &ignoredLosesInfo);
237 rewriter, loc, sourceType,
238 APFloat::getInf(sourceSem,
false));
240 rewriter, loc, sourceType, APFloat::getInf(sourceSem,
true));
242 loc, arith::CmpFPredicate::OEQ, source, inf);
244 loc, arith::CmpFPredicate::OEQ, source, negInf);
246 loc, arith::CmpFPredicate::UNO, source, source);
247 Value isNonFinite = arith::OrIOp::create(
248 rewriter, loc, arith::OrIOp::create(rewriter, loc, isInf, isNegInf),
251 Value clampedBelow = arith::MaximumFOp::create(rewriter, loc, source, minCst);
253 arith::MinimumFOp::create(rewriter, loc, clampedBelow, maxCst);
255 arith::SelectOp::create(rewriter, loc, isNonFinite, source, clamped);
260TruncFToFloat8RewritePattern::matchAndRewrite(arith::TruncFOp op,
261 PatternRewriter &rewriter)
const {
263 if (op.getRoundingmodeAttr())
265 Type outType = op.getOut().getType();
266 auto outVecType = dyn_cast<VectorType>(outType);
268 if (outVecType.isScalable())
270 outType = outVecType.getElementType();
273 if (inType && inType.getWidth() <= 8 && saturateFP8)
280 Location loc = op.getLoc();
281 Value in = op.getIn();
284 in =
clampInput(rewriter, loc, outElemType, in);
285 auto inVectorTy = dyn_cast<VectorType>(in.
getType());
286 VectorType truncResType = VectorType::get(4, outElemType);
288 Value asFloat =
castToF32(in, loc, rewriter);
289 Value asF8s = amdgpu::PackedTrunc2xFp8Op::create(
290 rewriter, loc, truncResType, asFloat,
nullptr, 0,
292 Value
result = vector::ExtractOp::create(rewriter, loc, asF8s, 0);
297 int64_t numElements = outVecType.getNumElements();
298 Value zero = arith::ConstantOp::create(
299 rewriter, loc, outElemType, rewriter.
getFloatAttr(outElemType, 0.0));
300 if (outVecType.getShape().empty()) {
302 vector::ExtractOp::create(rewriter, loc, in, ArrayRef<int64_t>{});
305 arith::TruncFOp::create(rewriter, loc, outElemType, scalarIn);
306 Value
result = vector::InsertOp::create(rewriter, loc, scalarTrunc, zero,
307 ArrayRef<int64_t>{});
312 VectorType flatTy = VectorType::get(SmallVector<int64_t>{numElements},
313 outVecType.getElementType());
316 if (inVectorTy.getRank() > 1) {
317 inVectorTy = VectorType::get(SmallVector<int64_t>{numElements},
318 inVectorTy.getElementType());
319 in = vector::ShapeCastOp::create(rewriter, loc, inVectorTy, in);
322 for (int64_t i = 0; i < numElements; i += 4) {
323 int64_t elemsThisOp = std::min(numElements, i + 4) - i;
324 Value thisResult =
nullptr;
325 for (int64_t j = 0; j < elemsThisOp; j += 2) {
326 Value elemA = vector::ExtractOp::create(rewriter, loc, in, i + j);
327 Value asFloatA =
castToF32(elemA, loc, rewriter);
328 Value asFloatB =
nullptr;
329 if (j + 1 < elemsThisOp) {
330 Value elemB = vector::ExtractOp::create(rewriter, loc, in, i + j + 1);
331 asFloatB =
castToF32(elemB, loc, rewriter);
333 thisResult = amdgpu::PackedTrunc2xFp8Op::create(
334 rewriter, loc, truncResType, asFloatA, asFloatB, j / 2, thisResult);
337 thisResult = vector::ExtractStridedSliceOp::create(
338 rewriter, loc, thisResult, 0, elemsThisOp, 1);
339 result = vector::InsertStridedSliceOp::create(rewriter, loc, thisResult,
343 if (inVectorTy.getRank() != outVecType.getRank()) {
344 result = vector::ShapeCastOp::create(rewriter, loc, outVecType,
result);
351LogicalResult TruncfToFloat16RewritePattern::matchAndRewrite(
352 arith::TruncFOp op, PatternRewriter &rewriter)
const {
353 Type outType = op.getOut().getType();
355 auto outVecType = dyn_cast<VectorType>(outType);
357 if (outVecType.isScalable())
359 outType = outVecType.getElementType();
364 Location loc = op.getLoc();
365 Value in = op.getIn();
367 VectorType truncResType = VectorType::get(2, outElemType);
368 auto inVectorTy = dyn_cast<VectorType>(in.
getType());
372 auto sourceB = LLVM::PoisonOp::create(rewriter, loc, rewriter.
getF32Type());
374 ROCDL::CvtPkRtz::create(rewriter, loc, truncResType, in, sourceB);
375 Value
result = vector::ExtractOp::create(rewriter, loc, asF16s, 0);
379 int64_t numElements = outVecType.getNumElements();
381 loc, outElemType, rewriter.
getFloatAttr(outElemType, 0.0));
383 rewriter.
createOrFold<vector::BroadcastOp>(loc, outVecType, zero);
385 if (inVectorTy.getRank() > 1) {
386 inVectorTy = VectorType::get(SmallVector<int64_t>{numElements},
387 inVectorTy.getElementType());
388 in = vector::ShapeCastOp::create(rewriter, loc, inVectorTy, in);
393 for (int64_t i = 0; i < numElements; i += 2) {
394 int64_t elemsThisOp = std::min(numElements, i + 2) - i;
395 Value thisResult =
nullptr;
396 Value elemA = vector::ExtractOp::create(rewriter, loc, in, i);
397 Value elemB = LLVM::PoisonOp::create(rewriter, loc, rewriter.
getF32Type());
399 if (elemsThisOp == 2) {
400 elemB = vector::ExtractOp::create(rewriter, loc, in, i + 1);
404 ROCDL::CvtPkRtz::create(rewriter, loc, truncResType, elemA, elemB);
407 thisResult = vector::ExtractStridedSliceOp::create(
408 rewriter, loc, thisResult, 0, elemsThisOp, 1);
409 result = vector::InsertStridedSliceOp::create(rewriter, loc, thisResult,
413 if (inVectorTy.getRank() != outVecType.getRank()) {
414 result = vector::ShapeCastOp::create(rewriter, loc, outVecType,
result);
423 Value current = value;
426 .Case([¤t](vector::ShapeCastOp op) {
427 current = op.getSource();
430 .Case([¤t](vector::BroadcastOp op) {
431 current = op.getSource();
444ScalingExtFRewritePattern::matchAndRewrite(arith::ScalingExtFOp op,
445 PatternRewriter &rewriter)
const {
446 Location loc = op.getLoc();
447 constexpr int64_t opOutWidth = 2;
449 Value in = op.getIn();
450 Value scale = op.getScale();
451 Value out = op.getOut();
460 VectorType outVecType = dyn_cast<VectorType>(out.
getType());
461 VectorType scaleVecType = dyn_cast<VectorType>(scale.
getType());
463 if (outVecType && outVecType.isScalable())
466 if (isa<RankedTensorType>(out.
getType()) ||
467 isa<RankedTensorType>(in.
getType()) ||
468 isa<RankedTensorType>(scale.
getType()))
472 scaleVecType ? VectorType::get(scaleVecType.getShape(), f32) : f32;
475 arith::ExtFOp::create(rewriter, loc,
TypeRange{scaleF32Type},
476 ValueRange{scale}, arith::ExtFOp::Properties{});
478 scale = arith::TruncFOp::create(rewriter, loc, scaleF32Type, scale);
480 VectorType extScaleResultType = VectorType::get(opOutWidth, outType);
483 Value inCast = vector::BroadcastOp::create(rewriter, loc,
484 VectorType::get(1, inType), in);
486 Value scaleExt = amdgpu::ScaledExtPackedOp::create(
487 rewriter, loc, extScaleResultType, inCast, scale, 0);
492 VectorType inVecType = cast<VectorType>(in.
getType());
494 VectorType origScaleVecType = dyn_cast<VectorType>(origScale.
getType());
496 ArrayRef<int64_t> inShape = inVecType.getShape();
497 SmallVector<int64_t> originalScaleShape;
498 if (origScaleVecType)
499 llvm::append_range(originalScaleShape, origScaleVecType.getShape());
501 originalScaleShape.insert(originalScaleShape.end(),
502 inShape.size() - originalScaleShape.size(), 1);
506 "failed to derive block size from broadcast or splat operation");
508 SmallVector<int64_t> ratio =
509 maybeRatio.value_or(SmallVector<int64_t>(inShape.size(), 1));
513 Value zero = arith::ConstantOp::create(rewriter, loc, outType,
516 rewriter.
createOrFold<vector::BroadcastOp>(loc, outVecType, zero);
518 for (SmallVector<int64_t> offsets : StaticTileOffsetRange(inShape, ratio)) {
519 SmallVector<int64_t> strides(offsets.size(), 1);
520 Value block = vector::ExtractStridedSliceOp::create(
521 rewriter, loc, in, offsets, ratio, strides);
522 VectorType block1DType = VectorType::get(blockSize, inType);
524 vector::ShapeCastOp::create(rewriter, loc, block1DType, block);
526 vector::ExtractOp::create(rewriter, loc, scale, offsets);
528 VectorType blockResultType = VectorType::get(blockSize, outType);
530 rewriter.
createOrFold<vector::BroadcastOp>(loc, blockResultType, zero);
532 for (int64_t i = 0, inSliceWidth = std::min(opInWidth, blockSize - i);
534 i += inSliceWidth, inSliceWidth = std::min(opInWidth, blockSize - i)) {
535 Value inSlice = vector::ExtractStridedSliceOp::create(
536 rewriter, loc, block1D, i, inSliceWidth, 1);
538 outSliceWidth = std::min(opOutWidth, inSliceWidth - j);
539 j < inSliceWidth; j += outSliceWidth,
540 outSliceWidth = std::min(opOutWidth, inSliceWidth - j)) {
542 Value scaleExt = amdgpu::ScaledExtPackedOp::create(
543 rewriter, loc, extScaleResultType, inSlice, uniformScale,
545 if (outSliceWidth < opOutWidth) {
546 scaleExt = vector::ExtractStridedSliceOp::create(
547 rewriter, loc, scaleExt, 0, outSliceWidth, 1);
549 blockResult = vector::InsertStridedSliceOp::create(
550 rewriter, loc, scaleExt, blockResult, i + j, 1);
554 VectorType resultType = VectorType::get(ratio, outType);
556 vector::ShapeCastOp::create(rewriter, loc, resultType, blockResult);
557 result = vector::InsertStridedSliceOp::create(rewriter, loc, cast,
result,
567ScalingTruncFRewritePattern::matchAndRewrite(arith::ScalingTruncFOp op,
568 PatternRewriter &rewriter)
const {
569 Location loc = op.getLoc();
570 constexpr int64_t opInWidth = 2;
572 Value in = op.getIn();
573 Value scale = op.getScale();
574 Value out = op.getOut();
581 VectorType outVecType = dyn_cast<VectorType>(out.
getType());
582 VectorType scaleVecType = dyn_cast<VectorType>(scale.
getType());
583 if (outVecType && outVecType.isScalable())
586 if (isa<RankedTensorType>(out.
getType()) ||
587 isa<RankedTensorType>(in.
getType()) ||
588 isa<RankedTensorType>(scale.
getType()))
592 scaleVecType ? VectorType::get(scaleVecType.getShape(), f32) : f32;
595 arith::ExtFOp::create(rewriter, loc,
TypeRange{scaleF32Type},
596 ValueRange{scale}, arith::ExtFOp::Properties{});
598 scale = arith::TruncFOp::create(rewriter, loc, scaleF32Type, scale);
600 Value zero = arith::ConstantOp::create(rewriter, loc, outType,
603 VectorType truncScaleResultType = VectorType::get(opOutWidth, outType);
606 Type inVecType = VectorType::get(1, inType);
607 Value inCast = vector::BroadcastOp::create(rewriter, loc, inVecType, in);
609 Value scaleTrunc = amdgpu::PackedScaledTruncOp::create(
610 rewriter, loc, truncScaleResultType, inCast, scale, 0,
617 VectorType inVecType = cast<VectorType>(in.
getType());
619 VectorType origScaleVecType = dyn_cast<VectorType>(origScale.
getType());
621 ArrayRef<int64_t> inShape = inVecType.getShape();
622 SmallVector<int64_t> scaleShape;
623 if (origScaleVecType)
624 llvm::append_range(scaleShape, origScaleVecType.getShape());
626 scaleShape.insert(scaleShape.end(), inShape.size() - scaleShape.size(), 1);
630 "failed to derive block size from broadcast or splat operation");
632 SmallVector<int64_t> ratio =
633 maybeRatio.value_or(SmallVector<int64_t>(inShape.size(), 1));
638 rewriter.
createOrFold<vector::BroadcastOp>(loc, outVecType, zero);
640 for (SmallVector<int64_t> offsets : StaticTileOffsetRange(inShape, ratio)) {
641 SmallVector<int64_t> strides(offsets.size(), 1);
642 Value block = vector::ExtractStridedSliceOp::create(
643 rewriter, loc, in, offsets, ratio, strides);
644 VectorType block1DType = VectorType::get(blockSize, inType);
646 vector::ShapeCastOp::create(rewriter, loc, block1DType, block);
648 vector::ExtractOp::create(rewriter, loc, scale, offsets);
650 VectorType blockResultType = VectorType::get(blockSize, outType);
652 rewriter.
createOrFold<vector::BroadcastOp>(loc, blockResultType, zero);
654 for (int64_t i = 0, outSliceWidth = std::min(opOutWidth, blockSize - i);
655 i < blockSize; i += outSliceWidth,
656 outSliceWidth = std::min(opOutWidth, blockSize - i)) {
659 if (outSliceWidth <= opInWidth) {
660 Value
slice = vector::ExtractStridedSliceOp::create(
661 rewriter, loc, block1D, i, outSliceWidth, 1);
663 scaleTrunc = amdgpu::PackedScaledTruncOp::create(
664 rewriter, loc, truncScaleResultType,
slice, uniformScale, 0,
667 scaleTrunc = vector::BroadcastOp::create(rewriter, loc,
668 truncScaleResultType, zero);
670 inSliceWidth = std::min(opInWidth, outSliceWidth - j);
671 j < outSliceWidth; j += opInWidth,
672 inSliceWidth = std::min(opInWidth, outSliceWidth - j)) {
673 Value
slice = vector::ExtractStridedSliceOp::create(
674 rewriter, loc, block1D, i + j, inSliceWidth, 1);
675 scaleTrunc = amdgpu::PackedScaledTruncOp::create(
676 rewriter, loc, truncScaleResultType,
slice, uniformScale,
677 j / opInWidth, scaleTrunc);
680 if (outSliceWidth != opOutWidth) {
681 scaleTrunc = vector::ExtractStridedSliceOp::create(
682 rewriter, loc, scaleTrunc, 0, outSliceWidth, 1);
684 blockResult = vector::InsertStridedSliceOp::create(
685 rewriter, loc, scaleTrunc, blockResult, i, 1);
688 VectorType resultType = VectorType::get(ratio, outType);
690 vector::ShapeCastOp::create(rewriter, loc, resultType, blockResult);
691 result = vector::InsertStridedSliceOp::create(rewriter, loc, cast,
result,
702 bool saturateFP8Truncf,
bool allowPackedF16Rtz,
bool supportsScaledExtTrunc,
705 if (convertFP8Arithmetic) {
708 patterns.
add<TruncFToFloat8RewritePattern>(
711 if (allowPackedF16Rtz)
712 patterns.
add<TruncfToFloat16RewritePattern>(patterns.
getContext(), benefit);
714 if (supportsScaledExtTrunc) {
715 patterns.
add<ScalingExtFRewritePattern>(patterns.
getContext(), benefit);
716 patterns.
add<ScalingTruncFRewritePattern>(patterns.
getContext(), benefit);
720void ArithToAMDGPUConversionPass::runOnOperation() {
726 [&] {
return emitError(UnknownLoc::get(ctx)); });
727 if (failed(targetInfo))
728 return signalPassFailure();
730 bool convertFP8Arithmetic =
731 targetInfo->has(llvm::AMDGPU::FEAT_FP8_CONVERSION_INSTS);
732 bool supportsScaledExtTrunc =
733 targetInfo->has(llvm::AMDGPU::FEAT_GFX950_INSTS);
735 patterns, convertFP8Arithmetic, saturateFP8Truncf, allowPackedF16Rtz,
736 supportsScaledExtTrunc, *targetInfo);
738 return signalPassFailure();
static Value getOriginalVectorValue(Value value)
Get the broadcasted / splatted value for a chain of ops.
static Value castF32To(Type desType, Value f32, Location loc, PatternRewriter &rewriter)
static Value castToF32(Value value, Location loc, PatternRewriter &rewriter)
static bool isSupportedF8(Type elementType, const ROCDL::TargetInfo &target)
static Value clampInput(PatternRewriter &rewriter, Location loc, Type outElemType, Value source)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static SmallVector< Value > slice(OpBuilder &b, Location loc, Value value, VectorType nativeType)
FloatAttr getFloatAttr(Type type, double value)
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.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
Operation is the basic unit of execution within MLIR.
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...
Describes the AMDGPU target a lowering is producing code for: the triple's subarch (which identifies ...
static FailureOr< TargetInfo > get(StringRef arch, unsigned waveSize=0, function_ref< InFlightDiagnostic()> emitError=nullptr)
Resolves a target description.
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.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
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.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
StringRef resolveArchOption(StringRef arch, StringRef deprecatedAlias)
Returns the target architecture that a pass should parse, given its arch option and the value of the ...
void populateArithToAMDGPUConversionPatterns(RewritePatternSet &patterns, bool convertFP8Arithmetic, bool saturateFP8Truncf, bool allowPackedF16Rtz, bool supportsScaledExtTrunc, const ROCDL::TargetInfo &target, PatternBenefit benefit=1)
Add patterns for rewriting arith.extf and arith.truncf on FP8 types to wrappers around AMDGPU–specifi...
Include the generated interface declarations.
Value createScalarOrSplatConstant(OpBuilder &builder, Location loc, Type type, const APInt &value)
Create a constant of type type at location loc whose value is value (an APInt or APFloat whose type m...
LogicalResult applyPatternsGreedily(Region ®ion, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
int64_t computeProduct(ArrayRef< int64_t > basis)
Self-explicit.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
std::optional< SmallVector< int64_t > > computeShapeRatio(ArrayRef< int64_t > shape, ArrayRef< int64_t > subShape)
Return the multi-dimensional integral ratio of subShape to the trailing dimensions of shape.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.