19#define DEBUG_TYPE "complex-to-spirv-pattern"
31 return spirv::ConstantOp::create(
32 builder, loc, type, builder.
getFloatAttr(cast<FloatType>(type), value));
35struct ConstantOpPattern final : OpConversionPattern<complex::ConstantOp> {
39 matchAndRewrite(complex::ConstantOp constOp, OpAdaptor adaptor,
40 ConversionPatternRewriter &rewriter)
const override {
42 getTypeConverter()->convertType<ShapedType>(constOp.getType());
44 return rewriter.notifyMatchFailure(constOp,
45 "unable to convert result type");
47 rewriter.replaceOpWithNewOp<spirv::ConstantOp>(
54struct CreateOpPattern final : OpConversionPattern<complex::CreateOp> {
58 matchAndRewrite(complex::CreateOp createOp, OpAdaptor adaptor,
59 ConversionPatternRewriter &rewriter)
const override {
60 Type spirvType = getTypeConverter()->convertType(createOp.getType());
62 return rewriter.notifyMatchFailure(createOp,
63 "unable to convert result type");
65 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
66 createOp, spirvType, adaptor.getOperands());
71struct ReOpPattern final : OpConversionPattern<complex::ReOp> {
75 matchAndRewrite(complex::ReOp reOp, OpAdaptor adaptor,
76 ConversionPatternRewriter &rewriter)
const override {
77 Type spirvType = getTypeConverter()->convertType(reOp.getType());
79 return rewriter.notifyMatchFailure(reOp,
"unable to convert result type");
81 rewriter.replaceOpWithNewOp<spirv::CompositeExtractOp>(
87struct ImOpPattern final : OpConversionPattern<complex::ImOp> {
91 matchAndRewrite(complex::ImOp imOp, OpAdaptor adaptor,
92 ConversionPatternRewriter &rewriter)
const override {
93 Type spirvType = getTypeConverter()->convertType(imOp.getType());
95 return rewriter.notifyMatchFailure(imOp,
"unable to convert result type");
97 rewriter.replaceOpWithNewOp<spirv::CompositeExtractOp>(
103template <
typename ComplexOp,
typename SPIRVOp>
104struct ElementwiseBinaryOpPattern final : OpConversionPattern<ComplexOp> {
105 using OpConversionPattern<ComplexOp>::OpConversionPattern;
106 using OpAdaptor =
typename ComplexOp::Adaptor;
109 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
110 ConversionPatternRewriter &rewriter)
const override {
112 this->getTypeConverter()->convertType(op.getResult().getType());
114 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
117 Value lhs = adaptor.getLhs();
118 Value rhs = adaptor.getRhs();
120 Value lhsRe = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
121 Value lhsIm = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
122 Value rhsRe = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
123 Value rhsIm = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
125 Value resultRe = SPIRVOp::create(rewriter, loc, lhsRe, rhsRe);
126 Value resultIm = SPIRVOp::create(rewriter, loc, lhsIm, rhsIm);
128 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
134template <
typename ComplexOp,
typename SPIRVCompareOp,
typename SPIRVCombinerOp>
135struct ComparisonOpPattern final : OpConversionPattern<ComplexOp> {
136 using OpConversionPattern<ComplexOp>::OpConversionPattern;
137 using OpAdaptor =
typename ComplexOp::Adaptor;
140 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
141 ConversionPatternRewriter &rewriter)
const override {
143 this->getTypeConverter()->convertType(op.getResult().getType());
145 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
148 Value lhs = adaptor.getLhs();
149 Value rhs = adaptor.getRhs();
151 Value lhsRe = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
152 Value lhsIm = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
153 Value rhsRe = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
154 Value rhsIm = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
156 Value cmpRe = SPIRVCompareOp::create(rewriter, loc, lhsRe, rhsRe);
157 Value cmpIm = SPIRVCompareOp::create(rewriter, loc, lhsIm, rhsIm);
159 rewriter.replaceOpWithNewOp<SPIRVCombinerOp>(op, spirvType, cmpRe, cmpIm);
164struct MulOpPattern final : OpConversionPattern<complex::MulOp> {
168 matchAndRewrite(complex::MulOp op, OpAdaptor adaptor,
169 ConversionPatternRewriter &rewriter)
const override {
170 Type spirvType = getTypeConverter()->convertType(op.getResult().getType());
172 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
175 Value lhs = adaptor.getLhs();
176 Value rhs = adaptor.getRhs();
178 Value a = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
179 Value b = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
180 Value c = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
181 Value d = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
183 Value ac = spirv::FMulOp::create(rewriter, loc, a, c);
184 Value bd = spirv::FMulOp::create(rewriter, loc,
b, d);
185 Value ad = spirv::FMulOp::create(rewriter, loc, a, d);
186 Value bc = spirv::FMulOp::create(rewriter, loc,
b, c);
187 Value resultRe = spirv::FSubOp::create(rewriter, loc, ac, bd);
188 Value resultIm = spirv::FAddOp::create(rewriter, loc, ad, bc);
190 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
196template <
typename SqrtOp>
197struct AbsOpPattern final : OpConversionPattern<complex::AbsOp> {
198 using OpConversionPattern<complex::AbsOp>::OpConversionPattern;
201 matchAndRewrite(complex::AbsOp op, OpAdaptor adaptor,
202 ConversionPatternRewriter &rewriter)
const override {
204 this->getTypeConverter()->convertType(op.getResult().getType());
206 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
209 Value complexVal = adaptor.getComplex();
212 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
214 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
216 Value reSq = spirv::FMulOp::create(rewriter, loc, re, re);
217 Value imSq = spirv::FMulOp::create(rewriter, loc, im, im);
218 Value sum = spirv::FAddOp::create(rewriter, loc, reSq, imSq);
220 rewriter.replaceOpWithNewOp<SqrtOp>(op, sum);
225template <
typename ComplexOp,
bool NegateReal>
226struct NegationOpPattern final : OpConversionPattern<ComplexOp> {
227 using OpConversionPattern<ComplexOp>::OpConversionPattern;
228 using OpAdaptor =
typename ComplexOp::Adaptor;
231 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
232 ConversionPatternRewriter &rewriter)
const override {
234 this->getTypeConverter()->convertType(op.getResult().getType());
236 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
239 Value complexVal = adaptor.getComplex();
242 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
244 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
247 NegateReal ? spirv::FNegateOp::create(rewriter, loc, re) : re;
248 Value resultIm = spirv::FNegateOp::create(rewriter, loc, im);
250 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
256struct DivOpPattern final : OpConversionPattern<complex::DivOp> {
260 matchAndRewrite(complex::DivOp op, OpAdaptor adaptor,
261 ConversionPatternRewriter &rewriter)
const override {
262 Type spirvType = getTypeConverter()->convertType(op.getResult().getType());
264 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
267 Value lhs = adaptor.getLhs();
268 Value rhs = adaptor.getRhs();
270 Value a = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
271 Value b = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
272 Value c = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
273 Value d = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
275 Value ac = spirv::FMulOp::create(rewriter, loc, a, c);
276 Value bd = spirv::FMulOp::create(rewriter, loc,
b, d);
277 Value bc = spirv::FMulOp::create(rewriter, loc,
b, c);
278 Value ad = spirv::FMulOp::create(rewriter, loc, a, d);
279 Value cc = spirv::FMulOp::create(rewriter, loc, c, c);
280 Value dd = spirv::FMulOp::create(rewriter, loc, d, d);
281 Value denom = spirv::FAddOp::create(rewriter, loc, cc, dd);
282 Value numRe = spirv::FAddOp::create(rewriter, loc, ac, bd);
283 Value numIm = spirv::FSubOp::create(rewriter, loc, bc, ad);
284 Value resultRe = spirv::FDivOp::create(rewriter, loc, numRe, denom);
285 Value resultIm = spirv::FDivOp::create(rewriter, loc, numIm, denom);
287 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
293template <
typename Atan2Op>
294struct AngleOpPattern final : OpConversionPattern<complex::AngleOp> {
295 using OpConversionPattern<complex::AngleOp>::OpConversionPattern;
298 matchAndRewrite(complex::AngleOp op, OpAdaptor adaptor,
299 ConversionPatternRewriter &rewriter)
const override {
301 this->getTypeConverter()->convertType(op.getResult().getType());
303 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
306 Value complexVal = adaptor.getComplex();
309 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
311 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
313 rewriter.replaceOpWithNewOp<Atan2Op>(op, im, re);
321template <
typename SqrtOp,
typename FAbsOp,
typename FMaxOp,
typename FMinOp>
322struct SignOpPattern final : OpConversionPattern<complex::SignOp> {
323 using OpConversionPattern<complex::SignOp>::OpConversionPattern;
326 matchAndRewrite(complex::SignOp op, OpAdaptor adaptor,
327 ConversionPatternRewriter &rewriter)
const override {
329 this->getTypeConverter()->convertType(op.getResult().getType());
331 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
334 Value complexVal = adaptor.getComplex();
337 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
339 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
341 Value absRe = FAbsOp::create(rewriter, loc, re);
342 Value absIm = FAbsOp::create(rewriter, loc, im);
343 Value max = FMaxOp::create(rewriter, loc, absRe, absIm);
344 Value min = FMinOp::create(rewriter, loc, absRe, absIm);
345 Value ratio = spirv::FDivOp::create(rewriter, loc,
min,
max);
346 Value ratioSq = spirv::FMulOp::create(rewriter, loc, ratio, ratio);
348 Value ratioSqPlusOne = spirv::FAddOp::create(rewriter, loc, ratioSq, one);
349 Value sqrt = SqrtOp::create(rewriter, loc, ratioSqPlusOne);
350 Value abs = spirv::FMulOp::create(rewriter, loc,
max, sqrt);
352 Value signRe = spirv::FDivOp::create(rewriter, loc, re, abs);
353 Value signIm = spirv::FDivOp::create(rewriter, loc, im, abs);
356 Value reIsZero = spirv::FOrdEqualOp::create(rewriter, loc, re, zero);
357 Value imIsZero = spirv::FOrdEqualOp::create(rewriter, loc, im, zero);
359 spirv::LogicalAndOp::create(rewriter, loc, reIsZero, imIsZero);
364 Value resultRe = spirv::SelectOp::create(rewriter, loc, isZero, re, signRe);
365 Value resultIm = spirv::SelectOp::create(rewriter, loc, isZero, im, signIm);
367 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
383 .
add<ConstantOpPattern, CreateOpPattern, ReOpPattern, ImOpPattern,
384 ElementwiseBinaryOpPattern<complex::AddOp, spirv::FAddOp>,
385 ElementwiseBinaryOpPattern<complex::SubOp, spirv::FSubOp>,
386 ComparisonOpPattern<complex::EqualOp, spirv::FOrdEqualOp,
387 spirv::LogicalAndOp>,
388 ComparisonOpPattern<complex::NotEqualOp, spirv::FUnordNotEqualOp,
390 MulOpPattern, DivOpPattern,
391 NegationOpPattern<complex::NegOp,
true>,
392 NegationOpPattern<complex::ConjOp,
false>,
393 AbsOpPattern<spirv::GLSqrtOp>, AbsOpPattern<spirv::CLSqrtOp>,
394 AngleOpPattern<spirv::GLAtan2Op>, AngleOpPattern<spirv::CLAtan2Op>,
395 SignOpPattern<spirv::GLSqrtOp, spirv::GLFAbsOp, spirv::GLFMaxOp,
397 SignOpPattern<spirv::CLSqrtOp, spirv::CLFAbsOp, spirv::CLFMaxOp,
398 spirv::CLFMinOp>>(typeConverter, context);
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value createFPConstant(Location loc, Type srcType, Type dstType, PatternRewriter &rewriter, double value)
Creates llvm.mlir.constant with a floating-point scalar or vector value.
FloatAttr getFloatAttr(Type type, double value)
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
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.
This class helps build Operations.
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.
Type conversion from builtin types to SPIR-V types for shader interface.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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.
Include the generated interface declarations.
void populateComplexToSPIRVPatterns(const SPIRVTypeConverter &typeConverter, RewritePatternSet &patterns)
Appends to a pattern list additional patterns for translating Complex ops to SPIR-V ops.