MLIR  19.0.0git
PolynomialAttributes.cpp
Go to the documentation of this file.
1 //===- PolynomialAttributes.cpp - Polynomial dialect attrs ------*- 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 //===----------------------------------------------------------------------===//
9 
11 #include "mlir/Support/LLVM.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/StringExtras.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/StringSet.h"
17 
18 namespace mlir {
19 namespace polynomial {
20 
21 void IntPolynomialAttr::print(AsmPrinter &p) const {
22  p << '<' << getPolynomial() << '>';
23 }
24 
25 void FloatPolynomialAttr::print(AsmPrinter &p) const {
26  p << '<' << getPolynomial() << '>';
27 }
28 
29 /// A callable that parses the coefficient using the appropriate method for the
30 /// given monomial type, and stores the parsed coefficient value on the
31 /// monomial.
32 template <typename MonomialType>
33 using ParseCoefficientFn = std::function<OptionalParseResult(MonomialType &)>;
34 
35 /// Try to parse a monomial. If successful, populate the fields of the outparam
36 /// `monomial` with the results, and the `variable` outparam with the parsed
37 /// variable name. Sets shouldParseMore to true if the monomial is followed by
38 /// a '+'.
39 ///
40 template <typename Monomial>
42 parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable,
43  bool &isConstantTerm, bool &shouldParseMore,
44  ParseCoefficientFn<Monomial> parseAndStoreCoefficient) {
45  OptionalParseResult parsedCoeffResult = parseAndStoreCoefficient(monomial);
46 
47  isConstantTerm = false;
48  shouldParseMore = false;
49 
50  // A + indicates it's a constant term with more to go, as in `1 + x`.
51  if (succeeded(parser.parseOptionalPlus())) {
52  // If no coefficient was parsed, and there's a +, then it's effectively
53  // parsing an empty string.
54  if (!parsedCoeffResult.has_value()) {
55  return failure();
56  }
57  monomial.setExponent(APInt(apintBitWidth, 0));
58  isConstantTerm = true;
59  shouldParseMore = true;
60  return success();
61  }
62 
63  // A monomial can be a trailing constant term, as in `x + 1`.
64  if (failed(parser.parseOptionalKeyword(&variable))) {
65  // If neither a coefficient nor a variable was found, then it's effectively
66  // parsing an empty string.
67  if (!parsedCoeffResult.has_value()) {
68  return failure();
69  }
70 
71  monomial.setExponent(APInt(apintBitWidth, 0));
72  isConstantTerm = true;
73  return success();
74  }
75 
76  // Parse exponentiation symbol as `**`. We can't use caret because it's
77  // reserved for basic block identifiers If no star is present, it's treated
78  // as a polynomial with exponent 1.
79  if (succeeded(parser.parseOptionalStar())) {
80  // If there's one * there must be two.
81  if (failed(parser.parseStar())) {
82  return failure();
83  }
84 
85  // If there's a **, then the integer exponent is required.
86  APInt parsedExponent(apintBitWidth, 0);
87  if (failed(parser.parseInteger(parsedExponent))) {
88  parser.emitError(parser.getCurrentLocation(),
89  "found invalid integer exponent");
90  return failure();
91  }
92 
93  monomial.setExponent(parsedExponent);
94  } else {
95  monomial.setExponent(APInt(apintBitWidth, 1));
96  }
97 
98  if (succeeded(parser.parseOptionalPlus())) {
99  shouldParseMore = true;
100  }
101  return success();
102 }
103 
104 template <typename Monomial>
107  llvm::StringSet<> &variables,
108  ParseCoefficientFn<Monomial> parseAndStoreCoefficient) {
109  while (true) {
110  Monomial parsedMonomial;
111  llvm::StringRef parsedVariableRef;
112  bool isConstantTerm;
113  bool shouldParseMore;
114  if (failed(parseMonomial<Monomial>(
115  parser, parsedMonomial, parsedVariableRef, isConstantTerm,
116  shouldParseMore, parseAndStoreCoefficient))) {
117  parser.emitError(parser.getCurrentLocation(), "expected a monomial");
118  return failure();
119  }
120 
121  if (!isConstantTerm) {
122  std::string parsedVariable = parsedVariableRef.str();
123  variables.insert(parsedVariable);
124  }
125  monomials.push_back(parsedMonomial);
126 
127  if (shouldParseMore)
128  continue;
129 
130  if (succeeded(parser.parseOptionalGreater())) {
131  break;
132  }
133  parser.emitError(
134  parser.getCurrentLocation(),
135  "expected + and more monomials, or > to end polynomial attribute");
136  return failure();
137  }
138 
139  if (variables.size() > 1) {
140  std::string vars = llvm::join(variables.keys(), ", ");
141  parser.emitError(
142  parser.getCurrentLocation(),
143  "polynomials must have one indeterminate, but there were multiple: " +
144  vars);
145  return failure();
146  }
147 
148  return success();
149 }
150 
152  if (failed(parser.parseLess()))
153  return {};
154 
156  llvm::StringSet<> variables;
157 
158  if (failed(parsePolynomialAttr<IntMonomial>(
159  parser, monomials, variables,
160  [&](IntMonomial &monomial) -> OptionalParseResult {
161  APInt parsedCoeff(apintBitWidth, 1);
162  OptionalParseResult result =
163  parser.parseOptionalInteger(parsedCoeff);
164  monomial.setCoefficient(parsedCoeff);
165  return result;
166  }))) {
167  return {};
168  }
169 
170  auto result = IntPolynomial::fromMonomials(monomials);
171  if (failed(result)) {
172  parser.emitError(parser.getCurrentLocation())
173  << "parsed polynomial must have unique exponents among monomials";
174  return {};
175  }
176  return IntPolynomialAttr::get(parser.getContext(), result.value());
177 }
178 Attribute FloatPolynomialAttr::parse(AsmParser &parser, Type type) {
179  if (failed(parser.parseLess()))
180  return {};
181 
183  llvm::StringSet<> variables;
184 
185  ParseCoefficientFn<FloatMonomial> parseAndStoreCoefficient =
186  [&](FloatMonomial &monomial) -> OptionalParseResult {
187  double coeffValue = 1.0;
188  ParseResult result = parser.parseFloat(coeffValue);
189  monomial.setCoefficient(APFloat(coeffValue));
190  return OptionalParseResult(result);
191  };
192 
193  if (failed(parsePolynomialAttr<FloatMonomial>(parser, monomials, variables,
194  parseAndStoreCoefficient))) {
195  return {};
196  }
197 
198  auto result = FloatPolynomial::fromMonomials(monomials);
199  if (failed(result)) {
200  parser.emitError(parser.getCurrentLocation())
201  << "parsed polynomial must have unique exponents among monomials";
202  return {};
203  }
204  return FloatPolynomialAttr::get(parser.getContext(), result.value());
205 }
206 
207 } // namespace polynomial
208 } // namespace mlir
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
Definition: AsmPrinter.cpp:73
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual ParseResult parseOptionalPlus()=0
Parse a '+' token if present.
virtual ParseResult parseOptionalGreater()=0
Parse a '>' token if present.
virtual ParseResult parseStar()=0
Parse a '*' token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalStar()=0
Parse a '*' token if present.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:49
This class represents success/failure for parsing-like operations that find it important to chain tog...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
static FailureOr< FloatPolynomial > fromMonomials(ArrayRef< FloatMonomial > monomials)
Definition: Polynomial.cpp:41
static FailureOr< IntPolynomial > fromMonomials(ArrayRef< IntMonomial > monomials)
Definition: Polynomial.cpp:36
LogicalResult parsePolynomialAttr(AsmParser &parser, llvm::SmallVector< Monomial > &monomials, llvm::StringSet<> &variables, ParseCoefficientFn< Monomial > parseAndStoreCoefficient)
ParseResult parseMonomial(AsmParser &parser, Monomial &monomial, llvm::StringRef &variable, bool &isConstantTerm, bool &shouldParseMore, ParseCoefficientFn< Monomial > parseAndStoreCoefficient)
Try to parse a monomial.
std::function< OptionalParseResult(MonomialType &)> ParseCoefficientFn
A callable that parses the coefficient using the appropriate method for the given monomial type,...
constexpr unsigned apintBitWidth
This restricts statically defined polynomials to have at most 64-bit coefficients.
Definition: Polynomial.h:31
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:21
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26