Chapter 6: MLIR Backend¶

This chapter introduces the MLIR backend, which replaces the LLVM backend from previous chapters. MLIR provides a more flexible and extensible framework for compiler optimization and code generation. We show how to lower RVSDG-IR to MLIR dialects and use MLIR's pass infrastructure for optimization.

The chapter covers:

  • How to implement an MLIR backend for RVSDG-IR
  • How to use MLIR dialects for different abstraction levels
  • How to apply MLIR passes for optimization

Imports and Setup¶

In [1]:
from __future__ import annotations
In [2]:
import ctypes
from contextlib import contextmanager
from dataclasses import dataclass
from typing import Any, Callable, TypedDict
In [3]:
import mlir.dialects.arith as arith
import mlir.dialects.cf as cf
import mlir.dialects.func as func
import mlir.dialects.scf as scf
import mlir.execution_engine as execution_engine
import mlir.ir as ir
import mlir.passmanager as passmanager
import mlir.runtime as runtime
import numpy as np
from sealir import ase
from sealir.rvsdg import grammar as rg
from sealir.rvsdg import internal_prefix
In [4]:
from ch03_egraph_program_rewrites import (
    run_test,
)
from ch04_1_typeinfer_ifelse import (
    Attributes,
)
from ch04_1_typeinfer_ifelse import (
    ExtendEGraphToRVSDG as ConditionalExtendGraphtoRVSDG,
)
from ch04_1_typeinfer_ifelse import (
    Int64,
    MyCostModel,
    NbOp_Add_Float64,
    NbOp_Add_Int64,
    NbOp_CastI64ToF64,
    NbOp_Div_Int64,
    NbOp_Gt_Int64,
    NbOp_Lt_Int64,
    NbOp_Sub_Float64,
    NbOp_Sub_Int64,
    NbOp_Type,
    SExpr,
    TypeInt64,
)
from ch04_1_typeinfer_ifelse import base_ruleset as if_else_ruleset
from ch04_1_typeinfer_ifelse import jit_compiler as _ch04_1_jit_compiler
from ch04_1_typeinfer_ifelse import (
    ruleset_type_infer_float,
    setup_argtypes,
)
from ch04_2_typeinfer_loops import (
    ExtendEGraphToRVSDG as LoopExtendEGraphToRVSDG,
)
from ch04_2_typeinfer_loops import (
    NbOp_Not_Int64,
)
from ch04_2_typeinfer_loops import base_ruleset as loop_ruleset
from utils import IN_NOTEBOOK, Report, display

MLIR Backend Implementation¶

Define the core MLIR backend class that handles type lowering and expression compilation.

In [5]:
_DEBUG = False
In [6]:
@dataclass(frozen=True)
class LowerStates(ase.TraverseState):
    push: Callable
    get_region_args: Callable
    function_block: func.FuncOp
    constant_block: ir.Block
In [7]:
function_name = "func"
In [8]:
class Backend:
    def __init__(self):
        self.context = context = ir.Context()
        self.f32 = ir.F32Type.get(context=context)
        self.f64 = ir.F64Type.get(context=context)
        self.i32 = ir.IntegerType.get_signless(32, context=context)
        self.i64 = ir.IntegerType.get_signless(64, context=context)
        self.boo = ir.IntegerType.get_signless(1, context=context)

    def lower_type(self, ty: NbOp_Type):
        """Type Lowering

        Convert SealIR types to MLIR types for compilation.
        """
        match ty:
            case NbOp_Type("Int64"):
                return self.i64
            case NbOp_Type("Float64"):
                return self.f64
            case NbOp_Type("Float32"):
                return self.f32
        raise NotImplementedError(f"unknown type: {ty}")

    def lower(self, root: rg.Func, argtypes):
        """Expression Lowering

        Lower RVSDG expressions to MLIR operations, handling control flow
        and data flow constructs.
        """
        context = self.context
        self.loc = loc = ir.Location.unknown(context=context)
        self.module = module = ir.Module.create(loc=loc)

        # Get the module body pointer so we can insert content into the
        # module.
        self.module_body = module_body = ir.InsertionPoint(module.body)
        # Convert SealIR types to MLIR types.
        input_types = tuple([self.lower_type(x) for x in argtypes])
        output_types = (
            self.lower_type(
                Attributes(root.body.begin.attrs).get_return_type(root.body)
            ),
        )

        with context, loc, module_body:
            # Constuct a function that emits a callable C-interface.
            fun = func.FuncOp(function_name, (input_types, output_types))
            fun.attributes["llvm.emit_c_interface"] = ir.UnitAttr.get()

            # Define two blocks within the function, a constant block to
            # define all the constants and a function block for the
            # actual content. This is done to prevent non-dominant use
            # of constants. (Use of a constant when declaration is done in
            # a region that isn't initialized.)
            const_block = fun.add_entry_block()
            fun.body.blocks.append(*[], arg_locs=None)
            func_block = fun.body.blocks[1]

        # Define entry points of both the blocks.
        constant_entry = ir.InsertionPoint(const_block)
        function_entry = ir.InsertionPoint(func_block)

        region_args = []

        @contextmanager
        def push(arg_values):
            region_args.append(tuple(arg_values))
            try:
                yield
            finally:
                region_args.pop()

        def get_region_args():
            return region_args[-1]

        with context, loc, function_entry:
            memo = ase.traverse(
                root,
                self.lower_expr,
                LowerStates(
                    push=push,
                    get_region_args=get_region_args,
                    function_block=fun,
                    constant_block=constant_entry,
                ),
            )

        # Use a break to jump from the constant block to the function block.
        # note that this is being inserted at end of constant block after the
        # Function construction when all the constants have been initialized.
        with context, loc, constant_entry:
            cf.br([], fun.body.blocks[1])

        return module

    def run_passes(self, module):
        """MLIR Pass Pipeline

        Apply MLIR passes for optimization and lowering to LLVM IR.
        """
        if _DEBUG:
            module.dump()

        if _DEBUG:
            module.context.enable_multithreading(False)
        if _DEBUG and not IN_NOTEBOOK:
            # notebook may hang if ir_printing is enabled and and MLIR failed.
            pass_man.enable_ir_printing()

        pass_man = passmanager.PassManager(context=module.context)
        pass_man.add("convert-linalg-to-loops")
        pass_man.add("convert-scf-to-cf")
        pass_man.add("finalize-memref-to-llvm")
        pass_man.add("convert-math-to-libm")
        pass_man.add("convert-func-to-llvm")
        pass_man.add("convert-index-to-llvm")
        pass_man.add("reconcile-unrealized-casts")
        pass_man.enable_verifier(True)
        pass_man.run(module.operation)
        # Output LLVM-dialect MLIR
        if _DEBUG:
            module.dump()
        return module

    def lower_expr(self, expr: SExpr, state: LowerStates):
        """Expression Lowering Implementation

        Implement the core expression lowering logic for various RVSDG
        constructs including functions, regions, control flow, and operations.
        """
        match expr:
            case rg.Func(args=args, body=body):
                names = {
                    argspec.name: state.function_block.arguments[i]
                    for i, argspec in enumerate(args.arguments)
                }
                argvalues = []
                for k in body.begin.inports:
                    if k == internal_prefix("io"):
                        v = arith.constant(self.i32, 0)
                    else:
                        v = names[k]
                    argvalues.append(v)

                with state.push(argvalues):
                    outs = yield body

                portnames = [p.name for p in body.ports]
                retval = outs[portnames.index(internal_prefix("ret"))]
                func.ReturnOp([retval])
            case rg.RegionBegin(inports=ins):
                portvalues = []
                for i, k in enumerate(ins):
                    pv = state.get_region_args()[i]
                    portvalues.append(pv)
                return tuple(portvalues)

            case rg.RegionEnd(
                begin=rg.RegionBegin() as begin,
                ports=ports,
            ):
                yield begin
                portvalues = []
                for p in ports:
                    pv = yield p.value
                    portvalues.append(pv)
                return tuple(portvalues)

            case rg.ArgRef(idx=int(idx), name=str(name)):
                return state.function_block.arguments[idx]

            case rg.Unpack(val=source, idx=int(idx)):
                ports = yield source
                return ports[idx]

            case rg.DbgValue(value=value):
                val = yield value
                return val

            case rg.PyInt(int(ival)):
                with state.constant_block:
                    const = arith.constant(self.i64, ival)
                return const

            case rg.PyBool(int(ival)):
                with state.constant_block:
                    const = arith.constant(self.boo, ival)
                return const

            case rg.PyFloat(float(fval)):
                with state.constant_block:
                    const = arith.constant(self.f64, fval)
                return const

            case NbOp_Gt_Int64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.cmpi(4, lhs, rhs)

            case NbOp_Add_Int64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.addi(lhs, rhs)

            case NbOp_Sub_Int64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.subi(lhs, rhs)

            case NbOp_Add_Float64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.addf(lhs, rhs)
            case NbOp_Sub_Float64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.subf(lhs, rhs)
            case NbOp_Lt_Int64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.cmpi(2, lhs, rhs)
            case NbOp_Sub_Int64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs
                return arith.subi(lhs, rhs)

            case NbOp_CastI64ToF64(operand):
                val = yield operand
                return arith.sitofp(self.f64, val)
            case NbOp_Div_Int64(lhs, rhs):
                lhs = yield lhs
                rhs = yield rhs

                return arith.divf(
                    arith.sitofp(self.f64, lhs), arith.sitofp(self.f64, rhs)
                )
            ##### more
            case NbOp_Not_Int64(operand):
                # Implement unary not
                opval = yield operand
                return arith.cmpi(0, opval, arith.constant(self.i64, 0))
            case rg.PyBool(val):
                return arith.constant(self.boo, val)

            case rg.PyInt(val):
                return arith.constant(self.i64, val)

            case rg.IfElse(
                cond=cond, body=body, orelse=orelse, operands=operands
            ):
                condval = yield cond

                # process operands
                rettys = Attributes(body.begin.attrs)
                result_tys = []
                for i in range(0, rettys.num_output_types() + 1):
                    out_ty = rettys.get_output_type(i)
                    if out_ty is not None:
                        match out_ty.name:
                            case "Int64":
                                result_tys.append(self.i64)
                            case "Float64":
                                result_tys.append(self.f64)
                            case "Bool":
                                result_tys.append(self.boo)
                    else:
                        result_tys.append(self.i32)

                if_op = scf.IfOp(
                    cond=condval, results_=result_tys, hasElse=bool(orelse)
                )

                with ir.InsertionPoint(if_op.then_block):
                    value_else = yield body
                    scf.YieldOp([x for x in value_else])

                with ir.InsertionPoint(if_op.else_block):
                    value_else = yield orelse
                    scf.YieldOp([x for x in value_else])

                return if_op.results
            case rg.Loop(body=rg.RegionEnd() as body, operands=operands):
                rettys = Attributes(body.begin.attrs)
                # process operands
                ops = []
                for op in operands:
                    ops.append((yield op))

                result_tys = []
                for i in range(1, rettys.num_output_types() + 1):
                    out_ty = rettys.get_output_type(i)
                    if out_ty is not None:
                        match out_ty.name:
                            case "Int64":
                                result_tys.append(self.i64)
                            case "Float64":
                                result_tys.append(self.f64)
                            case "Bool":
                                result_tys.append(self.boo)
                    else:
                        result_tys.append(self.i32)

                while_op = scf.WhileOp(
                    results_=result_tys, inits=[op for op in ops]
                )
                before_block = while_op.before.blocks.append(*result_tys)
                after_block = while_op.after.blocks.append(*result_tys)
                new_ops = before_block.arguments

                # Before Region
                with ir.InsertionPoint(before_block), state.push(new_ops):
                    values = yield body
                    scf.ConditionOp(
                        args=[val for val in values[1:]], condition=values[0]
                    )

                # After Region
                with ir.InsertionPoint(after_block):
                    scf.YieldOp(after_block.arguments)

                while_op_res = scf._get_op_results_or_values(while_op)
                return while_op_res

            case _:
                raise NotImplementedError(expr, type(expr))

    # ## JIT Compilation
    #
    # Implement JIT compilation for MLIR modules using the MLIR execution
    # engine.

    def jit_compile(self, llmod, func_node: rg.Func, func_name="func"):
        """JIT Compilation

        Convert the MLIR module into a JIT-callable function using the MLIR
        execution engine.
        """
        attributes = Attributes(func_node.body.begin.attrs)
        # Convert SealIR types into MLIR types
        with self.loc:
            input_types = tuple(
                [self.lower_type(x) for x in attributes.input_types()]
            )

        output_types = (
            self.lower_type(
                Attributes(func_node.body.begin.attrs).get_return_type(
                    func_node.body
                )
            ),
        )
        return self.jit_compile_extra(llmod, input_types, output_types)

    def jit_compile_extra(
        self,
        llmod,
        input_types,
        output_types,
        function_name="func",
        exec_engine=None,
        is_ufunc=False,
        **execution_engine_params,
    ):
        # Converts the MLIR module into a JIT-callable function.
        # Use MLIR's own internal execution engine
        if exec_engine is None:
            engine = execution_engine.ExecutionEngine(
                llmod, **execution_engine_params
            )
        else:
            engine = exec_engine

        assert (
            len(output_types) == 1
        ), "Execution of functions with output arguments > 1 not supported"
        nout = len(output_types)

        # Build a wrapper function
        def jit_func(*args):
            if is_ufunc:
                input_args = args[:-nout]
                output_args = args[-nout:]
            else:
                input_args = args
                output_args = [None]
            assert len(input_args) == len(input_types)
            for arg, arg_ty in zip(input_args, input_types):
                # assert isinstance(arg, arg_ty)
                # TODO: Assert types here
                pass
            # Transform the input arguments into C-types
            # with their respective values. All inputs to
            # the internal execution engine should
            # be C-Type pointers.
            input_exec_ptrs = [
                self.get_exec_ptr(ty, val)[0]
                for ty, val in zip(input_types, input_args)
            ]
            # Invokes the function that we built, internally calls
            # _mlir_ciface_function_name as a void pointer with the given
            # input pointers, there can only be one resulting pointer
            # appended to the end of all input pointers in the invoke call.
            res_ptr, res_val = self.get_exec_ptr(
                output_types[0], output_args[0]
            )
            engine.invoke(function_name, *input_exec_ptrs, res_ptr)

            return self.get_out_val(res_ptr, res_val)

        return jit_func

    @classmethod
    def get_exec_ptr(self, mlir_ty, val):
        """Get Execution Pointer

        Convert MLIR types to C-types and allocate memory for the value.
        """
        if isinstance(mlir_ty, ir.IntegerType):
            val = 0 if val is None else val
            ptr = ctypes.pointer(ctypes.c_int64(val))
        elif isinstance(mlir_ty, ir.F32Type):
            val = 0.0 if val is None else val
            ptr = ctypes.pointer(ctypes.c_float(val))
        elif isinstance(mlir_ty, ir.F64Type):
            val = 0.0 if val is None else val
            ptr = ctypes.pointer(ctypes.c_double(val))
        elif isinstance(mlir_ty, ir.MemRefType):
            if isinstance(mlir_ty.element_type, ir.F64Type):
                np_dtype = np.float64
            elif isinstance(mlir_ty.element_type, ir.F32Type):
                np_dtype = np.float32
            else:
                raise TypeError(
                    "The current array element type is not supported"
                )

            if val is None:
                if not mlir_ty.has_static_shape:
                    raise ValueError(f"{mlir_ty} does not have static shape")
                val = np.zeros(mlir_ty.shape, dtype=np_dtype)

            ptr = ctypes.pointer(
                ctypes.pointer(runtime.get_ranked_memref_descriptor(val))
            )

        return ptr, val

    @classmethod
    def get_out_val(cls, res_ptr, res_val):
        if isinstance(res_val, np.ndarray):
            return res_val
        else:
            return res_ptr.contents.value

Example 1: Simple If-Else¶

Demonstrate the MLIR backend with a simple conditional function.

In [9]:
def example_1(a, b):
    if a > b:
        z = a - b
    else:
        z = b - a
    return z + a
In [10]:
compiler_config = dict(
    converter_class=LoopExtendEGraphToRVSDG,
    backend=Backend(),
    cost_model=MyCostModel(),
    verbose=True,
)
In [11]:
class RunBEPassOutput(TypedDict):
    module: Any
In [12]:
def pipeline_run_be_passes(
    backend, module, pipeline_report=Report.Sink()
) -> RunBEPassOutput:
    with pipeline_report.nest("MLIR passes") as report:
        backend.run_passes(module)
        report.append("MLIR optimized", module)
    return dict(module=module)
In [13]:
jit_compiler = _ch04_1_jit_compiler.insert(-1, pipeline_run_be_passes)
In [14]:
if __name__ == "__main__":
    display(jit_compiler.visualize())
    report = Report("Pipeline execution report", enable_nested_metadata=True)
    jit_func = jit_compiler(
        fn=example_1,
        argtypes=(Int64, Int64),
        ruleset=(if_else_ruleset | setup_argtypes(TypeInt64, TypeInt64)),
        pipeline_report=report,
        **compiler_config,
    ).jit_func
    report.display()

    args = (10, 33)
    run_test(example_1, jit_func, args, verbose=True)
    args = (7, 3)
    run_test(example_1, jit_func, args, verbose=True)
Pipeline-jit_compiler cluster_legend Legend input_argtypes argtypes Any stage_5 Stage 5 pipeline_backend → BackendOutput input_argtypes->stage_5 argtypes input_backend backend Any input_backend->stage_5 backend stage_6 Stage 6 pipeline_run_be_passes → RunBEPassOutput input_backend->stage_6 backend stage_7 Stage 7 jit_compiler → JitCompilerOutput input_backend->stage_7 backend input_converter_class converter_class Any stage_4 Stage 4 pipeline_egraph_extraction → EGraphExtractionOutput input_converter_class->stage_4 converter_class input_cost_model cost_model Any input_cost_model->stage_4 cost_model input_fn fn Any stage_1 Stage 1 pipeline_frontend → FrontendOutput input_fn->stage_1 fn input_ruleset ruleset Ruleset stage_3 Stage 3 egraph_saturation_with_error_checking → EGraphOutput input_ruleset->stage_3 ruleset input_export_func_name export_func_name Any = func input_export_func_name->stage_7 export_func_name input_pipeline_debug pipeline_debug bool = False input_pipeline_debug->stage_3 pipeline_debug input_pipeline_report pipeline_report Any = DummyReport() input_pipeline_report->stage_1 pipeline_report stage_2 Stage 2 pipeline_egraph_conversion → EGraphOutput input_pipeline_report->stage_2 pipeline_report input_pipeline_report->stage_3 pipeline_report input_pipeline_report->stage_4 pipeline_report input_pipeline_report->stage_5 pipeline_report input_pipeline_report->stage_6 pipeline_report stage_1->stage_2 rvsdg_expr stage_1->stage_4 rvsdg_expr out_dbginfo dbginfo object stage_1->out_dbginfo dbginfo out_rvsdg_expr rvsdg_expr object stage_1->out_rvsdg_expr rvsdg_expr stage_2->stage_3 egraph stage_2->stage_3 egraph_root stage_3->stage_4 egraph out_egraph egraph EGraph stage_3->out_egraph egraph out_egraph_root egraph_root GraphRoot stage_3->out_egraph_root egraph_root stage_4->stage_5 extracted stage_4->stage_7 extracted out_cost cost float stage_4->out_cost cost out_extracted extracted Any stage_4->out_extracted extracted stage_5->stage_6 module stage_6->stage_7 module out_module module Any stage_6->out_module module out_jit_func jit_func Any stage_7->out_jit_func jit_func legend_input Required Input legend_optional Optional Input legend_input->legend_optional legend_stage Processing Stage legend_optional->legend_stage legend_output Output legend_stage->legend_output

Pipeline execution report

1. Frontend (11.20ms) ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   1|def example_1(a, b):
   2|    if a > b:
   3|        z = a - b
   4|    else:
   5|        z = b - a
   6|    return z + a
----------------------------------inter source----------------------------------
   1|def transformed_example_1(a, b):
   2|    """#file: /tmp/ipykernel_3723/3239589072.py"""
   3|    '#loc: 2:8-5:21'
   4|    if a > b:
   5|        '#loc: 3:12-3:21'
   6|        z = a - b
   7|    else:
   8|        z = b - a
   9|    '#loc: 6:8-6:20'
  10|    return z + a
RVSDG ▶
transformed_example_1 = Func (Args (ArgSpec 'a' (PyNone)) (ArgSpec 'b' (PyNone)))
$0 = Region[512] <- !io a b
{
  $1 = PyBinOp > $0[0] $0[1], $0[2]
  $2 = If $1[1] <- $0[0] $0[1] $0[2]
    $3 = Region[562] <- !io a b
    {
      $4 = PyBinOp - $3[0] $3[1], $3[2]
      $5 = DbgValue 'z' $4[1]
    } [769] -> !io=$4[0] a=$3[1] b=$3[2] z=$5
    Else
    $6 = Region[659] <- !io a b
    {
      $7 = PyBinOp - $6[0] $6[2], $6[1]
      $8 = DbgValue 'z' $7[1]
    } [797] -> !io=$7[0] a=$6[1] b=$6[2] z=$8
  Endif
  $9 = PyBinOp + $2[0] $2[3], $2[1]
} [889] -> !io=$9[0] !ret=$9[1]
[metadata] ▶
time elapsed 11.20ms
timing breakdown:
  8.99ms: Debug Info on RVSDG 
  2.21ms: RVSDG               
2. EGraph Conversion (36.09ms) ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_Port-42 cluster_Port-42 outer_cluster_Port-44 cluster_Port-44 outer_cluster_Port-27 cluster_Port-27 outer_cluster_Port-23 cluster_Port-23 outer_cluster_Port-32 cluster_Port-32 outer_cluster_Port-29 cluster_Port-29 outer_cluster_Port-18 cluster_Port-18 outer_cluster_Port-20 cluster_Port-20 outer_cluster_Port-19 cluster_Port-19 outer_cluster_Port-28 cluster_Port-28 outer_cluster_PortList-45 cluster_PortList-45 outer_cluster_PortList-33 cluster_PortList-33 outer_cluster_PortList-24 cluster_PortList-24 outer_cluster_Region-2 cluster_Region-2 outer_cluster_Region-8 cluster_Region-8 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Term-48 cluster_Term-48 outer_cluster_Term-26 cluster_Term-26 outer_cluster_Term-46 cluster_Term-46 outer_cluster_Term-47 cluster_Term-47 outer_cluster_Term-41 cluster_Term-41 outer_cluster_Term-15 cluster_Term-15 outer_cluster_Term-4 cluster_Term-4 outer_cluster_Term-40 cluster_Term-40 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-13 cluster_Term-13 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-39 cluster_Term-39 outer_cluster_Term-14 cluster_Term-14 outer_cluster_Term-36 cluster_Term-36 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-30 cluster_Term-30 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-37 cluster_Term-37 outer_cluster_Term-38 cluster_Term-38 outer_cluster_Term-34 cluster_Term-34 outer_cluster_Term-43 cluster_Term-43 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-5 cluster_Term-5 outer_cluster_Term-25 cluster_Term-25 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-11 cluster_Term-11 outer_cluster_Term-17 cluster_Term-17 outer_cluster_Term-21 cluster_Term-21 outer_cluster_TermList-35 cluster_TermList-35 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_String-0 cluster_Vec_String-0 outer_cluster_Vec_Term-0 cluster_Vec_Term-0 function-0-InPorts___init__:s->primitive-Vec_String-0 function-8-Port___init__:s->function-8-Term_getPort function-8-Term_getPort:s->function-0-Py_AddIO function-9-Port___init__:s->function-9-Term_getPort function-9-Term_getPort:s->function-0-Py_AddIO function-4-Port___init__:s->function-3-Term_getPort function-3-Term_getPort:s->function-1-Py_SubIO function-3-Port___init__:s->function-0-Term_DbgValue function-0-Term_DbgValue:s->function-2-Term_getPort function-7-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-4-Term_getPort function-6-Port___init__:s->function-3-Region_get function-3-Region_get:s->function-0-Region___init__ function-0-Port___init__:s->function-1-Term_getPort function-1-Term_getPort:s->function-0-Py_SubIO function-2-Port___init__:s->function-2-Region_get function-2-Region_get:s->function-1-Region___init__ function-1-Port___init__:s->function-1-Region_get function-1-Region_get:s->function-1-Region___init__ function-5-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-0-Region___init__ function-2-PortList___init__:s->primitive-Vec_Port-2 primitive-Vec_Port-2:s->function-8-Port___init__ primitive-Vec_Port-2:s->function-9-Port___init__ function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-4-Port___init__ primitive-Vec_Port-1:s->function-7-Port___init__ primitive-Vec_Port-1:s->function-6-Port___init__ primitive-Vec_Port-1:s->function-5-Port___init__ function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-3-Port___init__ primitive-Vec_Port-0:s->function-0-Port___init__ primitive-Vec_Port-0:s->function-2-Port___init__ primitive-Vec_Port-0:s->function-1-Port___init__ function-1-Region___init__:s->function-0-InPorts___init__ function-2-Region___init__:s->function-0-InPorts___init__ function-0-Region___init__:s->function-0-InPorts___init__ function-0-GraphRoot:s->function-0-Term_Func function-0-Term_Func:s->function-2-Term_RegionEnd function-1-Py_SubIO:s->function-3-Region_get function-1-Py_SubIO:s->function-6-Region_get function-1-Py_SubIO:s->function-5-Region_get function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-2-Region___init__ function-0-Py_AddIO:s->function-5-Term_getPort function-0-Py_AddIO:s->function-6-Term_getPort function-0-Py_AddIO:s->function-7-Term_getPort function-0-Py_GtIO:s->function-4-Region_get function-0-Py_GtIO:s->function-7-Region_get function-0-Py_GtIO:s->function-8-Region_get function-4-Region_get:s->function-2-Region___init__ function-7-Region_get:s->function-2-Region___init__ function-8-Region_get:s->function-2-Region___init__ function-5-Term_getPort:s->function-0-Term_IfElse function-6-Term_getPort:s->function-0-Term_IfElse function-7-Term_getPort:s->function-0-Term_IfElse function-5-Region_get:s->function-0-Region___init__ function-0-Term_IfElse:s->function-0-Term_getPort function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-0-TermList___init__ function-0-Term_getPort:s->function-0-Py_GtIO function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-1-Region___init__ function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-0-Region___init__ function-0-TermList___init__:s->primitive-Vec_Term-0 function-4-Term_getPort:s->function-1-Py_SubIO function-0-Region_get:s->function-1-Region___init__ function-0-Py_SubIO:s->function-2-Region_get function-0-Py_SubIO:s->function-1-Region_get function-0-Py_SubIO:s->function-0-Region_get function-2-Term_getPort:s->function-0-Py_SubIO primitive-Vec_Term-0:s->function-4-Region_get primitive-Vec_Term-0:s->function-7-Region_get primitive-Vec_Term-0:s->function-8-Region_get function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "a", "b") function-8-Port___init__ Port("!io", ·) function-8-Term_getPort ·.getPort(·, 0) function-9-Port___init__ Port("!ret", ·) function-9-Term_getPort ·.getPort(·, 1) function-4-Port___init__ Port("!io", ·) function-3-Term_getPort ·.getPort(·, 0) function-3-Port___init__ Port("z", ·) function-0-Term_DbgValue Term.DbgValue("z", ·) function-7-Port___init__ Port("z", ·) function-1-Term_DbgValue Term.DbgValue("z", ·) function-6-Port___init__ Port("b", ·) function-3-Region_get ·.get(·, 2) function-0-Port___init__ Port("!io", ·) function-1-Term_getPort ·.getPort(·, 0) function-2-Port___init__ Port("b", ·) function-2-Region_get ·.get(·, 2) function-1-Port___init__ Port("a", ·) function-1-Region_get ·.get(·, 1) function-5-Port___init__ Port("a", ·) function-6-Region_get ·.get(·, 1) function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-1-Region___init__ Region("562", ·) function-2-Region___init__ Region("512", ·) function-0-Region___init__ Region("659", ·) function-0-GraphRoot GraphRoot function-0-Term_Func Term.Func("895", "transformed_example_1", ·) function-1-Py_SubIO Py_SubIO function-2-Term_RegionEnd Term.RegionEnd function-0-Py_AddIO Py_AddIO function-0-Py_GtIO Py_GtIO function-4-Region_get ·.get(·, 0) function-7-Region_get ·.get(·, 1) function-8-Region_get ·.get(·, 2) function-5-Term_getPort ·.getPort(·, 0) function-6-Term_getPort ·.getPort(·, 3) function-7-Term_getPort ·.getPort(·, 1) function-5-Region_get ·.get(·, 0) function-0-Term_IfElse Term.IfElse function-0-Term_getPort ·.getPort(·, 1) function-0-Term_RegionEnd Term.RegionEnd function-1-Term_RegionEnd Term.RegionEnd function-0-TermList___init__ TermList function-4-Term_getPort ·.getPort(·, 1) function-0-Region_get ·.get(·, 0) function-0-Py_SubIO Py_SubIO function-2-Term_getPort ·.getPort(·, 1) primitive-Vec_Term-0 Vec
[metadata] ▶
time elapsed 36.09ms
timing breakdown:
  36.09ms: EGraph              
3. Egraph Saturation (0.00ms) ▶
Egraph Saturation
[metadata] ▶
time elapsed 0.00ms
timing breakdown:
4. EGraph Extraction (14.98ms) ▶
EGraph Extraction
Extracted RVSDG ▶
transformed_example_1 = Func (Args (ArgSpec 'a' (PyNone)) (ArgSpec 'b' (PyNone)))
$0 = Region[1076] <- !io a b; #attrs (_, Int64, Int64)->(_, Int64)
{
  $1 = NbOp_Gt_Int64 $0[1] $0[2]
  $2 = If $1 <- $0[0] $0[1] $0[2]
    $3 = Region[1131] <- !io a b; #attrs (_, Int64, Int64)->(_, Int64, Int64, Int64)
    {
      $4 = NbOp_Sub_Int64 $3[1] $3[2]
    } [1178] -> !io=$3[0] a=$3[1] b=$3[2] z=$4
    Else
    $5 = Region[1219] <- !io a b; #attrs (_, Int64, Int64)->(_, Int64, Int64, Int64)
    {
      $6 = NbOp_Sub_Int64 $5[2] $5[1]
    } [1266] -> !io=$5[0] a=$5[1] b=$5[2] z=$6
  Endif
  $7 = NbOp_Add_Int64 $2[3] $2[1]
} [1318] -> !io=$2[0] !ret=$7
Extracted cost ▶
5841595.0
[metadata] ▶
time elapsed 14.98ms
timing breakdown:
  14.96ms: Extracted RVSDG     
  0.01ms: Extracted cost      
5. Backend (2.36ms) ▶
Backend
Lowered module ▶
module {
  func.func @func(%arg0: i64, %arg1: i64) -> i64 attributes {llvm.emit_c_interface} {
    cf.br ^bb1
  ^bb1:  // pred: ^bb0
    %c0_i32 = arith.constant 0 : i32
    %0 = arith.cmpi sgt, %arg0, %arg1 : i64
    %1:4 = scf.if %0 -> (i32, i64, i64, i64) {
      %3 = arith.subi %arg0, %arg1 : i64
      scf.yield %c0_i32, %arg0, %arg1, %3 : i32, i64, i64, i64
    } else {
      %3 = arith.subi %arg1, %arg0 : i64
      scf.yield %c0_i32, %arg0, %arg1, %3 : i32, i64, i64, i64
    }
    %2 = arith.addi %1#3, %1#1 : i64
    return %2 : i64
  }
}
[metadata] ▶
time elapsed 2.36ms
timing breakdown:
  2.36ms: Lowered module      
6. MLIR passes (1.41ms) ▶
MLIR passes
MLIR optimized ▶
module {
  llvm.func @func(%arg0: i64, %arg1: i64) -> i64 attributes {llvm.emit_c_interface} {
    %0 = llvm.mlir.constant(0 : i32) : i32
    llvm.br ^bb1
  ^bb1:  // pred: ^bb0
    %1 = llvm.icmp "sgt" %arg0, %arg1 : i64
    llvm.cond_br %1, ^bb2, ^bb3
  ^bb2:  // pred: ^bb1
    %2 = llvm.sub %arg0, %arg1 : i64
    llvm.br ^bb4(%0, %arg0, %arg1, %2 : i32, i64, i64, i64)
  ^bb3:  // pred: ^bb1
    %3 = llvm.sub %arg1, %arg0 : i64
    llvm.br ^bb4(%0, %arg0, %arg1, %3 : i32, i64, i64, i64)
  ^bb4(%4: i32, %5: i64, %6: i64, %7: i64):  // 2 preds: ^bb2, ^bb3
    llvm.br ^bb5
  ^bb5:  // pred: ^bb4
    %8 = llvm.add %7, %5 : i64
    llvm.return %8 : i64
  }
  llvm.func @_mlir_ciface_func(%arg0: i64, %arg1: i64) -> i64 attributes {llvm.emit_c_interface} {
    %0 = llvm.call @func(%arg0, %arg1) : (i64, i64) -> i64
    llvm.return %0 : i64
  }
}
[metadata] ▶
time elapsed 1.41ms
timing breakdown:
  1.41ms: MLIR optimized      

Testing report

1. Args ▶
(10, 33)
2. JIT output ▶
33
3. Expected output ▶
33

Testing report

1. Args ▶
(7, 3)
2. JIT output ▶
11
3. Expected output ▶
11

Example 2: Float Operations¶

Test the MLIR backend with float operations and type conversion.

In [15]:
def example_2(a, b):
    if a > b:
        z = float(a - b)
    else:
        z = float(b) - 1 / a
    return z - float(a)

Add rules for float()

In [16]:
if __name__ == "__main__":
    report = Report("Pipeline execution report", enable_nested_metadata=True)
    jit_func = jit_compiler(
        fn=example_2,
        argtypes=(Int64, Int64),
        ruleset=(
            if_else_ruleset
            | setup_argtypes(TypeInt64, TypeInt64)
            | ruleset_type_infer_float  # < --- added for float()
        ),
        pipeline_report=report,
        **compiler_config,
    ).jit_func

    report.display()

    args = (10, 33)
    run_test(example_2, jit_func, args, verbose=True)
    args = (7, 3)
    run_test(example_2, jit_func, args, verbose=True)

Pipeline execution report

1. Frontend (9.67ms) ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   1|def example_2(a, b):
   2|    if a > b:
   3|        z = float(a - b)
   4|    else:
   5|        z = float(b) - 1 / a
   6|    return z - float(a)
----------------------------------inter source----------------------------------
   1|def transformed_example_2(a, b):
   2|    """#file: /tmp/ipykernel_3723/1511658715.py"""
   3|    '#loc: 2:8-5:32'
   4|    if a > b:
   5|        '#loc: 3:12-3:28'
   6|        z = float(a - b)
   7|    else:
   8|        z = float(b) - 1 / a
   9|    '#loc: 6:8-6:27'
  10|    return z - float(a)
RVSDG ▶
transformed_example_2 = Func (Args (ArgSpec 'a' (PyNone)) (ArgSpec 'b' (PyNone)))
$0 = Region[628] <- !io a b
{
  $1 = PyBinOp > $0[0] $0[1], $0[2]
  $2 = If $1[1] <- $0[0] $0[1] $0[2]
    $3 = Region[678] <- !io a b
    {
      $4 = PyBinOp - $3[0] $3[1], $3[2]
      $5 = PyLoadGlobal $4[0] 'float'
      $6 = PyCall $5 $4[0] $4[1]
      $7 = DbgValue 'z' $6[1]
    } [948] -> !io=$6[0] a=$3[1] b=$3[2] z=$7
    Else
    $8 = Region[796] <- !io a b
    {
      $9 = PyLoadGlobal $8[0] 'float'
      $10 = PyCall $9 $8[0] $8[2]
      $11 = PyInt 1
      $12 = PyBinOp / $10[0] $11, $8[1]
      $13 = PyBinOp - $12[0] $10[1], $12[1]
      $14 = DbgValue 'z' $13[1]
    } [976] -> !io=$13[0] a=$8[1] b=$8[2] z=$14
  Endif
  $15 = PyLoadGlobal $2[0] 'float'
  $16 = PyCall $15 $2[0] $2[1]
  $17 = PyBinOp - $16[0] $2[3], $16[1]
} [1089] -> !io=$17[0] !ret=$17[1]
[metadata] ▶
time elapsed 9.67ms
timing breakdown:
  7.28ms: Debug Info on RVSDG 
  2.39ms: RVSDG               
2. EGraph Conversion (44.71ms) ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_Port-43 cluster_Port-43 outer_cluster_Port-32 cluster_Port-32 outer_cluster_Port-34 cluster_Port-34 outer_cluster_Port-63 cluster_Port-63 outer_cluster_Port-42 cluster_Port-42 outer_cluster_Port-46 cluster_Port-46 outer_cluster_Port-41 cluster_Port-41 outer_cluster_Port-61 cluster_Port-61 outer_cluster_Port-37 cluster_Port-37 outer_cluster_Port-33 cluster_Port-33 outer_cluster_PortList-64 cluster_PortList-64 outer_cluster_PortList-38 cluster_PortList-38 outer_cluster_PortList-47 cluster_PortList-47 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Region-25 cluster_Region-25 outer_cluster_Region-4 cluster_Region-4 outer_cluster_Term-18 cluster_Term-18 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-48 cluster_Term-48 outer_cluster_Term-26 cluster_Term-26 outer_cluster_Term-45 cluster_Term-45 outer_cluster_Term-2 cluster_Term-2 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-14 cluster_Term-14 outer_cluster_Term-51 cluster_Term-51 outer_cluster_Term-65 cluster_Term-65 outer_cluster_Term-56 cluster_Term-56 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-44 cluster_Term-44 outer_cluster_Term-29 cluster_Term-29 outer_cluster_Term-5 cluster_Term-5 outer_cluster_Term-62 cluster_Term-62 outer_cluster_Term-50 cluster_Term-50 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-36 cluster_Term-36 outer_cluster_Term-55 cluster_Term-55 outer_cluster_Term-27 cluster_Term-27 outer_cluster_Term-67 cluster_Term-67 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-53 cluster_Term-53 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-58 cluster_Term-58 outer_cluster_Term-35 cluster_Term-35 outer_cluster_Term-59 cluster_Term-59 outer_cluster_Term-66 cluster_Term-66 outer_cluster_Term-39 cluster_Term-39 outer_cluster_Term-13 cluster_Term-13 outer_cluster_Term-28 cluster_Term-28 outer_cluster_Term-52 cluster_Term-52 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-21 cluster_Term-21 outer_cluster_Term-30 cluster_Term-30 outer_cluster_Term-57 cluster_Term-57 outer_cluster_Term-60 cluster_Term-60 outer_cluster_Term-17 cluster_Term-17 outer_cluster_Term-11 cluster_Term-11 outer_cluster_Term-23 cluster_Term-23 outer_cluster_Term-40 cluster_Term-40 outer_cluster_Term-24 cluster_Term-24 outer_cluster_TermList-15 cluster_TermList-15 outer_cluster_TermList-54 cluster_TermList-54 outer_cluster_TermList-12 cluster_TermList-12 outer_cluster_TermList-49 cluster_TermList-49 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_String-0 cluster_Vec_String-0 outer_cluster_Vec_Term-3 cluster_Vec_Term-3 outer_cluster_Vec_Term-0 cluster_Vec_Term-0 outer_cluster_Vec_Term-2 cluster_Vec_Term-2 outer_cluster_Vec_Term-1 cluster_Vec_Term-1 function-0-InPorts___init__:s->primitive-Vec_String-0 function-6-Port___init__:s->function-0-Region_get function-0-Region_get:s->function-0-Region___init__ function-0-Port___init__:s->function-7-Term_getPort function-7-Term_getPort:s->function-0-Py_Call function-2-Port___init__:s->function-3-Region_get function-3-Region_get:s->function-1-Region___init__ function-9-Port___init__:s->function-17-Term_getPort function-17-Term_getPort:s->function-2-Py_SubIO function-5-Port___init__:s->function-5-Region_get function-5-Region_get:s->function-0-Region___init__ function-7-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-10-Term_getPort function-4-Port___init__:s->function-9-Term_getPort function-9-Term_getPort:s->function-1-Py_SubIO function-8-Port___init__:s->function-16-Term_getPort function-16-Term_getPort:s->function-2-Py_SubIO function-3-Port___init__:s->function-0-Term_DbgValue function-0-Term_DbgValue:s->function-8-Term_getPort function-1-Port___init__:s->function-2-Region_get function-2-Region_get:s->function-1-Region___init__ function-2-PortList___init__:s->primitive-Vec_Port-2 primitive-Vec_Port-2:s->function-9-Port___init__ primitive-Vec_Port-2:s->function-8-Port___init__ function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-0-Port___init__ primitive-Vec_Port-0:s->function-2-Port___init__ primitive-Vec_Port-0:s->function-3-Port___init__ primitive-Vec_Port-0:s->function-1-Port___init__ function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-6-Port___init__ primitive-Vec_Port-1:s->function-5-Port___init__ primitive-Vec_Port-1:s->function-7-Port___init__ primitive-Vec_Port-1:s->function-4-Port___init__ function-0-Region___init__:s->function-0-InPorts___init__ function-2-Region___init__:s->function-0-InPorts___init__ function-1-Region___init__:s->function-0-InPorts___init__ function-4-Term_getPort:s->function-1-Py_Call function-1-Py_Call:s->function-1-Py_LoadGlobal function-1-Py_Call:s->function-1-Region_get function-1-Py_Call:s->function-1-TermList___init__ function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-0-Region___init__ function-6-Region_get:s->function-2-Region___init__ function-10-Term_getPort:s->function-1-Py_SubIO function-0-Py_SubIO:s->function-3-Region_get function-0-Py_SubIO:s->function-2-Region_get function-0-Py_SubIO:s->function-4-Region_get function-4-Region_get:s->function-1-Region___init__ function-0-Py_DivIO:s->function-5-Region_get function-0-Py_DivIO:s->function-0-Term_LiteralI64 function-0-Py_DivIO:s->function-2-Term_getPort function-2-Term_getPort:s->function-1-Py_Call function-0-Py_Call:s->function-0-Py_LoadGlobal function-0-Py_Call:s->function-0-Term_getPort function-0-Py_Call:s->function-0-TermList___init__ function-1-Py_LoadGlobal:s->function-1-Region_get function-1-Region_get:s->function-0-Region___init__ function-11-Term_getPort:s->function-0-Term_IfElse function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-6-Term_getPort function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-2-TermList___init__ function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-2-Region___init__ function-13-Term_getPort:s->function-2-Py_Call function-2-Py_Call:s->function-11-Term_getPort function-2-Py_Call:s->function-2-Py_LoadGlobal function-2-Py_Call:s->function-3-TermList___init__ function-1-TermList___init__:s->primitive-Vec_Term-1 function-1-Py_SubIO:s->function-4-Term_getPort function-1-Py_SubIO:s->function-3-Term_getPort function-1-Py_SubIO:s->function-5-Term_getPort function-0-Py_GtIO:s->function-6-Region_get function-0-Py_GtIO:s->function-7-Region_get function-0-Py_GtIO:s->function-8-Region_get function-7-Region_get:s->function-2-Region___init__ function-8-Region_get:s->function-2-Region___init__ function-2-Py_SubIO:s->function-13-Term_getPort function-2-Py_SubIO:s->function-15-Term_getPort function-2-Py_SubIO:s->function-14-Term_getPort function-6-Term_getPort:s->function-0-Py_GtIO function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-1-Region___init__ function-2-TermList___init__:s->primitive-Vec_Term-2 function-0-Py_LoadGlobal:s->function-0-Term_getPort function-0-Term_getPort:s->function-0-Py_SubIO function-8-Term_getPort:s->function-0-Py_Call function-2-Py_LoadGlobal:s->function-11-Term_getPort function-3-TermList___init__:s->primitive-Vec_Term-3 function-0-GraphRoot:s->function-0-Term_Func function-0-Term_Func:s->function-2-Term_RegionEnd function-12-Term_getPort:s->function-0-Term_IfElse function-15-Term_getPort:s->function-2-Py_Call function-14-Term_getPort:s->function-0-Term_IfElse function-0-TermList___init__:s->primitive-Vec_Term-0 function-3-Term_getPort:s->function-0-Py_DivIO function-1-Term_getPort:s->function-0-Py_SubIO function-5-Term_getPort:s->function-0-Py_DivIO primitive-Vec_Term-1:s->function-0-Region_get primitive-Vec_Term-3:s->function-12-Term_getPort primitive-Vec_Term-0:s->function-1-Term_getPort primitive-Vec_Term-2:s->function-6-Region_get primitive-Vec_Term-2:s->function-7-Region_get primitive-Vec_Term-2:s->function-8-Region_get function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "a", "b") function-6-Port___init__ Port("b", ·) function-0-Region_get ·.get(·, 2) function-0-Port___init__ Port("!io", ·) function-7-Term_getPort ·.getPort(·, 0) function-2-Port___init__ Port("b", ·) function-3-Region_get ·.get(·, 2) function-9-Port___init__ Port("!ret", ·) function-17-Term_getPort ·.getPort(·, 1) function-5-Port___init__ Port("a", ·) function-5-Region_get ·.get(·, 1) function-7-Port___init__ Port("z", ·) function-1-Term_DbgValue Term.DbgValue("z", ·) function-4-Port___init__ Port("!io", ·) function-9-Term_getPort ·.getPort(·, 0) function-8-Port___init__ Port("!io", ·) function-16-Term_getPort ·.getPort(·, 0) function-3-Port___init__ Port("z", ·) function-0-Term_DbgValue Term.DbgValue("z", ·) function-1-Port___init__ Port("a", ·) function-2-Region_get ·.get(·, 1) function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-0-Region___init__ Region("796", ·) function-2-Region___init__ Region("628", ·) function-1-Region___init__ Region("678", ·) function-0-Term_LiteralI64 Term.LiteralI64(1) function-4-Term_getPort ·.getPort(·, 1) function-1-Py_Call Py_Call function-1-Term_RegionEnd Term.RegionEnd function-6-Region_get ·.get(·, 0) function-10-Term_getPort ·.getPort(·, 1) function-0-Py_SubIO Py_SubIO function-4-Region_get ·.get(·, 0) function-0-Py_DivIO Py_DivIO function-2-Term_getPort ·.getPort(·, 0) function-0-Py_Call Py_Call function-1-Py_LoadGlobal Py_LoadGlobal(·, "float") function-1-Region_get ·.get(·, 0) function-11-Term_getPort ·.getPort(·, 0) function-0-Term_IfElse Term.IfElse function-2-Term_RegionEnd Term.RegionEnd function-13-Term_getPort ·.getPort(·, 0) function-2-Py_Call Py_Call function-1-TermList___init__ TermList function-1-Py_SubIO Py_SubIO function-0-Py_GtIO Py_GtIO function-7-Region_get ·.get(·, 1) function-8-Region_get ·.get(·, 2) function-2-Py_SubIO Py_SubIO function-6-Term_getPort ·.getPort(·, 1) function-0-Term_RegionEnd Term.RegionEnd function-2-TermList___init__ TermList function-0-Py_LoadGlobal Py_LoadGlobal(·, "float") function-0-Term_getPort ·.getPort(·, 0) function-8-Term_getPort ·.getPort(·, 1) function-2-Py_LoadGlobal Py_LoadGlobal(·, "float") function-3-TermList___init__ TermList function-0-GraphRoot GraphRoot function-0-Term_Func Term.Func("1095", "transformed_example_2", ·) function-12-Term_getPort ·.getPort(·, 1) function-15-Term_getPort ·.getPort(·, 1) function-14-Term_getPort ·.getPort(·, 3) function-0-TermList___init__ TermList function-3-Term_getPort ·.getPort(·, 0) function-1-Term_getPort ·.getPort(·, 1) function-5-Term_getPort ·.getPort(·, 1) primitive-Vec_Term-1 Vec primitive-Vec_Term-3 Vec primitive-Vec_Term-0 Vec primitive-Vec_Term-2 Vec
[metadata] ▶
time elapsed 44.71ms
timing breakdown:
  44.71ms: EGraph              
3. Egraph Saturation (0.00ms) ▶
Egraph Saturation
[metadata] ▶
time elapsed 0.00ms
timing breakdown:
4. EGraph Extraction (17.16ms) ▶
EGraph Extraction
Extracted RVSDG ▶
transformed_example_2 = Func (Args (ArgSpec 'a' (PyNone)) (ArgSpec 'b' (PyNone)))
$0 = Region[1328] <- !io a b; #attrs (_, Int64, Int64)->(_, Float64)
{
  $1 = NbOp_Gt_Int64 $0[1] $0[2]
  $2 = If $1 <- $0[0] $0[1] $0[2]
    $3 = Region[1383] <- !io a b; #attrs (_, Int64, Int64)->(_, Int64, Int64, Float64)
    {
      $4 = NbOp_Sub_Int64 $3[1] $3[2]
      $5 = NbOp_CastI64ToF64 $4
    } [1434] -> !io=$3[0] a=$3[1] b=$3[2] z=$5
    Else
    $6 = Region[1475] <- !io a b; #attrs (_, Int64, Int64)->(_, Int64, Int64, Float64)
    {
      $7 = NbOp_CastI64ToF64 $6[2]
      $8 = PyInt 1
      $9 = NbOp_Div_Int64 $8 $6[1]
      $10 = NbOp_Sub_Float64 $7 $9
    } [1535] -> !io=$6[0] a=$6[1] b=$6[2] z=$10
  Endif
  $11 = NbOp_CastI64ToF64 $2[1]
  $12 = NbOp_Sub_Float64 $2[3] $11
} [1591] -> !io=$2[0] !ret=$12
Extracted cost ▶
5880571.0
[metadata] ▶
time elapsed 17.16ms
timing breakdown:
  17.15ms: Extracted RVSDG     
  0.01ms: Extracted cost      
5. Backend (1.46ms) ▶
Backend
Lowered module ▶
module {
  func.func @func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %c1_i64 = arith.constant 1 : i64
    cf.br ^bb1
  ^bb1:  // pred: ^bb0
    %c0_i32 = arith.constant 0 : i32
    %0 = arith.cmpi sgt, %arg0, %arg1 : i64
    %1:4 = scf.if %0 -> (i32, i64, i64, f64) {
      %4 = arith.subi %arg0, %arg1 : i64
      %5 = arith.sitofp %4 : i64 to f64
      scf.yield %c0_i32, %arg0, %arg1, %5 : i32, i64, i64, f64
    } else {
      %4 = arith.sitofp %arg1 : i64 to f64
      %5 = arith.sitofp %c1_i64 : i64 to f64
      %6 = arith.sitofp %arg0 : i64 to f64
      %7 = arith.divf %5, %6 : f64
      %8 = arith.subf %4, %7 : f64
      scf.yield %c0_i32, %arg0, %arg1, %8 : i32, i64, i64, f64
    }
    %2 = arith.sitofp %1#1 : i64 to f64
    %3 = arith.subf %1#3, %2 : f64
    return %3 : f64
  }
}
[metadata] ▶
time elapsed 1.46ms
timing breakdown:
  1.46ms: Lowered module      
6. MLIR passes (1.23ms) ▶
MLIR passes
MLIR optimized ▶
module {
  llvm.func @func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %0 = llvm.mlir.constant(1.000000e+00 : f64) : f64
    %1 = llvm.mlir.constant(0 : i32) : i32
    llvm.br ^bb1
  ^bb1:  // pred: ^bb0
    %2 = llvm.icmp "sgt" %arg0, %arg1 : i64
    llvm.cond_br %2, ^bb2, ^bb3
  ^bb2:  // pred: ^bb1
    %3 = llvm.sub %arg0, %arg1 : i64
    %4 = llvm.sitofp %3 : i64 to f64
    llvm.br ^bb4(%1, %arg0, %arg1, %4 : i32, i64, i64, f64)
  ^bb3:  // pred: ^bb1
    %5 = llvm.sitofp %arg1 : i64 to f64
    %6 = llvm.sitofp %arg0 : i64 to f64
    %7 = llvm.fdiv %0, %6  : f64
    %8 = llvm.fsub %5, %7  : f64
    llvm.br ^bb4(%1, %arg0, %arg1, %8 : i32, i64, i64, f64)
  ^bb4(%9: i32, %10: i64, %11: i64, %12: f64):  // 2 preds: ^bb2, ^bb3
    llvm.br ^bb5
  ^bb5:  // pred: ^bb4
    %13 = llvm.sitofp %10 : i64 to f64
    %14 = llvm.fsub %12, %13  : f64
    llvm.return %14 : f64
  }
  llvm.func @_mlir_ciface_func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %0 = llvm.call @func(%arg0, %arg1) : (i64, i64) -> f64
    llvm.return %0 : f64
  }
}
[metadata] ▶
time elapsed 1.23ms
timing breakdown:
  1.23ms: MLIR optimized      

Testing report

1. Args ▶
(10, 33)
2. JIT output ▶
22.9
3. Expected output ▶
22.9

Testing report

1. Args ▶
(7, 3)
2. JIT output ▶
-3.0
3. Expected output ▶
-3.0

Example 3: Simple While Loop¶

Demonstrate loop compilation with the MLIR backend.

In [17]:
def example_3(init, n):
    c = float(init)
    i = 0
    while i < n:
        c = c + float(i)
        i = i + 1
    return c
In [18]:
if __name__ == "__main__":
    report = Report("Pipeline execution report", enable_nested_metadata=True)
    jit_func = jit_compiler(
        fn=example_3,
        argtypes=(Int64, Int64),
        ruleset=(loop_ruleset | setup_argtypes(TypeInt64, TypeInt64)),
        pipeline_report=report,
        **compiler_config,
    ).jit_func
    report.display()
    run_test(example_3, jit_func, (10, 7), verbose=True)

Pipeline execution report

1. Frontend (16.95ms) ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   1|def example_3(init, n):
   2|    c = float(init)
   3|    i = 0
   4|    while i < n:
   5|        c = c + float(i)
   6|        i = i + 1
   7|    return c
----------------------------------inter source----------------------------------
   1|def transformed_example_3(init, n):
   2|    """#file: /tmp/ipykernel_3723/840461217.py"""
   3|    '#loc: 2:8-2:23'
   4|    c = float(init)
   5|    '#loc: 3:8-3:13'
   6|    i = 0
   7|    '#loc: 4:8-6:21'
   8|    __scfg_loop_cont_1__ = True
   9|    while __scfg_loop_cont_1__:
  10|        if i < n:
  11|            '#loc: 5:12-5:28'
  12|            c = c + float(i)
  13|            '#loc: 6:12-6:21'
  14|            i = i + 1
  15|            __scfg_backedge_var_0__ = 0
  16|        else:
  17|            __scfg_backedge_var_0__ = 1
  18|        __scfg_loop_cont_1__ = not __scfg_backedge_var_0__
  19|    '#loc: 7:8-7:16'
  20|    return c
RVSDG ▶
transformed_example_3 = Func (Args (ArgSpec 'init' (PyNone)) (ArgSpec 'n' (PyNone)))
$0 = Region[940] <- !io init n
{
  $1 = PyLoadGlobal $0[0] 'float'
  $2 = PyCall $1 $0[0] $0[1]
  $3 = Undef __scfg_backedge_var_0__
  $4 = PyBool True
  $5 = DbgValue '__scfg_loop_cont_1__' $4
  $6 = DbgValue 'c' $2[1]
  $7 = PyInt 0
  $8 = DbgValue 'i' $7
  $9 = Loop [1745] <- $2[0] $3 $5 $6 $8 $0[1] $0[2]
    $10 = Region[1083] <- !io __scfg_backedge_var_0__ __scfg_loop_cont_1__ c i init n
    {
      $11 = PyBinOp < $10[0] $10[4], $10[6]
      $12 = If $11[1] <- $10[0] $10[1] $10[2] $10[3] $10[4] $10[5] $10[6]
        $13 = Region[1149] <- !io __scfg_backedge_var_0__ __scfg_loop_cont_1__ c i init n
        {
          $14 = PyLoadGlobal $13[0] 'float'
          $15 = PyCall $14 $13[0] $13[4]
          $16 = PyBinOp + $15[0] $13[3], $15[1]
          $17 = PyInt 1
          $18 = PyBinOp + $16[0] $13[4], $17
          $19 = PyInt 0
          $20 = DbgValue '__scfg_backedge_var_0__' $19
          $21 = DbgValue 'c' $16[1]
          $22 = DbgValue 'i' $18[1]
        } [1538] -> !io=$18[0] __scfg_backedge_var_0__=$20 __scfg_loop_cont_1__=$13[2] c=$21 i=$22 init=$13[5] n=$13[6]
        Else
        $23 = Region[1384] <- !io __scfg_backedge_var_0__ __scfg_loop_cont_1__ c i init n
        {
          $24 = PyInt 1
          $25 = DbgValue '__scfg_backedge_var_0__' $24
        } [1584] -> !io=$23[0] __scfg_backedge_var_0__=$25 __scfg_loop_cont_1__=$23[2] c=$23[3] i=$23[4] init=$23[5] n=$23[6]
      Endif
      $26 = PyUnaryOp not $12[0] $12[1]
      $27 = DbgValue '__scfg_loop_cont_1__' $26[1]
    } [1733] -> !_loopcond_0002=$27 !io=$26[0] __scfg_backedge_var_0__=$12[1] __scfg_loop_cont_1__=$27 c=$12[3] i=$12[4] init=$12[5] n=$12[6]
  EndLoop
} [1847] -> !io=$9[0] !ret=$9[3]
[metadata] ▶
time elapsed 16.95ms
timing breakdown:
  13.50ms: Debug Info on RVSDG 
  3.45ms: RVSDG               
2. EGraph Conversion (67.93ms) ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_InPorts-65 cluster_InPorts-65 outer_cluster_Port-100 cluster_Port-100 outer_cluster_Port-77 cluster_Port-77 outer_cluster_Port-80 cluster_Port-80 outer_cluster_Port-82 cluster_Port-82 outer_cluster_Port-37 cluster_Port-37 outer_cluster_Port-86 cluster_Port-86 outer_cluster_Port-43 cluster_Port-43 outer_cluster_Port-102 cluster_Port-102 outer_cluster_Port-23 cluster_Port-23 outer_cluster_Port-74 cluster_Port-74 outer_cluster_Port-51 cluster_Port-51 outer_cluster_Port-25 cluster_Port-25 outer_cluster_Port-84 cluster_Port-84 outer_cluster_Port-45 cluster_Port-45 outer_cluster_Port-35 cluster_Port-35 outer_cluster_Port-27 cluster_Port-27 outer_cluster_Port-33 cluster_Port-33 outer_cluster_Port-41 cluster_Port-41 outer_cluster_Port-49 cluster_Port-49 outer_cluster_Port-78 cluster_Port-78 outer_cluster_Port-53 cluster_Port-53 outer_cluster_Port-76 cluster_Port-76 outer_cluster_Port-30 cluster_Port-30 outer_cluster_Port-47 cluster_Port-47 outer_cluster_PortList-54 cluster_PortList-54 outer_cluster_PortList-103 cluster_PortList-103 outer_cluster_PortList-38 cluster_PortList-38 outer_cluster_PortList-87 cluster_PortList-87 outer_cluster_Region-66 cluster_Region-66 outer_cluster_Region-16 cluster_Region-16 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Region-15 cluster_Region-15 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-72 cluster_Term-72 outer_cluster_Term-36 cluster_Term-36 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-39 cluster_Term-39 outer_cluster_Term-61 cluster_Term-61 outer_cluster_Term-2 cluster_Term-2 outer_cluster_Term-81 cluster_Term-81 outer_cluster_Term-17 cluster_Term-17 outer_cluster_Term-11 cluster_Term-11 outer_cluster_Term-75 cluster_Term-75 outer_cluster_Term-93 cluster_Term-93 outer_cluster_Term-92 cluster_Term-92 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-63 cluster_Term-63 outer_cluster_Term-94 cluster_Term-94 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-44 cluster_Term-44 outer_cluster_Term-55 cluster_Term-55 outer_cluster_Term-59 cluster_Term-59 outer_cluster_Term-42 cluster_Term-42 outer_cluster_Term-64 cluster_Term-64 outer_cluster_Term-46 cluster_Term-46 outer_cluster_Term-106 cluster_Term-106 outer_cluster_Term-71 cluster_Term-71 outer_cluster_Term-79 cluster_Term-79 outer_cluster_Term-91 cluster_Term-91 outer_cluster_Term-83 cluster_Term-83 outer_cluster_Term-24 cluster_Term-24 outer_cluster_Term-26 cluster_Term-26 outer_cluster_Term-99 cluster_Term-99 outer_cluster_Term-85 cluster_Term-85 outer_cluster_Term-14 cluster_Term-14 outer_cluster_Term-101 cluster_Term-101 outer_cluster_Term-21 cluster_Term-21 outer_cluster_Term-48 cluster_Term-48 outer_cluster_Term-88 cluster_Term-88 outer_cluster_Term-67 cluster_Term-67 outer_cluster_Term-68 cluster_Term-68 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-40 cluster_Term-40 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-57 cluster_Term-57 outer_cluster_Term-98 cluster_Term-98 outer_cluster_Term-69 cluster_Term-69 outer_cluster_Term-89 cluster_Term-89 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-73 cluster_Term-73 outer_cluster_Term-29 cluster_Term-29 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-95 cluster_Term-95 outer_cluster_Term-4 cluster_Term-4 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-62 cluster_Term-62 outer_cluster_Term-58 cluster_Term-58 outer_cluster_Term-96 cluster_Term-96 outer_cluster_Term-56 cluster_Term-56 outer_cluster_Term-13 cluster_Term-13 outer_cluster_Term-32 cluster_Term-32 outer_cluster_Term-28 cluster_Term-28 outer_cluster_Term-50 cluster_Term-50 outer_cluster_Term-52 cluster_Term-52 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-90 cluster_Term-90 outer_cluster_Term-18 cluster_Term-18 outer_cluster_Term-105 cluster_Term-105 outer_cluster_Term-104 cluster_Term-104 outer_cluster_Term-34 cluster_Term-34 outer_cluster_TermList-70 cluster_TermList-70 outer_cluster_TermList-5 cluster_TermList-5 outer_cluster_TermList-97 cluster_TermList-97 outer_cluster_TermList-60 cluster_TermList-60 outer_cluster_Vec_Port-3 cluster_Vec_Port-3 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_String-0 cluster_Vec_String-0 outer_cluster_Vec_String-1 cluster_Vec_String-1 outer_cluster_Vec_Term-0 cluster_Vec_Term-0 outer_cluster_Vec_Term-1 cluster_Vec_Term-1 outer_cluster_Vec_Term-2 cluster_Vec_Term-2 outer_cluster_Vec_Term-3 cluster_Vec_Term-3 function-0-InPorts___init__:s->primitive-Vec_String-0 function-1-InPorts___init__:s->primitive-Vec_String-1 function-22-Port___init__:s->function-17-Term_getPort function-17-Term_getPort:s->function-0-Term_Loop function-16-Port___init__:s->function-8-Term_getPort function-8-Term_getPort:s->function-0-Term_IfElse function-18-Port___init__:s->function-11-Term_getPort function-11-Term_getPort:s->function-0-Term_IfElse function-19-Port___init__:s->function-12-Term_getPort function-12-Term_getPort:s->function-0-Term_IfElse function-6-Port___init__:s->function-8-Region_get function-8-Region_get:s->function-0-Region___init__ function-21-Port___init__:s->function-14-Term_getPort function-14-Term_getPort:s->function-0-Term_IfElse function-8-Port___init__:s->function-3-Term_DbgValue function-3-Term_DbgValue:s->function-0-Term_LiteralI64 function-23-Port___init__:s->function-18-Term_getPort function-18-Term_getPort:s->function-0-Term_Loop function-0-Port___init__:s->function-4-Term_getPort function-4-Term_getPort:s->function-1-Py_AddIO function-14-Port___init__:s->function-4-Term_DbgValue function-4-Term_DbgValue:s->function-9-Term_getPort function-12-Port___init__:s->function-13-Region_get function-13-Region_get:s->function-1-Region___init__ function-1-Port___init__:s->function-0-Term_DbgValue function-0-Term_DbgValue:s->function-1-Term_LiteralI64 function-20-Port___init__:s->function-13-Term_getPort function-13-Term_getPort:s->function-0-Term_IfElse function-9-Port___init__:s->function-10-Region_get function-10-Region_get:s->function-1-Region___init__ function-5-Port___init__:s->function-7-Region_get function-7-Region_get:s->function-0-Region___init__ function-2-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-0-Region___init__ function-4-Port___init__:s->function-2-Term_DbgValue function-2-Term_DbgValue:s->function-6-Term_getPort function-7-Port___init__:s->function-9-Region_get function-9-Region_get:s->function-1-Region___init__ function-11-Port___init__:s->function-12-Region_get function-12-Region_get:s->function-1-Region___init__ function-17-Port___init__:s->function-4-Term_DbgValue function-13-Port___init__:s->function-14-Region_get function-14-Region_get:s->function-1-Region___init__ function-15-Port___init__:s->function-10-Term_getPort function-10-Term_getPort:s->function-0-Py_NotIO function-3-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-5-Term_getPort function-10-Port___init__:s->function-11-Region_get function-11-Region_get:s->function-1-Region___init__ function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-8-Port___init__ primitive-Vec_Port-1:s->function-12-Port___init__ primitive-Vec_Port-1:s->function-9-Port___init__ primitive-Vec_Port-1:s->function-7-Port___init__ primitive-Vec_Port-1:s->function-11-Port___init__ primitive-Vec_Port-1:s->function-13-Port___init__ primitive-Vec_Port-1:s->function-10-Port___init__ function-3-PortList___init__:s->primitive-Vec_Port-3 primitive-Vec_Port-3:s->function-22-Port___init__ primitive-Vec_Port-3:s->function-23-Port___init__ function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-6-Port___init__ primitive-Vec_Port-0:s->function-0-Port___init__ primitive-Vec_Port-0:s->function-1-Port___init__ primitive-Vec_Port-0:s->function-5-Port___init__ primitive-Vec_Port-0:s->function-2-Port___init__ primitive-Vec_Port-0:s->function-4-Port___init__ primitive-Vec_Port-0:s->function-3-Port___init__ function-2-PortList___init__:s->primitive-Vec_Port-2 primitive-Vec_Port-2:s->function-16-Port___init__ primitive-Vec_Port-2:s->function-18-Port___init__ primitive-Vec_Port-2:s->function-19-Port___init__ primitive-Vec_Port-2:s->function-21-Port___init__ primitive-Vec_Port-2:s->function-14-Port___init__ primitive-Vec_Port-2:s->function-20-Port___init__ primitive-Vec_Port-2:s->function-17-Port___init__ primitive-Vec_Port-2:s->function-15-Port___init__ function-3-Region___init__:s->function-1-InPorts___init__ function-2-Region___init__:s->function-0-InPorts___init__ function-0-Region___init__:s->function-0-InPorts___init__ function-1-Region___init__:s->function-0-InPorts___init__ function-9-Term_getPort:s->function-0-Py_NotIO function-0-Py_NotIO:s->function-8-Term_getPort function-0-Py_NotIO:s->function-7-Term_getPort function-0-Py_Call:s->function-0-Py_LoadGlobal function-0-Py_Call:s->function-1-Region_get function-0-Py_Call:s->function-0-TermList___init__ function-0-Py_LoadGlobal:s->function-1-Region_get function-1-Region_get:s->function-0-Region___init__ function-0-TermList___init__:s->primitive-Vec_Term-0 function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-0-Region___init__ function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-3-Term_getPort function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-1-TermList___init__ function-3-Term_getPort:s->function-0-Py_LtIO function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-1-Region___init__ function-1-TermList___init__:s->primitive-Vec_Term-1 function-0-Region_get:s->function-0-Region___init__ function-3-Region_get:s->function-2-Region___init__ function-2-Term_getPort:s->function-0-Py_AddIO function-0-Py_AddIO:s->function-0-Term_getPort function-0-Py_AddIO:s->function-2-Region_get function-0-Py_AddIO:s->function-1-Term_getPort function-16-Term_getPort:s->function-1-Py_Call function-1-Py_Call:s->function-1-Py_LoadGlobal function-1-Py_Call:s->function-20-Region_get function-1-Py_Call:s->function-2-TermList___init__ function-5-Term_DbgValue:s->function-0-Term_LiteralBool function-0-Term_getPort:s->function-0-Py_Call function-2-Region_get:s->function-0-Region___init__ function-1-Term_getPort:s->function-0-Py_Call function-6-Term_DbgValue:s->function-16-Term_getPort function-18-Region_get:s->function-2-Region___init__ function-7-Term_getPort:s->function-0-Term_IfElse function-0-GraphRoot:s->function-0-Term_Func function-0-Term_Func:s->function-3-Term_RegionEnd function-1-Py_LoadGlobal:s->function-20-Region_get function-20-Region_get:s->function-3-Region___init__ function-2-TermList___init__:s->primitive-Vec_Term-2 function-0-Term_Loop:s->function-2-Term_RegionEnd function-0-Term_Loop:s->function-3-TermList___init__ function-0-Py_LtIO:s->function-3-Region_get function-0-Py_LtIO:s->function-5-Region_get function-0-Py_LtIO:s->function-4-Region_get function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-2-Region___init__ function-19-Region_get:s->function-3-Region___init__ function-1-Py_AddIO:s->function-0-Term_LiteralI64 function-1-Py_AddIO:s->function-0-Region_get function-1-Py_AddIO:s->function-2-Term_getPort function-6-Term_getPort:s->function-1-Py_AddIO function-5-Region_get:s->function-2-Region___init__ function-16-Region_get:s->function-2-Region___init__ function-3-TermList___init__:s->primitive-Vec_Term-3 function-15-Term_getPort:s->function-1-Py_Call function-5-Term_getPort:s->function-0-Py_AddIO function-4-Region_get:s->function-2-Region___init__ function-7-Term_DbgValue:s->function-1-Term_LiteralI64 function-17-Region_get:s->function-2-Region___init__ function-21-Region_get:s->function-3-Region___init__ function-15-Region_get:s->function-2-Region___init__ function-3-Term_RegionEnd:s->function-3-PortList___init__ function-3-Term_RegionEnd:s->function-3-Region___init__ primitive-Vec_Term-2:s->function-19-Region_get primitive-Vec_Term-0:s->function-0-Region_get primitive-Vec_Term-3:s->function-5-Term_DbgValue primitive-Vec_Term-3:s->function-6-Term_DbgValue primitive-Vec_Term-3:s->function-19-Region_get primitive-Vec_Term-3:s->function-15-Term_getPort primitive-Vec_Term-3:s->function-7-Term_DbgValue primitive-Vec_Term-3:s->function-21-Region_get primitive-Vec_Term-3:s->function-0-Term_Undef primitive-Vec_Term-1:s->function-3-Region_get primitive-Vec_Term-1:s->function-18-Region_get primitive-Vec_Term-1:s->function-5-Region_get primitive-Vec_Term-1:s->function-16-Region_get primitive-Vec_Term-1:s->function-4-Region_get primitive-Vec_Term-1:s->function-17-Region_get primitive-Vec_Term-1:s->function-15-Region_get function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "__scfg_backedge_var_0__", "__scfg_loop_cont_1__", "c", "i", "init", "n") function-1-InPorts___init__ InPorts primitive-Vec_String-1 Vec("!io", "init", "n") function-22-Port___init__ Port("!io", ·) function-17-Term_getPort ·.getPort(·, 0) function-16-Port___init__ Port("__scfg_backedge_var_0__", ·) function-8-Term_getPort ·.getPort(·, 1) function-18-Port___init__ Port("c", ·) function-11-Term_getPort ·.getPort(·, 3) function-19-Port___init__ Port("i", ·) function-12-Term_getPort ·.getPort(·, 4) function-6-Port___init__ Port("n", ·) function-8-Region_get ·.get(·, 6) function-21-Port___init__ Port("n", ·) function-14-Term_getPort ·.getPort(·, 6) function-8-Port___init__ Port("__scfg_backedge_var_0__", ·) function-3-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-23-Port___init__ Port("!ret", ·) function-18-Term_getPort ·.getPort(·, 3) function-0-Port___init__ Port("!io", ·) function-4-Term_getPort ·.getPort(·, 0) function-14-Port___init__ Port("!_loopcond_0002", ·) function-4-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-12-Port___init__ Port("init", ·) function-13-Region_get ·.get(·, 5) function-1-Port___init__ Port("__scfg_backedge_var_0__", ·) function-0-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-20-Port___init__ Port("init", ·) function-13-Term_getPort ·.getPort(·, 5) function-9-Port___init__ Port("__scfg_loop_cont_1__", ·) function-10-Region_get ·.get(·, 2) function-5-Port___init__ Port("init", ·) function-7-Region_get ·.get(·, 5) function-2-Port___init__ Port("__scfg_loop_cont_1__", ·) function-6-Region_get ·.get(·, 2) function-4-Port___init__ Port("i", ·) function-2-Term_DbgValue Term.DbgValue("i", ·) function-7-Port___init__ Port("!io", ·) function-9-Region_get ·.get(·, 0) function-11-Port___init__ Port("i", ·) function-12-Region_get ·.get(·, 4) function-17-Port___init__ Port("__scfg_loop_cont_1__", ·) function-13-Port___init__ Port("n", ·) function-14-Region_get ·.get(·, 6) function-15-Port___init__ Port("!io", ·) function-10-Term_getPort ·.getPort(·, 0) function-3-Port___init__ Port("c", ·) function-1-Term_DbgValue Term.DbgValue("c", ·) function-10-Port___init__ Port("c", ·) function-11-Region_get ·.get(·, 3) function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-3-PortList___init__ PortList primitive-Vec_Port-3 Vec function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-3-Region___init__ Region("940", ·) function-2-Region___init__ Region("1083", ·) function-0-Region___init__ Region("1149", ·) function-1-Region___init__ Region("1384", ·) function-0-Term_LiteralI64 Term.LiteralI64(1) function-9-Term_getPort ·.getPort(·, 1) function-0-Py_NotIO Py_NotIO function-0-Py_Call Py_Call function-0-Py_LoadGlobal Py_LoadGlobal(·, "float") function-1-Region_get ·.get(·, 0) function-0-TermList___init__ TermList function-0-Term_RegionEnd Term.RegionEnd function-0-Term_IfElse Term.IfElse function-3-Term_getPort ·.getPort(·, 1) function-1-Term_RegionEnd Term.RegionEnd function-1-TermList___init__ TermList function-0-Region_get ·.get(·, 4) function-3-Region_get ·.get(·, 0) function-2-Term_getPort ·.getPort(·, 0) function-0-Py_AddIO Py_AddIO function-16-Term_getPort ·.getPort(·, 1) function-1-Py_Call Py_Call function-5-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-0-Term_LiteralBool Term.LiteralBool(true) function-0-Term_getPort ·.getPort(·, 0) function-2-Region_get ·.get(·, 3) function-1-Term_getPort ·.getPort(·, 1) function-6-Term_DbgValue Term.DbgValue("c", ·) function-18-Region_get ·.get(·, 5) function-7-Term_getPort ·.getPort(·, 0) function-0-GraphRoot GraphRoot function-0-Term_Func Term.Func("1853", "transformed_example_3", ·) function-1-Py_LoadGlobal Py_LoadGlobal(·, "float") function-20-Region_get ·.get(·, 0) function-2-TermList___init__ TermList function-1-Term_LiteralI64 Term.LiteralI64(0) function-0-Term_Loop Term.Loop function-0-Py_LtIO Py_LtIO function-2-Term_RegionEnd Term.RegionEnd function-19-Region_get ·.get(·, 1) function-1-Py_AddIO Py_AddIO function-6-Term_getPort ·.getPort(·, 1) function-5-Region_get ·.get(·, 6) function-16-Region_get ·.get(·, 2) function-3-TermList___init__ TermList function-15-Term_getPort ·.getPort(·, 0) function-5-Term_getPort ·.getPort(·, 1) function-4-Region_get ·.get(·, 4) function-7-Term_DbgValue Term.DbgValue("i", ·) function-17-Region_get ·.get(·, 3) function-21-Region_get ·.get(·, 2) function-15-Region_get ·.get(·, 1) function-0-Term_Undef Term.Undef("__scfg_backedge_var_0__") function-3-Term_RegionEnd Term.RegionEnd primitive-Vec_Term-2 Vec primitive-Vec_Term-0 Vec primitive-Vec_Term-3 Vec primitive-Vec_Term-1 Vec
[metadata] ▶
time elapsed 67.93ms
timing breakdown:
  67.93ms: EGraph              
3. Egraph Saturation (0.00ms) ▶
Egraph Saturation
[metadata] ▶
time elapsed 0.00ms
timing breakdown:
4. EGraph Extraction (65.56ms) ▶
EGraph Extraction
Extracted RVSDG ▶
transformed_example_3 = Func (Args (ArgSpec 'init' (PyNone)) (ArgSpec 'n' (PyNone)))
$0 = Region[2116] <- !io init n; #attrs (_, Int64, Int64)->(_, Float64)
{
  $1 = PyInt 0
  $2 = PyBool True
  $3 = NbOp_CastI64ToF64 $0[1]
  $4 = Loop [2715] <- $0[0] $1 $2 $3 $1 $0[1] $0[2]
    $5 = Region[2208] <- !io __scfg_backedge_var_0__ __scfg_loop_cont_1__ c i init n; #attrs (_, Int64, Bool, Float64, Int64, Int64, Int64)->(Bool, _, Int64, Bool, Float64, Int64, Int64, Int64)
    {
      $6 = NbOp_Lt_Int64 $5[4] $5[6]
      $7 = If $6 <- $5[0] $5[1] $5[2] $5[3] $5[4] $5[5] $5[6]
        $8 = Region[2303] <- !io __scfg_backedge_var_0__ __scfg_loop_cont_1__ c i init n; #attrs (_, _, Bool, Float64, Int64, Int64, Int64)->(_, Int64, Bool, Float64, Int64, Int64, Int64)
        {
          $9 = NbOp_CastI64ToF64 $8[4]
          $10 = NbOp_Add_Float64 $8[3] $9
          $11 = PyInt 1
          $12 = NbOp_Add_Int64 $8[4] $11
        } [2401] -> !io=$8[0] __scfg_backedge_var_0__=$1 __scfg_loop_cont_1__=$8[2] c=$10 i=$12 init=$8[5] n=$8[6]
        Else
        $13 = Region[2481] <- !io __scfg_backedge_var_0__ __scfg_loop_cont_1__ c i init n; #attrs (_, _, Bool, Float64, Int64, Int64, Int64)->(_, Int64, Bool, Float64, Int64, Int64, Int64)
        {
        } [2557] -> !io=$13[0] __scfg_backedge_var_0__=$11 __scfg_loop_cont_1__=$13[2] c=$13[3] i=$13[4] init=$13[5] n=$13[6]
      Endif
      $14 = NbOp_Not_Int64 $7[1]
    } [2680] -> !_loopcond_0002=$14 !io=$7[0] __scfg_backedge_var_0__=$7[1] __scfg_loop_cont_1__=$14 c=$7[3] i=$7[4] init=$7[5] n=$7[6]
  EndLoop
} [2746] -> !io=$4[0] !ret=$4[3]
Extracted cost ▶
5761859147.0
[metadata] ▶
time elapsed 65.56ms
timing breakdown:
  65.55ms: Extracted RVSDG     
  0.01ms: Extracted cost      
5. Backend (1.93ms) ▶
Backend
Lowered module ▶
module {
  func.func @func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %c0_i64 = arith.constant 0 : i64
    %true = arith.constant true
    %c1_i64 = arith.constant 1 : i64
    cf.br ^bb1
  ^bb1:  // pred: ^bb0
    %c0_i32 = arith.constant 0 : i32
    %0 = arith.sitofp %arg0 : i64 to f64
    %1:7 = scf.while (%arg2 = %c0_i32, %arg3 = %c0_i64, %arg4 = %true, %arg5 = %0, %arg6 = %c0_i64, %arg7 = %arg0, %arg8 = %arg1) : (i32, i64, i1, f64, i64, i64, i64) -> (i32, i64, i1, f64, i64, i64, i64) {
      %2 = arith.cmpi slt, %arg6, %arg8 : i64
      %3:7 = scf.if %2 -> (i32, i64, i1, f64, i64, i64, i64) {
        %5 = arith.sitofp %arg6 : i64 to f64
        %6 = arith.addf %arg5, %5 : f64
        %7 = arith.addi %arg6, %c1_i64 : i64
        scf.yield %arg2, %c0_i64, %arg4, %6, %7, %arg7, %arg8 : i32, i64, i1, f64, i64, i64, i64
      } else {
        scf.yield %arg2, %c1_i64, %arg4, %arg5, %arg6, %arg7, %arg8 : i32, i64, i1, f64, i64, i64, i64
      }
      %c0_i64_0 = arith.constant 0 : i64
      %4 = arith.cmpi eq, %3#1, %c0_i64_0 : i64
      scf.condition(%4) %3#0, %3#1, %4, %3#3, %3#4, %3#5, %3#6 : i32, i64, i1, f64, i64, i64, i64
    } do {
    ^bb0(%arg2: i32, %arg3: i64, %arg4: i1, %arg5: f64, %arg6: i64, %arg7: i64, %arg8: i64):
      scf.yield %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8 : i32, i64, i1, f64, i64, i64, i64
    }
    return %1#3 : f64
  }
}
[metadata] ▶
time elapsed 1.93ms
timing breakdown:
  1.93ms: Lowered module      
6. MLIR passes (1.35ms) ▶
MLIR passes
MLIR optimized ▶
module {
  llvm.func @func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %0 = llvm.mlir.constant(0 : i32) : i32
    %1 = llvm.mlir.constant(0 : i64) : i64
    %2 = llvm.mlir.constant(true) : i1
    %3 = llvm.mlir.constant(1 : i64) : i64
    llvm.br ^bb1
  ^bb1:  // pred: ^bb0
    %4 = llvm.sitofp %arg0 : i64 to f64
    llvm.br ^bb2(%0, %1, %2, %4, %1, %arg0, %arg1 : i32, i64, i1, f64, i64, i64, i64)
  ^bb2(%5: i32, %6: i64, %7: i1, %8: f64, %9: i64, %10: i64, %11: i64):  // 2 preds: ^bb1, ^bb6
    %12 = llvm.icmp "slt" %9, %11 : i64
    llvm.cond_br %12, ^bb3, ^bb4
  ^bb3:  // pred: ^bb2
    %13 = llvm.sitofp %9 : i64 to f64
    %14 = llvm.fadd %8, %13  : f64
    %15 = llvm.add %9, %3 : i64
    llvm.br ^bb5(%5, %1, %7, %14, %15, %10, %11 : i32, i64, i1, f64, i64, i64, i64)
  ^bb4:  // pred: ^bb2
    llvm.br ^bb5(%5, %3, %7, %8, %9, %10, %11 : i32, i64, i1, f64, i64, i64, i64)
  ^bb5(%16: i32, %17: i64, %18: i1, %19: f64, %20: i64, %21: i64, %22: i64):  // 2 preds: ^bb3, ^bb4
    llvm.br ^bb6
  ^bb6:  // pred: ^bb5
    %23 = llvm.icmp "eq" %17, %1 : i64
    llvm.cond_br %23, ^bb2(%16, %17, %23, %19, %20, %21, %22 : i32, i64, i1, f64, i64, i64, i64), ^bb7
  ^bb7:  // pred: ^bb6
    llvm.return %19 : f64
  }
  llvm.func @_mlir_ciface_func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %0 = llvm.call @func(%arg0, %arg1) : (i64, i64) -> f64
    llvm.return %0 : f64
  }
}
[metadata] ▶
time elapsed 1.35ms
timing breakdown:
  1.35ms: MLIR optimized      

Testing report

1. Args ▶
(10, 7)
2. JIT output ▶
31.0
3. Expected output ▶
31.0

Example 4: Nested Loop¶

Test nested loop compilation with the MLIR backend.

In [19]:
def example_4(init, n):
    c = float(init)
    i = 0
    while i < n:
        j = 0
        while j < i:
            c = c + float(j)
            j = j + 1
        i = i + 1
    return c
In [20]:
if __name__ == "__main__":
    report = Report("Pipeline execution report", enable_nested_metadata=True)
    jit_func = jit_compiler(
        fn=example_4,
        argtypes=(Int64, Int64),
        ruleset=(loop_ruleset | setup_argtypes(TypeInt64, TypeInt64)),
        pipeline_report=report,
        **compiler_config,
    ).jit_func
    report.display()
    run_test(example_4, jit_func, (10, 7), verbose=True)

Pipeline execution report

1. Frontend (28.11ms) ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   1|def example_4(init, n):
   2|    c = float(init)
   3|    i = 0
   4|    while i < n:
   5|        j = 0
   6|        while j < i:
   7|            c = c + float(j)
   8|            j = j + 1
   9|        i = i + 1
  10|    return c
----------------------------------inter source----------------------------------
   1|def transformed_example_4(init, n):
   2|    """#file: /tmp/ipykernel_3723/2082353802.py"""
   3|    '#loc: 2:8-2:23'
   4|    c = float(init)
   5|    '#loc: 3:8-3:13'
   6|    i = 0
   7|    '#loc: 4:8-9:21'
   8|    __scfg_loop_cont_1__ = True
   9|    while __scfg_loop_cont_1__:
  10|        if i < n:
  11|            '#loc: 5:12-5:17'
  12|            j = 0
  13|            '#loc: 6:12-8:25'
  14|            __scfg_loop_cont_2__ = True
  15|            while __scfg_loop_cont_2__:
  16|                if j < i:
  17|                    '#loc: 7:16-7:32'
  18|                    c = c + float(j)
  19|                    '#loc: 8:16-8:25'
  20|                    j = j + 1
  21|                    __scfg_backedge_var_1__ = 0
  22|                else:
  23|                    __scfg_backedge_var_1__ = 1
  24|                __scfg_loop_cont_2__ = not __scfg_backedge_var_1__
  25|            '#loc: 9:12-9:21'
  26|            i = i + 1
  27|            __scfg_backedge_var_0__ = 0
  28|        else:
  29|            __scfg_backedge_var_0__ = 1
  30|        __scfg_loop_cont_1__ = not __scfg_backedge_var_0__
  31|    '#loc: 10:8-10:16'
  32|    return c
RVSDG ▶
transformed_example_4 = Func (Args (ArgSpec 'init' (PyNone)) (ArgSpec 'n' (PyNone)))
$0 = Region[1423] <- !io init n
{
  $1 = PyLoadGlobal $0[0] 'float'
  $2 = PyCall $1 $0[0] $0[1]
  $3 = Undef __scfg_backedge_var_0__
  $4 = Undef __scfg_backedge_var_1__
  $5 = PyBool True
  $6 = DbgValue '__scfg_loop_cont_1__' $5
  $7 = Undef __scfg_loop_cont_2__
  $8 = DbgValue 'c' $2[1]
  $9 = PyInt 0
  $10 = DbgValue 'i' $9
  $11 = Undef j
  $12 = Loop [3296] <- $2[0] $3 $4 $6 $7 $8 $10 $0[1] $11 $0[2]
    $13 = Region[1578] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n
    {
      $14 = PyBinOp < $13[0] $13[6], $13[9]
      $15 = If $14[1] <- $13[0] $13[1] $13[2] $13[3] $13[4] $13[5] $13[6] $13[7] $13[8] $13[9]
        $16 = Region[1662] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n
        {
          $17 = PyBool True
          $18 = DbgValue '__scfg_loop_cont_2__' $17
          $19 = PyInt 0
          $20 = DbgValue 'j' $19
          $21 = Loop [2618] <- $16[0] $16[1] $16[2] $16[3] $18 $16[5] $16[6] $16[7] $20 $16[9]
            $22 = Region[1791] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n
            {
              $23 = PyBinOp < $22[0] $22[8], $22[6]
              $24 = If $23[1] <- $22[0] $22[1] $22[2] $22[3] $22[4] $22[5] $22[6] $22[7] $22[8] $22[9]
                $25 = Region[1875] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n
                {
                  $26 = PyLoadGlobal $25[0] 'float'
                  $27 = PyCall $26 $25[0] $25[8]
                  $28 = PyBinOp + $27[0] $25[5], $27[1]
                  $29 = PyInt 1
                  $30 = PyBinOp + $28[0] $25[8], $29
                  $31 = PyInt 0
                  $32 = DbgValue '__scfg_backedge_var_1__' $31
                  $33 = DbgValue 'c' $28[1]
                  $34 = DbgValue 'j' $30[1]
                } [2351] -> !io=$30[0] __scfg_backedge_var_0__=$25[1] __scfg_backedge_var_1__=$32 __scfg_loop_cont_1__=$25[3] __scfg_loop_cont_2__=$25[4] c=$33 i=$25[6] init=$25[7] j=$34 n=$25[9]
                Else
                $35 = Region[2146] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n
                {
                  $36 = PyInt 1
                  $37 = DbgValue '__scfg_backedge_var_1__' $36
                } [2415] -> !io=$35[0] __scfg_backedge_var_0__=$35[1] __scfg_backedge_var_1__=$37 __scfg_loop_cont_1__=$35[3] __scfg_loop_cont_2__=$35[4] c=$35[5] i=$35[6] init=$35[7] j=$35[8] n=$35[9]
              Endif
              $38 = PyUnaryOp not $24[0] $24[2]
              $39 = DbgValue '__scfg_loop_cont_2__' $38[1]
            } [2603] -> !_loopcond_0004=$39 !io=$38[0] __scfg_backedge_var_0__=$24[1] __scfg_backedge_var_1__=$24[2] __scfg_loop_cont_1__=$24[3] __scfg_loop_cont_2__=$39 c=$24[5] i=$24[6] init=$24[7] j=$24[8] n=$24[9]
          EndLoop
          $40 = PyInt 1
          $41 = PyBinOp + $21[0] $21[6], $40
          $42 = PyInt 0
          $43 = DbgValue '__scfg_backedge_var_0__' $42
          $44 = DbgValue 'i' $41[1]
        } [3029] -> !io=$41[0] __scfg_backedge_var_0__=$43 __scfg_backedge_var_1__=$21[2] __scfg_loop_cont_1__=$21[3] __scfg_loop_cont_2__=$21[4] c=$21[5] i=$44 init=$21[7] j=$21[8] n=$21[9]
        Else
        $45 = Region[2824] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n
        {
          $46 = PyInt 1
          $47 = DbgValue '__scfg_backedge_var_0__' $46
        } [3093] -> !io=$45[0] __scfg_backedge_var_0__=$47 __scfg_backedge_var_1__=$45[2] __scfg_loop_cont_1__=$45[3] __scfg_loop_cont_2__=$45[4] c=$45[5] i=$45[6] init=$45[7] j=$45[8] n=$45[9]
      Endif
      $48 = PyUnaryOp not $15[0] $15[1]
      $49 = DbgValue '__scfg_loop_cont_1__' $48[1]
    } [3281] -> !_loopcond_0002=$49 !io=$48[0] __scfg_backedge_var_0__=$15[1] __scfg_backedge_var_1__=$15[2] __scfg_loop_cont_1__=$49 __scfg_loop_cont_2__=$15[4] c=$15[5] i=$15[6] init=$15[7] j=$15[8] n=$15[9]
  EndLoop
} [3434] -> !io=$12[0] !ret=$12[5]
[metadata] ▶
time elapsed 28.11ms
timing breakdown:
  21.18ms: Debug Info on RVSDG 
  6.93ms: RVSDG               
2. EGraph Conversion (151.95ms) ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-182 cluster_InPorts-182 outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_Port-94 cluster_Port-94 outer_cluster_Port-191 cluster_Port-191 outer_cluster_Port-59 cluster_Port-59 outer_cluster_Port-41 cluster_Port-41 outer_cluster_Port-147 cluster_Port-147 outer_cluster_Port-189 cluster_Port-189 outer_cluster_Port-91 cluster_Port-91 outer_cluster_Port-134 cluster_Port-134 outer_cluster_Port-136 cluster_Port-136 outer_cluster_Port-163 cluster_Port-163 outer_cluster_Port-169 cluster_Port-169 outer_cluster_Port-100 cluster_Port-100 outer_cluster_Port-141 cluster_Port-141 outer_cluster_Port-197 cluster_Port-197 outer_cluster_Port-23 cluster_Port-23 outer_cluster_Port-49 cluster_Port-49 outer_cluster_Port-102 cluster_Port-102 outer_cluster_Port-229 cluster_Port-229 outer_cluster_Port-167 cluster_Port-167 outer_cluster_Port-36 cluster_Port-36 outer_cluster_Port-153 cluster_Port-153 outer_cluster_Port-199 cluster_Port-199 outer_cluster_Port-98 cluster_Port-98 outer_cluster_Port-25 cluster_Port-25 outer_cluster_Port-88 cluster_Port-88 outer_cluster_Port-132 cluster_Port-132 outer_cluster_Port-195 cluster_Port-195 outer_cluster_Port-96 cluster_Port-96 outer_cluster_Port-165 cluster_Port-165 outer_cluster_Port-61 cluster_Port-61 outer_cluster_Port-84 cluster_Port-84 outer_cluster_Port-89 cluster_Port-89 outer_cluster_Port-201 cluster_Port-201 outer_cluster_Port-227 cluster_Port-227 outer_cluster_Port-31 cluster_Port-31 outer_cluster_Port-63 cluster_Port-63 outer_cluster_Port-138 cluster_Port-138 outer_cluster_Port-38 cluster_Port-38 outer_cluster_Port-205 cluster_Port-205 outer_cluster_Port-43 cluster_Port-43 outer_cluster_Port-53 cluster_Port-53 outer_cluster_Port-51 cluster_Port-51 outer_cluster_Port-128 cluster_Port-128 outer_cluster_Port-130 cluster_Port-130 outer_cluster_Port-203 cluster_Port-203 outer_cluster_Port-92 cluster_Port-92 outer_cluster_Port-86 cluster_Port-86 outer_cluster_Port-55 cluster_Port-55 outer_cluster_Port-159 cluster_Port-159 outer_cluster_Port-194 cluster_Port-194 outer_cluster_Port-143 cluster_Port-143 outer_cluster_Port-207 cluster_Port-207 outer_cluster_Port-192 cluster_Port-192 outer_cluster_Port-29 cluster_Port-29 outer_cluster_Port-145 cluster_Port-145 outer_cluster_Port-157 cluster_Port-157 outer_cluster_Port-57 cluster_Port-57 outer_cluster_Port-151 cluster_Port-151 outer_cluster_Port-34 cluster_Port-34 outer_cluster_Port-27 cluster_Port-27 outer_cluster_Port-65 cluster_Port-65 outer_cluster_Port-155 cluster_Port-155 outer_cluster_Port-161 cluster_Port-161 outer_cluster_Port-47 cluster_Port-47 outer_cluster_PortList-170 cluster_PortList-170 outer_cluster_PortList-103 cluster_PortList-103 outer_cluster_PortList-208 cluster_PortList-208 outer_cluster_PortList-44 cluster_PortList-44 outer_cluster_PortList-66 cluster_PortList-66 outer_cluster_PortList-148 cluster_PortList-148 outer_cluster_PortList-230 cluster_PortList-230 outer_cluster_Region-13 cluster_Region-13 outer_cluster_Region-81 cluster_Region-81 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Region-3 cluster_Region-3 outer_cluster_Region-183 cluster_Region-183 outer_cluster_Region-120 cluster_Region-120 outer_cluster_Region-121 cluster_Region-121 outer_cluster_Term-39 cluster_Term-39 outer_cluster_Term-42 cluster_Term-42 outer_cluster_Term-184 cluster_Term-184 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-154 cluster_Term-154 outer_cluster_Term-228 cluster_Term-228 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-119 cluster_Term-119 outer_cluster_Term-231 cluster_Term-231 outer_cluster_Term-210 cluster_Term-210 outer_cluster_Term-87 cluster_Term-87 outer_cluster_Term-216 cluster_Term-216 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-21 cluster_Term-21 outer_cluster_Term-187 cluster_Term-187 outer_cluster_Term-150 cluster_Term-150 outer_cluster_Term-202 cluster_Term-202 outer_cluster_Term-214 cluster_Term-214 outer_cluster_Term-219 cluster_Term-219 outer_cluster_Term-104 cluster_Term-104 outer_cluster_Term-32 cluster_Term-32 outer_cluster_Term-79 cluster_Term-79 outer_cluster_Term-172 cluster_Term-172 outer_cluster_Term-118 cluster_Term-118 outer_cluster_Term-17 cluster_Term-17 outer_cluster_Term-213 cluster_Term-213 outer_cluster_Term-220 cluster_Term-220 outer_cluster_Term-113 cluster_Term-113 outer_cluster_Term-52 cluster_Term-52 outer_cluster_Term-60 cluster_Term-60 outer_cluster_Term-107 cluster_Term-107 outer_cluster_Term-110 cluster_Term-110 outer_cluster_Term-162 cluster_Term-162 outer_cluster_Term-14 cluster_Term-14 outer_cluster_Term-106 cluster_Term-106 outer_cluster_Term-174 cluster_Term-174 outer_cluster_Term-176 cluster_Term-176 outer_cluster_Term-223 cluster_Term-223 outer_cluster_Term-97 cluster_Term-97 outer_cluster_Term-99 cluster_Term-99 outer_cluster_Term-76 cluster_Term-76 outer_cluster_Term-45 cluster_Term-45 outer_cluster_Term-73 cluster_Term-73 outer_cluster_Term-222 cluster_Term-222 outer_cluster_Term-82 cluster_Term-82 outer_cluster_Term-226 cluster_Term-226 outer_cluster_Term-129 cluster_Term-129 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-50 cluster_Term-50 outer_cluster_Term-28 cluster_Term-28 outer_cluster_Term-54 cluster_Term-54 outer_cluster_Term-123 cluster_Term-123 outer_cluster_Term-90 cluster_Term-90 outer_cluster_Term-78 cluster_Term-78 outer_cluster_Term-116 cluster_Term-116 outer_cluster_Term-11 cluster_Term-11 outer_cluster_Term-200 cluster_Term-200 outer_cluster_Term-58 cluster_Term-58 outer_cluster_Term-109 cluster_Term-109 outer_cluster_Term-74 cluster_Term-74 outer_cluster_Term-149 cluster_Term-149 outer_cluster_Term-140 cluster_Term-140 outer_cluster_Term-4 cluster_Term-4 outer_cluster_Term-5 cluster_Term-5 outer_cluster_Term-125 cluster_Term-125 outer_cluster_Term-83 cluster_Term-83 outer_cluster_Term-67 cluster_Term-67 outer_cluster_Term-105 cluster_Term-105 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-190 cluster_Term-190 outer_cluster_Term-233 cluster_Term-233 outer_cluster_Term-156 cluster_Term-156 outer_cluster_Term-152 cluster_Term-152 outer_cluster_Term-232 cluster_Term-232 outer_cluster_Term-95 cluster_Term-95 outer_cluster_Term-180 cluster_Term-180 outer_cluster_Term-64 cluster_Term-64 outer_cluster_Term-204 cluster_Term-204 outer_cluster_Term-24 cluster_Term-24 outer_cluster_Term-40 cluster_Term-40 outer_cluster_Term-160 cluster_Term-160 outer_cluster_Term-35 cluster_Term-35 outer_cluster_Term-178 cluster_Term-178 outer_cluster_Term-46 cluster_Term-46 outer_cluster_Term-126 cluster_Term-126 outer_cluster_Term-127 cluster_Term-127 outer_cluster_Term-56 cluster_Term-56 outer_cluster_Term-181 cluster_Term-181 outer_cluster_Term-26 cluster_Term-26 outer_cluster_Term-217 cluster_Term-217 outer_cluster_Term-15 cluster_Term-15 outer_cluster_Term-139 cluster_Term-139 outer_cluster_Term-164 cluster_Term-164 outer_cluster_Term-193 cluster_Term-193 outer_cluster_Term-48 cluster_Term-48 outer_cluster_Term-2 cluster_Term-2 outer_cluster_Term-80 cluster_Term-80 outer_cluster_Term-37 cluster_Term-37 outer_cluster_Term-62 cluster_Term-62 outer_cluster_Term-137 cluster_Term-137 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-111 cluster_Term-111 outer_cluster_Term-124 cluster_Term-124 outer_cluster_Term-198 cluster_Term-198 outer_cluster_Term-158 cluster_Term-158 outer_cluster_Term-30 cluster_Term-30 outer_cluster_Term-175 cluster_Term-175 outer_cluster_Term-186 cluster_Term-186 outer_cluster_Term-85 cluster_Term-85 outer_cluster_Term-135 cluster_Term-135 outer_cluster_Term-171 cluster_Term-171 outer_cluster_Term-70 cluster_Term-70 outer_cluster_Term-71 cluster_Term-71 outer_cluster_Term-225 cluster_Term-225 outer_cluster_Term-69 cluster_Term-69 outer_cluster_Term-142 cluster_Term-142 outer_cluster_Term-68 cluster_Term-68 outer_cluster_Term-112 cluster_Term-112 outer_cluster_Term-196 cluster_Term-196 outer_cluster_Term-144 cluster_Term-144 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-211 cluster_Term-211 outer_cluster_Term-188 cluster_Term-188 outer_cluster_Term-101 cluster_Term-101 outer_cluster_Term-114 cluster_Term-114 outer_cluster_Term-173 cluster_Term-173 outer_cluster_Term-133 cluster_Term-133 outer_cluster_Term-18 cluster_Term-18 outer_cluster_Term-215 cluster_Term-215 outer_cluster_Term-72 cluster_Term-72 outer_cluster_Term-206 cluster_Term-206 outer_cluster_Term-131 cluster_Term-131 outer_cluster_Term-221 cluster_Term-221 outer_cluster_Term-33 cluster_Term-33 outer_cluster_Term-146 cluster_Term-146 outer_cluster_Term-177 cluster_Term-177 outer_cluster_Term-218 cluster_Term-218 outer_cluster_Term-117 cluster_Term-117 outer_cluster_Term-122 cluster_Term-122 outer_cluster_Term-108 cluster_Term-108 outer_cluster_Term-168 cluster_Term-168 outer_cluster_Term-93 cluster_Term-93 outer_cluster_Term-185 cluster_Term-185 outer_cluster_Term-209 cluster_Term-209 outer_cluster_Term-77 cluster_Term-77 outer_cluster_Term-166 cluster_Term-166 outer_cluster_TermList-115 cluster_TermList-115 outer_cluster_TermList-7 cluster_TermList-7 outer_cluster_TermList-212 cluster_TermList-212 outer_cluster_TermList-224 cluster_TermList-224 outer_cluster_TermList-75 cluster_TermList-75 outer_cluster_TermList-179 cluster_TermList-179 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_Port-6 cluster_Vec_Port-6 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-3 cluster_Vec_Port-3 outer_cluster_Vec_Port-4 cluster_Vec_Port-4 outer_cluster_Vec_Port-5 cluster_Vec_Port-5 outer_cluster_Vec_String-0 cluster_Vec_String-0 outer_cluster_Vec_String-1 cluster_Vec_String-1 outer_cluster_Vec_Term-0 cluster_Vec_Term-0 outer_cluster_Vec_Term-4 cluster_Vec_Term-4 outer_cluster_Vec_Term-3 cluster_Vec_Term-3 outer_cluster_Vec_Term-1 cluster_Vec_Term-1 outer_cluster_Vec_Term-5 cluster_Vec_Term-5 outer_cluster_Vec_Term-2 cluster_Vec_Term-2 function-1-InPorts___init__:s->primitive-Vec_String-1 function-0-InPorts___init__:s->primitive-Vec_String-0 function-26-Port___init__:s->function-13-Term_getPort function-13-Term_getPort:s->function-0-Term_IfElse function-52-Port___init__:s->function-33-Term_getPort function-33-Term_getPort:s->function-1-Py_NotIO function-16-Port___init__:s->function-17-Region_get function-17-Region_get:s->function-1-Region___init__ function-8-Port___init__:s->function-2-Term_DbgValue function-2-Term_DbgValue:s->function-6-Term_getPort function-40-Port___init__:s->function-29-Term_getPort function-29-Term_getPort:s->function-0-Term_Loop function-51-Port___init__:s->function-10-Term_DbgValue function-10-Term_DbgValue:s->function-32-Term_getPort function-24-Port___init__:s->function-12-Term_getPort function-12-Term_getPort:s->function-0-Term_IfElse function-34-Port___init__:s->function-23-Term_getPort function-23-Term_getPort:s->function-0-Term_Loop function-35-Port___init__:s->function-24-Term_getPort function-24-Term_getPort:s->function-0-Term_Loop function-47-Port___init__:s->function-44-Region_get function-44-Region_get:s->function-4-Region___init__ function-50-Port___init__:s->function-47-Region_get function-47-Region_get:s->function-4-Region___init__ function-29-Port___init__:s->function-16-Term_getPort function-16-Term_getPort:s->function-0-Term_IfElse function-37-Port___init__:s->function-8-Term_DbgValue function-8-Term_DbgValue:s->function-26-Term_getPort function-56-Port___init__:s->function-35-Term_getPort function-35-Term_getPort:s->function-1-Term_IfElse function-0-Port___init__:s->function-4-Term_getPort function-4-Term_getPort:s->function-1-Py_AddIO function-11-Port___init__:s->function-13-Region_get function-13-Region_get:s->function-1-Region___init__ function-30-Port___init__:s->function-17-Term_getPort function-17-Term_getPort:s->function-0-Term_IfElse function-63-Port___init__:s->function-44-Term_getPort function-44-Term_getPort:s->function-1-Term_Loop function-49-Port___init__:s->function-46-Region_get function-46-Region_get:s->function-4-Region___init__ function-6-Port___init__:s->function-9-Region_get function-9-Region_get:s->function-0-Region___init__ function-42-Port___init__:s->function-9-Term_DbgValue function-9-Term_DbgValue:s->function-0-Term_LiteralI64 function-57-Port___init__:s->function-36-Term_getPort function-36-Term_getPort:s->function-1-Term_IfElse function-28-Port___init__:s->function-15-Term_getPort function-15-Term_getPort:s->function-0-Term_IfElse function-1-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-0-Region___init__ function-22-Port___init__:s->function-11-Term_getPort function-11-Term_getPort:s->function-0-Term_IfElse function-33-Port___init__:s->function-22-Term_getPort function-22-Term_getPort:s->function-0-Term_Loop function-55-Port___init__:s->function-10-Term_DbgValue function-27-Port___init__:s->function-14-Term_getPort function-14-Term_getPort:s->function-0-Term_IfElse function-48-Port___init__:s->function-45-Region_get function-45-Region_get:s->function-4-Region___init__ function-17-Port___init__:s->function-18-Region_get function-18-Region_get:s->function-1-Region___init__ function-20-Port___init__:s->function-4-Term_DbgValue function-4-Term_DbgValue:s->function-9-Term_getPort function-23-Port___init__:s->function-8-Term_getPort function-8-Term_getPort:s->function-0-Term_IfElse function-58-Port___init__:s->function-37-Term_getPort function-37-Term_getPort:s->function-1-Term_IfElse function-62-Port___init__:s->function-43-Term_getPort function-43-Term_getPort:s->function-1-Term_Loop function-4-Port___init__:s->function-8-Region_get function-8-Region_get:s->function-0-Region___init__ function-18-Port___init__:s->function-19-Region_get function-19-Region_get:s->function-1-Region___init__ function-36-Port___init__:s->function-25-Term_getPort function-25-Term_getPort:s->function-0-Term_Loop function-7-Port___init__:s->function-10-Region_get function-10-Region_get:s->function-0-Region___init__ function-60-Port___init__:s->function-39-Term_getPort function-39-Term_getPort:s->function-1-Term_IfElse function-9-Port___init__:s->function-11-Region_get function-11-Region_get:s->function-0-Region___init__ function-13-Port___init__:s->function-14-Region_get function-14-Region_get:s->function-1-Region___init__ function-12-Port___init__:s->function-3-Term_DbgValue function-3-Term_DbgValue:s->function-0-Term_LiteralI64 function-31-Port___init__:s->function-21-Term_getPort function-21-Term_getPort:s->function-2-Py_AddIO function-32-Port___init__:s->function-7-Term_DbgValue function-7-Term_DbgValue:s->function-1-Term_LiteralI64 function-59-Port___init__:s->function-38-Term_getPort function-38-Term_getPort:s->function-1-Term_IfElse function-25-Port___init__:s->function-4-Term_DbgValue function-21-Port___init__:s->function-10-Term_getPort function-10-Term_getPort:s->function-0-Py_NotIO function-14-Port___init__:s->function-15-Region_get function-15-Region_get:s->function-1-Region___init__ function-45-Port___init__:s->function-42-Region_get function-42-Region_get:s->function-4-Region___init__ function-54-Port___init__:s->function-34-Term_getPort function-34-Term_getPort:s->function-1-Term_IfElse function-38-Port___init__:s->function-27-Term_getPort function-27-Term_getPort:s->function-0-Term_Loop function-61-Port___init__:s->function-40-Term_getPort function-40-Term_getPort:s->function-1-Term_IfElse function-53-Port___init__:s->function-30-Term_getPort function-30-Term_getPort:s->function-1-Term_IfElse function-3-Port___init__:s->function-7-Region_get function-7-Region_get:s->function-0-Region___init__ function-39-Port___init__:s->function-28-Term_getPort function-28-Term_getPort:s->function-0-Term_Loop function-44-Port___init__:s->function-41-Region_get function-41-Region_get:s->function-4-Region___init__ function-15-Port___init__:s->function-16-Region_get function-16-Region_get:s->function-1-Region___init__ function-41-Port___init__:s->function-39-Region_get function-39-Region_get:s->function-4-Region___init__ function-5-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-5-Term_getPort function-2-Port___init__:s->function-0-Term_DbgValue function-0-Term_DbgValue:s->function-1-Term_LiteralI64 function-19-Port___init__:s->function-20-Region_get function-20-Region_get:s->function-1-Region___init__ function-43-Port___init__:s->function-40-Region_get function-40-Region_get:s->function-4-Region___init__ function-46-Port___init__:s->function-43-Region_get function-43-Region_get:s->function-4-Region___init__ function-10-Port___init__:s->function-12-Region_get function-12-Region_get:s->function-1-Region___init__ function-4-PortList___init__:s->primitive-Vec_Port-4 primitive-Vec_Port-4:s->function-47-Port___init__ primitive-Vec_Port-4:s->function-50-Port___init__ primitive-Vec_Port-4:s->function-49-Port___init__ primitive-Vec_Port-4:s->function-42-Port___init__ primitive-Vec_Port-4:s->function-48-Port___init__ primitive-Vec_Port-4:s->function-45-Port___init__ primitive-Vec_Port-4:s->function-44-Port___init__ primitive-Vec_Port-4:s->function-41-Port___init__ primitive-Vec_Port-4:s->function-43-Port___init__ primitive-Vec_Port-4:s->function-46-Port___init__ function-2-PortList___init__:s->primitive-Vec_Port-2 primitive-Vec_Port-2:s->function-26-Port___init__ primitive-Vec_Port-2:s->function-24-Port___init__ primitive-Vec_Port-2:s->function-29-Port___init__ primitive-Vec_Port-2:s->function-30-Port___init__ primitive-Vec_Port-2:s->function-28-Port___init__ primitive-Vec_Port-2:s->function-22-Port___init__ primitive-Vec_Port-2:s->function-27-Port___init__ primitive-Vec_Port-2:s->function-20-Port___init__ primitive-Vec_Port-2:s->function-23-Port___init__ primitive-Vec_Port-2:s->function-25-Port___init__ primitive-Vec_Port-2:s->function-21-Port___init__ function-5-PortList___init__:s->primitive-Vec_Port-5 primitive-Vec_Port-5:s->function-52-Port___init__ primitive-Vec_Port-5:s->function-51-Port___init__ primitive-Vec_Port-5:s->function-56-Port___init__ primitive-Vec_Port-5:s->function-57-Port___init__ primitive-Vec_Port-5:s->function-55-Port___init__ primitive-Vec_Port-5:s->function-58-Port___init__ primitive-Vec_Port-5:s->function-60-Port___init__ primitive-Vec_Port-5:s->function-59-Port___init__ primitive-Vec_Port-5:s->function-54-Port___init__ primitive-Vec_Port-5:s->function-61-Port___init__ primitive-Vec_Port-5:s->function-53-Port___init__ function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-8-Port___init__ primitive-Vec_Port-0:s->function-0-Port___init__ primitive-Vec_Port-0:s->function-6-Port___init__ primitive-Vec_Port-0:s->function-1-Port___init__ primitive-Vec_Port-0:s->function-4-Port___init__ primitive-Vec_Port-0:s->function-7-Port___init__ primitive-Vec_Port-0:s->function-9-Port___init__ primitive-Vec_Port-0:s->function-3-Port___init__ primitive-Vec_Port-0:s->function-5-Port___init__ primitive-Vec_Port-0:s->function-2-Port___init__ function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-16-Port___init__ primitive-Vec_Port-1:s->function-11-Port___init__ primitive-Vec_Port-1:s->function-17-Port___init__ primitive-Vec_Port-1:s->function-18-Port___init__ primitive-Vec_Port-1:s->function-13-Port___init__ primitive-Vec_Port-1:s->function-12-Port___init__ primitive-Vec_Port-1:s->function-14-Port___init__ primitive-Vec_Port-1:s->function-15-Port___init__ primitive-Vec_Port-1:s->function-19-Port___init__ primitive-Vec_Port-1:s->function-10-Port___init__ function-3-PortList___init__:s->primitive-Vec_Port-3 primitive-Vec_Port-3:s->function-40-Port___init__ primitive-Vec_Port-3:s->function-34-Port___init__ primitive-Vec_Port-3:s->function-35-Port___init__ primitive-Vec_Port-3:s->function-37-Port___init__ primitive-Vec_Port-3:s->function-33-Port___init__ primitive-Vec_Port-3:s->function-36-Port___init__ primitive-Vec_Port-3:s->function-31-Port___init__ primitive-Vec_Port-3:s->function-32-Port___init__ primitive-Vec_Port-3:s->function-38-Port___init__ primitive-Vec_Port-3:s->function-39-Port___init__ function-6-PortList___init__:s->primitive-Vec_Port-6 primitive-Vec_Port-6:s->function-63-Port___init__ primitive-Vec_Port-6:s->function-62-Port___init__ function-2-Region___init__:s->function-0-InPorts___init__ function-3-Region___init__:s->function-0-InPorts___init__ function-0-Region___init__:s->function-0-InPorts___init__ function-1-Region___init__:s->function-0-InPorts___init__ function-6-Region___init__:s->function-1-InPorts___init__ function-4-Region___init__:s->function-0-InPorts___init__ function-5-Region___init__:s->function-0-InPorts___init__ function-6-Term_getPort:s->function-1-Py_AddIO function-1-Py_AddIO:s->function-1-Region_get function-1-Py_AddIO:s->function-0-Term_LiteralI64 function-1-Py_AddIO:s->function-3-Term_getPort function-55-Region_get:s->function-6-Region___init__ function-4-Region_get:s->function-2-Region___init__ function-1-Term_Loop:s->function-5-Term_RegionEnd function-1-Term_Loop:s->function-5-TermList___init__ function-1-Region_get:s->function-0-Region___init__ function-2-Term_getPort:s->function-0-Py_LtIO function-0-Py_LtIO:s->function-4-Region_get function-0-Py_LtIO:s->function-5-Region_get function-0-Py_LtIO:s->function-3-Region_get function-2-Py_AddIO:s->function-18-Term_getPort function-2-Py_AddIO:s->function-19-Term_getPort function-2-Py_AddIO:s->function-0-Term_LiteralI64 function-18-Term_getPort:s->function-0-Term_Loop function-19-Term_getPort:s->function-0-Term_Loop function-6-Term_RegionEnd:s->function-6-PortList___init__ function-6-Term_RegionEnd:s->function-6-Region___init__ function-56-Region_get:s->function-6-Region___init__ function-0-Term_IfElse:s->function-2-Term_getPort function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-1-TermList___init__ function-3-Term_getPort:s->function-0-Py_AddIO function-0-Py_AddIO:s->function-2-Region_get function-0-Py_AddIO:s->function-1-Term_getPort function-0-Py_AddIO:s->function-0-Term_getPort function-2-Region_get:s->function-0-Region___init__ function-32-Term_getPort:s->function-1-Py_NotIO function-1-Py_NotIO:s->function-30-Term_getPort function-1-Py_NotIO:s->function-31-Term_getPort function-1-Term_IfElse:s->function-3-Term_RegionEnd function-1-Term_IfElse:s->function-20-Term_getPort function-1-Term_IfElse:s->function-4-Term_RegionEnd function-1-Term_IfElse:s->function-3-TermList___init__ function-41-Term_getPort:s->function-1-Py_Call function-1-Py_Call:s->function-56-Region_get function-1-Py_Call:s->function-1-Py_LoadGlobal function-1-Py_Call:s->function-4-TermList___init__ function-42-Term_getPort:s->function-1-Py_Call function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-2-Region___init__ function-5-Term_getPort:s->function-0-Py_AddIO function-0-Py_NotIO:s->function-8-Term_getPort function-0-Py_NotIO:s->function-7-Term_getPort function-7-Term_getPort:s->function-0-Term_IfElse function-48-Region_get:s->function-5-Region___init__ function-0-Term_Loop:s->function-2-Term_RegionEnd function-0-Term_Loop:s->function-2-TermList___init__ function-5-Region_get:s->function-2-Region___init__ function-1-Py_LoadGlobal:s->function-56-Region_get function-4-TermList___init__:s->primitive-Vec_Term-4 function-12-Term_DbgValue:s->function-42-Term_getPort function-6-Term_DbgValue:s->function-1-Term_LiteralI64 function-30-Region_get:s->function-3-Region___init__ function-32-Region_get:s->function-3-Region___init__ function-29-Region_get:s->function-3-Region___init__ function-50-Region_get:s->function-5-Region___init__ function-52-Region_get:s->function-5-Region___init__ function-57-Region_get:s->function-6-Region___init__ function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-0-Region___init__ function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-1-Region___init__ function-1-TermList___init__:s->primitive-Vec_Term-1 function-26-Region_get:s->function-2-Region___init__ function-9-Term_getPort:s->function-0-Py_NotIO function-0-Py_Call:s->function-0-Py_LoadGlobal function-0-Py_Call:s->function-0-Region_get function-0-Py_Call:s->function-0-TermList___init__ function-0-Py_LoadGlobal:s->function-0-Region_get function-0-Region_get:s->function-0-Region___init__ function-0-TermList___init__:s->primitive-Vec_Term-0 function-37-Region_get:s->function-5-Region___init__ function-2-TermList___init__:s->primitive-Vec_Term-2 function-1-Term_getPort:s->function-0-Py_Call function-5-Term_DbgValue:s->function-0-Term_LiteralBool function-27-Region_get:s->function-2-Region___init__ function-3-Term_RegionEnd:s->function-3-PortList___init__ function-3-Term_RegionEnd:s->function-3-Region___init__ function-26-Term_getPort:s->function-2-Py_AddIO function-1-Py_LtIO:s->function-37-Region_get function-1-Py_LtIO:s->function-36-Region_get function-1-Py_LtIO:s->function-38-Region_get function-36-Region_get:s->function-5-Region___init__ function-38-Region_get:s->function-5-Region___init__ function-28-Region_get:s->function-3-Region___init__ function-0-GraphRoot:s->function-0-Term_Func function-0-Term_Func:s->function-6-Term_RegionEnd function-20-Term_getPort:s->function-1-Py_LtIO function-4-Term_RegionEnd:s->function-4-PortList___init__ function-4-Term_RegionEnd:s->function-4-Region___init__ function-3-TermList___init__:s->primitive-Vec_Term-3 function-54-Region_get:s->function-5-Region___init__ function-11-Term_DbgValue:s->function-0-Term_LiteralBool function-3-Region_get:s->function-2-Region___init__ function-0-Term_getPort:s->function-0-Py_Call function-33-Region_get:s->function-3-Region___init__ function-51-Region_get:s->function-5-Region___init__ function-31-Term_getPort:s->function-1-Term_IfElse function-23-Region_get:s->function-2-Region___init__ function-24-Region_get:s->function-2-Region___init__ function-5-Term_RegionEnd:s->function-5-PortList___init__ function-5-Term_RegionEnd:s->function-5-Region___init__ function-5-TermList___init__:s->primitive-Vec_Term-5 function-22-Region_get:s->function-2-Region___init__ function-21-Region_get:s->function-2-Region___init__ function-34-Region_get:s->function-3-Region___init__ function-35-Region_get:s->function-3-Region___init__ function-49-Region_get:s->function-5-Region___init__ function-25-Region_get:s->function-2-Region___init__ function-13-Term_DbgValue:s->function-1-Term_LiteralI64 function-53-Region_get:s->function-5-Region___init__ function-31-Region_get:s->function-3-Region___init__ primitive-Vec_Term-2:s->function-6-Term_DbgValue primitive-Vec_Term-2:s->function-30-Region_get primitive-Vec_Term-2:s->function-32-Region_get primitive-Vec_Term-2:s->function-29-Region_get primitive-Vec_Term-2:s->function-5-Term_DbgValue primitive-Vec_Term-2:s->function-28-Region_get primitive-Vec_Term-2:s->function-33-Region_get primitive-Vec_Term-2:s->function-34-Region_get primitive-Vec_Term-2:s->function-35-Region_get primitive-Vec_Term-2:s->function-31-Region_get primitive-Vec_Term-0:s->function-1-Region_get primitive-Vec_Term-4:s->function-55-Region_get primitive-Vec_Term-5:s->function-55-Region_get primitive-Vec_Term-5:s->function-1-Term_Undef primitive-Vec_Term-5:s->function-41-Term_getPort primitive-Vec_Term-5:s->function-12-Term_DbgValue primitive-Vec_Term-5:s->function-57-Region_get primitive-Vec_Term-5:s->function-3-Term_Undef primitive-Vec_Term-5:s->function-11-Term_DbgValue primitive-Vec_Term-5:s->function-0-Term_Undef primitive-Vec_Term-5:s->function-13-Term_DbgValue primitive-Vec_Term-5:s->function-2-Term_Undef primitive-Vec_Term-1:s->function-4-Region_get primitive-Vec_Term-1:s->function-5-Region_get primitive-Vec_Term-1:s->function-26-Region_get primitive-Vec_Term-1:s->function-27-Region_get primitive-Vec_Term-1:s->function-3-Region_get primitive-Vec_Term-1:s->function-23-Region_get primitive-Vec_Term-1:s->function-24-Region_get primitive-Vec_Term-1:s->function-22-Region_get primitive-Vec_Term-1:s->function-21-Region_get primitive-Vec_Term-1:s->function-25-Region_get primitive-Vec_Term-3:s->function-48-Region_get primitive-Vec_Term-3:s->function-50-Region_get primitive-Vec_Term-3:s->function-52-Region_get primitive-Vec_Term-3:s->function-37-Region_get primitive-Vec_Term-3:s->function-36-Region_get primitive-Vec_Term-3:s->function-38-Region_get primitive-Vec_Term-3:s->function-54-Region_get primitive-Vec_Term-3:s->function-51-Region_get primitive-Vec_Term-3:s->function-49-Region_get primitive-Vec_Term-3:s->function-53-Region_get function-1-InPorts___init__ InPorts primitive-Vec_String-1 Vec("!io", "init", "n") function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "__scfg_backedge_var_0__", "__scfg_backedge_var_1__", "__scfg_loop_cont_1__", "__scfg_loop_cont_2__", "c", "i", "init", "j", "n") function-26-Port___init__ Port("c", ·) function-13-Term_getPort ·.getPort(·, 5) function-52-Port___init__ Port("!io", ·) function-33-Term_getPort ·.getPort(·, 0) function-16-Port___init__ Port("i", ·) function-17-Region_get ·.get(·, 6) function-8-Port___init__ Port("j", ·) function-2-Term_DbgValue Term.DbgValue("j", ·) function-40-Port___init__ Port("n", ·) function-29-Term_getPort ·.getPort(·, 9) function-51-Port___init__ Port("!_loopcond_0002", ·) function-10-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-24-Port___init__ Port("__scfg_loop_cont_1__", ·) function-12-Term_getPort ·.getPort(·, 3) function-34-Port___init__ Port("__scfg_loop_cont_1__", ·) function-23-Term_getPort ·.getPort(·, 3) function-35-Port___init__ Port("__scfg_loop_cont_2__", ·) function-24-Term_getPort ·.getPort(·, 4) function-47-Port___init__ Port("i", ·) function-44-Region_get ·.get(·, 6) function-50-Port___init__ Port("n", ·) function-47-Region_get ·.get(·, 9) function-29-Port___init__ Port("j", ·) function-16-Term_getPort ·.getPort(·, 8) function-37-Port___init__ Port("i", ·) function-8-Term_DbgValue Term.DbgValue("i", ·) function-56-Port___init__ Port("__scfg_loop_cont_2__", ·) function-35-Term_getPort ·.getPort(·, 4) function-0-Port___init__ Port("!io", ·) function-4-Term_getPort ·.getPort(·, 0) function-11-Port___init__ Port("__scfg_backedge_var_0__", ·) function-13-Region_get ·.get(·, 1) function-30-Port___init__ Port("n", ·) function-17-Term_getPort ·.getPort(·, 9) function-63-Port___init__ Port("!ret", ·) function-44-Term_getPort ·.getPort(·, 5) function-49-Port___init__ Port("j", ·) function-46-Region_get ·.get(·, 8) function-6-Port___init__ Port("i", ·) function-9-Region_get ·.get(·, 6) function-42-Port___init__ Port("__scfg_backedge_var_0__", ·) function-9-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-57-Port___init__ Port("c", ·) function-36-Term_getPort ·.getPort(·, 5) function-28-Port___init__ Port("init", ·) function-15-Term_getPort ·.getPort(·, 7) function-1-Port___init__ Port("__scfg_backedge_var_0__", ·) function-6-Region_get ·.get(·, 1) function-22-Port___init__ Port("__scfg_backedge_var_0__", ·) function-11-Term_getPort ·.getPort(·, 1) function-33-Port___init__ Port("__scfg_backedge_var_1__", ·) function-22-Term_getPort ·.getPort(·, 2) function-55-Port___init__ Port("__scfg_loop_cont_1__", ·) function-27-Port___init__ Port("i", ·) function-14-Term_getPort ·.getPort(·, 6) function-48-Port___init__ Port("init", ·) function-45-Region_get ·.get(·, 7) function-17-Port___init__ Port("init", ·) function-18-Region_get ·.get(·, 7) function-20-Port___init__ Port("!_loopcond_0004", ·) function-4-Term_DbgValue Term.DbgValue("__scfg_loop_cont_2__", ·) function-23-Port___init__ Port("__scfg_backedge_var_1__", ·) function-8-Term_getPort ·.getPort(·, 2) function-58-Port___init__ Port("i", ·) function-37-Term_getPort ·.getPort(·, 6) function-62-Port___init__ Port("!io", ·) function-43-Term_getPort ·.getPort(·, 0) function-4-Port___init__ Port("__scfg_loop_cont_2__", ·) function-8-Region_get ·.get(·, 4) function-18-Port___init__ Port("j", ·) function-19-Region_get ·.get(·, 8) function-36-Port___init__ Port("c", ·) function-25-Term_getPort ·.getPort(·, 5) function-7-Port___init__ Port("init", ·) function-10-Region_get ·.get(·, 7) function-60-Port___init__ Port("j", ·) function-39-Term_getPort ·.getPort(·, 8) function-9-Port___init__ Port("n", ·) function-11-Region_get ·.get(·, 9) function-13-Port___init__ Port("__scfg_loop_cont_1__", ·) function-14-Region_get ·.get(·, 3) function-12-Port___init__ Port("__scfg_backedge_var_1__", ·) function-3-Term_DbgValue Term.DbgValue("__scfg_backedge_var_1__", ·) function-31-Port___init__ Port("!io", ·) function-21-Term_getPort ·.getPort(·, 0) function-32-Port___init__ Port("__scfg_backedge_var_0__", ·) function-7-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-59-Port___init__ Port("init", ·) function-38-Term_getPort ·.getPort(·, 7) function-25-Port___init__ Port("__scfg_loop_cont_2__", ·) function-21-Port___init__ Port("!io", ·) function-10-Term_getPort ·.getPort(·, 0) function-14-Port___init__ Port("__scfg_loop_cont_2__", ·) function-15-Region_get ·.get(·, 4) function-45-Port___init__ Port("__scfg_loop_cont_2__", ·) function-42-Region_get ·.get(·, 4) function-54-Port___init__ Port("__scfg_backedge_var_1__", ·) function-34-Term_getPort ·.getPort(·, 2) function-38-Port___init__ Port("init", ·) function-27-Term_getPort ·.getPort(·, 7) function-61-Port___init__ Port("n", ·) function-40-Term_getPort ·.getPort(·, 9) function-53-Port___init__ Port("__scfg_backedge_var_0__", ·) function-30-Term_getPort ·.getPort(·, 1) function-3-Port___init__ Port("__scfg_loop_cont_1__", ·) function-7-Region_get ·.get(·, 3) function-39-Port___init__ Port("j", ·) function-28-Term_getPort ·.getPort(·, 8) function-44-Port___init__ Port("__scfg_loop_cont_1__", ·) function-41-Region_get ·.get(·, 3) function-15-Port___init__ Port("c", ·) function-16-Region_get ·.get(·, 5) function-41-Port___init__ Port("!io", ·) function-39-Region_get ·.get(·, 0) function-5-Port___init__ Port("c", ·) function-1-Term_DbgValue Term.DbgValue("c", ·) function-2-Port___init__ Port("__scfg_backedge_var_1__", ·) function-0-Term_DbgValue Term.DbgValue("__scfg_backedge_var_1__", ·) function-19-Port___init__ Port("n", ·) function-20-Region_get ·.get(·, 9) function-43-Port___init__ Port("__scfg_backedge_var_1__", ·) function-40-Region_get ·.get(·, 2) function-46-Port___init__ Port("c", ·) function-43-Region_get ·.get(·, 5) function-10-Port___init__ Port("!io", ·) function-12-Region_get ·.get(·, 0) function-4-PortList___init__ PortList primitive-Vec_Port-4 Vec function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-5-PortList___init__ PortList primitive-Vec_Port-5 Vec function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-3-PortList___init__ PortList primitive-Vec_Port-3 Vec function-6-PortList___init__ PortList primitive-Vec_Port-6 Vec function-2-Region___init__ Region("1791", ·) function-3-Region___init__ Region("1662", ·) function-0-Region___init__ Region("1875", ·) function-1-Region___init__ Region("2146", ·) function-6-Region___init__ Region("1423", ·) function-4-Region___init__ Region("2824", ·) function-5-Region___init__ Region("1578", ·) function-6-Term_getPort ·.getPort(·, 1) function-1-Py_AddIO Py_AddIO function-55-Region_get ·.get(·, 1) function-4-Region_get ·.get(·, 0) function-1-Term_Loop Term.Loop function-1-Region_get ·.get(·, 8) function-2-Term_getPort ·.getPort(·, 1) function-0-Py_LtIO Py_LtIO function-2-Py_AddIO Py_AddIO function-18-Term_getPort ·.getPort(·, 0) function-19-Term_getPort ·.getPort(·, 6) function-0-Term_LiteralI64 Term.LiteralI64(1) function-6-Term_RegionEnd Term.RegionEnd function-56-Region_get ·.get(·, 0) function-0-Term_IfElse Term.IfElse function-1-Term_Undef Term.Undef("__scfg_backedge_var_1__") function-3-Term_getPort ·.getPort(·, 0) function-0-Py_AddIO Py_AddIO function-2-Region_get ·.get(·, 5) function-32-Term_getPort ·.getPort(·, 1) function-1-Py_NotIO Py_NotIO function-1-Term_IfElse Term.IfElse function-41-Term_getPort ·.getPort(·, 0) function-1-Py_Call Py_Call function-42-Term_getPort ·.getPort(·, 1) function-2-Term_RegionEnd Term.RegionEnd function-5-Term_getPort ·.getPort(·, 1) function-0-Py_NotIO Py_NotIO function-7-Term_getPort ·.getPort(·, 0) function-48-Region_get ·.get(·, 1) function-0-Term_Loop Term.Loop function-5-Region_get ·.get(·, 6) function-1-Py_LoadGlobal Py_LoadGlobal(·, "float") function-4-TermList___init__ TermList function-12-Term_DbgValue Term.DbgValue("c", ·) function-6-Term_DbgValue Term.DbgValue("j", ·) function-1-Term_LiteralI64 Term.LiteralI64(0) function-30-Region_get ·.get(·, 2) function-32-Region_get ·.get(·, 5) function-29-Region_get ·.get(·, 1) function-50-Region_get ·.get(·, 3) function-52-Region_get ·.get(·, 5) function-57-Region_get ·.get(·, 2) function-0-Term_RegionEnd Term.RegionEnd function-1-Term_RegionEnd Term.RegionEnd function-1-TermList___init__ TermList function-26-Region_get ·.get(·, 7) function-3-Term_Undef Term.Undef("j") function-9-Term_getPort ·.getPort(·, 1) function-0-Py_Call Py_Call function-0-Py_LoadGlobal Py_LoadGlobal(·, "float") function-0-Region_get ·.get(·, 0) function-0-TermList___init__ TermList function-37-Region_get ·.get(·, 0) function-2-TermList___init__ TermList function-1-Term_getPort ·.getPort(·, 1) function-5-Term_DbgValue Term.DbgValue("__scfg_loop_cont_2__", ·) function-0-Term_LiteralBool Term.LiteralBool(true) function-27-Region_get ·.get(·, 9) function-3-Term_RegionEnd Term.RegionEnd function-26-Term_getPort ·.getPort(·, 1) function-1-Py_LtIO Py_LtIO function-36-Region_get ·.get(·, 6) function-38-Region_get ·.get(·, 9) function-28-Region_get ·.get(·, 0) function-0-GraphRoot GraphRoot function-0-Term_Func Term.Func("3440", "transformed_example_4", ·) function-20-Term_getPort ·.getPort(·, 1) function-4-Term_RegionEnd Term.RegionEnd function-3-TermList___init__ TermList function-54-Region_get ·.get(·, 8) function-11-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-3-Region_get ·.get(·, 8) function-0-Term_getPort ·.getPort(·, 0) function-33-Region_get ·.get(·, 6) function-51-Region_get ·.get(·, 4) function-31-Term_getPort ·.getPort(·, 0) function-23-Region_get ·.get(·, 3) function-24-Region_get ·.get(·, 4) function-5-Term_RegionEnd Term.RegionEnd function-5-TermList___init__ TermList function-22-Region_get ·.get(·, 2) function-21-Region_get ·.get(·, 1) function-34-Region_get ·.get(·, 7) function-35-Region_get ·.get(·, 9) function-49-Region_get ·.get(·, 2) function-0-Term_Undef Term.Undef("__scfg_backedge_var_0__") function-25-Region_get ·.get(·, 5) function-13-Term_DbgValue Term.DbgValue("i", ·) function-53-Region_get ·.get(·, 7) function-2-Term_Undef Term.Undef("__scfg_loop_cont_2__") function-31-Region_get ·.get(·, 3) primitive-Vec_Term-2 Vec primitive-Vec_Term-0 Vec primitive-Vec_Term-4 Vec primitive-Vec_Term-5 Vec primitive-Vec_Term-1 Vec primitive-Vec_Term-3 Vec
[metadata] ▶
time elapsed 151.95ms
timing breakdown:
  151.95ms: EGraph              
3. Egraph Saturation (0.00ms) ▶
Egraph Saturation
[metadata] ▶
time elapsed 0.00ms
timing breakdown:
4. EGraph Extraction (118.39ms) ▶
EGraph Extraction
Extracted RVSDG ▶
transformed_example_4 = Func (Args (ArgSpec 'init' (PyNone)) (ArgSpec 'n' (PyNone)))
$0 = Region[3811] <- !io init n; #attrs (_, Int64, Int64)->(_, Float64)
{
  $1 = PyInt 0
  $2 = PyBool True
  $3 = PyBool False
  $4 = NbOp_CastI64ToF64 $0[1]
  $5 = Loop [5472] <- $0[0] $1 $1 $2 $3 $4 $1 $0[1] $1 $0[2]
    $6 = Region[3939] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n; #attrs (_, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)->(Bool, _, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)
    {
      $7 = NbOp_Lt_Int64 $6[6] $6[9]
      $8 = If $7 <- $6[0] $6[1] $6[2] $6[3] $6[4] $6[5] $6[6] $6[7] $6[8] $6[9]
        $9 = Region[4067] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n; #attrs (_, Int64, Int64, Bool, _, Float64, Int64, Int64, _, Int64)->(_, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)
        {
          $10 = Loop [4924] <- $9[0] $9[1] $9[2] $9[3] $2 $9[5] $9[6] $9[7] $1 $9[9]
            $11 = Region[4198] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n; #attrs (_, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)->(Bool, _, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)
            {
              $12 = NbOp_Lt_Int64 $11[8] $11[6]
              $13 = If $12 <- $11[0] $11[1] $11[2] $11[3] $11[4] $11[5] $11[6] $11[7] $11[8] $11[9]
                $14 = Region[4332] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n; #attrs (_, Int64, _, Bool, Bool, Float64, Int64, Int64, Int64, Int64)->(_, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)
                {
                  $15 = NbOp_CastI64ToF64 $14[8]
                  $16 = NbOp_Add_Float64 $14[5] $15
                  $17 = PyInt 1
                  $18 = NbOp_Add_Int64 $14[8] $17
                } [4463] -> !io=$14[0] __scfg_backedge_var_0__=$14[1] __scfg_backedge_var_1__=$1 __scfg_loop_cont_1__=$14[3] __scfg_loop_cont_2__=$14[4] c=$16 i=$14[6] init=$14[7] j=$18 n=$14[9]
                Else
                $19 = Region[4582] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n; #attrs (_, Int64, _, Bool, Bool, Float64, Int64, Int64, Int64, Int64)->(_, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)
                {
                } [4691] -> !io=$19[0] __scfg_backedge_var_0__=$19[1] __scfg_backedge_var_1__=$17 __scfg_loop_cont_1__=$19[3] __scfg_loop_cont_2__=$19[4] c=$19[5] i=$19[6] init=$19[7] j=$19[8] n=$19[9]
              Endif
              $20 = NbOp_Not_Int64 $13[2]
            } [4865] -> !_loopcond_0004=$20 !io=$13[0] __scfg_backedge_var_0__=$13[1] __scfg_backedge_var_1__=$13[2] __scfg_loop_cont_1__=$13[3] __scfg_loop_cont_2__=$20 c=$13[5] i=$13[6] init=$13[7] j=$13[8] n=$13[9]
          EndLoop
          $21 = NbOp_Add_Int64 $10[6] $17
        } [5038] -> !io=$10[0] __scfg_backedge_var_0__=$1 __scfg_backedge_var_1__=$10[2] __scfg_loop_cont_1__=$10[3] __scfg_loop_cont_2__=$10[4] c=$10[5] i=$21 init=$10[7] j=$10[8] n=$10[9]
        Else
        $22 = Region[5151] <- !io __scfg_backedge_var_0__ __scfg_backedge_var_1__ __scfg_loop_cont_1__ __scfg_loop_cont_2__ c i init j n; #attrs (_, Int64, Int64, Bool, _, Float64, Int64, Int64, _, Int64)->(_, Int64, Int64, Bool, Bool, Float64, Int64, Int64, Int64, Int64)
        {
        } [5260] -> !io=$22[0] __scfg_backedge_var_0__=$17 __scfg_backedge_var_1__=$22[2] __scfg_loop_cont_1__=$22[3] __scfg_loop_cont_2__=$22[4] c=$22[5] i=$22[6] init=$22[7] j=$22[8] n=$22[9]
      Endif
      $23 = NbOp_Not_Int64 $8[1]
    } [5434] -> !_loopcond_0002=$23 !io=$8[0] __scfg_backedge_var_0__=$8[1] __scfg_backedge_var_1__=$8[2] __scfg_loop_cont_1__=$23 __scfg_loop_cont_2__=$8[4] c=$8[5] i=$8[6] init=$8[7] j=$8[8] n=$8[9]
  EndLoop
} [5506] -> !io=$5[0] !ret=$5[5]
Extracted cost ▶
4898841107495147.0
[metadata] ▶
time elapsed 118.39ms
timing breakdown:
  118.37ms: Extracted RVSDG     
  0.01ms: Extracted cost      
5. Backend (3.26ms) ▶
Backend
Lowered module ▶
module {
  func.func @func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %c0_i64 = arith.constant 0 : i64
    %true = arith.constant true
    %false = arith.constant false
    %c1_i64 = arith.constant 1 : i64
    cf.br ^bb1
  ^bb1:  // pred: ^bb0
    %c0_i32 = arith.constant 0 : i32
    %0 = arith.sitofp %arg0 : i64 to f64
    %1:10 = scf.while (%arg2 = %c0_i32, %arg3 = %c0_i64, %arg4 = %c0_i64, %arg5 = %true, %arg6 = %false, %arg7 = %0, %arg8 = %c0_i64, %arg9 = %arg0, %arg10 = %c0_i64, %arg11 = %arg1) : (i32, i64, i64, i1, i1, f64, i64, i64, i64, i64) -> (i32, i64, i64, i1, i1, f64, i64, i64, i64, i64) {
      %2 = arith.cmpi slt, %arg8, %arg11 : i64
      %3:10 = scf.if %2 -> (i32, i64, i64, i1, i1, f64, i64, i64, i64, i64) {
        %5:10 = scf.while (%arg12 = %arg2, %arg13 = %arg3, %arg14 = %arg4, %arg15 = %arg5, %arg16 = %true, %arg17 = %arg7, %arg18 = %arg8, %arg19 = %arg9, %arg20 = %c0_i64, %arg21 = %arg11) : (i32, i64, i64, i1, i1, f64, i64, i64, i64, i64) -> (i32, i64, i64, i1, i1, f64, i64, i64, i64, i64) {
          %7 = arith.cmpi slt, %arg20, %arg18 : i64
          %8:10 = scf.if %7 -> (i32, i64, i64, i1, i1, f64, i64, i64, i64, i64) {
            %10 = arith.sitofp %arg20 : i64 to f64
            %11 = arith.addf %arg17, %10 : f64
            %12 = arith.addi %arg20, %c1_i64 : i64
            scf.yield %arg12, %arg13, %c0_i64, %arg15, %arg16, %11, %arg18, %arg19, %12, %arg21 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
          } else {
            scf.yield %arg12, %arg13, %c1_i64, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
          }
          %c0_i64_1 = arith.constant 0 : i64
          %9 = arith.cmpi eq, %8#2, %c0_i64_1 : i64
          scf.condition(%9) %8#0, %8#1, %8#2, %8#3, %9, %8#5, %8#6, %8#7, %8#8, %8#9 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
        } do {
        ^bb0(%arg12: i32, %arg13: i64, %arg14: i64, %arg15: i1, %arg16: i1, %arg17: f64, %arg18: i64, %arg19: i64, %arg20: i64, %arg21: i64):
          scf.yield %arg12, %arg13, %arg14, %arg15, %arg16, %arg17, %arg18, %arg19, %arg20, %arg21 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
        }
        %6 = arith.addi %5#6, %c1_i64 : i64
        scf.yield %5#0, %c0_i64, %5#2, %5#3, %5#4, %5#5, %6, %5#7, %5#8, %5#9 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
      } else {
        scf.yield %arg2, %c1_i64, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
      }
      %c0_i64_0 = arith.constant 0 : i64
      %4 = arith.cmpi eq, %3#1, %c0_i64_0 : i64
      scf.condition(%4) %3#0, %3#1, %3#2, %4, %3#4, %3#5, %3#6, %3#7, %3#8, %3#9 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
    } do {
    ^bb0(%arg2: i32, %arg3: i64, %arg4: i64, %arg5: i1, %arg6: i1, %arg7: f64, %arg8: i64, %arg9: i64, %arg10: i64, %arg11: i64):
      scf.yield %arg2, %arg3, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64
    }
    return %1#5 : f64
  }
}
[metadata] ▶
time elapsed 3.26ms
timing breakdown:
  3.26ms: Lowered module      
6. MLIR passes (1.74ms) ▶
MLIR passes
MLIR optimized ▶
module {
  llvm.func @func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %0 = llvm.mlir.constant(0 : i32) : i32
    %1 = llvm.mlir.constant(0 : i64) : i64
    %2 = llvm.mlir.constant(true) : i1
    %3 = llvm.mlir.constant(false) : i1
    %4 = llvm.mlir.constant(1 : i64) : i64
    llvm.br ^bb1
  ^bb1:  // pred: ^bb0
    %5 = llvm.sitofp %arg0 : i64 to f64
    llvm.br ^bb2(%0, %1, %1, %2, %3, %5, %1, %arg0, %1, %arg1 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64)
  ^bb2(%6: i32, %7: i64, %8: i64, %9: i1, %10: i1, %11: f64, %12: i64, %13: i64, %14: i64, %15: i64):  // 2 preds: ^bb1, ^bb12
    %16 = llvm.icmp "slt" %12, %15 : i64
    llvm.cond_br %16, ^bb3, ^bb10
  ^bb3:  // pred: ^bb2
    llvm.br ^bb4(%6, %7, %8, %9, %2, %11, %12, %13, %1, %15 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64)
  ^bb4(%17: i32, %18: i64, %19: i64, %20: i1, %21: i1, %22: f64, %23: i64, %24: i64, %25: i64, %26: i64):  // 2 preds: ^bb3, ^bb8
    %27 = llvm.icmp "slt" %25, %23 : i64
    llvm.cond_br %27, ^bb5, ^bb6
  ^bb5:  // pred: ^bb4
    %28 = llvm.sitofp %25 : i64 to f64
    %29 = llvm.fadd %22, %28  : f64
    %30 = llvm.add %25, %4 : i64
    llvm.br ^bb7(%17, %18, %1, %20, %21, %29, %23, %24, %30, %26 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64)
  ^bb6:  // pred: ^bb4
    llvm.br ^bb7(%17, %18, %4, %20, %21, %22, %23, %24, %25, %26 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64)
  ^bb7(%31: i32, %32: i64, %33: i64, %34: i1, %35: i1, %36: f64, %37: i64, %38: i64, %39: i64, %40: i64):  // 2 preds: ^bb5, ^bb6
    llvm.br ^bb8
  ^bb8:  // pred: ^bb7
    %41 = llvm.icmp "eq" %33, %1 : i64
    llvm.cond_br %41, ^bb4(%31, %32, %33, %34, %41, %36, %37, %38, %39, %40 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64), ^bb9
  ^bb9:  // pred: ^bb8
    %42 = llvm.add %37, %4 : i64
    llvm.br ^bb11(%31, %1, %33, %34, %41, %36, %42, %38, %39, %40 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64)
  ^bb10:  // pred: ^bb2
    llvm.br ^bb11(%6, %4, %8, %9, %10, %11, %12, %13, %14, %15 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64)
  ^bb11(%43: i32, %44: i64, %45: i64, %46: i1, %47: i1, %48: f64, %49: i64, %50: i64, %51: i64, %52: i64):  // 2 preds: ^bb9, ^bb10
    llvm.br ^bb12
  ^bb12:  // pred: ^bb11
    %53 = llvm.icmp "eq" %44, %1 : i64
    llvm.cond_br %53, ^bb2(%43, %44, %45, %53, %47, %48, %49, %50, %51, %52 : i32, i64, i64, i1, i1, f64, i64, i64, i64, i64), ^bb13
  ^bb13:  // pred: ^bb12
    llvm.return %48 : f64
  }
  llvm.func @_mlir_ciface_func(%arg0: i64, %arg1: i64) -> f64 attributes {llvm.emit_c_interface} {
    %0 = llvm.call @func(%arg0, %arg1) : (i64, i64) -> f64
    llvm.return %0 : f64
  }
}
[metadata] ▶
time elapsed 1.74ms
timing breakdown:
  1.74ms: MLIR optimized      

Testing report

1. Args ▶
(10, 7)
2. JIT output ▶
45.0
3. Expected output ▶
45.0