Beaver.Walker (beaver v0.2.6)

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

@type container() ::
  operation()
  | Beaver.MLIR.CAPI.MlirRegion.t()
  | Beaver.MLIR.CAPI.MlirBlock.t()
  | Beaver.MLIR.CAPI.MlirNamedAttribute.t()
@type element() ::
  operation()
  | Beaver.MLIR.CAPI.MlirRegion.t()
  | Beaver.MLIR.CAPI.MlirBlock.t()
  | Beaver.MLIR.Value.t()
  | Beaver.MLIR.CAPI.MlirNamedAttribute.t()
Link to this type

element_module()

@type element_module() ::
  Beaver.MLIR.CAPI.MlirOperation
  | Beaver.MLIR.CAPI.MlirRegion
  | Beaver.MLIR.CAPI.MlirBlock
  | Beaver.MLIR.Value
  | Beaver.MLIR.CAPI.MlirAttribute
@type mlir() :: container() | element()
@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

Link to this function

arguments(block)

@spec arguments(Beaver.MLIR.CAPI.MlirBlock.t()) :: Enumerable.t()
@spec attributes(operation()) :: Enumerable.t()
@spec blocks(Beaver.MLIR.CAPI.MlirRegion.t()) :: Enumerable.t()
Link to this function

container(module)

Extract a container could be traversed by walker from an Op prototype or a Beaver.MLIR.Module.

Link to this function

new(container, element_module, list)

@spec operands(operation()) :: Enumerable.t()
Link to this function

operations(block)

@spec operations(Beaver.MLIR.CAPI.MlirBlock.t()) :: Enumerable.t()
Link to this function

postwalk(ast, fun)

@spec postwalk(mlir(), (mlir() -> mlir())) :: mlir()

Performs a depth-first, post-order traversal of a MLIR structure.

Link to this function

postwalk(ast, acc, fun)

@spec postwalk(mlir(), any(), (mlir(), any() -> {mlir(), any()})) :: {mlir(), any()}

Performs a depth-first, post-order traversal of a MLIR structure using an accumulator.

Link to this function

prewalk(ast, fun)

@spec prewalk(t(), (t() -> t())) :: t()

Performs a depth-first, pre-order traversal of a MLIR structure.

Link to this function

prewalk(ast, acc, fun)

@spec prewalk(t(), any(), (t(), any() -> {t(), any()})) :: {t(), any()}

Performs a depth-first, pre-order traversal of a MLIR structure using an accumulator.

@spec regions(operation()) :: Enumerable.t()
Link to this function

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

@spec results(operation()) :: Enumerable.t()
@spec successors(operation()) :: Enumerable.t()
Link to this function

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 new OpReplacement with replace/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.
@spec uses(Beaver.MLIR.Value.t()) :: Enumerable.t()