19#define DEBUG_TYPE "complex-to-spirv-pattern"
31 return spirv::ConstantOp::create(
32 builder, loc, type, builder.
getFloatAttr(cast<FloatType>(type), value));
37template <
typename SqrtOp,
typename FAbsOp,
typename FMaxOp,
typename FMinOp>
39 Value absRe = FAbsOp::create(builder, loc, re);
40 Value absIm = FAbsOp::create(builder, loc, im);
41 Value max = FMaxOp::create(builder, loc, absRe, absIm);
42 Value min = FMinOp::create(builder, loc, absRe, absIm);
43 Value ratio = spirv::FDivOp::create(builder, loc,
min,
max);
44 Value ratioSq = spirv::FMulOp::create(builder, loc, ratio, ratio);
46 Value ratioSqPlusOne = spirv::FAddOp::create(builder, loc, ratioSq, one);
47 Value sqrt = SqrtOp::create(builder, loc, ratioSqPlusOne);
48 return spirv::FMulOp::create(builder, loc,
max, sqrt);
54 Value reIsZero = spirv::FOrdEqualOp::create(builder, loc, re, zero);
55 Value imIsZero = spirv::FOrdEqualOp::create(builder, loc, im, zero);
56 return spirv::LogicalAndOp::create(builder, loc, reIsZero, imIsZero);
59struct ConstantOpPattern final : OpConversionPattern<complex::ConstantOp> {
63 matchAndRewrite(complex::ConstantOp constOp, OpAdaptor adaptor,
64 ConversionPatternRewriter &rewriter)
const override {
66 getTypeConverter()->convertType<ShapedType>(constOp.getType());
68 return rewriter.notifyMatchFailure(constOp,
69 "unable to convert result type");
71 rewriter.replaceOpWithNewOp<spirv::ConstantOp>(
78struct CreateOpPattern final : OpConversionPattern<complex::CreateOp> {
82 matchAndRewrite(complex::CreateOp createOp, OpAdaptor adaptor,
83 ConversionPatternRewriter &rewriter)
const override {
84 Type spirvType = getTypeConverter()->convertType(createOp.getType());
86 return rewriter.notifyMatchFailure(createOp,
87 "unable to convert result type");
89 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
90 createOp, spirvType, adaptor.getOperands());
95struct ReOpPattern final : OpConversionPattern<complex::ReOp> {
99 matchAndRewrite(complex::ReOp reOp, OpAdaptor adaptor,
100 ConversionPatternRewriter &rewriter)
const override {
101 Type spirvType = getTypeConverter()->convertType(reOp.getType());
103 return rewriter.notifyMatchFailure(reOp,
"unable to convert result type");
105 rewriter.replaceOpWithNewOp<spirv::CompositeExtractOp>(
111struct ImOpPattern final : OpConversionPattern<complex::ImOp> {
115 matchAndRewrite(complex::ImOp imOp, OpAdaptor adaptor,
116 ConversionPatternRewriter &rewriter)
const override {
117 Type spirvType = getTypeConverter()->convertType(imOp.getType());
119 return rewriter.notifyMatchFailure(imOp,
"unable to convert result type");
121 rewriter.replaceOpWithNewOp<spirv::CompositeExtractOp>(
127template <
typename ComplexOp,
typename SPIRVOp>
128struct ElementwiseBinaryOpPattern final : OpConversionPattern<ComplexOp> {
129 using OpConversionPattern<ComplexOp>::OpConversionPattern;
130 using OpAdaptor =
typename ComplexOp::Adaptor;
133 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
134 ConversionPatternRewriter &rewriter)
const override {
136 this->getTypeConverter()->convertType(op.getResult().getType());
138 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
141 Value lhs = adaptor.getLhs();
142 Value rhs = adaptor.getRhs();
144 Value lhsRe = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
145 Value lhsIm = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
146 Value rhsRe = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
147 Value rhsIm = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
149 Value resultRe = SPIRVOp::create(rewriter, loc, lhsRe, rhsRe);
150 Value resultIm = SPIRVOp::create(rewriter, loc, lhsIm, rhsIm);
152 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
158template <
typename ComplexOp,
typename SPIRVCompareOp,
typename SPIRVCombinerOp>
159struct ComparisonOpPattern final : OpConversionPattern<ComplexOp> {
160 using OpConversionPattern<ComplexOp>::OpConversionPattern;
161 using OpAdaptor =
typename ComplexOp::Adaptor;
164 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
165 ConversionPatternRewriter &rewriter)
const override {
167 this->getTypeConverter()->convertType(op.getResult().getType());
169 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
172 Value lhs = adaptor.getLhs();
173 Value rhs = adaptor.getRhs();
175 Value lhsRe = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
176 Value lhsIm = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
177 Value rhsRe = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
178 Value rhsIm = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
180 Value cmpRe = SPIRVCompareOp::create(rewriter, loc, lhsRe, rhsRe);
181 Value cmpIm = SPIRVCompareOp::create(rewriter, loc, lhsIm, rhsIm);
183 rewriter.replaceOpWithNewOp<SPIRVCombinerOp>(op, spirvType, cmpRe, cmpIm);
188struct MulOpPattern final : OpConversionPattern<complex::MulOp> {
192 matchAndRewrite(complex::MulOp op, OpAdaptor adaptor,
193 ConversionPatternRewriter &rewriter)
const override {
194 Type spirvType = getTypeConverter()->convertType(op.getResult().getType());
196 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
199 Value lhs = adaptor.getLhs();
200 Value rhs = adaptor.getRhs();
202 Value a = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
203 Value b = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
204 Value c = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
205 Value d = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
207 Value ac = spirv::FMulOp::create(rewriter, loc, a, c);
208 Value bd = spirv::FMulOp::create(rewriter, loc,
b, d);
209 Value ad = spirv::FMulOp::create(rewriter, loc, a, d);
210 Value bc = spirv::FMulOp::create(rewriter, loc,
b, c);
211 Value resultRe = spirv::FSubOp::create(rewriter, loc, ac, bd);
212 Value resultIm = spirv::FAddOp::create(rewriter, loc, ad, bc);
214 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
220template <
typename SqrtOp>
221struct AbsOpPattern final : OpConversionPattern<complex::AbsOp> {
222 using OpConversionPattern<complex::AbsOp>::OpConversionPattern;
225 matchAndRewrite(complex::AbsOp op, OpAdaptor adaptor,
226 ConversionPatternRewriter &rewriter)
const override {
228 this->getTypeConverter()->convertType(op.getResult().getType());
230 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
233 Value complexVal = adaptor.getComplex();
236 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
238 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
240 Value reSq = spirv::FMulOp::create(rewriter, loc, re, re);
241 Value imSq = spirv::FMulOp::create(rewriter, loc, im, im);
242 Value sum = spirv::FAddOp::create(rewriter, loc, reSq, imSq);
244 rewriter.replaceOpWithNewOp<SqrtOp>(op, sum);
249template <
typename ComplexOp,
bool NegateReal>
250struct NegationOpPattern final : OpConversionPattern<ComplexOp> {
251 using OpConversionPattern<ComplexOp>::OpConversionPattern;
252 using OpAdaptor =
typename ComplexOp::Adaptor;
255 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
256 ConversionPatternRewriter &rewriter)
const override {
258 this->getTypeConverter()->convertType(op.getResult().getType());
260 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
263 Value complexVal = adaptor.getComplex();
266 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
268 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
271 NegateReal ? spirv::FNegateOp::create(rewriter, loc, re) : re;
272 Value resultIm = spirv::FNegateOp::create(rewriter, loc, im);
274 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
280struct DivOpPattern final : OpConversionPattern<complex::DivOp> {
284 matchAndRewrite(complex::DivOp op, OpAdaptor adaptor,
285 ConversionPatternRewriter &rewriter)
const override {
286 Type spirvType = getTypeConverter()->convertType(op.getResult().getType());
288 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
291 Value lhs = adaptor.getLhs();
292 Value rhs = adaptor.getRhs();
294 Value a = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {0});
295 Value b = spirv::CompositeExtractOp::create(rewriter, loc, lhs, {1});
296 Value c = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {0});
297 Value d = spirv::CompositeExtractOp::create(rewriter, loc, rhs, {1});
299 Value ac = spirv::FMulOp::create(rewriter, loc, a, c);
300 Value bd = spirv::FMulOp::create(rewriter, loc,
b, d);
301 Value bc = spirv::FMulOp::create(rewriter, loc,
b, c);
302 Value ad = spirv::FMulOp::create(rewriter, loc, a, d);
303 Value cc = spirv::FMulOp::create(rewriter, loc, c, c);
304 Value dd = spirv::FMulOp::create(rewriter, loc, d, d);
305 Value denom = spirv::FAddOp::create(rewriter, loc, cc, dd);
306 Value numRe = spirv::FAddOp::create(rewriter, loc, ac, bd);
307 Value numIm = spirv::FSubOp::create(rewriter, loc, bc, ad);
308 Value resultRe = spirv::FDivOp::create(rewriter, loc, numRe, denom);
309 Value resultIm = spirv::FDivOp::create(rewriter, loc, numIm, denom);
311 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
317template <
typename Atan2Op>
318struct AngleOpPattern final : OpConversionPattern<complex::AngleOp> {
319 using OpConversionPattern<complex::AngleOp>::OpConversionPattern;
322 matchAndRewrite(complex::AngleOp op, OpAdaptor adaptor,
323 ConversionPatternRewriter &rewriter)
const override {
325 this->getTypeConverter()->convertType(op.getResult().getType());
327 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
330 Value complexVal = adaptor.getComplex();
333 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
335 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
337 rewriter.replaceOpWithNewOp<Atan2Op>(op, im, re);
345template <
typename SqrtOp,
typename FAbsOp,
typename FMaxOp,
typename FMinOp>
346struct SignOpPattern final : OpConversionPattern<complex::SignOp> {
347 using OpConversionPattern<complex::SignOp>::OpConversionPattern;
350 matchAndRewrite(complex::SignOp op, OpAdaptor adaptor,
351 ConversionPatternRewriter &rewriter)
const override {
353 this->getTypeConverter()->convertType(op.getResult().getType());
355 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
358 Value complexVal = adaptor.getComplex();
361 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
363 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
366 createComplexAbs<SqrtOp, FAbsOp, FMaxOp, FMinOp>(rewriter, loc, re, im);
368 Value signRe = spirv::FDivOp::create(rewriter, loc, re, abs);
369 Value signIm = spirv::FDivOp::create(rewriter, loc, im, abs);
371 Value isZero = createIsZero(rewriter, loc, re, im);
376 Value resultRe = spirv::SelectOp::create(rewriter, loc, isZero, re, signRe);
377 Value resultIm = spirv::SelectOp::create(rewriter, loc, isZero, im, signIm);
379 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
385enum class SinCos { Sin, Cos };
390template <SinCos Kind,
typename SinOp,
typename CosOp,
typename SinhOp,
392 typename ComplexOp = std::conditional_t<
393 Kind == SinCos::Sin, complex::SinOp, complex::CosOp>>
394struct TrigonometricOpPattern final : OpConversionPattern<ComplexOp> {
395 using OpConversionPattern<ComplexOp>::OpConversionPattern;
396 using OpAdaptor =
typename ComplexOp::Adaptor;
399 matchAndRewrite(ComplexOp op, OpAdaptor adaptor,
400 ConversionPatternRewriter &rewriter)
const override {
402 this->getTypeConverter()->convertType(op.getResult().getType());
404 return rewriter.notifyMatchFailure(op,
"unable to convert result type");
407 Value complexVal = adaptor.getComplex();
410 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {0});
412 spirv::CompositeExtractOp::create(rewriter, loc, complexVal, {1});
414 Value sin = SinOp::create(rewriter, loc, re);
415 Value cos = CosOp::create(rewriter, loc, re);
416 Value sinh = SinhOp::create(rewriter, loc, im);
417 Value cosh = CoshOp::create(rewriter, loc, im);
419 bool isSin = Kind == SinCos::Sin;
421 spirv::FMulOp::create(rewriter, loc, isSin ? sin : cos, cosh);
423 spirv::FMulOp::create(rewriter, loc, isSin ? cos : sin, sinh);
425 resultIm = spirv::FNegateOp::create(rewriter, loc, resultIm);
427 rewriter.replaceOpWithNewOp<spirv::CompositeConstructOp>(
443 .
add<ConstantOpPattern, CreateOpPattern, ReOpPattern, ImOpPattern,
444 ElementwiseBinaryOpPattern<complex::AddOp, spirv::FAddOp>,
445 ElementwiseBinaryOpPattern<complex::SubOp, spirv::FSubOp>,
446 ComparisonOpPattern<complex::EqualOp, spirv::FOrdEqualOp,
447 spirv::LogicalAndOp>,
448 ComparisonOpPattern<complex::NotEqualOp, spirv::FUnordNotEqualOp,
450 MulOpPattern, DivOpPattern,
451 NegationOpPattern<complex::NegOp,
true>,
452 NegationOpPattern<complex::ConjOp,
false>,
453 AbsOpPattern<spirv::GLSqrtOp>, AbsOpPattern<spirv::CLSqrtOp>,
454 AngleOpPattern<spirv::GLAtan2Op>, AngleOpPattern<spirv::CLAtan2Op>,
455 SignOpPattern<spirv::GLSqrtOp, spirv::GLFAbsOp, spirv::GLFMaxOp,
457 SignOpPattern<spirv::CLSqrtOp, spirv::CLFAbsOp, spirv::CLFMaxOp,
459 TrigonometricOpPattern<SinCos::Sin, spirv::GLSinOp, spirv::GLCosOp,
460 spirv::GLSinhOp, spirv::GLCoshOp>,
461 TrigonometricOpPattern<SinCos::Sin, spirv::CLSinOp, spirv::CLCosOp,
462 spirv::CLSinhOp, spirv::CLCoshOp>,
463 TrigonometricOpPattern<SinCos::Cos, spirv::GLSinOp, spirv::GLCosOp,
464 spirv::GLSinhOp, spirv::GLCoshOp>,
465 TrigonometricOpPattern<SinCos::Cos, spirv::CLSinOp, spirv::CLCosOp,
466 spirv::CLSinhOp, spirv::CLCoshOp>>(
467 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.