This class implements a switch-like dispatch statement for a value of 'T' using dyn_cast functionality. Each `Case<T>` takes a callable to be invoked if the root value isa<T>, the callable is invoked with the result of dyn_cast<T>() as a parameter.
Differential Revision: https://reviews.llvm.org/D78070
This revision moves the various range utilities present in MLIR to LLVM to enable greater reuse. This revision moves the following utilities:
* indexed_accessor_*
This is set of utility iterator/range base classes that allow for building a range class where the iterators are represented by an object+index pair.
* make_second_range
Given a range of pairs, returns a range iterating over the `second` elements.
* hasSingleElement
Returns if the given range has 1 element. size() == 1 checks end up being very common, but size() is not always O(1) (e.g., ilist). This method provides O(1) checks for those cases.
Differential Revision: https://reviews.llvm.org/D78064
Summary: This fixes the return value of helper methods on the base range class.
Reviewed By: jpienaar
Differential Revision: https://reviews.llvm.org/D72127
This class provides a simplified mechanism for defining a switch over a set of types using llvm casting functionality. More specifically, this allows for defining a switch over a value of type T where each case corresponds to a type(CaseT) that can be used with dyn_cast<CaseT>(...). An example is shown below:
// Traditional piece of code:
Operation *op = ...;
if (auto constant = dyn_cast<ConstantOp>(op))
...;
else if (auto return = dyn_cast<ReturnOp>(op))
...;
else
...;
// New piece of code:
Operation *op = ...;
TypeSwitch<Operation *>(op)
.Case<ConstantOp>([](ConstantOp constant) { ... })
.Case<ReturnOp>([](ReturnOp return) { ... })
.Default([](Operation *op) { ... });
Aside from the above, TypeSwitch supports return values, void return, multiple types per case, etc. The usability is intended to be very similar to StringSwitch.
(Using c++14 template lambdas makes everything even nicer)
More complex example of how this makes certain things easier:
LogicalResult process(Constant op);
LogicalResult process(ReturnOp op);
LogicalResult process(FuncOp op);
TypeSwitch<Operation *, LogicalResult>(op)
.Case<ConstantOp, ReturnOp, FuncOp>([](auto op) { return process(op); })
.Default([](Operation *op) { return op->emitError() << "could not be processed"; });
PiperOrigin-RevId: 286003613
We now have sufficient extensibility in dialects to move attribute components
such as SDBM out of the core IR into a dedicated dialect and make them
optional. Introduce an SDBM dialect and move the code. This is a mostly
non-functional change.
--
PiperOrigin-RevId: 249244802
Currently predicates are written with positional placeholders `{N}` and rely on
`formatv` as the engine to do substitution. The problem with this approach is that
the definitions of those positional placeholders are not consistent; they are
entirely up to the defining predicate of question. For example, `{0}` in various
attribute constraints is used to mean the attribute, while it is used to main the
builder for certain attribute transformations. This can become very confusing.
This CL introduces `tgfmt` as a new mechanism to better support for predicate and
rewrite rule specification. Instead of entirely relying on positional placeholders,
`tgfmt` support both positional and special placeholders. The former is used for
DAG operands. The latter, including $_builder, $_op, $_self, are used as special
"hooks" to entities in the context. With this, the predicate and rewrite rules
specification can be more consistent is more readable.
--
PiperOrigin-RevId: 243249671