Chapter 2: Adding the EGraph Middle-End¶

Traditional compiler design depends on a series of compiler passes. However, this approach suffers from the phase-ordering problem—where the specific order of optimization steps can influence the resulting code, often leading to missed optimizations or less efficient output due to the inflexible sequence of transformations. The use of EGraphs and Equality Saturation overcomes this issue. By representing a program as a graph of equivalent expressions and evaluating multiple optimization possibilities at once, these techniques enable the compiler to identify the most effective code version without being limited by a predetermined order of passes.

In this chapter, we will define the middle end—--the stage of a compiler that optimizes and transforms an intermediate representation (IR) of a program, connecting the front end (which con,verts source code into IR) to the back end (which produces target machine code). The egglog library powers our use of EGraphs. Before exploring how to write rules for EGraphs, we'll first establish a conversion from RVSDG-IR to EGraph. RVSDG-IR must be encoded into the EGraph, enabling us to apply rewrite rulesets for program optimization or analysis. Afterward, an extraction step selects the most efficient variant from the EGraph.

Imports and Setup¶

In [1]:
from typing import Any, TypedDict
In [2]:
from egglog import EGraph
from sealir import rvsdg
from sealir.eqsat.rvsdg_convert import egraph_conversion
from sealir.eqsat.rvsdg_eqsat import GraphRoot
from sealir.eqsat.rvsdg_extract import egraph_extraction
In [3]:
# We'll be extending from chapter 1.
from ch01_basic_compiler import (
    backend,
)
from ch01_basic_compiler import compiler_pipeline as pipeline_jit_compile
from ch01_basic_compiler import (
    jit_compile,
    pipeline_backend,
    pipeline_frontend,
    run_test,
)
from utils import IN_NOTEBOOK, Report, display

Simple EGraph Roundtripping¶

Our initial middle-end is a simple roundtripping from RVSDG-IR to EGraph and back to RVSDG-IR. SealIR provides egraph_conversion() for RVSDG-IR to EGraph, and egraph_extraction() for EGraph to RVSDG-IR.

Convert RVSDG to EGraph¶

The following code shows the RVSDG-IR and egraph for the max_if_else() function. The two are almost a direct mapping.

In [4]:
class EGraphOutput(TypedDict):
    egraph: EGraph
    egraph_root: GraphRoot
In [5]:
@pipeline_frontend.extend
def pipeline_egraph_conversion(
    rvsdg_expr, pipeline_report=Report.Sink()
) -> EGraphOutput:
    with pipeline_report.nest(
        "EGraph Conversion", default_expanded=True
    ) as report:
        memo = egraph_conversion(rvsdg_expr)
        egraph = EGraph()
        root = GraphRoot(memo[rvsdg_expr])
        egraph.let("root", root)
        report.append("EGraph", egraph)
        return {"egraph": egraph, "egraph_root": root}
In [6]:
if __name__ == "__main__":

    display(pipeline_egraph_conversion.visualize())

    def max_if_else(x, y):
        if x > y:
            return x
        else:
            return y

    # Get RVSDG
    report = Report("EGraph Conversion", default_expanded=True)
    cres = pipeline_egraph_conversion(fn=max_if_else, pipeline_report=report)
    report.display()
Pipeline-pipeline_egraph_conversion cluster_legend Legend input_fn fn Any stage_1 Stage 1 pipeline_frontend → FrontendOutput input_fn->stage_1 fn 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 stage_1->stage_2 rvsdg_expr out_dbginfo dbginfo object stage_1->out_dbginfo dbginfo out_rvsdg_expr rvsdg_expr object stage_1->out_rvsdg_expr rvsdg_expr out_egraph egraph EGraph stage_2->out_egraph egraph out_egraph_root egraph_root GraphRoot stage_2->out_egraph_root egraph_root 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

EGraph Conversion

1. Frontend ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   5|    def max_if_else(x, y):
   6|        if x > y:
   7|            return x
   8|        else:
   9|            return y
----------------------------------inter source----------------------------------
   1|def transformed_max_if_else(x, y):
   2|    """#file: /tmp/ipykernel_3431/2769577028.py"""
   3|    '#loc: 6:8-9:20'
   4|    if x > y:
   5|        '#loc: 7:12-7:20'
   6|        __scfg_return_value__ = x
   7|    else:
   8|        __scfg_return_value__ = y
   9|    return __scfg_return_value__
RVSDG ▶
transformed_max_if_else = Func (Args (ArgSpec 'x' (PyNone)) (ArgSpec 'y' (PyNone)))
$0 = Region[392] <- !io x y
{
  $1 = PyBinOp > $0[0] $0[1], $0[2]
  $2 = If $1[1] <- $0[0] $0[1] $0[2]
    $3 = Region[442] <- !io x y
    {
      $4 = DbgValue '__scfg_return_value__' $3[1]
    } [615] -> !io=$3[0] __scfg_return_value__=$4 x=$3[1] y=$3[2]
    Else
    $5 = Region[522] <- !io x y
    {
      $6 = DbgValue '__scfg_return_value__' $5[2]
    } [643] -> !io=$5[0] __scfg_return_value__=$6 x=$5[1] y=$5[2]
  Endif
} [714] -> !io=$2[0] !ret=$2[1]
2. EGraph Conversion ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_Port-34 cluster_Port-34 outer_cluster_Port-32 cluster_Port-32 outer_cluster_Port-14 cluster_Port-14 outer_cluster_Port-15 cluster_Port-15 outer_cluster_Port-17 cluster_Port-17 outer_cluster_Port-26 cluster_Port-26 outer_cluster_Port-11 cluster_Port-11 outer_cluster_Port-21 cluster_Port-21 outer_cluster_Port-25 cluster_Port-25 outer_cluster_Port-23 cluster_Port-23 outer_cluster_PortList-18 cluster_PortList-18 outer_cluster_PortList-27 cluster_PortList-27 outer_cluster_PortList-35 cluster_PortList-35 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Region-2 cluster_Region-2 outer_cluster_Region-4 cluster_Region-4 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-28 cluster_Term-28 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-36 cluster_Term-36 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-30 cluster_Term-30 outer_cluster_Term-37 cluster_Term-37 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-38 cluster_Term-38 outer_cluster_Term-24 cluster_Term-24 outer_cluster_Term-33 cluster_Term-33 outer_cluster_Term-5 cluster_Term-5 outer_cluster_Term-13 cluster_Term-13 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-9 cluster_Term-9 outer_cluster_TermList-29 cluster_TermList-29 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 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-9-Port___init__:s->function-2-Term_getPort function-2-Term_getPort:s->function-0-Term_IfElse function-8-Port___init__:s->function-1-Term_getPort function-1-Term_getPort:s->function-0-Term_IfElse function-1-Port___init__:s->function-0-Term_DbgValue function-0-Term_DbgValue:s->function-5-Region_get function-2-Port___init__:s->function-5-Region_get function-5-Region_get:s->function-0-Region___init__ function-3-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-0-Region___init__ function-7-Port___init__:s->function-0-Region_get function-0-Region_get:s->function-1-Region___init__ function-0-Port___init__:s->function-4-Region_get function-4-Region_get:s->function-0-Region___init__ function-4-Port___init__:s->function-7-Region_get function-7-Region_get:s->function-1-Region___init__ function-6-Port___init__:s->function-8-Region_get function-8-Region_get:s->function-1-Region___init__ function-5-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-0-Region_get function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-1-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-0-Port___init__ function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-7-Port___init__ primitive-Vec_Port-1:s->function-4-Port___init__ primitive-Vec_Port-1:s->function-6-Port___init__ primitive-Vec_Port-1:s->function-5-Port___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-Region___init__:s->function-0-InPorts___init__ function-1-Region___init__:s->function-0-InPorts___init__ function-2-Region___init__:s->function-0-InPorts___init__ function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-0-Term_getPort function-0-Term_IfElse:s->function-0-TermList___init__ function-0-Py_GtIO:s->function-2-Region_get function-0-Py_GtIO:s->function-1-Region_get function-0-Py_GtIO:s->function-3-Region_get function-2-Region_get:s->function-2-Region___init__ function-1-Region_get:s->function-2-Region___init__ function-3-Region_get:s->function-2-Region___init__ function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-1-Region___init__ function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-0-Region___init__ function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-2-Region___init__ function-0-Term_getPort:s->function-0-Py_GtIO function-0-TermList___init__:s->primitive-Vec_Term-0 function-0-Term_Func:s->function-2-Term_RegionEnd function-0-GraphRoot:s->function-0-Term_Func primitive-Vec_Term-0:s->function-2-Region_get primitive-Vec_Term-0:s->function-1-Region_get primitive-Vec_Term-0:s->function-3-Region_get function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "x", "y") function-9-Port___init__ Port("!ret", ·) function-2-Term_getPort ·.getPort(·, 1) function-8-Port___init__ Port("!io", ·) function-1-Term_getPort ·.getPort(·, 0) function-1-Port___init__ Port("__scfg_return_value__", ·) function-0-Term_DbgValue Term.DbgValue("__scfg_return_value__", ·) function-2-Port___init__ Port("x", ·) function-5-Region_get ·.get(·, 1) function-3-Port___init__ Port("y", ·) function-6-Region_get ·.get(·, 2) function-7-Port___init__ Port("y", ·) function-0-Region_get ·.get(·, 2) function-0-Port___init__ Port("!io", ·) function-4-Region_get ·.get(·, 0) function-4-Port___init__ Port("!io", ·) function-7-Region_get ·.get(·, 0) function-6-Port___init__ Port("x", ·) function-8-Region_get ·.get(·, 1) function-5-Port___init__ Port("__scfg_return_value__", ·) function-1-Term_DbgValue Term.DbgValue("__scfg_return_value__", ·) function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-0-Region___init__ Region("442", ·) function-1-Region___init__ Region("522", ·) function-2-Region___init__ Region("392", ·) function-0-Term_IfElse Term.IfElse function-0-Py_GtIO Py_GtIO function-2-Region_get ·.get(·, 0) function-1-Region_get ·.get(·, 1) function-3-Region_get ·.get(·, 2) function-1-Term_RegionEnd Term.RegionEnd function-0-Term_RegionEnd Term.RegionEnd function-2-Term_RegionEnd Term.RegionEnd function-0-Term_getPort ·.getPort(·, 1) function-0-TermList___init__ TermList function-0-Term_Func Term.Func("720", "transformed_max_if_else", ·) function-0-GraphRoot GraphRoot primitive-Vec_Term-0 Vec

Extract from EGraph¶

An EGraph can represent numerous variants of a program. These variants are generated by applying rewrite rules, which produce equivalent versions of the code that differ in structure or efficiency. While all variants are functionally identical, we are primarily interested in identifying the "best" one, where "best" depends on context--—such as execution speed, code size, or energy efficiency. To address this, the egraph_extraction() function allows users to define custom cost models, tailoring the selection process to prioritize the variant that aligns with their specific optimization goals.

In [7]:
if __name__ == "__main__":
    help(egraph_extraction)
Help on function egraph_extraction in module sealir.eqsat.rvsdg_extract:

egraph_extraction(egraph: 'EGraph', rvsdg_sexpr, *, cost_model=None, converter_class=<class 'sealir.eqsat.rvsdg_extract_details.EGraphToRVSDG'>)

Here, we will use the default cost model, which is based on the node count.

In [8]:
class EGraphExtractionOutput(TypedDict):
    cost: float
    extracted: Any
In [9]:
@pipeline_egraph_conversion.extend
def pipeline_egraph_extraction(
    egraph, rvsdg_expr, pipeline_report=Report.Sink()
) -> EGraphExtractionOutput:
    with pipeline_report.nest(
        "EGraph Extraction", default_expanded=True
    ) as report:
        cost, extracted = egraph_extraction(egraph, rvsdg_expr)
        report.append("Cost", cost)
        report.append("Extracted", rvsdg.format_rvsdg(extracted))
        return {"cost": cost, "extracted": extracted}
In [10]:
if __name__ == "__main__":
    report = Report("EGraph Extraction", default_expanded=True)
    cres = pipeline_egraph_extraction(fn=max_if_else, pipeline_report=report)
    report.display()

EGraph Extraction

1. Frontend ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   5|    def max_if_else(x, y):
   6|        if x > y:
   7|            return x
   8|        else:
   9|            return y
----------------------------------inter source----------------------------------
   1|def transformed_max_if_else(x, y):
   2|    """#file: /tmp/ipykernel_3431/2769577028.py"""
   3|    '#loc: 6:8-9:20'
   4|    if x > y:
   5|        '#loc: 7:12-7:20'
   6|        __scfg_return_value__ = x
   7|    else:
   8|        __scfg_return_value__ = y
   9|    return __scfg_return_value__
RVSDG ▶
transformed_max_if_else = Func (Args (ArgSpec 'x' (PyNone)) (ArgSpec 'y' (PyNone)))
$0 = Region[392] <- !io x y
{
  $1 = PyBinOp > $0[0] $0[1], $0[2]
  $2 = If $1[1] <- $0[0] $0[1] $0[2]
    $3 = Region[442] <- !io x y
    {
      $4 = DbgValue '__scfg_return_value__' $3[1]
    } [615] -> !io=$3[0] __scfg_return_value__=$4 x=$3[1] y=$3[2]
    Else
    $5 = Region[522] <- !io x y
    {
      $6 = DbgValue '__scfg_return_value__' $5[2]
    } [643] -> !io=$5[0] __scfg_return_value__=$6 x=$5[1] y=$5[2]
  Endif
} [714] -> !io=$2[0] !ret=$2[1]
2. EGraph Conversion ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_Port-21 cluster_Port-21 outer_cluster_Port-34 cluster_Port-34 outer_cluster_Port-23 cluster_Port-23 outer_cluster_Port-11 cluster_Port-11 outer_cluster_Port-26 cluster_Port-26 outer_cluster_Port-25 cluster_Port-25 outer_cluster_Port-14 cluster_Port-14 outer_cluster_Port-17 cluster_Port-17 outer_cluster_Port-15 cluster_Port-15 outer_cluster_Port-32 cluster_Port-32 outer_cluster_PortList-35 cluster_PortList-35 outer_cluster_PortList-18 cluster_PortList-18 outer_cluster_PortList-27 cluster_PortList-27 outer_cluster_Region-2 cluster_Region-2 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Region-4 cluster_Region-4 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-13 cluster_Term-13 outer_cluster_Term-24 cluster_Term-24 outer_cluster_Term-33 cluster_Term-33 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-36 cluster_Term-36 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-38 cluster_Term-38 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-30 cluster_Term-30 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-37 cluster_Term-37 outer_cluster_Term-5 cluster_Term-5 outer_cluster_Term-28 cluster_Term-28 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-10 cluster_Term-10 outer_cluster_TermList-29 cluster_TermList-29 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-4-Port___init__:s->function-7-Region_get function-7-Region_get:s->function-1-Region___init__ function-9-Port___init__:s->function-2-Term_getPort function-2-Term_getPort:s->function-0-Term_IfElse function-5-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-0-Region_get function-0-Port___init__:s->function-4-Region_get function-4-Region_get:s->function-0-Region___init__ function-7-Port___init__:s->function-0-Region_get function-0-Region_get:s->function-1-Region___init__ function-6-Port___init__:s->function-8-Region_get function-8-Region_get:s->function-1-Region___init__ function-1-Port___init__:s->function-0-Term_DbgValue function-0-Term_DbgValue:s->function-5-Region_get function-3-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-0-Region___init__ function-2-Port___init__:s->function-5-Region_get function-5-Region_get:s->function-0-Region___init__ function-8-Port___init__:s->function-1-Term_getPort function-1-Term_getPort:s->function-0-Term_IfElse 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-1-Port___init__ primitive-Vec_Port-0:s->function-3-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-4-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-6-Port___init__ function-1-Region___init__:s->function-0-InPorts___init__ function-0-Region___init__:s->function-0-InPorts___init__ function-2-Region___init__:s->function-0-InPorts___init__ function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-0-Term_getPort function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-0-TermList___init__ function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-0-Region___init__ function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-2-Region___init__ function-0-GraphRoot:s->function-0-Term_Func function-0-Term_Func:s->function-2-Term_RegionEnd function-0-Term_getPort:s->function-0-Py_GtIO function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-1-Region___init__ function-0-TermList___init__:s->primitive-Vec_Term-0 function-2-Region_get:s->function-2-Region___init__ function-0-Py_GtIO:s->function-2-Region_get function-0-Py_GtIO:s->function-1-Region_get function-0-Py_GtIO:s->function-3-Region_get function-1-Region_get:s->function-2-Region___init__ function-3-Region_get:s->function-2-Region___init__ primitive-Vec_Term-0:s->function-2-Region_get primitive-Vec_Term-0:s->function-1-Region_get primitive-Vec_Term-0:s->function-3-Region_get function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "x", "y") function-4-Port___init__ Port("!io", ·) function-7-Region_get ·.get(·, 0) function-9-Port___init__ Port("!ret", ·) function-2-Term_getPort ·.getPort(·, 1) function-5-Port___init__ Port("__scfg_return_value__", ·) function-1-Term_DbgValue Term.DbgValue("__scfg_return_value__", ·) function-0-Port___init__ Port("!io", ·) function-4-Region_get ·.get(·, 0) function-7-Port___init__ Port("y", ·) function-0-Region_get ·.get(·, 2) function-6-Port___init__ Port("x", ·) function-8-Region_get ·.get(·, 1) function-1-Port___init__ Port("__scfg_return_value__", ·) function-0-Term_DbgValue Term.DbgValue("__scfg_return_value__", ·) function-3-Port___init__ Port("y", ·) function-6-Region_get ·.get(·, 2) function-2-Port___init__ Port("x", ·) function-5-Region_get ·.get(·, 1) function-8-Port___init__ Port("!io", ·) function-1-Term_getPort ·.getPort(·, 0) 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-1-Region___init__ Region("522", ·) function-0-Region___init__ Region("442", ·) function-2-Region___init__ Region("392", ·) function-0-Term_IfElse Term.IfElse function-0-Term_RegionEnd Term.RegionEnd function-2-Term_RegionEnd Term.RegionEnd function-0-GraphRoot GraphRoot function-0-Term_Func Term.Func("720", "transformed_max_if_else", ·) function-0-Term_getPort ·.getPort(·, 1) function-1-Term_RegionEnd Term.RegionEnd function-0-TermList___init__ TermList function-2-Region_get ·.get(·, 0) function-0-Py_GtIO Py_GtIO function-1-Region_get ·.get(·, 1) function-3-Region_get ·.get(·, 2) primitive-Vec_Term-0 Vec
3. EGraph Extraction ▶
EGraph Extraction
Cost ▶
5556347.0
Extracted ▶
transformed_max_if_else = Func (Args (ArgSpec 'x' (PyNone)) (ArgSpec 'y' (PyNone)))
$0 = Region[837] <- !io x y
{
  $1 = PyBinOp > $0[0] $0[1], $0[2]
  $2 = If $1[1] <- $0[0] $0[1] $0[2]
    $3 = Region[874] <- !io x y
    {
      $4 = DbgValue '__scfg_return_value__' $3[1]
    } [939] -> !io=$3[0] __scfg_return_value__=$4 x=$3[1] y=$3[2]
    Else
    $5 = Region[950] <- !io x y
    {
      $6 = DbgValue '__scfg_return_value__' $5[2]
    } [1015] -> !io=$5[0] __scfg_return_value__=$6 x=$5[1] y=$5[2]
  Endif
} [1052] -> !io=$2[0] !ret=$2[1]

Extended Compiler Pipeline¶

Redefine the compiler pipeline to include the middle-end with EGraph optimization capabilities.

In [11]:
def egraph_action(
    egraph: EGraph,
    egraph_root: GraphRoot,
    pipeline_report=Report.Sink(),
) -> EGraphOutput:
    # For now, the middle end is just an identity function that exercise
    # the encoding into and out of egraph.
    with pipeline_report.nest("EGraph Action") as report:
        report.append("EGraph", egraph)
    return {"egraph": egraph, "egraph_root": egraph_root}
In [12]:
pipeline_middle_end = pipeline_egraph_extraction.insert(-1, egraph_action)
In [13]:
if __name__ == "__main__":
    display(pipeline_middle_end.visualize())
Pipeline-pipeline_egraph_extraction cluster_legend Legend input_fn fn Any stage_1 Stage 1 pipeline_frontend → FrontendOutput input_fn->stage_1 fn 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 stage_3 Stage 3 egraph_action → EGraphOutput input_pipeline_report->stage_3 pipeline_report stage_4 Stage 4 pipeline_egraph_extraction → EGraphExtractionOutput input_pipeline_report->stage_4 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 out_cost cost float stage_4->out_cost cost out_extracted extracted Any stage_4->out_extracted extracted 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
In [14]:
class BackendOutput(TypedDict):
    jit_func: Any
    llmod: Any
In [15]:
@pipeline_middle_end.extend
def pipeline_backend(
    extracted, pipeline_report=Report.Sink()
) -> BackendOutput:
    with pipeline_report.nest("Backend", default_expanded=True) as report:
        llmod = backend(extracted)
        report.append("LLVM", llmod)
        jt = jit_compile(llmod, extracted)
        return {"jit_func": jt, "llmod": llmod}
In [16]:
compiler_pipeline = pipeline_backend
In [17]:
if __name__ == "__main__":
    display(compiler_pipeline.visualize())
Pipeline-pipeline_backend cluster_legend Legend input_fn fn Any stage_1 Stage 1 pipeline_frontend → FrontendOutput input_fn->stage_1 fn 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 stage_3 Stage 3 egraph_action → EGraphOutput input_pipeline_report->stage_3 pipeline_report stage_4 Stage 4 pipeline_egraph_extraction → EGraphExtractionOutput input_pipeline_report->stage_4 pipeline_report stage_5 Stage 5 pipeline_backend → BackendOutput input_pipeline_report->stage_5 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 out_cost cost float stage_4->out_cost cost out_extracted extracted Any stage_4->out_extracted extracted out_jit_func jit_func Any stage_5->out_jit_func jit_func out_llmod llmod Any stage_5->out_llmod llmod 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

Example: Testing the EGraph Pipeline¶

Exercise the new pipeline with a simple function to demonstrate the EGraph-based optimization process.

In [18]:
if __name__ == "__main__":

    def sum_ints(n):
        c = 1 + n
        for i in range(n):
            c += i
        return c

    report = Report("Compiler Pipeline", default_expanded=True)
    jt = compiler_pipeline(fn=sum_ints, pipeline_report=report).jit_func
    report.display()
    run_test(sum_ints, jt, (12,), verbose=True)

Compiler Pipeline

1. Frontend ▶
Frontend
Debug Info on RVSDG ▶
--------------------------------original source---------------------------------
   3|    def sum_ints(n):
   4|        c = 1 + n
   5|        for i in range(n):
   6|            c += i
   7|        return c
----------------------------------inter source----------------------------------
   1|def transformed_sum_ints(n):
   2|    """#file: /tmp/ipykernel_3431/6310283.py"""
   3|    '#loc: 4:8-4:17'
   4|    c = 1 + n
   5|    '#loc: 5:8-6:18'
   6|    __scfg_iterator_1__ = iter(range(n))
   7|    i = None
   8|    __scfg_loop_cont_1__ = True
   9|    while __scfg_loop_cont_1__:
  10|        __scfg_iter_last_1__ = i
  11|        i = next(__scfg_iterator_1__, '__scfg_sentinel__')
  12|        if i != '__scfg_sentinel__':
  13|            '#loc: 6:12-6:18'
  14|            c += i
  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|    i = __scfg_iter_last_1__
  20|    '#loc: 7:8-7:16'
  21|    return c
RVSDG ▶
transformed_sum_ints = Func (Args (ArgSpec 'n' (PyNone)))
$0 = Region[958] <- !io n
{
  $1 = PyInt 1
  $2 = PyBinOp + $0[0] $1, $0[1]
  $3 = PyLoadGlobal $2[0] 'range'
  $4 = PyCall $3 $2[0] $0[1]
  $5 = PyLoadGlobal $4[0] 'iter'
  $6 = PyCall $5 $4[0] $4[1]
  $7 = Undef __scfg_backedge_var_0__
  $8 = Undef __scfg_iter_last_1__
  $9 = DbgValue '__scfg_iterator_1__' $6[1]
  $10 = PyBool True
  $11 = DbgValue '__scfg_loop_cont_1__' $10
  $12 = DbgValue 'c' $2[1]
  $13 = PyNone
  $14 = DbgValue 'i' $13
  $15 = Loop [1860] <- $6[0] $7 $8 $9 $11 $12 $14 $0[1]
    $16 = Region[1159] <- !io __scfg_backedge_var_0__ __scfg_iter_last_1__ __scfg_iterator_1__ __scfg_loop_cont_1__ c i n
    {
      $17 = PyLoadGlobal $16[0] 'next'
      $18 = PyStr '__scfg_sentinel__'
      $19 = PyCall $17 $16[0] $16[3], $18
      $20 = DbgValue '__scfg_iter_last_1__' $16[6]
      $21 = DbgValue 'i' $19[1]
      $22 = PyStr '__scfg_sentinel__'
      $23 = PyBinOp != $19[0] $21, $22
      $24 = If $23[1] <- $19[0] $16[1] $20 $16[3] $16[4] $16[5] $21 $16[7]
        $25 = Region[1307] <- !io __scfg_backedge_var_0__ __scfg_iter_last_1__ __scfg_iterator_1__ __scfg_loop_cont_1__ c i n
        {
          $26 = PyInplaceBinOp + $25[0], $25[5], $25[6]
          $27 = PyInt 0
          $28 = DbgValue '__scfg_backedge_var_0__' $27
        } [1633] -> !io=$26[0] __scfg_backedge_var_0__=$28 __scfg_iter_last_1__=$25[2] __scfg_iterator_1__=$25[3] __scfg_loop_cont_1__=$25[4] c=$26[1] i=$25[6] n=$25[7]
        Else
        $29 = Region[1462] <- !io __scfg_backedge_var_0__ __scfg_iter_last_1__ __scfg_iterator_1__ __scfg_loop_cont_1__ c i n
        {
          $30 = PyInt 1
          $31 = DbgValue '__scfg_backedge_var_0__' $30
        } [1685] -> !io=$29[0] __scfg_backedge_var_0__=$31 __scfg_iter_last_1__=$29[2] __scfg_iterator_1__=$29[3] __scfg_loop_cont_1__=$29[4] c=$29[5] i=$29[6] n=$29[7]
      Endif
      $32 = PyUnaryOp not $24[0] $24[1]
      $33 = DbgValue '__scfg_loop_cont_1__' $32[1]
    } [1847] -> !_loopcond_0002=$33 !io=$32[0] __scfg_backedge_var_0__=$24[1] __scfg_iter_last_1__=$24[2] __scfg_iterator_1__=$24[3] __scfg_loop_cont_1__=$33 c=$24[5] i=$24[6] n=$24[7]
  EndLoop
} [1997] -> !io=$15[0] !ret=$15[5]
2. EGraph Conversion ▶
EGraph Conversion
EGraph ▶
outer_cluster_InPorts-64 cluster_InPorts-64 outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_Port-91 cluster_Port-91 outer_cluster_Port-35 cluster_Port-35 outer_cluster_Port-88 cluster_Port-88 outer_cluster_Port-85 cluster_Port-85 outer_cluster_Port-33 cluster_Port-33 outer_cluster_Port-93 cluster_Port-93 outer_cluster_Port-41 cluster_Port-41 outer_cluster_Port-49 cluster_Port-49 outer_cluster_Port-51 cluster_Port-51 outer_cluster_Port-28 cluster_Port-28 outer_cluster_Port-39 cluster_Port-39 outer_cluster_Port-43 cluster_Port-43 outer_cluster_Port-32 cluster_Port-32 outer_cluster_Port-116 cluster_Port-116 outer_cluster_Port-45 cluster_Port-45 outer_cluster_Port-21 cluster_Port-21 outer_cluster_Port-86 cluster_Port-86 outer_cluster_Port-83 cluster_Port-83 outer_cluster_Port-95 cluster_Port-95 outer_cluster_Port-26 cluster_Port-26 outer_cluster_Port-47 cluster_Port-47 outer_cluster_Port-97 cluster_Port-97 outer_cluster_Port-90 cluster_Port-90 outer_cluster_Port-114 cluster_Port-114 outer_cluster_Port-53 cluster_Port-53 outer_cluster_Port-24 cluster_Port-24 outer_cluster_Port-30 cluster_Port-30 outer_cluster_PortList-36 cluster_PortList-36 outer_cluster_PortList-117 cluster_PortList-117 outer_cluster_PortList-98 cluster_PortList-98 outer_cluster_PortList-54 cluster_PortList-54 outer_cluster_Region-4 cluster_Region-4 outer_cluster_Region-5 cluster_Region-5 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Region-65 cluster_Region-65 outer_cluster_Term-82 cluster_Term-82 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-25 cluster_Term-25 outer_cluster_Term-75 cluster_Term-75 outer_cluster_Term-92 cluster_Term-92 outer_cluster_Term-103 cluster_Term-103 outer_cluster_Term-77 cluster_Term-77 outer_cluster_Term-60 cluster_Term-60 outer_cluster_Term-27 cluster_Term-27 outer_cluster_Term-69 cluster_Term-69 outer_cluster_Term-84 cluster_Term-84 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-105 cluster_Term-105 outer_cluster_Term-23 cluster_Term-23 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-40 cluster_Term-40 outer_cluster_Term-106 cluster_Term-106 outer_cluster_Term-70 cluster_Term-70 outer_cluster_Term-96 cluster_Term-96 outer_cluster_Term-80 cluster_Term-80 outer_cluster_Term-87 cluster_Term-87 outer_cluster_Term-15 cluster_Term-15 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-68 cluster_Term-68 outer_cluster_Term-14 cluster_Term-14 outer_cluster_Term-67 cluster_Term-67 outer_cluster_Term-58 cluster_Term-58 outer_cluster_Term-119 cluster_Term-119 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-66 cluster_Term-66 outer_cluster_Term-57 cluster_Term-57 outer_cluster_Term-79 cluster_Term-79 outer_cluster_Term-55 cluster_Term-55 outer_cluster_Term-120 cluster_Term-120 outer_cluster_Term-101 cluster_Term-101 outer_cluster_Term-63 cluster_Term-63 outer_cluster_Term-108 cluster_Term-108 outer_cluster_Term-74 cluster_Term-74 outer_cluster_Term-44 cluster_Term-44 outer_cluster_Term-29 cluster_Term-29 outer_cluster_Term-107 cluster_Term-107 outer_cluster_Term-17 cluster_Term-17 outer_cluster_Term-34 cluster_Term-34 outer_cluster_Term-99 cluster_Term-99 outer_cluster_Term-38 cluster_Term-38 outer_cluster_Term-89 cluster_Term-89 outer_cluster_Term-118 cluster_Term-118 outer_cluster_Term-112 cluster_Term-112 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-2 cluster_Term-2 outer_cluster_Term-113 cluster_Term-113 outer_cluster_Term-18 cluster_Term-18 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-48 cluster_Term-48 outer_cluster_Term-59 cluster_Term-59 outer_cluster_Term-50 cluster_Term-50 outer_cluster_Term-61 cluster_Term-61 outer_cluster_Term-78 cluster_Term-78 outer_cluster_Term-81 cluster_Term-81 outer_cluster_Term-115 cluster_Term-115 outer_cluster_Term-110 cluster_Term-110 outer_cluster_Term-37 cluster_Term-37 outer_cluster_Term-46 cluster_Term-46 outer_cluster_Term-56 cluster_Term-56 outer_cluster_Term-102 cluster_Term-102 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-104 cluster_Term-104 outer_cluster_Term-73 cluster_Term-73 outer_cluster_Term-42 cluster_Term-42 outer_cluster_Term-11 cluster_Term-11 outer_cluster_Term-72 cluster_Term-72 outer_cluster_Term-100 cluster_Term-100 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-52 cluster_Term-52 outer_cluster_Term-94 cluster_Term-94 outer_cluster_TermList-71 cluster_TermList-71 outer_cluster_TermList-76 cluster_TermList-76 outer_cluster_TermList-111 cluster_TermList-111 outer_cluster_TermList-62 cluster_TermList-62 outer_cluster_TermList-13 cluster_TermList-13 outer_cluster_Vec_Port-3 cluster_Vec_Port-3 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 outer_cluster_Vec_String-0 cluster_Vec_String-0 outer_cluster_Vec_String-1 cluster_Vec_String-1 outer_cluster_Vec_Term-1 cluster_Vec_Term-1 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-4 cluster_Vec_Term-4 function-1-InPorts___init__:s->primitive-Vec_String-1 function-0-InPorts___init__:s->primitive-Vec_String-0 function-21-Port___init__:s->function-4-Term_DbgValue function-4-Term_DbgValue:s->function-10-Term_getPort function-7-Port___init__:s->function-8-Region_get function-8-Region_get:s->function-2-Region___init__ function-19-Port___init__:s->function-12-Term_getPort function-12-Term_getPort:s->function-0-Term_IfElse function-17-Port___init__:s->function-11-Term_getPort function-11-Term_getPort:s->function-0-Py_NotIO function-6-Port___init__:s->function-3-Region_get function-3-Region_get:s->function-2-Region___init__ function-22-Port___init__:s->function-14-Term_getPort function-14-Term_getPort:s->function-0-Term_IfElse function-9-Port___init__:s->function-2-Term_DbgValue function-2-Term_DbgValue:s->function-0-Term_LiteralI64 function-13-Port___init__:s->function-13-Region_get function-13-Region_get:s->function-1-Region___init__ function-14-Port___init__:s->function-14-Region_get function-14-Region_get:s->function-1-Region___init__ function-3-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-2-Region___init__ function-8-Port___init__:s->function-9-Region_get function-9-Region_get:s->function-1-Region___init__ function-10-Port___init__:s->function-10-Region_get function-10-Region_get:s->function-1-Region___init__ function-5-Port___init__:s->function-4-Term_getPort function-4-Term_getPort:s->function-0-Py_InplaceAddIO function-26-Port___init__:s->function-21-Term_getPort function-21-Term_getPort:s->function-0-Term_Loop function-11-Port___init__:s->function-11-Region_get function-11-Region_get:s->function-1-Region___init__ function-0-Port___init__:s->function-3-Term_getPort function-3-Term_getPort:s->function-0-Py_InplaceAddIO function-18-Port___init__:s->function-9-Term_getPort function-9-Term_getPort:s->function-0-Term_IfElse function-16-Port___init__:s->function-4-Term_DbgValue function-23-Port___init__:s->function-15-Term_getPort function-15-Term_getPort:s->function-0-Term_IfElse function-2-Port___init__:s->function-5-Region_get function-5-Region_get:s->function-2-Region___init__ function-12-Port___init__:s->function-12-Region_get function-12-Region_get:s->function-1-Region___init__ function-24-Port___init__:s->function-16-Term_getPort function-16-Term_getPort:s->function-0-Term_IfElse function-20-Port___init__:s->function-13-Term_getPort function-13-Term_getPort:s->function-0-Term_IfElse function-25-Port___init__:s->function-20-Term_getPort function-20-Term_getPort:s->function-0-Term_Loop function-15-Port___init__:s->function-15-Region_get function-15-Region_get:s->function-1-Region___init__ function-1-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-1-Term_LiteralI64 function-4-Port___init__:s->function-7-Region_get function-7-Region_get:s->function-2-Region___init__ function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-7-Port___init__ primitive-Vec_Port-0:s->function-6-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-0-Port___init__ primitive-Vec_Port-0:s->function-2-Port___init__ primitive-Vec_Port-0:s->function-1-Port___init__ primitive-Vec_Port-0:s->function-4-Port___init__ function-3-PortList___init__:s->primitive-Vec_Port-3 primitive-Vec_Port-3:s->function-26-Port___init__ primitive-Vec_Port-3:s->function-25-Port___init__ function-2-PortList___init__:s->primitive-Vec_Port-2 primitive-Vec_Port-2:s->function-21-Port___init__ primitive-Vec_Port-2:s->function-19-Port___init__ primitive-Vec_Port-2:s->function-17-Port___init__ primitive-Vec_Port-2:s->function-22-Port___init__ primitive-Vec_Port-2:s->function-18-Port___init__ primitive-Vec_Port-2:s->function-16-Port___init__ primitive-Vec_Port-2:s->function-23-Port___init__ primitive-Vec_Port-2:s->function-24-Port___init__ primitive-Vec_Port-2:s->function-20-Port___init__ function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-9-Port___init__ primitive-Vec_Port-1:s->function-13-Port___init__ primitive-Vec_Port-1:s->function-14-Port___init__ primitive-Vec_Port-1:s->function-8-Port___init__ primitive-Vec_Port-1:s->function-10-Port___init__ primitive-Vec_Port-1:s->function-11-Port___init__ primitive-Vec_Port-1:s->function-12-Port___init__ primitive-Vec_Port-1:s->function-15-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-3-Region___init__:s->function-1-InPorts___init__ function-10-Term_getPort:s->function-0-Py_NotIO function-2-Term_getPort:s->function-0-Py_NeIO function-0-Py_NeIO:s->function-0-Term_getPort function-0-Py_NeIO:s->function-0-Term_LiteralStr function-0-Py_NeIO:s->function-0-Term_DbgValue function-7-Term_getPort:s->function-1-Py_Call function-1-Py_Call:s->function-5-Term_getPort function-1-Py_Call:s->function-1-Py_LoadGlobal function-1-Py_Call:s->function-2-TermList___init__ function-0-Term_IfElse:s->function-2-Term_getPort function-0-Term_IfElse:s->function-1-Term_RegionEnd function-0-Term_IfElse:s->function-0-Term_RegionEnd function-0-Term_IfElse:s->function-1-TermList___init__ function-18-Term_getPort:s->function-2-Py_Call function-2-Py_Call:s->function-2-Py_LoadGlobal function-2-Py_Call:s->function-6-Term_getPort function-2-Py_Call:s->function-3-TermList___init__ function-2-Py_LoadGlobal:s->function-6-Term_getPort function-6-Term_getPort:s->function-1-Py_Call function-3-TermList___init__:s->primitive-Vec_Term-3 function-19-Region_get:s->function-0-Region___init__ function-5-Term_getPort:s->function-0-Py_AddIO function-0-Py_AddIO:s->function-0-Term_LiteralI64 function-0-Py_AddIO:s->function-21-Region_get function-0-Py_AddIO:s->function-22-Region_get function-0-Py_NotIO:s->function-9-Term_getPort function-0-Py_NotIO:s->function-8-Term_getPort function-0-Py_InplaceAddIO:s->function-3-Region_get function-0-Py_InplaceAddIO:s->function-1-Region_get function-0-Py_InplaceAddIO:s->function-2-Region_get function-1-Region_get:s->function-2-Region___init__ function-2-Region_get:s->function-2-Region___init__ function-6-Term_DbgValue:s->function-0-Term_LiteralBool function-1-Py_LoadGlobal:s->function-5-Term_getPort function-8-Term_getPort:s->function-0-Term_IfElse function-0-Term_getPort:s->function-0-Py_Call function-0-Py_Call:s->function-0-Py_LoadGlobal function-0-Py_Call:s->function-4-Region_get function-0-Py_Call:s->function-0-TermList___init__ function-21-Region_get:s->function-3-Region___init__ function-22-Region_get:s->function-3-Region___init__ function-0-Py_LoadGlobal:s->function-4-Region_get function-4-Region_get:s->function-0-Region___init__ function-0-TermList___init__:s->primitive-Vec_Term-0 function-3-Term_DbgValue:s->function-17-Region_get function-17-Region_get:s->function-0-Region___init__ function-0-Term_Func:s->function-3-Term_RegionEnd function-3-Term_RegionEnd:s->function-3-PortList___init__ function-3-Term_RegionEnd:s->function-3-Region___init__ function-1-Term_RegionEnd:s->function-1-PortList___init__ function-1-Term_RegionEnd:s->function-1-Region___init__ function-0-GraphRoot:s->function-0-Term_Func function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-2-Region___init__ function-1-TermList___init__:s->primitive-Vec_Term-1 function-7-Term_DbgValue:s->function-19-Term_getPort function-19-Term_getPort:s->function-0-Py_AddIO function-0-Term_DbgValue:s->function-1-Term_getPort function-1-Term_getPort:s->function-0-Py_Call function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-0-Region___init__ function-0-Term_Loop:s->function-2-Term_RegionEnd function-0-Term_Loop:s->function-4-TermList___init__ function-4-TermList___init__:s->primitive-Vec_Term-4 function-0-Region_get:s->function-0-Region___init__ function-18-Region_get:s->function-0-Region___init__ function-20-Region_get:s->function-0-Region___init__ function-16-Region_get:s->function-0-Region___init__ function-5-Term_DbgValue:s->function-18-Term_getPort function-2-TermList___init__:s->primitive-Vec_Term-2 function-17-Term_getPort:s->function-2-Py_Call primitive-Vec_Term-2:s->function-22-Region_get primitive-Vec_Term-3:s->function-7-Term_getPort primitive-Vec_Term-4:s->function-6-Term_DbgValue primitive-Vec_Term-4:s->function-22-Region_get primitive-Vec_Term-4:s->function-0-Term_Undef primitive-Vec_Term-4:s->function-7-Term_DbgValue primitive-Vec_Term-4:s->function-8-Term_DbgValue primitive-Vec_Term-4:s->function-1-Term_Undef primitive-Vec_Term-4:s->function-5-Term_DbgValue primitive-Vec_Term-4:s->function-17-Term_getPort primitive-Vec_Term-1:s->function-19-Region_get primitive-Vec_Term-1:s->function-0-Term_getPort primitive-Vec_Term-1:s->function-3-Term_DbgValue primitive-Vec_Term-1:s->function-0-Term_DbgValue primitive-Vec_Term-1:s->function-0-Region_get primitive-Vec_Term-1:s->function-18-Region_get primitive-Vec_Term-1:s->function-20-Region_get primitive-Vec_Term-1:s->function-16-Region_get primitive-Vec_Term-0:s->function-0-Term_LiteralStr primitive-Vec_Term-0:s->function-0-Region_get function-1-InPorts___init__ InPorts primitive-Vec_String-1 Vec("!io", "n") function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "__scfg_backedge_var_0__", "__scfg_iter_last_1__", "__scfg_iterator_1__", "__scfg_loop_cont_1__", "c", "i", "n") function-21-Port___init__ Port("__scfg_loop_cont_1__", ·) function-4-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-7-Port___init__ Port("n", ·) function-8-Region_get ·.get(·, 7) function-19-Port___init__ Port("__scfg_iter_last_1__", ·) function-12-Term_getPort ·.getPort(·, 2) function-17-Port___init__ Port("!io", ·) function-11-Term_getPort ·.getPort(·, 0) function-6-Port___init__ Port("i", ·) function-3-Region_get ·.get(·, 6) function-22-Port___init__ Port("c", ·) function-14-Term_getPort ·.getPort(·, 5) function-9-Port___init__ Port("__scfg_backedge_var_0__", ·) function-2-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-13-Port___init__ Port("c", ·) function-13-Region_get ·.get(·, 5) function-14-Port___init__ Port("i", ·) function-14-Region_get ·.get(·, 6) function-3-Port___init__ Port("__scfg_iterator_1__", ·) function-6-Region_get ·.get(·, 3) function-8-Port___init__ Port("!io", ·) function-9-Region_get ·.get(·, 0) function-10-Port___init__ Port("__scfg_iter_last_1__", ·) function-10-Region_get ·.get(·, 2) function-5-Port___init__ Port("c", ·) function-4-Term_getPort ·.getPort(·, 1) function-26-Port___init__ Port("!ret", ·) function-21-Term_getPort ·.getPort(·, 5) function-11-Port___init__ Port("__scfg_iterator_1__", ·) function-11-Region_get ·.get(·, 3) function-0-Port___init__ Port("!io", ·) function-3-Term_getPort ·.getPort(·, 0) function-18-Port___init__ Port("__scfg_backedge_var_0__", ·) function-9-Term_getPort ·.getPort(·, 1) function-16-Port___init__ Port("!_loopcond_0002", ·) function-23-Port___init__ Port("i", ·) function-15-Term_getPort ·.getPort(·, 6) function-2-Port___init__ Port("__scfg_iter_last_1__", ·) function-5-Region_get ·.get(·, 2) function-12-Port___init__ Port("__scfg_loop_cont_1__", ·) function-12-Region_get ·.get(·, 4) function-24-Port___init__ Port("n", ·) function-16-Term_getPort ·.getPort(·, 7) function-20-Port___init__ Port("__scfg_iterator_1__", ·) function-13-Term_getPort ·.getPort(·, 3) function-25-Port___init__ Port("!io", ·) function-20-Term_getPort ·.getPort(·, 0) function-15-Port___init__ Port("n", ·) function-15-Region_get ·.get(·, 7) function-1-Port___init__ Port("__scfg_backedge_var_0__", ·) function-1-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-4-Port___init__ Port("__scfg_loop_cont_1__", ·) function-7-Region_get ·.get(·, 4) function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-3-PortList___init__ PortList primitive-Vec_Port-3 Vec function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-1-Region___init__ Region("1462", ·) function-2-Region___init__ Region("1307", ·) function-0-Region___init__ Region("1159", ·) function-3-Region___init__ Region("958", ·) function-10-Term_getPort ·.getPort(·, 1) function-2-Term_getPort ·.getPort(·, 1) function-0-Py_NeIO Py_NeIO function-7-Term_getPort ·.getPort(·, 1) function-1-Py_Call Py_Call function-0-Term_IfElse Term.IfElse function-18-Term_getPort ·.getPort(·, 1) function-2-Py_Call Py_Call function-2-Py_LoadGlobal Py_LoadGlobal(·, "iter") function-6-Term_getPort ·.getPort(·, 0) function-3-TermList___init__ TermList function-19-Region_get ·.get(·, 5) function-5-Term_getPort ·.getPort(·, 0) function-0-Py_AddIO Py_AddIO function-0-Py_NotIO Py_NotIO function-0-Py_InplaceAddIO Py_InplaceAddIO function-1-Region_get ·.get(·, 0) function-2-Region_get ·.get(·, 5) function-0-Term_LiteralBool Term.LiteralBool(true) function-1-Term_LiteralI64 Term.LiteralI64(0) function-0-Term_LiteralI64 Term.LiteralI64(1) function-6-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-1-Py_LoadGlobal Py_LoadGlobal(·, "range") function-8-Term_getPort ·.getPort(·, 0) function-0-Term_getPort ·.getPort(·, 0) function-0-Py_Call Py_Call function-21-Region_get ·.get(·, 0) function-22-Region_get ·.get(·, 1) function-0-Py_LoadGlobal Py_LoadGlobal(·, "next") function-4-Region_get ·.get(·, 0) function-0-TermList___init__ TermList function-3-Term_DbgValue Term.DbgValue("__scfg_iter_last_1__", ·) function-17-Region_get ·.get(·, 6) function-0-Term_Func Term.Func("2003", "transformed_sum_ints", ·) function-3-Term_RegionEnd Term.RegionEnd function-0-Term_LiteralStr Term.LiteralStr("__scfg_sentinel__") function-1-Term_RegionEnd Term.RegionEnd function-0-GraphRoot GraphRoot function-0-Term_Undef Term.Undef("__scfg_backedge_var_0__") function-0-Term_RegionEnd Term.RegionEnd function-1-TermList___init__ TermList function-7-Term_DbgValue Term.DbgValue("c", ·) function-19-Term_getPort ·.getPort(·, 1) function-0-Term_DbgValue Term.DbgValue("i", ·) function-1-Term_getPort ·.getPort(·, 1) function-2-Term_RegionEnd Term.RegionEnd function-0-Term_Loop Term.Loop function-4-TermList___init__ TermList function-0-Region_get ·.get(·, 3) function-18-Region_get ·.get(·, 4) function-20-Region_get ·.get(·, 7) function-8-Term_DbgValue Term.DbgValue("i", Term.LiteralNone) function-16-Region_get ·.get(·, 1) function-1-Term_Undef Term.Undef("__scfg_iter_last_1__") function-5-Term_DbgValue Term.DbgValue("__scfg_iterator_1__", ·) function-2-TermList___init__ TermList function-17-Term_getPort ·.getPort(·, 0) primitive-Vec_Term-2 Vec primitive-Vec_Term-3 Vec primitive-Vec_Term-4 Vec primitive-Vec_Term-1 Vec primitive-Vec_Term-0 Vec
3. EGraph Action ▶
EGraph Action
EGraph ▶
outer_cluster_InPorts-0 cluster_InPorts-0 outer_cluster_InPorts-64 cluster_InPorts-64 outer_cluster_Port-32 cluster_Port-32 outer_cluster_Port-43 cluster_Port-43 outer_cluster_Port-45 cluster_Port-45 outer_cluster_Port-83 cluster_Port-83 outer_cluster_Port-35 cluster_Port-35 outer_cluster_Port-85 cluster_Port-85 outer_cluster_Port-53 cluster_Port-53 outer_cluster_Port-21 cluster_Port-21 outer_cluster_Port-39 cluster_Port-39 outer_cluster_Port-41 cluster_Port-41 outer_cluster_Port-91 cluster_Port-91 outer_cluster_Port-51 cluster_Port-51 outer_cluster_Port-26 cluster_Port-26 outer_cluster_Port-30 cluster_Port-30 outer_cluster_Port-33 cluster_Port-33 outer_cluster_Port-114 cluster_Port-114 outer_cluster_Port-90 cluster_Port-90 outer_cluster_Port-93 cluster_Port-93 outer_cluster_Port-47 cluster_Port-47 outer_cluster_Port-88 cluster_Port-88 outer_cluster_Port-116 cluster_Port-116 outer_cluster_Port-24 cluster_Port-24 outer_cluster_Port-86 cluster_Port-86 outer_cluster_Port-49 cluster_Port-49 outer_cluster_Port-28 cluster_Port-28 outer_cluster_Port-97 cluster_Port-97 outer_cluster_Port-95 cluster_Port-95 outer_cluster_PortList-54 cluster_PortList-54 outer_cluster_PortList-36 cluster_PortList-36 outer_cluster_PortList-117 cluster_PortList-117 outer_cluster_PortList-98 cluster_PortList-98 outer_cluster_Region-4 cluster_Region-4 outer_cluster_Region-65 cluster_Region-65 outer_cluster_Region-5 cluster_Region-5 outer_cluster_Region-1 cluster_Region-1 outer_cluster_Term-112 cluster_Term-112 outer_cluster_Term-25 cluster_Term-25 outer_cluster_Term-19 cluster_Term-19 outer_cluster_Term-67 cluster_Term-67 outer_cluster_Term-8 cluster_Term-8 outer_cluster_Term-50 cluster_Term-50 outer_cluster_Term-66 cluster_Term-66 outer_cluster_Term-99 cluster_Term-99 outer_cluster_Term-29 cluster_Term-29 outer_cluster_Term-23 cluster_Term-23 outer_cluster_Term-79 cluster_Term-79 outer_cluster_Term-10 cluster_Term-10 outer_cluster_Term-96 cluster_Term-96 outer_cluster_Term-107 cluster_Term-107 outer_cluster_Term-108 cluster_Term-108 outer_cluster_Term-14 cluster_Term-14 outer_cluster_Term-80 cluster_Term-80 outer_cluster_Term-68 cluster_Term-68 outer_cluster_Term-61 cluster_Term-61 outer_cluster_Term-7 cluster_Term-7 outer_cluster_Term-70 cluster_Term-70 outer_cluster_Term-57 cluster_Term-57 outer_cluster_Term-48 cluster_Term-48 outer_cluster_Term-77 cluster_Term-77 outer_cluster_Term-15 cluster_Term-15 outer_cluster_Term-20 cluster_Term-20 outer_cluster_Term-42 cluster_Term-42 outer_cluster_Term-104 cluster_Term-104 outer_cluster_Term-3 cluster_Term-3 outer_cluster_Term-110 cluster_Term-110 outer_cluster_Term-58 cluster_Term-58 outer_cluster_Term-103 cluster_Term-103 outer_cluster_Term-9 cluster_Term-9 outer_cluster_Term-73 cluster_Term-73 outer_cluster_Term-75 cluster_Term-75 outer_cluster_Term-34 cluster_Term-34 outer_cluster_Term-102 cluster_Term-102 outer_cluster_Term-72 cluster_Term-72 outer_cluster_Term-84 cluster_Term-84 outer_cluster_Term-89 cluster_Term-89 outer_cluster_Term-94 cluster_Term-94 outer_cluster_Term-18 cluster_Term-18 outer_cluster_Term-38 cluster_Term-38 outer_cluster_Term-27 cluster_Term-27 outer_cluster_Term-115 cluster_Term-115 outer_cluster_Term-17 cluster_Term-17 outer_cluster_Term-82 cluster_Term-82 outer_cluster_Term-69 cluster_Term-69 outer_cluster_Term-119 cluster_Term-119 outer_cluster_Term-60 cluster_Term-60 outer_cluster_Term-46 cluster_Term-46 outer_cluster_Term-63 cluster_Term-63 outer_cluster_Term-78 cluster_Term-78 outer_cluster_Term-81 cluster_Term-81 outer_cluster_Term-12 cluster_Term-12 outer_cluster_Term-40 cluster_Term-40 outer_cluster_Term-118 cluster_Term-118 outer_cluster_Term-44 cluster_Term-44 outer_cluster_Term-22 cluster_Term-22 outer_cluster_Term-101 cluster_Term-101 outer_cluster_Term-105 cluster_Term-105 outer_cluster_Term-100 cluster_Term-100 outer_cluster_Term-120 cluster_Term-120 outer_cluster_Term-11 cluster_Term-11 outer_cluster_Term-2 cluster_Term-2 outer_cluster_Term-31 cluster_Term-31 outer_cluster_Term-52 cluster_Term-52 outer_cluster_Term-37 cluster_Term-37 outer_cluster_Term-113 cluster_Term-113 outer_cluster_Term-56 cluster_Term-56 outer_cluster_Term-92 cluster_Term-92 outer_cluster_Term-16 cluster_Term-16 outer_cluster_Term-59 cluster_Term-59 outer_cluster_Term-55 cluster_Term-55 outer_cluster_Term-74 cluster_Term-74 outer_cluster_Term-87 cluster_Term-87 outer_cluster_Term-6 cluster_Term-6 outer_cluster_Term-106 cluster_Term-106 outer_cluster_TermList-62 cluster_TermList-62 outer_cluster_TermList-13 cluster_TermList-13 outer_cluster_TermList-71 cluster_TermList-71 outer_cluster_TermList-76 cluster_TermList-76 outer_cluster_TermList-111 cluster_TermList-111 outer_cluster_Vec_Port-0 cluster_Vec_Port-0 outer_cluster_Vec_Port-2 cluster_Vec_Port-2 outer_cluster_Vec_Port-1 cluster_Vec_Port-1 outer_cluster_Vec_Port-3 cluster_Vec_Port-3 outer_cluster_Vec_String-1 cluster_Vec_String-1 outer_cluster_Vec_String-0 cluster_Vec_String-0 outer_cluster_Vec_Term-2 cluster_Vec_Term-2 outer_cluster_Vec_Term-3 cluster_Vec_Term-3 outer_cluster_Vec_Term-1 cluster_Vec_Term-1 outer_cluster_Vec_Term-0 cluster_Vec_Term-0 outer_cluster_Vec_Term-4 cluster_Vec_Term-4 function-0-InPorts___init__:s->primitive-Vec_String-0 function-1-InPorts___init__:s->primitive-Vec_String-1 function-5-Port___init__:s->function-4-Term_getPort function-4-Term_getPort:s->function-0-Py_InplaceAddIO function-10-Port___init__:s->function-10-Region_get function-10-Region_get:s->function-1-Region___init__ function-11-Port___init__:s->function-11-Region_get function-11-Region_get:s->function-1-Region___init__ function-16-Port___init__:s->function-4-Term_DbgValue function-4-Term_DbgValue:s->function-10-Term_getPort function-7-Port___init__:s->function-8-Region_get function-8-Region_get:s->function-2-Region___init__ function-17-Port___init__:s->function-11-Term_getPort function-11-Term_getPort:s->function-0-Py_NotIO function-15-Port___init__:s->function-15-Region_get function-15-Region_get:s->function-1-Region___init__ function-0-Port___init__:s->function-3-Term_getPort function-3-Term_getPort:s->function-0-Py_InplaceAddIO function-8-Port___init__:s->function-9-Region_get function-9-Region_get:s->function-1-Region___init__ function-9-Port___init__:s->function-2-Term_DbgValue function-2-Term_DbgValue:s->function-0-Term_LiteralI64 function-21-Port___init__:s->function-4-Term_DbgValue function-14-Port___init__:s->function-14-Region_get function-14-Region_get:s->function-1-Region___init__ function-2-Port___init__:s->function-5-Region_get function-5-Region_get:s->function-2-Region___init__ function-4-Port___init__:s->function-7-Region_get function-7-Region_get:s->function-2-Region___init__ function-6-Port___init__:s->function-3-Region_get function-3-Region_get:s->function-2-Region___init__ function-25-Port___init__:s->function-20-Term_getPort function-20-Term_getPort:s->function-0-Term_Loop function-20-Port___init__:s->function-13-Term_getPort function-13-Term_getPort:s->function-0-Term_IfElse function-22-Port___init__:s->function-14-Term_getPort function-14-Term_getPort:s->function-0-Term_IfElse function-12-Port___init__:s->function-12-Region_get function-12-Region_get:s->function-1-Region___init__ function-19-Port___init__:s->function-12-Term_getPort function-12-Term_getPort:s->function-0-Term_IfElse function-26-Port___init__:s->function-21-Term_getPort function-21-Term_getPort:s->function-0-Term_Loop function-1-Port___init__:s->function-1-Term_DbgValue function-1-Term_DbgValue:s->function-1-Term_LiteralI64 function-18-Port___init__:s->function-9-Term_getPort function-9-Term_getPort:s->function-0-Term_IfElse function-13-Port___init__:s->function-13-Region_get function-13-Region_get:s->function-1-Region___init__ function-3-Port___init__:s->function-6-Region_get function-6-Region_get:s->function-2-Region___init__ function-24-Port___init__:s->function-16-Term_getPort function-16-Term_getPort:s->function-0-Term_IfElse function-23-Port___init__:s->function-15-Term_getPort function-15-Term_getPort:s->function-0-Term_IfElse function-1-PortList___init__:s->primitive-Vec_Port-1 primitive-Vec_Port-1:s->function-10-Port___init__ primitive-Vec_Port-1:s->function-11-Port___init__ primitive-Vec_Port-1:s->function-15-Port___init__ primitive-Vec_Port-1:s->function-8-Port___init__ primitive-Vec_Port-1:s->function-9-Port___init__ primitive-Vec_Port-1:s->function-14-Port___init__ primitive-Vec_Port-1:s->function-12-Port___init__ primitive-Vec_Port-1:s->function-13-Port___init__ function-0-PortList___init__:s->primitive-Vec_Port-0 primitive-Vec_Port-0:s->function-5-Port___init__ primitive-Vec_Port-0:s->function-7-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-4-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-3-Port___init__ function-3-PortList___init__:s->primitive-Vec_Port-3 primitive-Vec_Port-3:s->function-25-Port___init__ primitive-Vec_Port-3:s->function-26-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-17-Port___init__ primitive-Vec_Port-2:s->function-21-Port___init__ primitive-Vec_Port-2:s->function-20-Port___init__ primitive-Vec_Port-2:s->function-22-Port___init__ primitive-Vec_Port-2:s->function-19-Port___init__ primitive-Vec_Port-2:s->function-18-Port___init__ primitive-Vec_Port-2:s->function-24-Port___init__ primitive-Vec_Port-2:s->function-23-Port___init__ function-1-Region___init__:s->function-0-InPorts___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-0-Term_Loop:s->function-2-Term_RegionEnd function-0-Term_Loop:s->function-4-TermList___init__ function-2-Term_RegionEnd:s->function-2-PortList___init__ function-2-Term_RegionEnd:s->function-0-Region___init__ function-4-TermList___init__:s->primitive-Vec_Term-4 function-2-Term_getPort:s->function-0-Py_NeIO function-0-Py_NeIO:s->function-0-Term_getPort function-0-Py_NeIO:s->function-0-Term_LiteralStr function-0-Py_NeIO:s->function-0-Term_DbgValue function-22-Region_get:s->function-3-Region___init__ function-21-Region_get:s->function-3-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-19-Term_getPort:s->function-0-Py_AddIO function-0-Py_AddIO:s->function-22-Region_get function-0-Py_AddIO:s->function-21-Region_get function-0-Py_AddIO:s->function-0-Term_LiteralI64 function-7-Term_DbgValue:s->function-19-Term_getPort function-0-Py_Call:s->function-0-Py_LoadGlobal function-0-Py_Call:s->function-4-Region_get function-0-Py_Call:s->function-0-TermList___init__ function-0-Py_LoadGlobal:s->function-4-Region_get function-4-Region_get:s->function-0-Region___init__ function-0-TermList___init__:s->primitive-Vec_Term-0 function-0-Py_NotIO:s->function-9-Term_getPort function-0-Py_NotIO:s->function-8-Term_getPort function-8-Term_getPort:s->function-0-Term_IfElse function-20-Region_get:s->function-0-Region___init__ function-2-Region_get:s->function-2-Region___init__ function-1-Py_LoadGlobal:s->function-5-Term_getPort function-5-Term_getPort:s->function-0-Py_AddIO function-17-Region_get:s->function-0-Region___init__ function-2-Py_Call:s->function-2-Py_LoadGlobal function-2-Py_Call:s->function-6-Term_getPort function-2-Py_Call:s->function-3-TermList___init__ function-2-Py_LoadGlobal:s->function-6-Term_getPort function-6-Term_getPort:s->function-1-Py_Call function-3-TermList___init__:s->primitive-Vec_Term-3 function-0-Term_getPort:s->function-0-Py_Call function-0-Py_InplaceAddIO:s->function-3-Region_get function-0-Py_InplaceAddIO:s->function-2-Region_get function-0-Py_InplaceAddIO:s->function-1-Region_get function-5-Term_DbgValue:s->function-18-Term_getPort function-18-Term_getPort:s->function-2-Py_Call function-3-Term_DbgValue:s->function-17-Region_get function-1-Region_get:s->function-2-Region___init__ function-1-Py_Call:s->function-1-Py_LoadGlobal function-1-Py_Call:s->function-5-Term_getPort function-1-Py_Call:s->function-2-TermList___init__ function-7-Term_getPort:s->function-1-Py_Call function-2-TermList___init__:s->primitive-Vec_Term-2 function-0-Term_DbgValue:s->function-1-Term_getPort function-1-Term_getPort:s->function-0-Py_Call function-10-Term_getPort:s->function-0-Py_NotIO function-0-Term_Func:s->function-3-Term_RegionEnd function-3-Term_RegionEnd:s->function-3-PortList___init__ function-3-Term_RegionEnd:s->function-3-Region___init__ function-19-Region_get:s->function-0-Region___init__ function-0-Term_RegionEnd:s->function-0-PortList___init__ function-0-Term_RegionEnd:s->function-2-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-17-Term_getPort:s->function-2-Py_Call function-0-GraphRoot:s->function-0-Term_Func function-0-Region_get:s->function-0-Region___init__ function-16-Region_get:s->function-0-Region___init__ function-18-Region_get:s->function-0-Region___init__ function-6-Term_DbgValue:s->function-0-Term_LiteralBool primitive-Vec_Term-1:s->function-20-Region_get primitive-Vec_Term-1:s->function-0-Term_getPort primitive-Vec_Term-1:s->function-3-Term_DbgValue primitive-Vec_Term-1:s->function-0-Term_DbgValue primitive-Vec_Term-1:s->function-19-Region_get primitive-Vec_Term-1:s->function-0-Region_get primitive-Vec_Term-1:s->function-16-Region_get primitive-Vec_Term-1:s->function-18-Region_get primitive-Vec_Term-0:s->function-0-Term_LiteralStr primitive-Vec_Term-0:s->function-0-Region_get primitive-Vec_Term-2:s->function-22-Region_get primitive-Vec_Term-3:s->function-7-Term_getPort primitive-Vec_Term-4:s->function-22-Region_get primitive-Vec_Term-4:s->function-7-Term_DbgValue primitive-Vec_Term-4:s->function-5-Term_DbgValue primitive-Vec_Term-4:s->function-8-Term_DbgValue primitive-Vec_Term-4:s->function-1-Term_Undef primitive-Vec_Term-4:s->function-0-Term_Undef primitive-Vec_Term-4:s->function-17-Term_getPort primitive-Vec_Term-4:s->function-6-Term_DbgValue function-0-InPorts___init__ InPorts primitive-Vec_String-0 Vec("!io", "__scfg_backedge_var_0__", "__scfg_iter_last_1__", "__scfg_iterator_1__", "__scfg_loop_cont_1__", "c", "i", "n") function-1-InPorts___init__ InPorts primitive-Vec_String-1 Vec("!io", "n") function-5-Port___init__ Port("c", ·) function-4-Term_getPort ·.getPort(·, 1) function-10-Port___init__ Port("__scfg_iter_last_1__", ·) function-10-Region_get ·.get(·, 2) function-11-Port___init__ Port("__scfg_iterator_1__", ·) function-11-Region_get ·.get(·, 3) function-16-Port___init__ Port("!_loopcond_0002", ·) function-4-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) function-7-Port___init__ Port("n", ·) function-8-Region_get ·.get(·, 7) function-17-Port___init__ Port("!io", ·) function-11-Term_getPort ·.getPort(·, 0) function-15-Port___init__ Port("n", ·) function-15-Region_get ·.get(·, 7) function-0-Port___init__ Port("!io", ·) function-3-Term_getPort ·.getPort(·, 0) function-8-Port___init__ Port("!io", ·) function-9-Region_get ·.get(·, 0) function-9-Port___init__ Port("__scfg_backedge_var_0__", ·) function-2-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-21-Port___init__ Port("__scfg_loop_cont_1__", ·) function-14-Port___init__ Port("i", ·) function-14-Region_get ·.get(·, 6) function-2-Port___init__ Port("__scfg_iter_last_1__", ·) function-5-Region_get ·.get(·, 2) function-4-Port___init__ Port("__scfg_loop_cont_1__", ·) function-7-Region_get ·.get(·, 4) function-6-Port___init__ Port("i", ·) function-3-Region_get ·.get(·, 6) function-25-Port___init__ Port("!io", ·) function-20-Term_getPort ·.getPort(·, 0) function-20-Port___init__ Port("__scfg_iterator_1__", ·) function-13-Term_getPort ·.getPort(·, 3) function-22-Port___init__ Port("c", ·) function-14-Term_getPort ·.getPort(·, 5) function-12-Port___init__ Port("__scfg_loop_cont_1__", ·) function-12-Region_get ·.get(·, 4) function-19-Port___init__ Port("__scfg_iter_last_1__", ·) function-12-Term_getPort ·.getPort(·, 2) function-26-Port___init__ Port("!ret", ·) function-21-Term_getPort ·.getPort(·, 5) function-1-Port___init__ Port("__scfg_backedge_var_0__", ·) function-1-Term_DbgValue Term.DbgValue("__scfg_backedge_var_0__", ·) function-18-Port___init__ Port("__scfg_backedge_var_0__", ·) function-9-Term_getPort ·.getPort(·, 1) function-13-Port___init__ Port("c", ·) function-13-Region_get ·.get(·, 5) function-3-Port___init__ Port("__scfg_iterator_1__", ·) function-6-Region_get ·.get(·, 3) function-24-Port___init__ Port("n", ·) function-16-Term_getPort ·.getPort(·, 7) function-23-Port___init__ Port("i", ·) function-15-Term_getPort ·.getPort(·, 6) function-1-PortList___init__ PortList primitive-Vec_Port-1 Vec function-0-PortList___init__ PortList primitive-Vec_Port-0 Vec function-3-PortList___init__ PortList primitive-Vec_Port-3 Vec function-2-PortList___init__ PortList primitive-Vec_Port-2 Vec function-1-Region___init__ Region("1462", ·) function-3-Region___init__ Region("958", ·) function-2-Region___init__ Region("1307", ·) function-0-Region___init__ Region("1159", ·) function-0-Term_Loop Term.Loop function-2-Term_RegionEnd Term.RegionEnd function-4-TermList___init__ TermList function-2-Term_getPort ·.getPort(·, 1) function-0-Py_NeIO Py_NeIO function-22-Region_get ·.get(·, 1) function-21-Region_get ·.get(·, 0) function-1-Term_LiteralI64 Term.LiteralI64(0) function-0-Term_IfElse Term.IfElse function-0-Term_LiteralI64 Term.LiteralI64(1) function-19-Term_getPort ·.getPort(·, 1) function-0-Py_AddIO Py_AddIO function-7-Term_DbgValue Term.DbgValue("c", ·) function-0-Py_Call Py_Call function-0-Py_LoadGlobal Py_LoadGlobal(·, "next") function-4-Region_get ·.get(·, 0) function-0-TermList___init__ TermList function-0-Py_NotIO Py_NotIO function-8-Term_getPort ·.getPort(·, 0) function-20-Region_get ·.get(·, 7) function-2-Region_get ·.get(·, 5) function-1-Py_LoadGlobal Py_LoadGlobal(·, "range") function-5-Term_getPort ·.getPort(·, 0) function-17-Region_get ·.get(·, 6) function-2-Py_Call Py_Call function-2-Py_LoadGlobal Py_LoadGlobal(·, "iter") function-6-Term_getPort ·.getPort(·, 0) function-3-TermList___init__ TermList function-0-Term_getPort ·.getPort(·, 0) function-0-Py_InplaceAddIO Py_InplaceAddIO function-5-Term_DbgValue Term.DbgValue("__scfg_iterator_1__", ·) function-18-Term_getPort ·.getPort(·, 1) function-0-Term_LiteralStr Term.LiteralStr("__scfg_sentinel__") function-8-Term_DbgValue Term.DbgValue("i", Term.LiteralNone) function-3-Term_DbgValue Term.DbgValue("__scfg_iter_last_1__", ·) function-1-Region_get ·.get(·, 0) function-1-Py_Call Py_Call function-7-Term_getPort ·.getPort(·, 1) function-1-Term_Undef Term.Undef("__scfg_iter_last_1__") function-2-TermList___init__ TermList function-0-Term_DbgValue Term.DbgValue("i", ·) function-1-Term_getPort ·.getPort(·, 1) function-10-Term_getPort ·.getPort(·, 1) function-0-Term_Func Term.Func("2003", "transformed_sum_ints", ·) function-3-Term_RegionEnd Term.RegionEnd function-19-Region_get ·.get(·, 5) function-0-Term_RegionEnd Term.RegionEnd function-1-Term_RegionEnd Term.RegionEnd function-1-TermList___init__ TermList function-0-Term_Undef Term.Undef("__scfg_backedge_var_0__") function-0-Term_LiteralBool Term.LiteralBool(true) function-17-Term_getPort ·.getPort(·, 0) function-0-GraphRoot GraphRoot function-0-Region_get ·.get(·, 3) function-16-Region_get ·.get(·, 1) function-18-Region_get ·.get(·, 4) function-6-Term_DbgValue Term.DbgValue("__scfg_loop_cont_1__", ·) primitive-Vec_Term-1 Vec primitive-Vec_Term-0 Vec primitive-Vec_Term-2 Vec primitive-Vec_Term-3 Vec primitive-Vec_Term-4 Vec
4. EGraph Extraction ▶
EGraph Extraction
Cost ▶
168527825595.0
Extracted ▶
transformed_sum_ints = Func (Args (ArgSpec 'n' (PyNone)))
$0 = Region[2240] <- !io n
{
  $1 = PyInt 1
  $2 = PyBinOp + $0[0] $1, $0[1]
  $3 = PyLoadGlobal $2[0] 'range'
  $4 = PyCall $3 $2[0] $0[1]
  $5 = PyLoadGlobal $4[0] 'iter'
  $6 = PyCall $5 $4[0] $4[1]
  $7 = Undef __scfg_backedge_var_0__
  $8 = Undef __scfg_iter_last_1__
  $9 = DbgValue '__scfg_iterator_1__' $6[1]
  $10 = PyBool True
  $11 = DbgValue '__scfg_loop_cont_1__' $10
  $12 = DbgValue 'c' $2[1]
  $13 = PyNone
  $14 = DbgValue 'i' $13
  $15 = Loop [2977] <- $6[0] $7 $8 $9 $11 $12 $14 $0[1]
    $16 = Region[2249] <- !io __scfg_backedge_var_0__ __scfg_iter_last_1__ __scfg_iterator_1__ __scfg_loop_cont_1__ c i n
    {
      $17 = PyLoadGlobal $16[0] 'next'
      $18 = PyStr '__scfg_sentinel__'
      $19 = PyCall $17 $16[0] $16[3], $18
      $20 = DbgValue '__scfg_iter_last_1__' $16[6]
      $21 = DbgValue 'i' $19[1]
      $22 = PyBinOp != $19[0] $21, $18
      $23 = If $22[1] <- $19[0] $16[1] $20 $16[3] $16[4] $16[5] $21 $16[7]
        $24 = Region[2335] <- !io __scfg_backedge_var_0__ __scfg_iter_last_1__ __scfg_iterator_1__ __scfg_loop_cont_1__ c i n
        {
          $25 = PyInplaceBinOp + $24[0], $24[5], $24[6]
          $26 = PyInt 0
          $27 = DbgValue '__scfg_backedge_var_0__' $26
        } [2466] -> !io=$25[0] __scfg_backedge_var_0__=$27 __scfg_iter_last_1__=$24[2] __scfg_iterator_1__=$24[3] __scfg_loop_cont_1__=$24[4] c=$25[1] i=$24[6] n=$24[7]
        Else
        $28 = Region[2481] <- !io __scfg_backedge_var_0__ __scfg_iter_last_1__ __scfg_iterator_1__ __scfg_loop_cont_1__ c i n
        {
          $29 = DbgValue '__scfg_backedge_var_0__' $1
        } [2595] -> !io=$28[0] __scfg_backedge_var_0__=$29 __scfg_iter_last_1__=$28[2] __scfg_iterator_1__=$28[3] __scfg_loop_cont_1__=$28[4] c=$28[5] i=$28[6] n=$28[7]
      Endif
      $30 = PyUnaryOp not $23[0] $23[1]
      $31 = DbgValue '__scfg_loop_cont_1__' $30[1]
    } [2788] -> !_loopcond_0002=$31 !io=$30[0] __scfg_backedge_var_0__=$23[1] __scfg_iter_last_1__=$23[2] __scfg_iterator_1__=$23[3] __scfg_loop_cont_1__=$31 c=$23[5] i=$23[6] n=$23[7]
  EndLoop
} [3009] -> !io=$15[0] !ret=$15[5]
5. Backend ▶
Backend
LLVM ▶
; ModuleID = ""
target triple = "unknown-unknown-unknown"
target datalayout = ""

define ptr @"foo"(ptr %".1")
{
.3:
  %".4" = alloca ptr
  store ptr null, ptr %".4"
  br label %".6"
.6:
  br label %".8"
.8:
  %".10" = call ptr @"PyLong_FromSsize_t"(i64 1)
  %".11" = call ptr @"PyNumber_Add"(ptr %".10", ptr %".1")
  %"global.range" = inttoptr i64 94131196160960 to ptr
  %".12" = call ptr (ptr, ...) @"PyObject_CallFunctionObjArgs"(ptr %"global.range", ptr %".1", ptr null)
  %"global.iter" = inttoptr i64 140272991505120 to ptr
  %".13" = call ptr (ptr, ...) @"PyObject_CallFunctionObjArgs"(ptr %"global.iter", ptr %".12", ptr null)
  %".14" = call ptr @"PyLong_FromSsize_t"(i64 1)
  call void @"Py_IncRef"(ptr @"_Py_NoneStruct")
  br label %"loopbody"
loopbody:
  %".17" = phi  ptr [null, %".8"], [%".36", %"endif"]
  %".18" = phi  ptr [null, %".8"], [%".37", %"endif"]
  %".19" = phi  ptr [%".13", %".8"], [%".38", %"endif"]
  %".20" = phi  ptr [%".14", %".8"], [%".45", %"endif"]
  %".21" = phi  ptr [%".11", %".8"], [%".40", %"endif"]
  %".22" = phi  ptr [@"_Py_NoneStruct", %".8"], [%".41", %"endif"]
  %".23" = phi  ptr [%".1", %".8"], [%".42", %"endif"]
  %"global.next" = inttoptr i64 140272991505600 to ptr
  %".24" = bitcast ptr @"const_string" to ptr
  %".25" = call ptr @"PyUnicode_FromString"(ptr %".24")
  %".26" = call ptr (ptr, ...) @"PyObject_CallFunctionObjArgs"(ptr %"global.next", ptr %".19", ptr %".25", ptr null)
  %".27" = call ptr @"PyObject_RichCompare"(ptr %".26", ptr %".25", i32 3)
  %".28" = call i32 @"PyObject_IsTrue"(ptr %".27")
  %".29" = icmp ne i32 0, %".28"
  br i1 %".29", label %"then", label %"else"
endloop:
  ret ptr %".40"
then:
  %".31" = call ptr @"PyNumber_InPlaceAdd"(ptr %".21", ptr %".26")
  %".32" = call ptr @"PyLong_FromSsize_t"(i64 0)
  br label %"endif"
else:
  %".34" = call ptr @"PyLong_FromSsize_t"(i64 1)
  br label %"endif"
endif:
  %".36" = phi  ptr [%".32", %"then"], [%".34", %"else"]
  %".37" = phi  ptr [%".22", %"then"], [%".22", %"else"]
  %".38" = phi  ptr [%".19", %"then"], [%".19", %"else"]
  %".39" = phi  ptr [%".20", %"then"], [%".20", %"else"]
  %".40" = phi  ptr [%".31", %"then"], [%".21", %"else"]
  %".41" = phi  ptr [%".26", %"then"], [%".26", %"else"]
  %".42" = phi  ptr [%".23", %"then"], [%".23", %"else"]
  %".43" = call i32 @"PyObject_Not"(ptr %".36")
  %".44" = zext i32 %".43" to i64
  %".45" = call ptr @"PyBool_FromLong"(i64 %".44")
  %".46" = call i32 @"PyObject_IsTrue"(ptr %".45")
  %".47" = icmp ne i32 0, %".46"
  br i1 %".47", label %"loopbody", label %"endloop"
}

declare ptr @"PyLong_FromSsize_t"(i64 %".1")

declare ptr @"PyNumber_Add"(ptr %".1", ptr %".2")

declare ptr @"PyObject_CallFunctionObjArgs"(ptr %".1", ...)

@"_Py_NoneStruct" = external global i8
declare void @"Py_IncRef"(ptr %".1")

@"const_string" = internal constant [18 x i8] c"__scfg_sentinel__\00"
declare ptr @"PyUnicode_FromString"(ptr %".1")

declare ptr @"PyObject_RichCompare"(ptr %".1", ptr %".2", i32 %".3")

declare i32 @"PyObject_IsTrue"(ptr %".1")

declare ptr @"PyNumber_InPlaceAdd"(ptr %".1", ptr %".2")

declare i32 @"PyObject_Not"(ptr %".1")

declare ptr @"PyBool_FromLong"(i64 %".1")

Testing report

1. Args ▶
(12,)
2. JIT output ▶
79
3. Expected output ▶
79