Compile-time expressions and optimizations
By default, the compiler evaluates expressions at compile time and performs other optimizations.
You can specify any expression that can be completely evaluated at compile time in a data declaration. This includes expressions whose operands are literals and intrinsic function calls that can be evaluated at compile time. The following functions are evaluated at compile time:
- ^ARGNUM
- ^VARIANT
- ^SIZE
- ^DEFINED
- %ABS
- %ATRIM
- %BIN
- %BIT_IS_CLR
- %BIT_IS_SET
- %CHAR
- %DATECOMPILED
- %DECML
- %FALSE
- %HEX
- %IMPLIED
- %INT
- %INTEGER
- %OCT
- %RND
- %ROUND
- %STRING
- %SYSID
- %TRIM
- %TRIMZ
- %TRUE
- %TRUNC
- %TRUNCATE
- %UNSIGNED
- %VMS
- %ZONED
For example, the following is valid:
record fld ,a(^size(prior_rec)+2)
As another example, on the following function:
%false
the compiler will evaluate %FALSE and emit a zero to the object file (instead of having the runtime evaluate %FALSE). On the function
%atrim("ab ")
the compiler will emit the literal ab to the object file.
Optimizations
The compiler optimizes expressions as much as possible. At level 1, the compiler performs the following optimizations:
- Constant folding occurs (except for objects in expressions). For example, A = B + 10 + 2 is converted to A = B + 12.
- Expressions such as A = A + B, A = A – B, and so forth are optimized to use the +=, -=, *=, and /= assignment operators. See Additional numeric assignment operators for more information.
- Descriptors for unused variables are not emitted to the target .dbo file.
- Literal pooling occurs when multiple literals point to a single string. For example, if there are two literals “AB” and “ABC”, the compiler only stores “ABC” in the literal space. Alpha literals are sorted largest first to improve reuse.
- A+=1 and a = a+1 are optimized to incr for noninteger numeric variables.
- A-=1 and a = a - 1 are optimized to decr for noninteger numeric variables.
- Var(cnt, cnt +offset) is optimized to a relative range operation (cnt:offset).
- Var(cnt, cnt + var -1) is optimized to a relative range operation.
- A numeric variable .ne.0 is optimized to the equivalent of IF var.
- A numeric var .eq.0 is optimized to .NOT..
- An integer-to-integer store uses an ISTO opcode. (traditional Synergy only)
- An alpha-to-alpha store uses an ASTO opcode. (traditional Synergy only)
- Any function that can be resolved at compile time is replaced by the compile-time constant, for example, %char(0).
- Expressions are reordered (except for expressions involving objects). Expressions containing mixtures of data types are ordered to evaluate related data types as long as the reordering does not affect the result. For instance, all integers are evaluated together, then all decimal variables. Therefore, the evaluation order of an expression may not be exactly the same left-to-right order that you’ve specified. For example, the expression
I1 + D2 - 22 + -2.4 + F2 + D1 + 25 - F1 - I2
(where I1 and I2 are integer variables, D1 and D2 are decimal variables, and F1 and F2 are implied-decimal variables) is evaluated as follows:
I1 - I2 + %integer(3) + D1 + D2 - F1 + F2 - 2.4
- The changing of single dimension real array access to pseudo array access (that is, changing the DIMEN opcode to the INDEX opcode) does not occur when -qstrict is specified (or in Synergy .NET) due to enforcing the bounds checking of real arrays on all accesses.
- The code generator uses integer literals when numeric literals are passed as arguments to a method, function, or subroutine and both a prototype exists and the argument is either n or i (or i1, i2, i4, or i8).
- Real array access using an index of literal 1 is optimized to a nondimensioned access. (traditional Synergy only)