Method and apparatus for register resource allocation for reusability and relative indexing in function calls

By optimizing register resource allocation at runtime through the compiler, and utilizing dynamic resource reuse and indexed access, the problem of register resource exhaustion during function calls is solved, thereby improving processor performance and energy efficiency.

CN116113927BActive Publication Date: 2026-02-06HUAWEI TECH CO LTD
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202180054297.8
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Priority Date
2020-09-04
Filing Date
2021-05-20
Publication Date
2026-02-06
Estimated Expiration
2041-05-20

AI Technical Summary

Technical Problem

The overflow problem caused by the processor exhausting register resources during function calls results in high performance and energy costs, and existing technologies struggle to optimize register resource allocation in indirect function calls.

Method used

By enabling dynamic resource reuse and dynamic indexing of resource access at runtime, the compiler optimizes register resource allocation. It analyzes resource usage patterns at function call points and generates custom allocation maps and allocation pointers to achieve dynamic register resource allocation.

Benefits of technology

It improves the utilization of register resources, reduces overflow operations caused by exhaustion of register file resources, and improves processor performance and energy efficiency.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN116113927B_ABST
    Figure CN116113927B_ABST
Patent Text Reader

Abstract

Systems, apparatuses, and methods disclosed herein relate to optimizing register resource allocation for functions in a module using a register file comprising a limited number of registers by a compiler. After performing inter-procedural analysis in the module, the compiler calculates the number of registers used by each function and compiles the functions into final machine code except at call points where a call to another function is detected. At each call point, for each called function, the compiler extends the call instruction into the final machine code after calculating and setting a relative index for the called function to run in an available portion of the register file. The relative index optimizes register resource allocation by minimizing the number of spilled registers before the called function.
Need to check novelty before this filing date? Find Prior Art

Description

[0001] Related Applications

[0002] This application claims priority to the prior filed U.S. Non-Provisional Application No. 17 / 012,203, filed September 4, 2020, entitled “METHOD AND APPARATUS FOR REUSABLE AND RELATIVE INDEXED REGISTER RESOURCE ALLOCATION IN FUNCTION CALLS,” the contents of which are incorporated by reference herein in its entirety to the extent such incorporation is permitted in the jurisdiction involved. TECHNICAL FIELD

[0003] The present application relates generally to the field of register resource optimization, and more specifically to a method and apparatus for optimizing resource allocation in function calls. BACKGROUND

[0004] Processors typically have general purpose registers or register files that are shared by processing threads and are partitioned at runtime. These resources provide the ability to store very quickly access the processor, but are limited in number due to the hardware cost of these resources. Processors also use more plentiful, cheaper memory resources, such as caches and main memory, but read / write performance is much slower. Exhausting register resources during processing forces the processor to spill the values held in registers to caches and / or main memory. This spilling causes a significant loss of processing and is very costly in both performance and energy, thus being very inefficient.

[0005] For function calls, conventional calling conventions typically require the caller and callee to spill live registers to the stack and restore live registers upon return from the callee. Such conventional calling conventions require determining how many registers need to be saved for the caller and how many registers need to be passed to the callee, resulting in partitioning of the available register file and resulting in a large amount of spilling to other memory resources.

[0006] This can result in underutilization of the register file (i.e., data is stored / loaded to / from the stack round trip despite the fact that there are enough registers to hold the live data of the caller and callee). In addition to this, processor programming typically uses inlining when possible (large main functions and small call functions).

[0007] For example, certain computing environments can exacerbate this problem: ray tracing processing using a Graphical Processing Unit (GPU), where the shader pipeline makes the interaction between shaders more dynamic. Shaders can call other shaders, much like indirect method calls in procedural programming. In this computing environment, inlining is not even possible.

[0008] Typically, all function / shader register resource allocation requests are resolved and finalized at compile time. These requests are encoded in the generated binary, so once compiled, the register resource allocation is unchangeable. Indirect function calls make the register resource allocation dynamic between the function / shader caller and callee. SUMMARY

[0009] The present technology provides a register allocation scheme to enable the callee to "reuse" free register resources at the call site (a basic category of dynamic calls), which is "relative" to the caller. More specifically, the present technology enables the compiler to perform optimized dynamic register resource allocation in calls, especially indirect calls. The present technology optimizes register resource allocation, e.g., register allocation in calls, through dynamic resource reuse and dynamically indexed resource access. The present technology proposes a new mechanism to manage and optimize register resource allocation at runtime based on actual resource usage analysis at compile time for each call site, thereby enabling more efficient resource utilization and reducing the probability of overflowing operations due to register heap resource exhaustion. The present technology provides the compiler with the ability to optimize runtime code that anticipates and handles register resource exhaustion, where the resource is only overflowed when it is actually about to be exhausted.

[0010] The present technology enables the compiler to perform register resource dataflow analysis to find resource reuse patterns at each call site. Based on the analysis, the compiler creates custom allocation maps and allocation pointers for the callee to use, enabling an optimized, dynamic allocation scheme between the caller and one or more callees.

[0011] The present technology also proposes a dynamic relative register resource access mechanism to facilitate the allocation scheme, which enables the compiler to flexibly generate a copy of the compiled code at runtime for different allocation scenarios.

[0012] Accordingly, it is an object of the present technology to provide a technique to optimize the use of the register file by a function by exploiting the availability of free registers, to avoid having to spill the values held in registers to the much slower cache and / or main memory. The apparatuses, methods and systems disclosed herein enable the compiler to pass relevant indices to the called functions after analyzing the calling interaction between functions, so that these functions use the free registers in the register file before having to spill values from registers.

[0013] According to this object, one aspect of the present technology provides a method for optimizing the allocation of register resources of functions S file (i>0) in a module, by a compiler using a register file comprising a number Nof_reg i (i>0) of registers. The method comprises: performing an inter-procedural analysis in the module; (i) computing the number Nof_regi of registers used by the function S i i; (ii) compiling the function S i i into final machine code, wherein, if the compiler detects a call j to another function S i (j<>i), the compiler leaves the call instruction as a pseudo instruction Callsite ij i; the method further comprises: for each Callsite ij i, (i) determining one or more called functions S k (k<>i) as Calltarget ijk ; (ii) computing the maximum number maxRegIndex i of live registers used by the function S ij i at Callsite ij , and computing RegIndexForRelIndex ij =maxRegIndex ij +1. The method further comprises: for each Callsite ij i and each Calltarget ijk , extending the call instruction to the final machine code to: read the value of the relative index Rel_Index i of the function S i i, and compute the sum Rel_Index ijk +RegIndexForRelIndex i +Nof_reg ij of the function Calltarget k ; (ii) compare the computed sum to Nof_reg filea comparison is made, wherein if the computed sum is less than or equal to Nof_reg file then the relative index Rel_Index ij is computed and set for each Calltarget ijk passing to Callsite ijk to be used by Calltarget ijk as a register offset running through the available part of the register file; otherwise, registers are computed and spilled from the register file, the associated relative index Rel_Index ijk is computed and set, wherein the relative index accounts for the spilled registers and is passed to each Calltarget ij passing to Callsite ijk to be used by Calltarget ijk as a register offset running through the available part of the register file; the computation, compilation, determination, computation, reading, comparison, computation and spilling and setting are repeated for all functions S i in the module.

[0014] In some embodiments of the method, the functions S i are shader functions performing ray tracing in a Graphical Processing Unit (GPU).

[0015] In some other embodiments of the method, the performing inter-procedural analysis in the module comprises analyzing at least one of (i) the caller-callee relationships between the functions S i or (ii) the function S k call target information.

[0016] In some other embodiments of the method, the compiler uses profile information in addition to performing inter-procedural analysis.

[0017] In some other embodiments of the method, the relative index Rel_Index ijk is passed by writing the relative index into a register R0 of Calltarget ijk .

[0018] In some other embodiments of the method, the relative index Rel_Index ijk is passed by writing the relative index into a processor register not belonging to the register file and fetching the relative index in the register by Calltarget ijk .ijk .

[0019] In some other embodiments of the method, when performing inter-procedural analysis in the module includes analyzing the caller-callee relationships among the functions S i , the number of registers Nof_reg i used by the function S i is computed. i This is performed by the following steps: (i) computing Nof_reg i for each leaf function in the function S i ; (ii) for each leaf function, iteratively computing Nof_reg i for each function in the function S k that has a caller-callee relationship with the leaf function, moving up the call chain.

[0020] In some other embodiments of the method, when performing inter-procedural analysis in the module includes analyzing the call target information for the functions S i , the number of registers Nof_reg i used by the function S ij is computed on demand, and if the call target information for Callsite i is not known, the compiler returns Nof_reg file as Nof_reg file .

[0021] In some other embodiments of the method, in the case where the computed sum is less than or equal to Nof_reg ij , the computing and setting the relative index Rel_Index ijk passed to each Calltarget ijk at Callsite ijk includes: extending the call instruction to the final machine code to (i) compute: Rel_Index ij = R0 + RegIndexForRelIndex i , where R0 holds the Rel_Index i for the function S ijk ; (ii) store the value Rel_Index ij in memory R RegIndexForRelIndexij indexed by RegIndexForRelIndex k ; (iii) set: Rel_Index RegIndexForRelIndexij = R k ; (v) call S(v) Calculate: R0 = R0 – R RegIndexForRelIndexij (vi) Setting: Rel_Index i =R0.

[0022] In some other embodiments of the method, the calculated sum is less than or equal to Nof_reg file In this case, the calculation and setting are passed to the Callsite. ij Each Calltarget ijk Relative index Rel_Index ijk This includes: expanding the calling instruction to the final machine code to: (i) calculate the number of registers overflowing from the register file (NSpill). ij :NSpill ij =(Nof_reg file –(R0+RegIndexForRelIndex ij +Nof_reg k (ii) Setting: Rel_Index i =Rel_Index ijk (iii) Overflow registers R0 to R NSpillij –1; (iv) Set Rel_Index ijk Stored in R0, and (RegIndexForRelIndex) ij –NSpill ij (v) Stored in R1; (v) Call S k (vi) Calculate: R free =R0+R1, and set R free Stored in registers other than R0 or R1; (vi) Do not overflow registers R0 to R NSpillij -1; (vii) Settings: Set Rel_Index i =R free .

[0023] In accordance with this objective, another aspect of the present invention provides an apparatus. The apparatus includes a processor, comprising a plurality of (Nof_reg) file The processor includes the register file and memory of the registers, and runs a compiler that compiles modules including function S into processor executable instructions. The compiler also optimizes function S within the modules. i (i>0) register resource allocation, the optimization includes: performing inter-procedural analysis in the module, (i) calculating the function S i The number of registers used, Nof_reg i (ii) The function Si into processor executable instructions. The optimization further comprises, if the compiler detects a call j (j<>i) to another function S i , leaving the call instruction as a pseudo instruction Callsite ij ; for each Callsite ij , (i) determining one or more called functions S k (k<>i) as Calltarget ijk ; (ii) computing the maximum number of live registers maxRegIndex i used by the function S ij at the Callsite ij , and computing RegIndexForRelIndex ij = maxRegIndex ij +1. The optimization further comprises, for each Callsite ij and each Calltarget ijk , extending the call instruction to the processor executable instructions to: (i) read the value of the relative index Rel_Index i of the function S i , and compute the sum Rel_Index ijk + RegIndexForRelIndex i + Nof_reg ij of the function Calltarget k ; (ii) compare the computed sum with Nof_reg file , wherein, if the computed sum is less than or equal to Nof_reg file , computing and setting the relative index Rel_Index ij passed to each Calltarget ijk at the Callsite ijk for use by the Calltarget ijk as a register offset to run through the available part of the register file; otherwise, computing and spilling registers from the register file to the memory, computing and setting the associated relative index Rel_Index ijk , wherein the relative index accounts for the spilled registers, and passing to each Calltarget ij at the Callsite ijk for use by the Calltarget ijk as a register offset to run through the available part of the register file. The optimization is performed for all functions Si The computing, compiling, determining, calculating, reading, comparing, calculating and overflowing and setting are repeated.

[0024] In some embodiments of the apparatus, the processor is a Graphical Processing Unit (GPU) and the function S i is a shader function performing ray tracing.

[0025] In some other embodiments of the apparatus, the relative index Rel_Index ijk is passed by writing the relative index into a register R0 of the Calltarget ijk .

[0026] In some other embodiments of the apparatus, the relative index Rel_Index ijk is passed by writing the relative index into a register of the processor not belonging to the register file and by the Calltarget ijk fetching the relative index in the register. ijk .

[0027] According to this object, a further aspect of the present technology provides a non-transitory computer readable medium storing computer executable instructions. The instructions, when executed by a processor, cause the processor to optimize register resource allocation of a function S file (i>0) in a module using a register file comprising a number Nof_reg i of registers, the optimization comprising: performing inter-procedural analysis in the module; (i) calculating the number Nof_regi of registers used by the function S i ; (ii) compiling the function S i into final machine code, wherein, if the compiler detects a call to another function S i j (j<>i), the compiler leaves the call instruction as a pseudo instruction Callsite ij . The optimization further comprises, for each Callsite ij , (i) determining one or more called functions S k (k<>i) as Calltarget ijk ; (ii) calculating the maximum number maxRegIndex i of live registers used by the function S ij at the Callsite ij , and calculating RegIndexForRelIndex ij= maxRegIndex ij + 1. The optimization further comprises, for each Callsite ij and each Calltarget ijk , expanding the call instruction to the final machine code to: read the value of the relative index Rel_Index i of the function S i and compute the sum Rel_Index ijk + RegIndexForRelIndex i + Nof_reg ij of the function Calltarget k ; (ii) compare the computed sum with Nof_reg file , wherein, if the computed sum is less than or equal to Nof_reg file , compute and set the relative index Rel_Index ij passed to each Calltarget ijk at Callsite ijk for use by Calltarget ijk as a register offset to run through the available portion of the register file; otherwise, compute and spill a register from the register file, compute and set the associated relative index Rel_Index ijk , wherein the index accounts for the spilled register, and pass to each Calltarget ij at Callsite ijk for use by Calltarget ijk as a register offset to run through the available portion of the register file; repeat the computing, compiling, determining, computing, reading, comparing, computing, and spilling and setting for all functions S i in the module.

[0028] In some embodiments of the non-transitory computer-readable medium storing computer-executable instructions, the performing inter-procedural analysis in the module comprises analyzing at least one of (i) caller-callee relationships among functions S i or (ii) function S k call target information.

[0029] In still other embodiments of the non-transitory computer-readable medium storing computer-executable instructions, the compiler uses profile information in addition to performing inter-procedural analysis.

[0030] In the context of this description, the expression "processor" is intended to include a single dedicated processor, a single shared processor, or a plurality of separate processors provided some of which can be shared. In some aspects of the present technology, the processor can be, for example, a general purpose processor, such as a Central Processing Unit (CPU), a dedicated processor, such as a GPU, or a processor implemented in an FPGA. Other conventional and / or custom hardware can also be included. BRIEF DESCRIPTION OF DRAWINGS

[0031] The features and advantages of the present technology will become apparent from the following detailed description in conjunction with the drawings in which:

[0032] Figure 1 A call between functions that can be optimized using the present technology is shown;

[0033] Figure 2 A top-level function that makes a call to a function that can be optimized using the present technology is shown;

[0034] Figure 3 A top-level function that makes an indirect call is shown, where the actual target function can be one of several functions that can be optimized using the present technology;

[0035] Figure 4 Method steps of a compiler according to the present technology are depicted;

[0036] Figure 5 A computing system that can implement the method and process steps described herein is depicted.

[0037] It should be understood that, in all of the drawings, like reference numerals refer to like parts throughout the several views and that the drawings and the following description are intended to illustrate the present technology and are not intended to limit the scope of the claims. DETAILED DESCRIPTION

[0038] The present technology is described in the context of a general computing environment, however, those skilled in the art will appreciate that the guidance herein is also applicable to specific computing environments, such as the computing environment of a ray-tracer and shader caller and callee in a GPU, as a method and system to optimize register resource allocation in function calls by dynamic relative indexing and reusing resources.

[0039] For a processing function being compiled, such as a calling function (caller), a reference to an allocation map and an allocation pointer can be made to find reusable register resources along the call chain up. To access register resources within the compiled body, a relative index to the resource can be used, where the base index is dynamically set according to the allocation map and the allocation pointer passed at the call point. "Function" herein defines a software processing element comprising instructions and formed by a module or library, where "inter-process analysis" by the compiler can determine caller / callee relationships in direct calls, and for indirect calls and a given caller, a view of possible callees with associated likelihoods or possible callers called. In particular embodiments of the technology, profiling information can be used in addition to inter-process analysis. "Call," "called," or "calling" herein are used interchangeably with "invoke," "invoked," or "invoking," and refer to the act of causing a program, function, routine, etc. to execute, without technical differences affecting the generality of the guidance herein.

[0040] Runtime code can be generated at each call point to check for register resource exhaustion and perform minimal instructions for necessary spill operations / non-spill operations. If a compiled function calls other functions, data flow analysis can be performed to determine potentially reusable register resources at each call point. The maximum contiguous free index resource can be determined, which forms an allocation map that can be passed to the called function (callee). The callee can be compiled using the same mechanism.

[0041] Figure 1 Calls between functions that can be optimized using the technology herein are shown. Those skilled in the art will appreciate that the language and representation used are that of a pseudo-code and are not specific to any programming language, but reflect a particular architecture. Function 101 calls (104) function 102, which in turn calls (105) function 103. An example assumption is that the processor in the environment can use a register file 100 comprising 64 registers numbered R0 through R63.

[0042] With respect to function 101, more example assumptions include that function 101 (i) uses 62 registers R0 through R61 in total (as shown at 106), (ii) uses 21 live registers R0 through R20 at the call point to function 102, and (iii) the value in R0 is "0." "Live register" herein defines a register that stores a data value that is needed by the function after it has called a lower function.

[0043] Function 101 includes a number of instructions that use R0 through R20. Then, before the call to function 102 (104), (i) the value read from R0 can be added to the value "21" (the number of live registers used at the call point, a constant of the compiler (not shown), or an immediate value that can be encoded directly in the instruction), and the result can be stored in R21 (instruction: R21 = R0 + 21 = 21), (ii) a special instruction (set Rel Index = R21) can pass a relative index / offset to function 102 that the hardware can use to offset the physical location of the registers used by function 102 (as shown in 107) relative to the register file 100.

[0044] From function 102, the value can be read from R0, at which point R0 is still the value of R0 used by function 102 (21), and "21" (the number of live registers used at the call point) can be subtracted from the value. The relative index can actually be restored to its value before the call 104. Function 101 can then run instructions using R21 through R61.

[0045] The number of registers used by function 101, Nof reg 101 This can be calculated as the minimum of "64" (the number of registers in the register file 100) and "62" (the 62 registers used by function 101) and a number that depends on the registers used by functions down the call chain from function 101, as described below.

[0046] More illustrative assumptions regarding function 102 include that function 102 (i) uses 31 registers R0 through R30 in total (as shown in 107), (ii) uses 11 live registers R0 through R10 at the call point to function 103. The value of R0 can be "21" by the set Rel Index = R21 instruction in function 101.

[0047] Function 102 includes a number of instructions that use R0 through R10. Then, before the call to function 103 (105), (i) the value read from R0 can be added to the value "11" (the number of live registers used at the call point, a constant of the compiler, or an immediate value that can be encoded directly in the instruction), and the result can be stored in R11 (instruction: R11 = R0 + 11 = 32), (ii) a special instruction (set Rel Index = R11) can pass a relative index / offset to function 103 that the hardware can use to offset the physical location of the registers used by function 103 (as shown in 108) relative to the register file 100.

[0048] Returning from function 103, the value can be read from R0, which at this point is still the R0 value of 11 used by function 103 (because the relative index is still the relative index set by the above-mentioned instruction: Set Rel_Index = Rl l), and "11" (the number of live registers used at the call site) can be subtracted from this value. The relative index can in effect be restored to its value prior to the call 105. Function 102 can then execute instructions using Rl l through R30.

[0049] The number of registers used by function 102, Nof reg 102 This can be calculated as the minimum of the maximum of "64" (the number of registers in register file 100) and "31" (the 31 registers used by function 102) and a number that depends on the registers used by functions down the call chain from function 102, as described below.

[0050] With respect to function 103, further illustrative assumptions include that function 103 (i) uses a total of 27 registers R0 through R26 (as shown at 108), (ii) does not call any other functions down the call chain. Thus, the number of registers used by function 103, Nof reg 103 This can be calculated as "27", which in turn can calculate Nof reg 102 and Nof reg 101 .

[0051] Thus, the physical registers R21 through R61 in register file 100 are best suited for use by functions 102 and 103.

[0052] Figure 2 A top-level function is shown that calls functions that can be optimized using the techniques of the present invention, in the same processing environment of register file 100 that includes 64 registers.

[0053] With respect to top-level function 201, illustrative assumptions include that top-level function 201 (i) uses a total of 31 registers R0 through R30 (as shown at 204), (ii) uses 9 live registers R0 through R8 at the call site to function 202, (iii) the value in R0 is "0". With respect to called function 202, further illustrative assumptions include that called function 202 uses a total of 62 registers R0 through R61 (as shown at 205).

[0054] Function 201 includes a number of instructions using R0 to R8. Then, in a call (203) to function 202, the compiler (not shown) can do inter-procedural analysis and can see the register requirements of all functions, so it can know at the call point in top-level function 201 that (i) function 202 is the only possible call target, (ii) function 201 needs 9 live registers, (iii) Nof_reg 202 = 62. The sum 9 + 62 = 71 is greater than the total number of available registers (Nof_reg 100 = 64) in register file 100, so 7 registers need to be spilled before the call 203. Then, the top-level function 201 run-time spill check can be a comparison between the following values:

[0055] [Nof_live reg 201 + R0 + Nof_reg 202 ] and Nof_reg 100

[0056] The compiler can dynamically generate a spill of 7 registers R2 to R8 before the call 203. The spill can be to cache / memory 206.

[0057] The spilled registers can be the 7 consecutive registers immediately before the last live register R8, i.e., function 201 can spill registers R2 to R8. Next, (i) the value read from R0 can be added with the value "9 - 7" (a constant of the compiler, or an immediate value that can be directly encoded in the instruction: the number of live registers used at the call point minus the number of spilled registers), and the result can be stored where the next available register is after the spill, i.e., R2 (instruction: R2 = R0 + (9 - 7) = 2), (ii) a special instruction (set Rel_Index = R2) can pass the relative index / offset to function 202, which can be used by the hardware to offset the physical location of the registers used by function 202 (as shown in 205) relative to register file 100.

[0058] From function 202, the value can be read from R0, at which point R0 is still the R0 used by function 202 with the value 2 (because the relative index is still the relative index set by the above instruction: set Rel_Index = R2), and "9 - 7" (the number of live registers used at the call point minus the number of spilled registers) can be subtracted from this value. The relative index can actually be restored to its value before the call 203. Then, function 201 can run instructions using R9 to R30.

[0059] The number of registers used by function 201 Nof_reg 201"9+62" (9 live registers used by function 201 plus 62 registers used by function 202) and "31" (number of registers used by function 201).

[0060] The compiler can then spill registers R2 to R8 from cache / memory 206 back to register file 100. In this way, just the right amount of spill / non-spill can be generated by the present technology. The compiler can check the number of any temporary or local registers that are invalidated at the call site and re-use these registers for the callee by dynamically setting the relative index of the callee.

[0061] Figure 3 A top-level function is shown making an indirect call, where the actual target function can be one of several functions. Unless otherwise noted, the assumptions shown by Figure 1 and Figure 2 The call site in top-level function 301 can have two possible targets and can make an indirect call 302 to function 202 or an indirect call 303 to function 102.

[0062] With respect to top-level function 301, the example assumptions include that (i) top-level function 301 uses a total of 35 registers R0 to R34, (ii) 11 live registers R0 to R10 are used at the call site to indirectly call one of functions 202 or 102, and (iii) the value in R0 is "0". With respect to the potential callee functions 202 and 102, more assumptions are shown by Figure 1 and Figure 2

[0063] Function 301 includes multiple instructions that use R0 to R10. Before the indirect call (302, 303), the compiler (not shown) can perform inter-procedural analysis and can see that either function 202 or 102 can be called, with the associated likelihoods or call %, that function 103 can be called by function 102, and can see all register requirements for all functions, so that it can learn at the call site in top-level function 301 that (i) function 301 needs 11 live registers, (ii) Nof_reg 202 = 62, and (iii) Nof_reg 102 = 38.

[0064] The compiler can therefore generate code that checks all possible target functions for the call and determines any need for spill registers based on the actual target by comparing the following values, respectively, for call 302: [Nof_live reg 301 + R0 + Nof_reg​202 ] with Nof_reg 100 ; for call 303, compare [Nof_live reg 301 + R0 + Nof_reg 102 ] with Nof_reg 100 .

[0065] Correspondingly, the compiler can generate code that both spills registers and sets the relative index according to the target function:

[0066] - if the target is function 202, the sum [Nof_live reg 301 + R0 + Nof_reg 202 ] is 11 + 0 + 62, which is larger than the number of registers in register file 100; in this case, 9 registers need to be spilled, 73 - 64 = 9. The compiler can dynamically generate a spill of 9 registers, R2 to R10. The spill can be to cache / memory 206. Next, the value read from R0 can be added with the value “11 - 9” (a constant of the compiler, or an immediate value that can be directly encoded in the instruction: the number of live registers used at the call site minus the number of spilled registers), the result can be stored at the place that becomes the next available register after the spill, i.e. R2 (instruction: R2 = R0 + (11 - 9) = 2), (ii) a special instruction (set Rel_Index = R2) can pass the relative index / offset to function 202 (if called), which can be used by the hardware to offset the physical location of the registers used by function 202 relative to register file 100;

[0067] - if the target is function 102, the sum [Nof_live reg 301 + R0 + Nof_reg 102 ] is 11 + 0 + 38, which is smaller than the number of registers in register file 100; in this case, no register needs to be spilled. Next, (i) the value “11” (the number of live registers used at the call site, a constant of the compiler, or an immediate value that can be directly encoded in the instruction) can be entered in R11, (ii) a special instruction (set Rel_Index = R11) can pass the relative index / offset to function 102 (if called), which can be used by the hardware to offset the physical location of the registers used by function 102 relative to register file 100.

[0068] Thus, the compiler can spill registers according to the actual target and its register usage, and spill only the minimum number of registers. The spill is optimized, and the best spill code is adjusted according to the target.

[0069] From the indirect call return,

[0070] - If returning from function 202, the value can be read from R0, which is still the value 2 of R0 used by function 202 (as the relative index is still the relative index set by the above instruction: Set Rel_Index = R2), and "11 - 9" (the number of live registers used at the call site minus the number of spilled registers) can be subtracted from this value. The relative index can actually be restored to its value before the call 302. Then, the compiler can spill registers R2 to R10 from the cache / memory 206 back to the register file 100;

[0071] - If returning from function 102, the value can be read from R0, which is still the value 11 of R0 used by function 102 (as the relative index is still the relative index set by the above instruction: Set Rel_Index = R11), and "11" (the number of live registers used at the call site) can be subtracted from this value. The relative index can actually be restored to its value before the call 303;

[0072] - Then, function 301 can run instructions using R11 to R34.

[0073] In this way, with the present technology, just the right amount of spilling can be generated.

[0074] In the above example and figures, it is assumed that the value in R0 of functions 101, 201 and 301 is "0", indicating that functions 101, 201 and 301 are respectively top-level functions. In general, it is assumed that at the time of compilation of a given function, the compiler can know the value of R0 for each analyzed function, or know the relative index of that function, or know the level of that function (top-level or other level), by inter-procedural analysis or the like. However, there can be cases where at the time of compilation, the compiler can not have access to or infer the above information.

[0075] Figure 4 Method steps of a compiler (not shown) according to the present technology are depicted for the following general case: the compiler of the analyzed function does not have access to the above information, in particular cannot determine at the time of compilation that the value of R0 of the function is "0" (case of a top-level function), or more generally cannot determine the value of the relative index in R0 (case of a called function). The hardware environment is a hardware environment comprising a register file 100 of a limited number (Nof_reg file ) of registers.

[0076] In step 401, the compiler can perform inter-procedural analysis within the module, and for all functions S i , (i) compute the corresponding number Nof_reg i of registers used by function S i(ii) the analysis of the function call site information, the compiler computes the number of registers needed by the function S i to be compiled into final machine code, except if the compiler detects a call j to another function in the function S i , then the compiler leaves the corresponding call instruction as a pseudo instruction (Callsite ij ) to be expanded to final machine code in a later step.

[0077] For a leaf function, i.e. a function without calls, Nof_reg i is simply the maximum register index used by the function + 1. For example, if a leaf function f uses registers R0 to R35, then Nof_reg f = 35 + 1 = 36. For a non-leaf function n and each call site c in n, RegIndex c can be computed as maxRegIndex nc + 1, where maxRegIndex nc is the maximum register index used by the non-leaf function n at call site c. For each call site c in n and each call target t of c, the compiler can compute the number of registers needed by t as: Nof_reg tc = RegIndex c + Nof_reg t . Nof_reg n is defined as min(Nof_reg file , max(Nof_reg tc , RegIndex n ).

[0078] In one embodiment of the technology, the compiler can utilize inter-procedural analysis to compute the Nof_reg i of functions in a certain order; for example, by first computing leaf functions and iteratively moving up the call chain to caller functions in the caller-callee relationship graph. In another embodiment, the compiler can compute Nof_reg i on demand and refer to inter-procedural analysis results to obtain call targets. If the call target information of Callsite ij is not known, the compiler can simply return Nof_reg file as a conservative estimate.

[0079] In step 402, for each function S i and each Callsite ij , the compiler computes the number of registers needed by the function S ione or more called functions determined as Calltarget ijk .

[0080] In step 403, for each function S i and each encountered Callsite ij , the compiler computes the maximum number of live registers at the Callsite ij maxRegIndex ij . This maximum number is the maximum register index on any execution path from the function S i to the Callsite ij . For example, in Figure 1 , the maximum register index for the function 106 is R20. The compiler further computes RegIndexForRelIndex ij : RegIndexForRelIndex ij= maxRegIndex ij + 1.

[0081] At step 404, for each function S i , each encountered Callsite ij and each encountered Calltarget ijk , the compiler extends the pseudo-call instruction and generates runtime instructions for the function S i to: (i) read the value of the relative index Rel_Index i for the function S i in R0, (ii) compute the sum of: RegIndexForRelIndex ij , Rel_Index i and the number of registers Nof_reg ijk used by the function Calltarget k .

[0082] In step 405, for each function S i , each encountered Callsite ij and each encountered Calltarget ijk , the compiler generates runtime instructions to compare the sum computed in step 404 with the total number of registers Nof_reg file in the register heap 100.

[0083] In step 406, if the sum computed in step 404 is less than or equal to the total number of registers Nof_reg filethen the compiler extends the pseudo-call instruction with a runtime instruction to compute and set the relative index Rel lndex ij for each Calltarget ijk passed to Callsite ijk for the function Calltarget ijk to use as a register offset to run through the available part of the register file 100.

[0084] In one embodiment of the above technique, this can be achieved by a runtime instruction that (i) computes: Rel lndex ijk = R0 + ReglndexForRellndex ij where R0 holds the Rel lndex i of the function S i ; (ii) stores the value Rel lndex ijk in register R ij indexed by ReglndexForRellndex RegIndexForRelIndexij ; if needed, other parameters can be set in R RegIndexForRelIndexij+1 , R RegIndexForRelIndexij+2 etc.; (iii) generates the instruction: set Rel lndex k = R RegIndexForRelIndexij to set the new relative index for S k , (iv) generates the call instruction, (v) generates the instruction: R0 = R0 - R RegIndexForRelIndexij to reset the R0 value back to the previous value of S i , generates the instruction: set Rel lndex i = R0 to reset the relative index for S i .

[0085] In step 407, if the sum computed in step 404 is greater than the total number of registers Nof reg file in the register file 100, then the compiler extends the pseudo-call instruction with a runtime instruction for the function S i to compute and spill a number of registers from the register file 100, call Calltarget ijk , i.e. to compute and set the associated relative index Rel lndex ijk that accounts for these spilled registers and passed to each Calltarget ij at Callsite ijk for the Calltarget ijk to use as a register offset to run through the available part of the register file 100.

[0086] In one embodiment of the above technique, this can be achieved by runtime instructions that (i) generate instructions to compute the number of registers NSpill ij and the associated relative index Rel_Index ijk , where the relative index is passed to the Calltarget ij at Callsite ijk for use as a register offset by the Calltarget ijk running through the available part of the register file 100. NSpill ij = (Nof_reg file - (R0 + RegIndexForRelIndex ij + Nof_reg k ); (ii) generate spill instructions for NSpill ij registers, first generating instructions to set Rel_Index i = Rel_Index ijk to adjust the relative index first, then spill R0, R1 to R NSpillij - 1; (iii) generate instructions to store the value Rel_Index ijk in R0 and the value (RegIndexForRelIndex ij - NSpill ij ) in R1. The value in R1 can be used as an additional parameter to indicate how the callee’s relative index is shifted compared to the caller’s relative index, (iv) generate call instructions, (v) generate instructions: R free = R0 + R1 to compute Rel_Index i and save it in a free register, since R0 and R1 are overwritten after the non-spill, (vi) generate non-spill instructions to restore NSpill ij registers starting from the register indexed at R0, (vii) generate instructions: set Rel_Index i = R free to reset the relative index of S i to Rel_Index i .

[0087] Regarding (i) above, NSpill ij is a runtime value that can be larger than RegIndexForRelIndex ij . This indicates that in addition to saving all live registers at Callsite ij in Si In addition, some live registers along the call chain upwards can also be saved. Thus, the range of registers to be spilled can start from NSpill ij registers indexed by Rel_Index ijk = (R0 + RegIndexForRelIndex ij - NSpill ij ).

[0088] In the compilation of a given function, the compiler has learned the value of R0 for each analyzed function through inter-procedural analysis, etc., or learned the relative index of the function, or learned the level of the function (top level or other level), then some computation in the above steps of checking overflow, etc. can be performed at compile time instead of run time using the instructions generated by the compiler. In Figure 1 for example, if the compiler knows the information that R0 holds a certain value or has an upper limit, the checking in step 405 can be performed at compile time. If the checking indicates that no overflow will occur, the compiler will not generate any overflow instructions

[0089] The above method steps and process steps and the compiler (not shown) can be implemented in a computing system, examples of which are not limited to find. Those skilled in the art will appreciate that such a computing system can be implemented in any other suitable hardware, software, and / or firmware or a combination thereof, and can be a single physical entity, or a plurality of separate physical entities with distributed functionality. Figure 5

[0090] In some aspects of the present technology, computing system 500 can include various hardware components, including one or more single-core or multi-core processors represented collectively by processor 501, solid state drive 502, memory 503, and input / output interface 504. In this context, processor 501 can or can not be included in an FPGA. In some other aspects, computing system 500 can be an “off-the-shelf” general purpose computing system. In some aspects, computing system 500 can also be distributed among multiple systems. Computing system 500 can also be specialized for the implementation of the present technology. Those skilled in the art of the present technology can appreciate that a wide variety of variations can be envisioned with respect to how computer system 500 is implemented without departing from the scope of the present technology.

[0091] Processor 501 can include register file 100. In some aspects, register file 100 can also be included in memory 503, or distributed among multiple systems.

[0092] ​Communication between various components in the computing system 500 can be achieved by one or more internal and / or external buses 505 (e.g., a PCI bus, a general purpose bus, a Universal Serial Bus, an IEEE 1394 "Firewire" bus, an SCSI bus, a Serial-ATA bus, an ARINC bus, etc.), to which various hardware components are electrically coupled.

[0093] The input / output interface 504 can enable network capabilities, such as wired or wireless access. For example, the input / output interface 504 can include a network interface, such as, but not limited to, a network port, a network socket, a network interface controller, etc. Numerous examples of how a network interface can be implemented will be apparent to those of ordinary skill in the art of the present technology. Depending on the implementation of the present technology, the solid state drive 502 can store program instructions, such as, for example, those portions of libraries, applications, etc., suitable for loading into the memory 503 and execution by the processor 501, for performing the method steps and process steps in accordance with the present technology.

[0094] The memory 503 can include the cache / memory 206. In some aspects, the cache / memory 206 can also be included in the processor 501, or distributed among multiple systems.

[0095] In this environment, each function S i Depending on the case, the call function executes in its register R0 passed own relative index, as a register offset for running through the available part of the register heap 100. In one embodiment of the present technology, the consequence of executing the set Rel Index instruction is that the value of the relative index can be stored in a hardware register not belonging to the register heap 100. The currently active relative index can be read via this hardware register. In such an embodiment, it is not necessary to pass the current relative index as a parameter in R0, since it can always be read from the hardware register.

[0096] It should be understood that the operations and functions of the disclosed methods and apparatuses can be implemented by hardware-based elements, software-based elements, firmware-based elements, and / or combinations thereof. Such operation alternatives do not limit the scope of the present technology in any way.

[0097] It should also be understood that, while the present inventive concepts and principles set forth herein have been described in relation to particular features, structures, and embodiments, it is clear that various modifications and combinations can be practiced without departing from these disclosures. Therefore, the specification and drawings are to be regarded as illustrative only and are to be construed in accordance with the appended claims, which define the present inventive concepts and principles, and their equivalents.

Claims

1. A method for optimizing function S in a module by using a register file including multiple registers through the compiler. i The method for allocating register resources, wherein, i>0, characterized in that the method includes: Inter-process analysis is performed in the module. Calculate the function S i The number of registers used, Nof_reg i ; The function S i Compiled into the final machine code, whereby the compiler detects an error in another function S. i If the call is j, the compiler will retain the call instruction as the pseudo-instruction Callsite. ij , where j<>i; For each Callsite ij , One or more called functions S k Determined as Calltarget ijk , where k<>i; Calculate the function S i At Callsite ij The maximum number of active registers used at maxRegIndex ij And calculate RegIndexForRelIndex ij =maxRegIndex ij +1; For each Callsite ij and each call target ijk The invocation instruction is extended to the final machine code to: Read the function S i Relative index Rel_Index i The value of is calculated, and the function Calltarget is calculated. ijk The sum of Rel_Index i +RegIndexForRelIndex ij +The function Calltarget ijk The number of registers used, Nof_reg k ; The calculated sum is compared with Nof_reg file In comparison, among which, If the calculated sum is less than or equal to Nof_reg file Then calculate and set the data to be passed to the Callsite. ij Each Calltarget ijk Relative index Rel_Index ijk For Calltarget ijk The register offset used to operate through the available portion of the register file; Otherwise, calculate and overflow registers from the register file, calculate and set the associated relative index Rel_Index. ijk The relative index indicates the number of overflowing registers NSpill. ij and pass it to Callsite ij Each Calltarget ijk For Calltarget ijk The register offset used to operate through the available portion of the register file; Repeat the process for all functions S in the module. i Perform calculations, compile, determine, calculate, read, compare, calculate, overflow, and set.

2. The method according to claim 1, characterized in that, The function S i It is a shader function that performs ray tracing in the Graphical Processing Unit (GPU).

3. The method according to claim 1 or 2, characterized in that, The inter-process analysis performed in the module includes: for function S i The caller-callee relationship or function S k At least one of the target information is called for analysis.

4. The method according to claim 1 or 2, characterized in that, In addition to performing inter-process analysis, the compiler also uses profile information.

5. The method according to claim 1 or 2, characterized in that, The relative index Rel_Index ijk This is achieved by writing the relative index into the Calltarget. ijk It is passed through register R0.

6. The method according to claim 1 or 2, characterized in that, The relative index Rel_Index ijk This is achieved by writing the relative index into a processor register that does not belong to the register file, and then using Calltarget. ijk Extract the relative index from the register to pass to the Calltarget. ijk .

7. The method according to claim 3, characterized in that, When performing inter-process analysis in the module, it includes the function S i When analyzing the caller-callee relationship, the calculation of the function S i The number of registers used, Nof_reg i Perform the following steps: Calculate the function S i Nof_reg for each leaf function in i ; For each leaf function, iteratively compute the function S that has a caller-callee relationship with the leaf function. i The Nof_reg for each function moving up the call chain i .

8. The method according to claim 3, characterized in that, When performing inter-process analysis in the module, it includes the function S k When calling target information for analysis, the calculation of the function S i The number of registers used, Nof_reg i It is executed on demand, if Callsite ij If the target information for the call is unknown, the compiler returns Nof_reg. i As Nof_reg file .

9. The method according to claim 1 or 2, characterized in that, The calculated sum is less than or equal to Nof_reg file In this case, the calculation and setting are passed to the Callsite. ij Each Calltarget ijk Relative index Rel_Index ijk Includes: expanding the calling instruction to the final machine code, to: Calculate: Rel_Index ijk =R0+RegIndexForRelIndex ij R0 stores the function S i Rel_Index i ; The Rel_Index ijk Stored in RegIndexForRelIndex ij Register R indexed RegIndexForRelIndexij middle; Setting: Rel_Index k =R RegIndexForRelIndexij ; Call S k ; Calculate: R0 = R0 – R RegIndexForRelIndexij ; Setting: Rel_Index i =R0.

10. The method according to claim 1 or 2, characterized in that, The calculated sum is greater than Nof_reg file In this case, the calculation and setting are passed to the Callsite. ij Each Calltarget ijk Relative index Rel_Index ijk Includes: expanding the calling instruction to the final machine code, to: Calculate the number of registers that overflowed from the register file. ij :NSpill ij =(Nof_reg file –(R0+RegIndexForRelIndex ij +Nof_reg k ); Setting: Rel_Index i =Rel_Index ijk ; Overflow registers R0 to R NSpillij -1; Rel_Index ijk Stored in R0, and (RegIndexForRelIndex) ij –NSpill ij ) is stored in R1; Call S k ; Calculate: R free =R0+R1, and R free Stored in registers other than R0 or R1; Non-overflow registers R0 to R NSpillij -1; Settings: Set Rel_Index i =R free .

11. An apparatus, characterized in that, The device includes a processor, a register file including multiple registers, and memory. The processor runs a compiler that compiles a module including a function S into processor executable instructions. The compiler is also used to optimize the function S in the module. i The allocation of register resources, where i > 0, includes the following optimizations: Inter-process analysis is performed in the module. Calculate the function S i The number of registers used, Nof_reg i ; The function S i Compile into processor executable instructions, wherein if the compiler detects a reference to another function S i If the call is j, the compiler will retain the call instruction as the pseudo-instruction Callsite. ij , where j<>i; For each Callsite ij , One or more called functions S k Determined as Calltarget ijk , where k<>i; Calculate function S i At Callsite ij The maximum number of active registers used at maxRegIndex ij And calculate RegIndexForRelIndex ij =maxRegIndex ij +1; For each Callsite ij and each call target ijk The calling instruction is expanded to the processor executable instructions to: Read the function S i Relative index Rel_Index i The value of is calculated, and the function Calltarget is calculated. ijk The sum of Rel_Index i +RegIndexForRelIndex ij +The function Calltarget ijk The number of registers used, Nof_reg k ; The calculated sum is compared with Nof_reg file In comparison, among which, If the calculated sum is less than or equal to Nof_reg file Then calculate and set the data to be passed to the Callsite. ij Each Calltarget ijk Relative index Rel_Index ijk For Calltarget ijk The register offset used to operate through the available portion of the register file; Otherwise, calculate and overflow the register from the register file into the memory, and calculate and set the associated relative index Rel_Index. ijk The relative index indicates the number of overflowing registers NSpill. ij and pass it to Callsite ij Each Calltarget ijk For Calltarget ijk The register offset used to operate through the available portion of the register file; Repeat the process for all functions S in the module. i Perform calculations, compile, determine, calculate, read, compare, calculate, overflow, and set.

12. The apparatus according to claim 11, characterized in that, The processor is a Graphical Processing Unit (GPU), and the function S... i It is a shader function that performs ray tracing.

13. The apparatus according to claim 11 or 12, characterized in that, The relative index Rel_Index ijk This is achieved by writing the relative index into the Calltarget. ijk It is passed through register R0.

14. The apparatus according to claim 11 or 12, characterized in that, The relative index Rel_Index ijk This is achieved by writing the relative index into a register in the processor that is not part of the register file, and then using Calltarget. ijk Extract the relative index from the register to pass to the Calltarget. ijk .

15. A non-transitory computer-readable medium storing computer-executable instructions, characterized in that, When executed by the processor, the instruction causes the processor to use a register file, which includes multiple registers, to optimize function S in the module. i The allocation of register resources, where i > 0, includes the following optimizations: Inter-process analysis is performed in the module. Calculate the function S i The number of registers used, Nof_reg i ; The function S i Compiled into the final machine code, where the compiler detects an error in another function S. i If the call is j, the compiler will retain the call instruction as the pseudo-instruction Callsite. ij , where j<>i; For each Callsite ij , One or more called functions S k Determined as Calltarget ijk , where k<>i; Calculate function S i At Callsite ij The maximum number of active registers used at maxRegIndex ij And calculate RegIndexForRelIndex ij =maxRegIndex ij +1; For each Callsite ij and each call target ijk The invocation instruction is extended to the final machine code to: Read the function S i Relative index Rel_Index i The value of is calculated, and the function Calltarget is calculated. ijk The sum of Rel_Index i +RegIndexForRelIndex ij +The function Calltarget ijk The number of registers used, Nof_reg k ; The calculated sum is compared with Nof_reg file In comparison, among which, If the sum of the calculations is less than or equal to Nof_reg file Then calculate and set the data to be passed to the Callsite. ij Each Calltarget ijk Relative index Rel_Index ijk For Calltarget ijk The register offset used to operate through the available portion of the register file; Otherwise, calculate and overflow registers from the register file, calculate and set the associated relative index Rel_Index. ijk The relative index indicates the number of overflowing registers NSpill. ij and pass it to Callsite ij Each Calltarget ijk For Calltarget ijk The register offset used to operate through the available portion of the register file; Repeat the process for all functions S in the module. i Perform calculations, compile, determine, calculate, read, compare, calculate, overflow, and set.

16. The non-transitory computer-readable medium according to claim 15, characterized in that, The inter-process analysis performed in the module includes: for function S i The caller-callee relationship or function S k At least one of the target information is called for analysis.

17. The non-transitory computer-readable medium according to claim 15 or 16, characterized in that, In addition to performing inter-process analysis, the compiler also uses profile information.

Citation Information

Patent Citations

  • Expanding a software program by insertion of statements

    US7207032B1

  • Method and apparatus for register spill minimization

    WO2013112282A1