Beaver.Walker (beaver v0.2.12)
Walker to traverse MLIR structures including operands, results, successors, attributes, regions.
It implements the Enumerable
protocol and the Access
behavior.
Link to this section Summary
Functions
Extract a container could be traversed by walker from an Op prototype or a Beaver.MLIR.Module
.
Performs a depth-first, post-order traversal of a MLIR structure.
Performs a depth-first, post-order traversal of a MLIR structure using an accumulator.
Performs a depth-first, pre-order traversal of a MLIR structure.
Performs a depth-first, pre-order traversal of a MLIR structure using an accumulator.
Replace a operation with a value
Traverse and transform a container in MLIR, it could be a operation, region, block.
You might expect this function works like Macro.traverse/4
.
Link to this section Types
container()
@type container() :: operation() | Beaver.MLIR.CAPI.MlirRegion.t() | Beaver.MLIR.CAPI.MlirBlock.t() | Beaver.MLIR.CAPI.MlirNamedAttribute.t()
element()
@type element() :: operation() | Beaver.MLIR.CAPI.MlirRegion.t() | Beaver.MLIR.CAPI.MlirBlock.t() | Beaver.MLIR.Value.t() | Beaver.MLIR.CAPI.MlirNamedAttribute.t()
element_module()
@type element_module() ::
Beaver.MLIR.CAPI.MlirOperation
| Beaver.MLIR.CAPI.MlirRegion
| Beaver.MLIR.CAPI.MlirBlock
| Beaver.MLIR.Value
| Beaver.MLIR.CAPI.MlirAttribute
mlir()
operation()
@type operation() :: Beaver.MLIR.CAPI.Module.t() | Beaver.MLIR.CAPI.MlirOperation.t() | Beaver.Walker.OpReplacement.t() | Beaver.DSL.Op.Prototype.t()
@type t() :: %Beaver.Walker{ container: container(), element_equal: (element(), element() -> Beaver.Native.Bool.t() | bool()) | nil, element_module: element_module(), get_element: (container(), integer() -> element()) | nil, get_first: (container() -> element()) | nil, get_next: (element() -> element()) | nil, get_num: (container() -> Beaver.Native.I64.t() | integer()) | nil, get_parent: (element() -> container()) | nil, is_null: (element() -> Beaver.Native.Bool.t() | bool()) | nil, num: non_neg_integer() | nil, parent_equal: (element(), element() -> Beaver.Native.Bool.t() | bool()) | nil, this: element() | non_neg_integer() | nil }
Link to this section Functions
arguments(block)
@spec arguments(Beaver.MLIR.CAPI.MlirBlock.t()) :: Enumerable.t()
attributes(op)
@spec attributes(operation()) :: Enumerable.t()
blocks(region)
@spec blocks(Beaver.MLIR.CAPI.MlirRegion.t()) :: Enumerable.t()
container(module)
Extract a container could be traversed by walker from an Op prototype or a Beaver.MLIR.Module
.
new(container, element_module, list)
operands(op)
@spec operands(operation()) :: Enumerable.t()
operations(block)
@spec operations(Beaver.MLIR.CAPI.MlirBlock.t()) :: Enumerable.t()
postwalk(ast, fun)
Performs a depth-first, post-order traversal of a MLIR structure.
postwalk(ast, acc, fun)
Performs a depth-first, post-order traversal of a MLIR structure using an accumulator.
prewalk(ast, fun)
Performs a depth-first, pre-order traversal of a MLIR structure.
prewalk(ast, acc, fun)
Performs a depth-first, pre-order traversal of a MLIR structure using an accumulator.
regions(op)
@spec regions(operation()) :: Enumerable.t()
replace(op, value)
@spec replace( Beaver.MLIR.CAPI.MlirOperation.t(), [Beaver.MLIR.Value.t()] | Beaver.MLIR.Value.t() ) :: Beaver.Walker.OpReplacement.t()
Replace a operation with a value
results(op)
@spec results(operation()) :: Enumerable.t()
successors(op)
@spec successors(operation()) :: Enumerable.t()
traverse(mlir, acc, pre, post)
@spec traverse( container(), any(), (container() | element(), any() -> {mlir(), any()}), (container() | element(), any() -> {mlir(), any()}) ) :: {mlir(), any()}
Traverse and transform a container in MLIR, it could be a operation, region, block.
You might expect this function works like Macro.traverse/4
.
more-on-manipulating-the-ir
More on manipulating the IR
During the traversal, there are generally two choices to manipulate the IR:
- Use
Beaver.concrete/1
to extract a op/attribute to a elixir structure, and generate a newOpReplacement
withreplace/2
. - Use a pattern defined by macro
Beaver.defpat/2
to have the PDL interpreter transform the IR for you. You can use both if it is proper to do so. It could be mind-boggling to think the IR is mutable but not an issue if your approach is very functional. Inappropriate mutation might cause crash or bugs if somewhere else is keeping a reference of the replace op.
some-tips
Some tips
- If your matching is very complicated, using
with/1
in Elixir should cover it. - Use
defpat
if you want MLIR's greedy pattern application based on benefits instead of implementing something alike yourself. - You can run traversals in a MLIR pass by calling them in
run/1
so that it joins the general MLIR pass manager's orchestration and will be run in parallel when possible.
uses(value)
@spec uses(Beaver.MLIR.Value.t()) :: Enumerable.t()