Method and system for compiler optimization of domain specific languages based on multi-layer intermediate representations
By defining a DSL and combining it with the Monte Carlo tree search algorithm to optimize the compiler decision-making process, the problems of high programming complexity and insufficient performance of LLVM IR in specific fields are solved, and efficient compiler optimization is achieved.
Patent Information
- Application Number
- CN202411429388.7
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2024-10-14
- Publication Date
- 2025-10-14
- Estimated Expiration
- 2044-10-14
AI Technical Summary
When using LLVM IR for compilation, existing technologies have high programming complexity, insufficient program performance, and difficulty in meeting the optimization requirements of specific fields, making it impossible to implement efficient optimization strategies.
By defining the syntax of DSL, classifying and mapping MLIR operators to corresponding expressions in DSL, and combining the Monte Carlo tree search algorithm to optimize the compiler decision process, DSL code is generated and the optimization strategy is found.
The MLIR structure has been simplified, programming complexity has been reduced, program performance and flexibility have been improved, and it is particularly suitable for rapid development and optimization in specific fields.
Smart Images

Figure CN119512557B_ABST
Abstract
Description
TECHNICAL FIELD
[0001] The present application relates to the technical field of compiler, and particularly relates to a domain-specific language compiler optimization method and system based on multi-layer intermediate representation. BACKGROUND
[0002] LLVM (Low Level Virtual Machine) is a series of modular and reusable compiler and tool chain technologies, which provides a common compiler architecture to provide high-level information for compiler conversion, to support transparent and continuous analysis and conversion of any program during compilation, linking, runtime and running interval. The LLVM architecture divides the compilation process into several key stages: front end, optimizer and back end. The front end stage (Fronted) converts the source code into intermediate representation (Intermediate Representation, IR). The front end LLVM supports multiple programming languages (such as C, Fortran, Haskell) through Clang, and generates an abstract syntax tree (Abstract Syntax Tree, AST) after lexical analysis and syntax analysis, and then converts it into a low-level programming language-independent LLVM IR. The IR design of LLVM allows the compiler to optimize in multiple stages, including compile-time, link-time, installation-time, and even runtime. The optimizer stage (Optimizer) uses various optimization techniques to optimize the IR to improve the quality and execution efficiency of the code. The optimization techniques used by the optimizer, such as constant propagation, dead code elimination, and loop optimization, can eliminate redundant calculations and improve the execution efficiency of the code. At the same time, advanced techniques such as SSA-based optimization and global value numbering can further improve the quality and execution efficiency of the code. The back end stage (Backend) supports multiple hardware architectures and can convert LLVM IR into target machine assembly code, and then generate machine code optimized for specific hardware. The LLVM back end also supports both Just-In-Time (JIT) and Ahead-Of-Time (AOT) modes, providing language designers with more options. In this process, the back end is also responsible for handling issues related to the target machine, such as register allocation, instruction selection, and code scheduling.
[0003] To address the limitations of LLVM IR in specific domains, a new compilation infrastructure, MLIR (Multi-Level Intermediate Representation), has been proposed. MLIR's design allows compiler developers to define multi-level IR, even custom operations and abstractions within it and optimize based on it, thereby building an optimal model for the problem domain. This flexibility makes MLIR a powerful tool for developers to create customized compilers and optimization strategies for specific hardware and model requirements. Existing technologies typically use LLVM as the compiler foundation, implementing optimization strategies based on MLIR's multi-level intermediate representation and providing JIT support infrastructure, allowing developers to leverage LLVM modules for just-in-time compilation. However, these approaches not only increase programming complexity and impact program performance, but can also be inaccurate for specific optimization requirements. They often struggle to meet all requirements in a specific domain, hindering the implementation of efficient optimization strategies for that domain. Summary of the Invention
[0004] The technical problem to be solved by the present invention is: in response to the technical problems existing in the prior art, the present invention provides a domain-specific language compiler optimization method and system based on multi-layer intermediate representation, which has a simple implementation method, low programming complexity, high program performance and strong flexibility.
[0005] In order to solve the above technical problems, the technical solution proposed by the present invention is:
[0006] A domain-specific language compiler optimization method based on multi-layer intermediate representation, comprising the following steps:
[0007] Step S1. DSL design based on MLIR: Define the syntax of the DSL to simplify the representation and operations in MLIR, classify the operators in MLIR, and map each type of operator in MLIR to a keyword in the DSL;
[0008] Step S2. MLIR to DSL translation: Parse the target MLIR code, extract the input, output, and control flow semantics of each operation, map the operators in the MLIR code to corresponding expressions in the DSL, and convert each optimization strategy in the target MLIR code into a DSL representation, thereby translating the target MLIR code into a DSL representation.
[0009] Step S3. AI-based compilation optimization: generating DSL code based on the translated DSL representation, obtaining different optimization strategies respectively, and using the Monte Carlo tree search algorithm to continuously simulate and evaluate the performance of different optimization strategies to find the optimal optimization strategy. In the search process, the search tree is used to represent different optimization states, each node represents an optimization decision, and the search tree is continuously expanded by expanding each child node until the optimal optimization strategy is obtained, achieving compiler optimization.
[0010] Further, in step S1, the operators in MLIR are classified into arithmetic operators, logical operators, comparison operators, memory operators, function operations, control flow operators, and vector and tensor operators.
[0011] Further, in the syntax of the DSL defined in step S1, the definition types include def_func, def_mod, call, comm, log, and profile to correspond to defining functions, defining models, calculations, communication, printing logs, and tracking running information, respectively, and const, var, and ext are used as prefixes to represent constants, variables, and execution parameters, respectively.
[0012] Further, in step S2, the target MLIR code is parsed, and the operators in the MLIR code are mapped to the corresponding expressions in the DSL, including:
[0013] Step S201. Traverse the intermediate representation of the target MLIR code, and parse each operator according to the operation type, extracting the input, output, and control flow semantics of each operation;
[0014] Step S202. In the parsing process, a mapping table is used to map the operators in the target MLIR code to the corresponding expressions in the DSL.
[0015] Furthermore, in step S2, converting each optimization strategy in the target MLIR code into a DSL representation includes converting loop unrolling, function inlining optimization, vectorization optimization, and constant folding in the target MLIR code into a DSL representation, wherein the process of converting the loop unrolling code includes simplifying the operations therein according to the DSL syntax, removing the type declarations in the MLIR code, and mapping the operators in the MLIR code to corresponding expressions in the DSL; the process of converting the function inlining optimization code includes mapping the operators in the MLIR code to corresponding expressions in the DSL, simplifying the declarations of parameters and return types according to the DSL syntax, removing redundant type information and symbolic variable representations; the process of converting the vectorization optimization code includes mapping the operators in the MLIR code to corresponding expressions in the DSL, directly passing the array name and index as parameters in the vector load operation, and the parameters in the vector addition operation are the loaded vector variables; the process of converting the constant folding code includes mapping the operators in the MLIR code to corresponding expressions in the DSL, directly declaring constants using corresponding keywords, and removing redundant syntax elements.
[0016] Furthermore, in step S3, the steps of using the Monte Carlo tree search algorithm to continuously simulate and evaluate the performance of different optimization strategies to find the optimal optimization strategy include:
[0017] Step S301. Build a search tree: The root node of the search tree represents the state of the original program, that is, the code without any optimization operation, and each child node represents a specific optimization decision state;
[0018] Step S302. Selection: Starting from the root node, traverse the search tree, selecting child nodes that meet the preset requirements each time, and traverse until reaching a node that is not fully expanded;
[0019] Step S303. Expansion: creating a new child node for the currently incompletely expanded node to perform node expansion;
[0020] Step S304. Simulation: Simulate the effect of the optimization strategy corresponding to the newly expanded child node;
[0021] Step S305: Feedback: The simulated performance evaluation results are fed back along the path from the root node to the current node, and the visit count and performance estimate of each node on the path are updated. If the simulation result of the current node meets the preset requirements, the performance evaluation results of the node corresponding to the current optimization strategy and its ancestor nodes are improved during the feedback process to increase the probability of the current node and its ancestor nodes being selected in the future.
[0022] Step S306. Loop search and optimal strategy determination: Loop through steps S302 to S305 to continuously explore the loop expansion strategy space through repeated selection, expansion, simulation and return steps, so that the search tree continues to grow and optimize until the iteration reaches the preset requirements, and then select the optimization strategy corresponding to the node with the best performance as the optimal optimization strategy.
[0023] Furthermore, when the loop unrolling optimization strategy is used, the node in step S301 represents the number of loop unrollings, and the node expansion in step S303 will expand the loop K times, and the goal after multiple iterative searches is the optimal number of loop unrollings; when the function inlining optimization strategy is used, the node in step S301 represents the state of inlining the function to the call point, and the frequently called small functions will be inlined during the node expansion in step S303, and the goal after multiple iterative searches is the best function inlining selection; when the vectorization optimization strategy is used, the node in step S301 represents the vectorization operation on the data segment, and the data block will be vectorized during the node expansion in step S303, and the goal after multiple iterative searches is the most effective vectorization solution; when the constant folding optimization strategy is used, the node in step S301 represents the state of constant folding in the expression, and the node expansion in step S303 will calculate the constants in the expression in advance and fold them, and the goal after multiple iterative searches is the most reasonable constant folding combination.
[0024] Furthermore, in step S302, the child node with the highest UCB value is selected for traversal, or the selection score is calculated by combining the UCB algorithm and the strategy network score according to the following formula: , select the one with the highest selection score Traverse the child nodes of
[0025]
[0026]
[0027] in, and are the weights of UCB and policy network scores, represents the policy network score, represents the UCB value of the i-th node, is the average performance estimate at the ith node, is the number of visits to the i-th node, is the number of visits to its parent node.
[0028] A compiler system includes a processor and a memory, wherein the memory is used to store a computer program, and the processor is used to execute the computer program to perform the above method.
[0029] A computer-readable storage medium storing a computer program, wherein the computer program implements the above method when executed.
[0030] Compared with the existing technology, the advantages of the present invention are: the present invention realizes compiler optimization by combining DSL design with AI algorithm, expands the design of corresponding DSL based on MLIR, translates MLIR into DSL representation and generates DSL code, which can greatly simplify the complex MLIR structure and avoid the use of lengthy function calls and complex syntax structures in general programming languages. It is particularly suitable for rapid development and optimization in specific fields. At the same time, it is optimized according to the needs of AI. By combining the AI algorithm of introducing Monte Carlo tree search to optimize the decision-making process and scheduling strategy of the compiler, it can better support AI-guided compilation optimization, which can not only reduce programming complexity, but also effectively improve program performance and application flexibility. BRIEF DESCRIPTION OF THE DRAWINGS
[0031] Figure 1 This is a schematic diagram of the principle architecture of implementing compiler optimization using DSL in this embodiment.
[0032] Figure 2 This is a schematic diagram of the implementation flow of the domain-specific language compiler optimization method based on multi-layer intermediate representation in this embodiment.
[0033] Figure 3 This is a schematic diagram of the principle of the traditional MLIR operation flow.
[0034] Figure 4 This is a schematic diagram of the DSL-based operation process principle of this embodiment.
[0035] Figure 5 This is a flowchart of the AI-based code optimization implementation process of this embodiment. DETAILED DESCRIPTION
[0036] The present invention will be further described below in conjunction with the accompanying drawings and specific preferred embodiments, but the scope of protection of the present invention is not limited thereby.
[0037] To facilitate understanding, the technical background related to the present invention is first exemplified.
[0038] Traditional, common general-purpose programming languages (such as Java, C++, and Python) are designed to solve a wide variety of problems and can be applied across multiple domains. However, these languages typically have complex syntax and extensive functionality, leading to a steep learning curve. Domain-specific languages (DSLs) are programming languages designed specifically for a specific problem domain. They are designed to solve specific domain problems, removing complexity unrelated to that domain. They typically feature concise syntax and expressiveness, and their syntax and structure are often more intuitive. This allows domain experts to express their needs in a more intuitive and efficient manner, improving code readability and maintainability. This makes programming tasks within a specific domain easier and more efficient, and the code easier to understand and maintain. DSLs also align more closely with the essence of the domain problem, allowing developers to understand and write code more quickly and reduce the occurrence of errors. For researchers familiar with specific domains, using DSLs can significantly improve development efficiency. Furthermore, because DSLs make it easier for compilers to understand program semantics, they offer more opportunities for performance optimization and enable deeper optimizations. For example, deep learning compilers can leverage DSLs to identify and optimize operators in computation graphs. In automatic tuning, DSL helps define a clear search space so that the compiler can search for the optimal execution strategy more efficiently.
[0039] MLIR manages extensibility through dialects. A dialect is a set of operations and associated semantics that together define a specific IR for expressing and manipulating domain-specific computations. MLIR allows developers to define their own dialects for specific application domains or computational models. The unified and modular compiler infrastructure provided by MLIR enables integration and conversion between different dialects (including LLVM IR). Based on the dialect mechanism within the MLIR ecosystem, once a DSL that meets all the requirements of a specific domain has been designed, it can be integrated into the unified MLIR ecosystem by creating a new dialect. MLIR's compiler support and optimizations for operations within the dialect can be leveraged to implement efficient optimization strategies for specific domain-specific problems.
[0040] The prior art usually uses LLVM as the compiler foundation and implements optimization strategies based on the multi-layer intermediate representation of MLIR, while providing an infrastructure for JIT support, and developers can use the existing LLVM modules to implement the just-in-time compilation function. The present application is aimed at specific field-specific scenarios, and the compiler optimization is realized by combining DSL design and AI algorithms. The corresponding DSL is designed based on MLIR, MLIR is translated into DSL representation and DSL code is generated, which can greatly simplify the complex MLIR structure, and the decision-making process and scheduling strategy of the compiler are optimized by combining the introduction of the AI algorithm of Monte Carlo tree search (MCTS), which can better support AI-guided compilation optimization, not only reducing the programming complexity, but also effectively improving the program performance.
[0041] As shown in Figure 1 The present embodiment is to realize the field-specific language compiler optimization based on the multi-layer intermediate representation, including the DSL design based on MLIR, the translation of MLIR to DSL, and the AI-based compilation optimization. In the DSL design process based on MLIR, the MLIR operators are classified, the DSL syntax is defined, and the MLIR operators are corresponded to the DSL keywords. Then, the MLIR is translated into the DSL representation based on the above-mentioned DSL design method, including parsing the MLIR code, mapping the MLIR operators to the corresponding expressions in the DSL, and converting the optimization strategies in the MLIR to the corresponding DSL representation. Then, the compilation optimization is further performed based on the above-mentioned DSL representation based on AI, which includes the DSL code generation and the decision-making generation based on AI. After the DSL representation generates the corresponding DSL code, the Monte Carlo tree search algorithm is used to continuously simulate and evaluate the performance of each optimization strategy to identify the optimization opportunities, and the optimal optimization strategy is determined according to the search results. The decision-making process and scheduling strategy of the compiler can be effectively optimized by combining the DSL and AI algorithms.
[0042] As shown in Figure 2 The steps of the field-specific language compiler optimization method based on the multi-layer intermediate representation of the present embodiment include:
[0043] Step S1. DSL design based on MLIR: define the syntax of DSL to simplify the representation and operation in MLIR, classify the operators in MLIR, and correspond the operators in MLIR to the keywords in DSL.
[0044] MLIR is a complex infrastructure encompassing numerous concepts, such as dialects, operations, a type system, and conversion passes. Understanding and mastering these concepts and being able to skillfully apply them to build and optimize compilers is a challenging task for beginners. For example, defining a new dialect requires a deep understanding of its definition rules, operational semantics, and how it interacts with other dialects. This steep learning curve makes AI for Compilers extremely challenging. Furthermore, MLIR is designed for generality, capable of handling a wide range of computations and intermediate representations. However, each specific domain often has unique computational patterns, data structures, and performance bottlenecks. MLIR's general optimization strategies may not be precise enough for the specific optimization requirements of AI. While maintaining generality, MLIR struggles to meet the optimization needs of specific domains.
[0045] This embodiment performs AI-guided deep optimization for the LLVM compiler. By expanding the design of a corresponding DSL based on MLIR and designing a DSL for "AI for Compiler", it can make up for the shortcomings of general-purpose MLIR in terms of AI optimization potential. The new DSL can define specialized syntax and semantics based on common computing patterns and data structures in the field, making programming in this field more natural and efficient. At the same time, during the compiler implementation process, specialized optimization strategies can be designed for these specific computing patterns to improve performance. In addition, the new JAIT-DSL can be designed to seamlessly integrate with existing tools and systems in specific fields. The DSL works better with data preprocessing tools, model training frameworks, and deployment platforms, which can improve the efficiency of the entire workflow and reduce the cost of data conversion and interface adaptation.
[0046] To implement MLIR-based DSL design, this embodiment first abstracts and summarizes MLIR, and then uses DSL as an intermediate language to abstract MLIR and describe the front-end program.
[0047] Specifically, this embodiment analyzes the input and output of Operation and its control flow and data flow semantics, and can classify operators in MLIR into arithmetic operators, logical operators, comparison operators, memory operators, function operations, control flow operators, and vector and tensor operators, as shown in Tables 1 to 7 for details.
[0048] Table 1: Arithmetic operators
[0049]
[0050] Table 2: Logical operators
[0051]
[0052] Table 3: Comparison operators
[0053]
[0054] Table 4: Memory operators
[0055]
[0056] Table 5: Function operators
[0057]
[0058] Table 6: Control flow operators
[0059]
[0060] Table 7: Vector and tensor operators
[0061]
[0062] Then the design of DSL is carried out, and the description of the front-end program is realized by translating MLIR into the prescribed format of DSL. In the DSL, a sentence completes the description of a front-end program language. The DSL code is a json format script, which is mainly composed of a list of json dictionaries called sentences. The sentence is a unit structure for describing the operation in the distributed computing graph, and each sentence is composed of an element, which represents the parameter of each operation, including keywords, variables, constants and next parameters.
[0063] Table 8 is the category definition and related syntax in the DSL designed in this embodiment, wherein, in the type column, “const”, “var” and “ext” prefix respectively represent constant, variable and execution parameter, and the parameters in the last row are common parameters of all types of operations, which are helpful for debugging and can be set by manual repair. Further, the MLIR can be corresponded to the DSL keyword as shown in Table 9 to simplify the expression of the operation in the MLIR.
[0064] Table 8: Category definition and related syntax in DSL
[0065]
[0066] Table 9: Correspondence between MLIR and DSL keywords
[0067]
[0068] The following is part of the code generated by the DSL:
[0069]
[0070] The embodiment can simplify the compilation optimization process, avoid using lengthy function calls and complex syntax structures in general programming languages, and is particularly suitable for rapid development and optimization in the field by designing DSL according to the above method.
[0071] Step S2. MLIR to DSL translation: the target MLIR code is parsed, the input, output and control flow semantics of each operation are extracted, and the operators in the MLIR code are mapped to the corresponding expressions in the DSL, and each optimization strategy in the target MLIR code is converted into a DSL representation, so as to translate the target MLIR code into a DSL representation.
[0072] The operators in MLIR cover multiple aspects such as arithmetic operations, logical operations, control flow and memory operations, these operators are described in a general way in MLIR, while DSL focuses on the computing mode in a specific field, therefore an efficient translation mechanism is needed to complete the conversion from MLIR to DSL. The translation from MLIR to DSL is to efficiently convert the operators and structures in MLIR (multi-level intermediate representation) into the syntax of DSL (domain-specific language), so that the compilation process is more suitable for the optimization needs of a specific field.
[0073] In the embodiment, the parsing of the target MLIR code in step S2 and the mapping of the operators in the MLIR code to the corresponding expressions in the DSL specifically includes:
[0074] Step S201. Traverse the intermediate representation in the target MLIR code, and parse each operator according to the operation type to extract the input, output and control flow semantics of each operation;
[0075] Step S202. In the parsing process, a mapping table is used to map the operators in the target MLIR code to the corresponding expressions in the DSL.
[0076] Specifically, to achieve MLIR-to-DSL translation, the system first traverses the intermediate representation (IR) in MLIR and gradually parses each operator according to the different operation types. Each operator corresponds to a specific computational behavior, such as arithmetic operators (such as arith.addi for integer addition), logical operators (such as arith.and for bitwise AND), memory operators (such as memref.load for loading data from memory), and control flow operators (such as cond_br for conditional branching). By parsing these operators, the system can extract the input, output, and control flow semantics of each operation. During the parsing process, the system also uses a mapping table to map MLIR operators to equivalent expressions in the DSL. For example, the arith.addi operation in MLIR is translated into the addi operation in the DSL, and the memref.load operation is translated into the load statement in the DSL.
[0077] It should be noted that the conversion process from MLIR to DSL is not limited to syntax replacement. It can also simplify or adjust the semantics of operations according to domain-specific requirements, making the expression in DSL more closely aligned with computing scenarios in specific domains.
[0078] To improve translation efficiency and code readability, specific syntax optimization rules can be further designed. For example, certain complex MLIR operations can be replaced by a concise expression in the DSL, making the DSL code more intuitive and easy to read. Furthermore, the translation process can be configured to support dynamic semantic adjustments. Based on different compilation contexts and optimization requirements, the syntax in the DSL can be adaptively adjusted to match different hardware platforms or computing environments. This flexibility enables the DSL to not only accurately express the logic in MLIR, but also make corresponding optimizations based on domain requirements.
[0079] In this embodiment, converting each optimization strategy in the target MLIR code into a DSL representation includes converting loop unrolling, function inlining optimization, vectorization optimization, and constant folding in the target MLIR code into a DSL representation, as detailed below:
[0080] (1) DSL representation of loop unrolling
[0081] Loop unrolling optimization is a common compiler optimization technique that reduces loop control overhead by replicating the loop body multiple times, thereby improving program execution efficiency. Loop unrolling is suitable for scenarios where the loop body overhead is low but the loop control overhead is high, such as small-scale or high-frequency loops. The unrolled loop can better utilize pipeline technology, thereby improving the execution efficiency of modern processors. In MLIR, loop unrolling is implemented using the affine loop structure. During the optimization phase, the compiler analyzes the number of loop iterations and the complexity of the loop body to determine how to unroll the loop body. The process of converting the loop unrolling code in this embodiment includes simplifying the operations according to the DSL syntax, removing type declarations in the MLIR code, and mapping operators in the MLIR code to corresponding expressions in the DSL.
[0082] The following is an example of converting MLIR loop unrolling code to DSL representation, where N is the number of loop iterations.
[0083] The MLIR loop unrolling code is:
[0084]
[0085] The above MLIR loop unrolling code is converted to DSL as follows:
[0086]
[0087] The above example primarily describes a basic loop structure, where each iteration performs a memory load, an arithmetic operation, and a result store. In MLIR code, affine.for is used to represent a loop structure, with the index variable %i starting at 0 and incrementing by 1 until it reaches an upper limit %N. In each loop iteration, the program loads a floating-point value %a from memory array %A at location %A[%i], then adds this value to another floating-point value %c, storing the result in memory location %B[%i]. Here, memref.load loads data from memory, arith.addf performs the floating-point addition operation, and memref.store writes the result back to memory. In the converted DSL representation, the logic of the entire operation remains unchanged—memory loads, additions, and stores are performed in a loop—but the representation is simplified. The DSL loop structure still uses for, but eliminates the type declarations and complex operator representations found in MLIR. For example, arith.addf is simplified to addf in the DSL, and the syntax of memref.load and memref.store is also simplified to direct load and store operations. As can be seen above, through simplification, the DSL provides a clearer and more concise expression, making it easier to understand the computational logic of the code without having to deeply understand the complex syntax of MLIR.
[0088] (2) DSL representation of function inlining
[0089] Function inlining optimization is an optimization technique that eliminates function call overhead by replacing function calls with function body code. In particular, for small or frequently called functions, inlining can reduce stack operations and function call jumps, improving program execution efficiency. MLIR defines functions using the "func" operation and calls them using the "call" operation. MLIR's optimization pass can automatically inline functions when appropriate. During the optimization phase, the compiler analyzes the size and call frequency of each function and automatically determines whether inlining is necessary. This method is suitable for situations where function calls are frequent and the overhead is high. The conversion process for function inline optimization in this embodiment includes mapping operators in the MLIR code to corresponding expressions in the DSL, simplifying parameter and return type declarations according to the DSL syntax, removing redundant type information and symbolic variable representations, etc.
[0090] The following is an example of converting a simple function inlining optimized code into DSL representation.
[0091] Function inline optimization code is:
[0092]
[0093] The function inlining optimization code is converted to DSL as follows:
[0094]
[0095] The above example shows how to define and call a function in a program, where the MLIR code uses the func keyword to define a function named add that takes two floating-point number parameters %a and %b and returns their sum. Inside the function, a floating-point addition operation is performed using arith.addf, and the result is stored in %result. Finally, the result is returned to the caller through return. In the subsequent code, the add function is called using the call statement, passing two parameters %5 and %10, and the returned value is stored in %result. After conversion to DSL, this code is greatly simplified while retaining its core computing logic. In the DSL, function definition is represented by func, parameter and return type declaration is more concise, and the floating-point addition operation addf is still retained, but the redundant type information and symbolic variable representation are removed. The function call add(5, 10) in the DSL simplifies the call syntax in MLIR, making the call operation look more natural, similar to the function call method in traditional programming languages. As can be seen from the above, according to the above simplification method, not only does the code become easier to read and understand, but also highlights the characteristics of function inlining, i.e., the function call and definition method in the DSL is more intuitive and clear.
[0096] (3) DSL representation of vectorization optimization
[0097] Vectorization optimization is an optimization strategy that uses SIMD (Single Instruction Multiple Data) instructions to parallelize data processing, thereby accelerating computation. Vectorization allows multiple data to be processed in one instruction operation, which can significantly improve performance in applications that require a large amount of data processing (such as matrix computation, image processing, etc.). MLIR supports vectorization operations through the “vector” type, which can use “vector.load`” and “vector.store`” to define vector operations in memory. The compiler will automatically optimize it to SIMD instructions based on the data type and operation mode. The “vector” operation of MLIR provides powerful parallel computing capabilities and can be automatically converted through the vectorization optimization pass.
[0098] In this embodiment, the process of converting the vectorized optimized code includes mapping operators in the MLIR code to corresponding expressions in the DSL. In the vector load operation, the array name and index are directly passed as parameters, and in the vector addition operation, the parameters are the loaded vector variables.
[0099] The following is an example of a simple vectorized optimized code converted to DSL representation.
[0100] The vectorized optimized code is:
[0101]
[0102] The vectorized optimized code is converted into DSL as follows:
[0103]
[0104] The above example demonstrates how vectorized operations can improve program execution efficiency. In the MLIR code, vector.load is used to load floating-point vectors from arrays %A and %B . These operations load the data into vector variables %a and %b , respectively. Next, arith.addf is used to perform vector addition, adding the loaded vectors to produce the result vector %c . Finally, vector.store is used to store the result vector %c into array %C , ensuring the computation result is preserved. After conversion to a DSL, this code is simplified while retaining the core computation logic. The vector load operation in the DSL is represented by vector.load , but the syntax is more intuitive, directly passing the array name and index as arguments, simplifying the lengthy MLIR representation. The vector addition operation addf remains, with the loaded vector variables as arguments, forming a natural addition expression. Finally, the store operation is expressed using store_vector , further enhancing code readability and clarifying the entire vectorized computation process.
[0105] (4) DSL representation of constant folding
[0106] Constant folding is a compile-time optimization technique that aims to compute the constant results in expressions ahead of time during compilation, avoiding the repeated execution of the same calculations at runtime. In this way, the compiler can reduce the computational burden at runtime and generate more concise and efficient code. Constant folding is usually applicable to expressions containing constant operands such as arithmetic operations and logical operations. MLIR uses constant operators (such as arith.constant) to represent constant values. The compiler's optimization pass automatically performs constant folding, identifying and calculating the results of expressions containing constants. During constant folding, the calculation results are replaced with specific constant values, avoiding unnecessary runtime calculations.
[0107] In the conversion process of constant folding code, this embodiment includes mapping operators in MLIR code to corresponding expressions in DSL, declaring constants directly through corresponding keywords, and removing redundant syntax elements, etc.
[0108] The following is an example of a simple constant folding code converted to DSL representation.
[0109] The constant folding code is:
[0110]
[0111] The constant folding code converted to DSL is:
[0112]
[0113] The above example shows how to use the constant folding technique to improve the efficiency of the program during compilation. In the MLIR code, the arith.constant keyword is used to define two constants %a and %b, which are assigned values of 10 and 20 respectively. These constants are then used to perform addition operations, and the result is stored in %result. Since the addition operation involves constants, the compiler can directly calculate the result as 30 during the compilation phase without the need to perform the addition operation at runtime. After converting to DSL, the expression of the code is simplified. In DSL, constants are declared directly through the const keyword, clearly indicating the value of the variable. Then, the addf(a, b) operation is used to perform the addition operation to get the final result. Compared with the complex operator and type declaration in MLIR, the DSL representation is more intuitive, and the redundant syntax elements are removed, making the intent of the code more clear.
[0114] Step S3. AI-based compilation optimization: generate DSL code based on the translated DSL representation, obtain different optimization strategies respectively, and use the Monte Carlo tree search algorithm to continuously simulate and evaluate the performance of different optimization strategies to find the optimal optimization strategy. In the search process, use the search tree to represent different optimization states, each node represents an optimization decision, and continuously grow the search tree by expanding each child node until the optimal optimization strategy is obtained, achieving compiler optimization.
[0115] The traditional MLIR compilation process mainly relies on a general intermediate representation and heuristic optimization strategies. Although it has a certain flexibility, its generality brings redundancy and inefficiency when facing complex computing scenarios or specific fields. Moreover, due to the complexity of its multi-level representation and general optimization rules, the compilation time is often long, and the generated code may not have optimal performance in all scenarios. In this embodiment, the DSL representation is obtained by translating MLIR to DSL in step S2, which provides an efficient and clear operation basis for AI optimization. This allows the capture of domain-specific computing patterns and operations, and through the combination of DSL and AI optimization algorithms, the compilation process can be intelligently optimized to generate highly optimized target code while flexibly meeting different optimization needs.
[0116] Unlike traditional MLIR compilation optimization work, this embodiment defines a set of DSL for AI optimization, with Sentence in DSL as the operation object, and these Sentences as the optimization unit to complete the corresponding compilation optimization process. The traditional MLIR compilation process is shown in Figure 3 , and the DSL-based compilation process of this embodiment is shown in Figure 4 . As can be seen from the figure, the DSL-based compilation process of this embodiment can be greatly simplified, reducing the additional Dialect generation process, thereby achieving compilation process acceleration.
[0117] As shown in Figure 5 , the AI-based code optimization process of this embodiment includes DSL code generation and AI decision support to achieve efficient code execution. The DSL code generation module generates more compact and efficient machine code through domain-specific language (DSL), and the AI decision support module uses the Monte Carlo tree search algorithm to optimize the functions of the compiler. Monte Carlo tree search is an algorithm used to search for the optimal strategy in the decision-making process. In this embodiment, the AI decision support module continuously simulates and evaluates different optimization strategies to find the optimal solution.
[0118] In this embodiment, the step of using the Monte Carlo tree search algorithm to continuously simulate and evaluate the performance of different optimization strategies to find the optimal optimization strategy includes:
[0119] Step S301. Construct a search tree: The root node of the search tree represents the state of the original program, that is, the code without any optimization operation, and each child node represents a specific optimization decision state.
[0120] Specifically, this embodiment uses a search tree to represent different optimization states in various scenarios, including loop unrolling, function inlining, vectorization, and constant folding. Therefore, when constructing the search tree, for loop unrolling, a node represents the number of loop unrolls, K; for function inlining, a node represents the state of inlining a function to the call site; for vectorization, a node represents the vectorization operation performed on a data segment. In other words, each node represents the application state of a vectorization operation (for example, vectorizing a loop body or data set), and its child nodes represent vectorization operations performed on different data blocks or dimensions; for constant folding, a node represents the state after the constant folding operation in an expression. By expanding each child node, the search tree continuously grows, exploring different optimization combinations. The goal of loop unrolling optimization strategy search is to find the optimal number of loop unrolls; the goal of function inlining optimization strategy search is to find the best function inlining selection; the goal of vectorization optimization strategy search is to find the most effective vectorization solution; and the goal of constant folding optimization strategy search is to find the most reasonable constant folding combination.
[0121] Step S302. Selection: traverse the search tree starting from the root node, selecting child nodes that meet preset requirements each time for traversal until reaching a node that is not fully expanded.
[0122] The selection strategy is a crucial step, which determines which node in the current tree should be expanded from. We can adopt the following two selection strategies to ensure that the best node is selected first.
[0123] In this embodiment, the following two selection strategies can be adopted to ensure that the optimal node can be selected first:
[0124] (1) Using the UCB (Upper Confidence Bound) algorithm
[0125] The classic UCB selection strategy balances exploration and exploitation. Each time a node is selected, it considers the average performance estimate of the current node (utilization) while giving some opportunities to nodes with fewer visits (exploration). The UCB formula is used to calculate the value: ,in At the current node The average performance estimate, is a node Number of visits, is the number of visits to its parent node, Indicates the UCB value of the i-th node, and selects the child node with the highest UCB value for traversal.
[0126] (2) Combining the UCB algorithm with the policy network algorithm
[0127] Specifically, the selection score can be obtained by combining the UCB and the strategy network score. , select the one with the highest selection score The policy network can learn the best decision from a large number of optimization examples, thereby accelerating the search process.
[0128] Select Score It can be calculated according to the following formula:
[0129]
[0130]
[0131] in, and are the weights of UCB and policy network scores, represents the policy network score, represents the UCB value of the i-th node, is the average performance estimate at the ith node, is the number of visits to the i-th node, is the number of visits to its parent node.
[0132] It is understandable that in addition to adopting the above-mentioned selection strategies, other types of selection strategies can also be adopted according to actual needs. For example, the policy network can be directly used to score the status of each node. The higher the score of the node, the more likely its corresponding optimization strategy is to bring performance improvement. The policy network in AlphaGo can also be used for reference to make selections. By training a neural network, the optimal decision for the next step can be predicted based on the current optimization status of the program and historical data.
[0133] Step S303. Expansion: creating a new child node for the node that is not fully expanded to perform node expansion.
[0134] Once an incompletely expanded node is selected, a new child node is created, representing further optimization operations. Specifically, for loop unrolling, node expansion will expand a loop K times; for function inlining, node expansion will inline a frequently called small function; for vectorization, node expansion will vectorize a data block; and for constant folding, node expansion will pre-calculate constants in expressions and fold them. When a new node is expanded, the possibilities of each optimization operation can also be considered, such as the range of expansion times and the selection of functions to inline.
[0135] Step S304. Simulation: Simulate the effect of the optimization strategy corresponding to the newly expanded child node.
[0136] After the new node is expanded, the simulation begins. This step simulates the performance of the program after applying the remaining optimization strategies from the current state.
[0137] Specifically, simulation can be done in the following two ways:
[0138] Random simulation: Based on randomly selected optimization strategies, a set of random optimization decisions are made to estimate the potential performance gains from these decisions. This method is suitable for rapid evaluation. 2. Heuristic simulation: Based on experience or heuristic rules, optimization strategies that are more likely to result in performance gains are prioritized. For example, when inlining functions, smaller and more frequently called functions are prioritized, or simple constant expressions are prioritized for folding. The simulation results can be performance metrics such as program execution time, memory usage, and code size.
[0139] Step S305 feedback: The performance evaluation results obtained by simulation are fed back along the path from the root node to the current node, and the number of visits and performance estimates of each node on the path are updated. If the simulation result of the current node meets the preset requirements, the performance evaluation results of the node corresponding to the current optimization strategy and its ancestor node are improved during the feedback process to increase the probability of the current node and its ancestor node being selected in the future.
[0140] Specifically, after the simulation concludes, the performance evaluation results for that node are propagated back along the path from the root node to that node, updating the visit counts and performance estimates of all nodes along the path. If a strategy performs well, the average performance estimate of its ancestor nodes will increase, giving these nodes a higher probability of being selected in future selection steps. This propagation process ensures that the performance estimate for each node reflects the most recent simulation results, encouraging more exploration of high-performing strategies in the search tree.
[0141] Step S306. Loop search and optimal strategy determination: Loop through steps S302 to S305 to continuously explore the loop expansion strategy space through repeated selection, expansion, simulation and return steps, so that the search tree continues to grow and optimize until the iteration reaches the preset requirements, and then select the optimization strategy corresponding to the node with the best performance as the optimal optimization strategy.
[0142] By repeatedly executing the selection, expansion, simulation, and backpropagation steps, the optimization space is gradually explored, causing the search tree to continuously grow and improve. At the end of each search round, the node in the tree with the highest average performance estimate represents the optimal optimization strategy. For example, this could be the optimal number of loop unrollings, the best choice of function inlining, the most effective vectorization scheme, or the most appropriate constant folding combination. Ultimately, these optimization strategies are applied to the entire program, generating optimized code that can significantly improve its execution efficiency.
[0143] Taking the loop unrolling partial search algorithm to solve the optimal loop unrolling number K as an example, the above solution process is specifically as follows:
[0144] a) Construct a search tree: Each node in the search tree is represented as a loop expansion state with a loop count of k; the root node represents the initial loop unexpanded state.
[0145] b) Selection: Starting from the root node, select the node based on the UCB formula or the selection score. To select nodes traverse the tree until you reach a node that is not fully expanded.
[0146] c) Expand: Once a node that is not fully expanded is selected, a new child node is created accordingly.
[0147] d) Expansion: Starting from the newly expanded node, a random simulation is performed, where the loop is continuously expanded according to a random or simple heuristic loop unrolling strategy until the maximum number of unrollings is reached. During the simulation, the performance of this random unrolling strategy is evaluated, and the execution time of the current unrolling strategy is measured.
[0148] e) Backpropagation: The performance evaluation results obtained from the simulation are backpropagated along the search path to update the number of visits and performance estimates of each node on the path. If the simulation results show that a certain loop unrolling strategy performs well, then during the backpropagation process, the performance estimates of the nodes corresponding to the strategy and their ancestor nodes are increased to make these nodes more likely to be selected in the subsequent selection steps.
[0149] This embodiment can be further integrated into a deep learning framework for user convenience. Users can use the provided tuning function in the deep learning framework to directly optimize the model without manually writing tuning code.
[0150] This embodiment can be applied in various fields, such as software development, healthcare, and automotive manufacturing. Typical DSLs include the Raven framework, the QuantLib library, and the FHIR standard. Taking the Raven framework as an example, DSL-based design allows software developers to focus on implementing business logic rather than getting bogged down in tedious configuration details. For example, in healthcare, DSLs enable seamless integration between different medical information systems, significantly improving the efficiency and security of data sharing. In automotive manufacturing, DSLs can optimize automated processes on production lines.
[0151] The present invention is based on DSL, which can be used in the context of MLIR to define and optimize specific types of calculations. DSL compensates for the limitations of MLIR in specific fields, provides more refined and specialized abstractions for specific computing patterns and problems, and can more easily generate high-performance, highly optimized code. As a result, the compiler provides a more efficient and professional way to handle specific types of computing tasks, simplify programming in specific fields, improve code readability and maintainability, achieve performance optimization, and increase applicability flexibility. It is particularly suitable for application scenarios with high performance requirements and obvious domain characteristics.
[0152] This embodiment further provides a compiler system, including a processor and a memory, wherein the memory is used to store a computer program, and the processor is used to execute the computer program to perform the above method.
[0153] It is understandable that the above method of this embodiment can be executed by a single device, such as a computer or server, etc., and can also be applied to a distributed scenario and completed by multiple devices cooperating with each other. In the case of a distributed scenario, one of the multiple devices can only execute one or more steps in the above method of this embodiment, and multiple devices interact to complete the above method. The processor can be implemented in the form of a general-purpose CPU, a microprocessor, an application-specific integrated circuit, or one or more integrated circuits, etc., for executing relevant programs to implement the above method of this embodiment. The memory can be implemented in the form of a read-only memory ROM, a random access memory RAM, a static storage device, and a dynamic storage device. The memory can store an operating system and other application programs. When the above method of this embodiment is implemented by software or firmware, the relevant program code is stored in the memory and called and executed by the processor.
[0154] This embodiment further provides a computer-readable storage medium storing a computer program, which implements the above method when executed by a processor.
[0155] Those skilled in the art will appreciate that the above-mentioned embodiments of the present application may be provided as methods, systems, or computer program products. Therefore, the present application may take the form of a completely hardware embodiment, a completely software embodiment, or an embodiment combining software and hardware aspects. Moreover, the present application may take the form of a computer program product implemented on one or more computer-readable storage media (including but not limited to disk storage, CD-ROM, optical storage, etc.) containing computer-usable program code. The present application is described with reference to the flowcharts and / or block diagrams of the methods, devices (systems), and computer program products according to the embodiments of the present application. It should be understood that each process and / or box in the flowchart and / or block diagram, as well as the combination of processes and / or boxes in the flowchart and / or block diagram, may be implemented by computer program instructions. These computer program instructions may be provided to a processor of a general-purpose computer, a special-purpose computer, an embedded processor, or other programmable data processing device to produce a machine, so that instructions executed by the processor of the computer or other programmable data processing device generate instructions for implementing the steps in the process. Figure 1 a process or multiple processes and / or boxes Figure 1 These computer program instructions can also be stored in a computer-readable memory that can guide a computer or other programmable data processing device to work in a specific way, so that the instructions stored in the computer-readable memory produce a product including the instruction device, which implements the function specified in the process. Figure 1 a process or multiple processes and / or boxes Figure 1 These computer program instructions can also be loaded onto a computer or other programmable data processing device, so that a series of operation steps are executed on the computer or other programmable device to produce a computer-implemented process, thereby providing instructions for implementing the process in the computer or other programmable device. Figure 1 a process or multiple processes and / or boxes Figure 1 A step that specifies a function in one or more boxes.
[0156] The above description is merely a preferred embodiment of the present invention and does not constitute any form of limitation to the present invention. Although the present invention has been disclosed above with reference to the preferred embodiment, it is not intended to limit the present invention. Therefore, any simple modifications, equivalent variations, and modifications to the above embodiment that do not depart from the technical solution of the present invention and are based on the technical essence of the present invention shall fall within the scope of protection of the technical solution of the present invention.
Claims
1. A method for optimizing a domain-specific language compiler based on a multi-layer intermediate representation, characterized in that the steps include: Step S1. DSL design based on MLIR: Define the syntax of the DSL to simplify the representation and operations in MLIR, classify the operators in MLIR, and map each type of operator in MLIR to a keyword in the DSL; Step S2. MLIR to DSL translation: Parse the target MLIR code, extract the input, output, and control flow semantics of each operation, map the operators in the MLIR code to corresponding expressions in the DSL, and convert each optimization strategy in the target MLIR code into a DSL representation, thereby translating the target MLIR code into a DSL representation. Step S3. AI-based compilation optimization: Generate DSL code based on the translated DSL representation, obtain different optimization strategies, and use the Monte Carlo tree search algorithm to continuously simulate and evaluate the performance of different optimization strategies to find the optimal optimization strategy. During the search process, a search tree is used to represent different optimization states, and each node represents an optimization decision. By expanding each child node, the search tree continues to grow until the optimal optimization strategy is obtained, achieving compiler optimization.
2. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to claim 1, characterized in that: In step S1, operators in MLIR are classified into arithmetic operators, logical operators, comparison operators, memory operators, function operations, control flow operators, and vector and tensor operators.
3. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to claim 1, characterized in that: In step S1, the syntax of the DSL is defined. The defined types include def_func, def_mod, call, comm, log, and profile, which correspond to defining functions, defining models, calculations, communications, printing logs, and tracking running information, respectively. Const, var, and ext are used as prefixes to represent constants, variables, and execution parameters, respectively.
4. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to claim 1, characterized in that: In step S2, the target MLIR code is parsed, and the operators in the MLIR code are mapped to corresponding expressions in the DSL, including: Step S201: Traverse the intermediate representation in the target MLIR code, parse each operator according to the operation type, and extract the input, output, and control flow semantics of each operation; Step S202: During the parsing process, a mapping table is used to map operators in the target MLIR code to corresponding expressions in the DSL.
5. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to claim 1, characterized in that: In step S2, converting each optimization strategy in the target MLIR code into a DSL representation includes converting loop unrolling, function inlining optimization, vectorization optimization, and constant folding in the target MLIR code into a DSL representation. The conversion of the loop unrolling code includes simplifying operations therein according to the DSL syntax, removing type declarations in the MLIR code, and mapping operators in the MLIR code to corresponding expressions in the DSL. The conversion of the function inlining optimization code includes mapping operators in the MLIR code to corresponding expressions in the DSL, simplifying parameter and return type declarations according to the DSL syntax, removing redundant type information and symbolic variable representations. The conversion of the vectorization optimization code includes mapping operators in the MLIR code to corresponding expressions in the DSL, directly passing array names and indices as parameters in vector load operations, and using loaded vector variables as parameters in vector addition operations. The conversion of the constant folding code includes mapping operators in the MLIR code to corresponding expressions in the DSL, directly declaring constants using corresponding keywords, and removing redundant syntax elements.
6. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to any one of claims 1 to 5, characterized in that: In step S3, the steps of using the Monte Carlo tree search algorithm to continuously simulate and evaluate the performance of different optimization strategies to find the optimal optimization strategy include: Step S301. Build a search tree: The root node of the search tree represents the state of the original program, that is, the code without any optimization operation, and each child node represents a specific optimization decision state; Step S302. Selection: Starting from the root node, traverse the search tree, selecting child nodes that meet the preset requirements each time, and traverse until reaching a node that is not fully expanded; Step S303. Expansion: creating a new child node for the currently incompletely expanded node to perform node expansion; Step S304. Simulation: Simulate the effect of the optimization strategy corresponding to the newly expanded child node; Step S305: Feedback: The simulated performance evaluation results are fed back along the path from the root node to the current node, and the visit count and performance estimate of each node on the path are updated. If the simulation result of the current node meets the preset requirements, the performance evaluation results of the node corresponding to the current optimization strategy and its ancestor nodes are improved during the feedback process to increase the probability of the current node and its ancestor nodes being selected in the future. Step S306. Loop search and optimal strategy determination: Loop through steps S302 to S305 to continuously explore the loop expansion strategy space through repeated selection, expansion, simulation and return steps, so that the search tree continues to grow and optimize until the iteration reaches the preset requirements, and then select the optimization strategy corresponding to the node with the best performance as the optimal optimization strategy.
7. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to claim 6, characterized in that: When the loop unrolling optimization strategy is used, the node in step S301 represents the number of loop unrollings, and the node expansion in step S303 will expand the loop K times. The goal after multiple iterative searches is the optimal number of loop unrollings. When the function inlining optimization strategy is used, the node in step S301 represents the state of inlining the function to the call point, and the frequently called small functions will be inlined during the node expansion in step S303. The goal after multiple iterative searches is the best function inlining selection. When the vectorization optimization strategy is used, the node in step S301 represents the vectorization operation on the data segment, and the data block will be vectorized during the node expansion in step S303. The goal after multiple iterative searches is the most effective vectorization solution. When the constant folding optimization strategy is used, the node in step S301 represents the state of constant folding in the expression, and the node expansion in step S303 will calculate the constants in the expression in advance and fold them. The goal after multiple iterative searches is the most reasonable constant folding combination.
8. The domain-specific language compiler optimization method based on multi-layer intermediate representation according to claim 6, characterized in that: In step S302, the child node with the highest UCB value is selected for traversal, or the selection score is calculated by combining the UCB algorithm and the strategy network score according to the following formula: , select the one with the highest selection score Traverse the child nodes of in, and are the weights of UCB and policy network scores, represents the policy network score, represents the UCB value of the i-th node, is the average performance estimate at the ith node, is the number of visits to the i-th node, is the number of visits to its parent node.
9. A compiler system comprising a processor and a memory, wherein the memory is used to store a computer program, wherein: The processor is configured to execute the computer program to perform the method according to any one of claims 1 to 8.
10. A computer-readable storage medium storing a computer program, characterized in that: When the computer program is executed, the method according to any one of claims 1 to 8 is implemented.
Citation Information
Patent Citations
Probability model AI field compiling system and method based on multistage intermediate representation
CN116679933A
Compiling method of multilayer intermediate representation based on field programmable logic gate array
CN118689486A