22OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
return getValue(); }
24void ConstantOp::getAsmResultNames(
26 setNameFn(getResult(),
"cst");
30 if (
auto arrAttr = llvm::dyn_cast<ArrayAttr>(value)) {
31 auto complexTy = llvm::dyn_cast<ComplexType>(type);
32 if (!complexTy || arrAttr.size() != 2)
34 auto complexEltTy = complexTy.getElementType();
35 if (
auto fre = llvm::dyn_cast<FloatAttr>(arrAttr[0])) {
36 auto im = llvm::dyn_cast<FloatAttr>(arrAttr[1]);
37 return im && fre.getType() == complexEltTy &&
38 im.getType() == complexEltTy;
40 if (
auto ire = llvm::dyn_cast<IntegerAttr>(arrAttr[0])) {
41 auto im = llvm::dyn_cast<IntegerAttr>(arrAttr[1]);
42 return im && ire.getType() == complexEltTy &&
43 im.getType() == complexEltTy;
49LogicalResult ConstantOp::verify() {
51 if (arrayAttr.size() != 2) {
53 "requires 'value' to be a complex constant, represented as array of "
57 auto complexEltTy =
getType().getElementType();
58 if (!isa<FloatAttr, IntegerAttr>(arrayAttr[0]) ||
59 !isa<FloatAttr, IntegerAttr>(arrayAttr[1]))
61 "requires attribute's elements to be float or integer attributes");
62 auto re = llvm::dyn_cast<TypedAttr>(arrayAttr[0]);
63 auto im = llvm::dyn_cast<TypedAttr>(arrayAttr[1]);
64 if (complexEltTy != re.getType() || complexEltTy != im.getType()) {
66 <<
"requires attribute's element types (" << re.getType() <<
", "
68 <<
") to match the element type of the op's return type ("
69 << complexEltTy <<
")";
85LogicalResult BitcastOp::verify() {
86 auto operandType = getOperand().getType();
90 if (operandType == resultType)
93 if (!operandType.isIntOrFloat() && !isa<ComplexType>(operandType)) {
94 return emitOpError(
"operand must be int/float/complex");
97 if (!resultType.isIntOrFloat() && !isa<ComplexType>(resultType)) {
98 return emitOpError(
"result must be int/float/complex");
101 if (isa<ComplexType>(operandType) == isa<ComplexType>(resultType)) {
103 "requires that either input or output has a complex type");
106 if (isa<ComplexType>(resultType))
107 std::swap(operandType, resultType);
109 int32_t operandBitwidth = dyn_cast<ComplexType>(operandType)
111 .getIntOrFloatBitWidth() *
113 int32_t resultBitwidth = resultType.getIntOrFloatBitWidth();
115 if (operandBitwidth != resultBitwidth) {
116 return emitOpError(
"casting bitwidths do not match");
127 if (
auto defining = op.getOperand().getDefiningOp<BitcastOp>()) {
128 if (isa<ComplexType>(op.getType()) ||
129 isa<ComplexType>(defining.getOperand().getType())) {
132 defining.getOperand());
135 defining.getOperand());
140 if (
auto defining = op.getOperand().getDefiningOp<arith::BitcastOp>()) {
142 defining.getOperand());
155 if (
auto defining = op.getOperand().getDefiningOp<complex::BitcastOp>()) {
157 defining.getOperand());
176 if (
auto reOp = getOperand(0).getDefiningOp<ReOp>()) {
177 if (
auto imOp = getOperand(1).getDefiningOp<ImOp>()) {
178 if (reOp.getOperand() == imOp.getOperand()) {
179 return reOp.getOperand();
192 llvm::dyn_cast_if_present<ArrayAttr>(adaptor.getComplex());
193 if (arrayAttr && arrayAttr.size() == 2)
195 if (
auto createOp = getOperand().getDefiningOp<CreateOp>())
196 return createOp.getOperand(1);
201template <
typename OpKind,
int ComponentIndex>
203 using OpRewritePattern<OpKind>::OpRewritePattern;
205 LogicalResult matchAndRewrite(OpKind op,
206 PatternRewriter &rewriter)
const override {
207 auto negOp = op.getOperand().template getDefiningOp<NegOp>();
211 auto createOp = negOp.getComplex().template getDefiningOp<CreateOp>();
215 Type elementType = createOp.getType().getElementType();
216 assert(isa<FloatType>(elementType));
219 op, elementType, createOp.getOperand(ComponentIndex));
227 results.
add<FoldComponentNeg<ImOp, 1>>(context);
236 llvm::dyn_cast_if_present<ArrayAttr>(adaptor.getComplex());
237 if (arrayAttr && arrayAttr.size() == 2)
239 if (
auto createOp = getOperand().getDefiningOp<CreateOp>())
240 return createOp.getOperand(0);
246 results.
add<FoldComponentNeg<ReOp, 0>>(context);
258 if (arith::bitEnumContainsAll(getFastmath(), arith::FastMathFlags::reassoc |
259 arith::FastMathFlags::nsz)) {
260 if (
auto sub = getLhs().getDefiningOp<SubOp>())
261 if (getRhs() == sub.getRhs() &&
262 arith::bitEnumContainsAll(sub.getFastmath(),
263 arith::FastMathFlags::reassoc))
266 if (
auto sub = getRhs().getDefiningOp<SubOp>())
267 if (getLhs() == sub.getRhs() &&
268 arith::bitEnumContainsAll(sub.getFastmath(),
269 arith::FastMathFlags::reassoc))
274 if (
auto constantOp = getRhs().getDefiningOp<ConstantOp>()) {
275 auto arrayAttr = constantOp.getValue();
276 if (llvm::cast<FloatAttr>(arrayAttr[0]).getValue().isNegZero() &&
277 llvm::cast<FloatAttr>(arrayAttr[1]).getValue().isNegZero()) {
293 if (arith::bitEnumContainsAll(getFastmath(), arith::FastMathFlags::reassoc |
294 arith::FastMathFlags::nsz))
295 if (
auto add = getLhs().getDefiningOp<AddOp>())
296 if (getRhs() ==
add.getRhs() &&
297 arith::bitEnumContainsAll(
add.getFastmath(),
298 arith::FastMathFlags::reassoc))
302 if (
auto constantOp = getRhs().getDefiningOp<ConstantOp>()) {
303 auto arrayAttr = constantOp.getValue();
304 if (llvm::cast<FloatAttr>(arrayAttr[0]).getValue().isZero() &&
305 llvm::cast<FloatAttr>(arrayAttr[1]).getValue().isZero()) {
319 if (
auto negOp = getOperand().getDefiningOp<NegOp>())
320 return negOp.getOperand();
334 if (arith::bitEnumContainsAll(getFastmath(), arith::FastMathFlags::reassoc))
335 if (
auto logOp = getOperand().getDefiningOp<LogOp>())
336 if (arith::bitEnumContainsAll(
338 arith::FastMathFlags::reassoc | arith::FastMathFlags::nnan |
339 arith::FastMathFlags::ninf | arith::FastMathFlags::nsz))
340 return logOp.getOperand();
351 if (
auto conjOp = getOperand().getDefiningOp<ConjOp>())
352 return conjOp.getOperand();
362 auto constant = getRhs().getDefiningOp<ConstantOp>();
366 ArrayAttr arrayAttr = constant.getValue();
367 APFloat
real = cast<FloatAttr>(arrayAttr[0]).getValue();
368 APFloat
imag = cast<FloatAttr>(arrayAttr[1]).getValue();
374 if (
real == APFloat(
real.getSemantics(), 1))
391 bool isLhsComplexHasNan =
false;
392 ArrayAttr lhsArrayAttr = dyn_cast_if_present<ArrayAttr>(lhs);
393 if (lhsArrayAttr && lhsArrayAttr.size() == 2) {
394 APFloat lhsReal = cast<FloatAttr>(lhsArrayAttr[0]).getValue();
395 APFloat lhsImag = cast<FloatAttr>(lhsArrayAttr[1]).getValue();
396 isLhsComplexHasNan = lhsReal.isNaN() || lhsImag.isNaN();
397 if (isLhsComplexHasNan) {
398 Attribute nanValue = lhsReal.isNaN() ? lhsArrayAttr[0] : lhsArrayAttr[1];
399 return ArrayAttr::get(
getContext(), {nanValue, nanValue});
403 ArrayAttr rhsArrayAttr = dyn_cast_if_present<ArrayAttr>(rhs);
404 if (!rhsArrayAttr || rhsArrayAttr.size() != 2)
408 APFloat rhsImag = cast<FloatAttr>(rhsArrayAttr[1]).getValue();
409 APFloat rhsReal = cast<FloatAttr>(rhsArrayAttr[0]).getValue();
410 if (!rhsImag.isZero() || rhsReal != APFloat(rhsReal.getSemantics(), 1))
415 if ((lhsArrayAttr && !isLhsComplexHasNan) ||
416 arith::bitEnumContainsAll(getFastmath(), arith::FastMathFlags::nnan))
426#define GET_OP_CLASSES
427#include "mlir/Dialect/Complex/IR/ComplexOps.cpp.inc"
Attributes are known-constant values of operations.
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents a single result from folding an operation.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
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...
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
constexpr T real(const NonFloatComplex< T > &x)
constexpr T imag(const NonFloatComplex< T > &x)
llvm::function_ref< Fn > function_ref
LogicalResult matchAndRewrite(arith::BitcastOp op, PatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(BitcastOp op, PatternRewriter &rewriter) const override
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})