@@ -61,4 +61,150 @@ considering the specific requirements of the compiler's design.
6161:label : ` ch06/ch06-categorize `
6262
6363
64+ ### Linear Intermediate Representation
6465
66+ Linear IRs are widely used in compiler design, resembling assembly code
67+ for abstract machines. They represent the code to be compiled as a
68+ sequentially ordered series of operations. This ordering is important in
69+ practical terms. Linear IRs are popular because most processors utilize
70+ linear assembly languages.
71+
72+ Two common types of linear IRs are stack machine code and three-address
73+ code . Stack machine code, a form of single-address code, offers a
74+ straightforward and compact representation. Instructions in stack
75+ machine code typically consist solely of an opcode that specifies an
76+ operation, with operands stored on a stack. Most instructions retrieve
77+ operands from the stack and push the results of their operations back
78+ onto it. On the other hand, three-address code (3AC) emulates the
79+ instruction format used in modern RISC machines. It employs a set of
80+ quadruples, each containing an operator and three addresses (two
81+ operands and one target). Figure
82+ :numref:` ch04/ch04-linearIR ` illustrates the stack machine code
83+ and three-address code representations for the expression $a-b* 5$.
84+
85+ ![ Stack machine code and three-addresscode] ( ../img/ch04/IR-linear_IR.png )
86+ :label : ` ch04/ch04-linearIR `
87+
88+ ### Graphical Intermediate Representation
89+
90+ Graphical IRs store information about the compilation process in the
91+ form of graphs. These graphs utilize nodes, edges, lists, trees, and
92+ other elements to collectively represent an algorithm. Although all
93+ graphical IRs consist of nodes and edges, they differ in terms of
94+ abstraction levels and graph structures. Common examples of graphical
95+ IRs include abstract syntax trees (ASTs), directed acyclic graphs
96+ (DAGs), and control-flow graphs (CFGs).
97+
98+ An AST is a tree-structured IR that closely resembles the structure of
99+ the source code. Figure :numref:` ch04/ch04-AST_DAG ` depicts the AST for the expression
100+ $a5+a5b$. It is worth noting that the AST contains two identical copies
101+ of $a5$, which introduces redundancy. To address this redundancy, the
102+ DAG offers a simplified representation where identical subtrees can be
103+ shared by multiple parent nodes. By reusing subtrees, the DAG reduces
104+ the cost of the evaluation process, especially when the compiler can
105+ verify that the value of $a$ remains constant.
106+
107+ ![ AST and DAG] ( ../img/ch04/IR-ASTDAG.png )
108+ :label : ` ch04/ch04-AST_DAG `
109+
110+ ### Hybrid Intermediate Representation
111+
112+ Hybrid IRs combine both linear IR and graphical IR elements. An example
113+ of a hybrid IR is LLVM IR , which is illustrated in Figure
114+ :numref:` ch04/ch04-LLVM_IR ` . LLVM is an open-source compiler
115+ framework with the goal of providing unified IRs for different frontends
116+ and backends.
117+
118+ In LLVM IR, linear IRs are used to construct basic blocks, while
119+ graphical IRs represent the control flow between these blocks. Each
120+ instruction within a basic block is presented as a static single
121+ assignment (SSA) . SSA requires each variable to be defined before use,
122+ with values assigned to them only once. Multiple SSA instructions form a
123+ linear list within a basic block.
124+
125+ In the control flow graph (CFG), each node represents a basic block, and
126+ control transfer between these blocks is implemented through edges. This
127+ combination of linear IR for basic blocks and graphical IR for control
128+ flow allows for a flexible and efficient representation in LLVM IR.
129+
130+ ![ LLVM IR] ( ../img/ch04/IR-LLVMIR.png )
131+ :label : ` ch04/ch04-LLVM_IR `
132+
133+ ## Intermediate Representation in Machine Learning Frameworks
134+
135+ Classical IRs (such as LLVM IR) primarily target programming languages
136+ for general-purpose computation tasks, which falls short of satisfying
137+ the unique requirements of machine-learning-related computation. When
138+ designing IRs tailored for machine learning frameworks, certain vital
139+ factors warrant attention:
140+
141+ - ** Tensor Representation** . Given the predominance of tensor data in
142+ machine learning frameworks, it's imperative that the IRs can
143+ effectively handle tensor representation.
144+
145+ - ** Automatic Differentiation** . A core aspect of machine learning
146+ involves evaluating derivatives of neural networks and optimizers
147+ through automatic differentiation. Accordingly, IRs must prioritize
148+ simplicity, performance, and scalability of higher-order
149+ differentials for automatic differentiation.
150+
151+ - ** Computational Graph Mode** . Machine learning frameworks like
152+ TensorFlow, PyTorch, and MindSpore operate on two computational
153+ graph modes: static and dynamic. The static mode, with pre-defined
154+ computational graphs, enhances optimization but compromises on
155+ flexibility. Conversely, the dynamic mode trades running speed for
156+ flexibility and easier debugging by executing operators immediately
157+ in the computational graph. IRs should therefore support both modes,
158+ enabling users to choose the one best suited for their tasks while
159+ building algorithm models.
160+
161+ - ** Support for Higher-order Functions and Closures** . Essential in
162+ functional programming, higher-order functions take or return
163+ functions, while closures bundle code blocks with references to the
164+ surrounding environment, facilitating access to an outer function's
165+ scope from an inner function. Such support reduces redundant code,
166+ improves abstraction, and enhances the flexibility and simplicity of
167+ framework representations.
168+
169+ - ** Compilation Optimization** . Machine learning frameworks lean on
170+ compilation optimizations, including hardware-agnostic,
171+ hardware-specific, and deployment- or inference-related
172+ optimizations. These rely significantly on IRs implementations.
173+
174+ - ** Just-in-Time (JIT) Compilation** . For expedited compilation and
175+ execution in machine learning frameworks, JIT compilation is
176+ frequently utilized. Optimization of JIT compilation, including loop
177+ unrolling, fusion, and inlining, plays a crucial role in optimizing
178+ parts of data flow graphs in IRs. A flawed IR design could
179+ potentially hamper JIT compilation performance in machine learning
180+ frameworks, thereby impacting the program's running capabilities.
181+
182+ Considering these factors, developers persistently refine classical IRs
183+ and introduce new IRs specifically tailored for machine learning
184+ frameworks. In the following section, we will delve into the IRs
185+ employed by various machine learning frameworks.
186+
187+ ### Intermediate Representation in PyTorch
188+
189+ PyTorch is a dynamic, Python-oriented machine learning framework.
190+ Renowned for its usability and flexibility, PyTorch simplifies the
191+ process of writing and debugging machine learning programs. It
192+ introduces TorchScript, a method used for constructing serializable and
193+ optimizable models during the saving and loading of neural networks.
194+
195+ Particularly, TorchScript IR employs JIT compilation to convert Python
196+ code into target model files. All TorchScript programs can be saved
197+ within the Python process and later loaded into processes devoid of
198+ Python dependencies.
199+
200+ Aligning with the imperative programming paradigm, PyTorch incorporates
201+ the TorchScript IR, composed primarily of Single Static Assignment
202+ (SSA)-based linear IRs, to represent Python code. This representation
203+ can be achieved through either the Tracing or Scripting method of JIT
204+ compilation. TorchScript IR not only amplifies model deployment
205+ capabilities but also bolsters compilation performance. Additionally,
206+ TorchScript IR greatly improves the model visualization within the
207+ PyTorch framework.
208+
209+ Code ` lst:torchscript ` illustrates the use of the Scripting method
210+ to print a TorchScript IR graph.
0 commit comments