
Optimizing Ada On The Fly Sheri J. Bernstein Robert A. Duff AverStar, Inc. AverStar, Inc. 23 Fourth Ave. 23 Fourth Ave. Burlington, Mass. 01803 Burlington, Mass. 01803 (781) 221-6990 (781) 221-6990 [email protected] [email protected] programming language is its use of run-time constraint 1. ABSTRACT checks. However, there are two drawbacks with run-time checks: One of the features that makes Ada such a 1) Efficiency. Run-time checks slow the program's reliable programming language is its use of execution and increase its size. For an embedded run-time constraint checks. However, such real-time system, it is especially critical to checks slow program execution and increase minimize size and maximize run-time speed. program size. 2) Safety. Although run-time checks increase the probability that testing will catch bugs, it is more desirable to catch potential problems sooner in the The AdaMagic™ compiler uses one-pass, on- development cycle. In general, catching a bug the-fly flow analysis during intermediate- earlier reduces the amount of time (and money) language generation specifically to eliminate spent testing/debugging/rebuilding one's system. unnecessary constraint checks and to warn The efficiency issue can be alleviated if the compiler can about potential error situations such as the use prove, at compile time, that certain run-time checks cannot of uninitialized variables. fail. In such cases, the compiler can eliminate the code associated with the checks. The safety issue can be The one-pass nature of our method allows for alleviated if the compiler can prove, at compile time, that faster compile times than more elaborate certain checks will fail, and then issue warnings about these problems. In such cases, the programmer can fix these multi-pass flow analysis. Thus, we are able to problems immediately, without any need for testing and generate efficient code without the impact on debugging. compile-time, and without the added implementation complexity, associated with a The programmer could use pragma Suppress to eliminate traditional separate optimization phase. the overhead of run-time checks, if he can prove by hand that certain checks will not fail; he can even tell the compiler to blindly suppress all checks. However, if the 1.1 Keywords programmer is mistaken, suppressing checks will often Ada, compiler, optimization, check elimination, range cause serious bugs, such as overwriting arbitrary memory checking, range propagation, array bounds checking, locations. A safer solution is for the compiler to perform warnings, uninitialized variables. the proofs automatically, and to eliminate only those checks that cannot fail. This paper describes how the 2. INTRODUCTION AdaMagic compiler uses one-pass, on-the-fly flow analysis One of the features that makes Ada such a reliable to eliminate unnecessary checks, and to warn about potential error situations. Most Ada compilers are able to eliminate some checks based on declarative information. However, to do a better Permission to make digital or hard copies of all or part of this work for job of check elimination, flow analysis is necessary. personal or classroom use is granted without fee provided that copies are Consider the example in Figure 1. Ada requires an index not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. check on A(I), but it's easy to eliminate this check based To copy otherwise, to republish, to post on servers or to redistribute to lists, purely on the fact that I's subtype range matches the index requires prior specific permission and/or a fee. SIGAda'99 10/99 Redondo Beach, CA, USA subtype of Float_Array. However, in more complex cases © 1999 ACM 1-58113-127-5/99/0010...$5.00 such as the example in Figure 2, the relevant declarations 169 are not enough. Our method allows the elimination of the 2. TRACKED INFORMATION index check on A(I). The compiler recognizes that, As each statement in an Ada subprogram is processed, the although the subtype of I allows out-of-range values, these compiler checks to see if it can learn anything interesting values can never exist inside the if statement. about the value of local variables, formal parameters, and expression results. Value-related items of interest type Index is range 1..100; (collectively referred to as “value-info”) are recorded using type Float_Array is array(Index) of Float; the data structure in Figure 3, which is associated with each variable and expression result being tracked. The fields of procedure P(A: Float_Array) is the data structure are described in more detail below. I : Index := Index'First; begin type Value_Info is ... A(I) ... record end P; Possible_Values : Value_Set; Figure 1. Check Elimination Uses Declarative Information -- the set of values the variable could have Init_State : Init_State_Kind; -- known to be initialized? procedure P(A: Float_Array) is BB: Basic_Block_Ptr; I: Integer; -- the basic block in which this value begin -- information applies ... -- some code that sets I ... invalidation flags ... if I in Index then -- flags used to track Ada constructs that ... A(I) ... -- could invalidate value-info that has end if; -- already been gathered end P; end record; Figure 2. Check Elimination Requires Flow Analysis Figure 3 : Data Structure To Record Value-Info The AdaMagic technology consists of a Front End and a 2.1 Possible Value Sets portable Ada run-time system, as well as various other tools. The technology is intended to be combined with a For each local variable, the compiler tracks the set of Back End that was more than likely designed to optimize possible values that the variable might have at any and generate code for a language more like C or Pascal. particular point in the program. The Front End parses the input, performs semantic analysis, and emits a fairly low-level intermediate language (“IL”), Possible value sets are represented by the (private) type all in a (mostly) single pass. The Front End was designed Value_Set, which is an access type to Value_Set_Rec. The to have a tailorable IL emitter so that it could directly relevant data structures are supplied in Figure 4. generate whatever IL was needed by the Back End. For example, in the case of our “AdaMagic with C A set of integers is represented as a range plus a flag Intermediate” compiler, the Front End emits C source code, indicating whether the value 0 is included. and the Back End consists of a standard C compiler. Our AppletMagic™ compiler generates Java byte codes as the For example: intermediate language. (Integer_Kind, Bounds => (-10, 10), Might_Be_Zero => True) represents -10..10. Because generation of IL occurs in the same pass as the rest (Integer_Kind, Bounds => (-10, 10), of the Front End processing, constraint-check elimination is Might_Be_Zero => False) represents -10..-1 plus 1..10. most conveniently implemented by performing on-the-fly (Integer_Kind, Bounds => (1, 10), “basic-block”-oriented flow analysis during IL generation, Might_Be_Zero => False) represents 1..10. and therefore is target-independent. The Back End is presumed to take the IL and perform “traditional” Note that this set type cannot represent all possible integer optimizations like common subexpression (CSE) sets. For example, if the compiler can prove that a certain elimination, loop optimizations, etc.; as such, the primary expression will always be 1, 2, or 4, then it must include 3 goal of the Front End optimizer is to perform Ada-specific as well and pessimistically use 1..4. optimizations. Ranges are tracked because two of the most common constraint checks are range checks and index checks. The reason for tracking Might_Be_Zero is twofold. First, this helps us eliminate divide-by-zero checks. Second, we use 170 the same integer sets to represent access values, with “null” of an if statement is executed. Fixed point sets are also being represented as zero. This helps us eliminate null represented in terms of integers. checks. type UI_Ptr is ...; When the compiler cannot determine any information about -- Represents a compile-time-known a variable, it uses the Unknown_Value_Set to represent the -- universal integer value. variable's possible values : (Kind => Unknown_Kind). -- This is declared in a package that implements -- arbitrary-precision integer arithmetic, as is In general, sets are allocated on the fly in a mark-release -- required for implementing static expressions. heap. However, certain sets which are commonly used, -- This type has special “infinite" values, which can such as the empty set and the set of all integers, are -- be used to represent the range of all integers. preallocated and shared among all uses. type UI_Range is 2.2 Init State record In Ada 95, reading an uninitialized scalar variable is a First, Last: UI_Ptr; bounded error. To address this situation, our run-time end record; model generates checks “early”, which prevents the -- Represents the range First..Last (inclusive). propagation of out-of-range values caused by -- The empty range is always represented as 1..0. uninitialized variables. type Value_Set_Rec(Kind: Value_Set_Kind_Enum) Consider the example in Figure 5. is record case Kind is subtype S is Integer range 1..10; when Integer_Kind => I, J : S; Might_Be_Zero: Boolean; Message: String(S); Bounds: UI_Range; when Unknown_Kind => ... null; I := J; when others => while ... loop ... Message(I) := ...; end case; Figure 5 : Compiler Generates Constraint Check On Assignment end record; Figure 4 : Data Structures To Represent Possible Value Set The compiler generates a constraint check on the assignment to I, to make sure that its value is within the The possible values for an access-type expression are the range of subtype S. As such, there is no need for an index actual run-time integer values used on the target machine. check on the array indexing.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages12 Page
-
File Size-