Generalized Constant Values
In the UnifiedVariables IR there may be a nice way to deal with constant values.
(Credit goes to c_u, who had the idea back then in "Wiedenbräu". BTW never eat a Cordon Bleu there!)
Take the following example:
ALOAD 0 ILOAD 1 ICONST 123 IASTORE
By marking the destination temporary of ICONST with a "CONSTVAL" flag and putting the constant 123 into the varinfo, this would turn into:
ALOAD L0 => La0 ILOAD L1 => Li1 ICONST 123 => i:123(T2) IASTORE La0 Li1 i:123(T2)
where <type>:<value>(T<index>) denotes a temporary variable T_index that has a constant value of the given type.
In this case the emit_load_s3 for ICMD_IASTORE in the codegen would load the constant value 123 into the reserved register.
If the architecture (like CISC) can do even better than that, the codegen just would have to check like this (completely optional):
case ICMD_IASTORE:
if (IS_CONST_S3) {
/* store constant directly to mem */
}
else {
/* general path using emit_load_s3 */
}
with IS_CONST_S3 being a convenience macro for
(jd->var[iptr->sx.s23.s3.varindex].flags & CONSTVAL)
This scheme has many advantages:
- no need for all the *CONST ICMDs.
- no need for architecture specific #ifdefs and spaghetti code in stack.c.
- the codegen itself decides what it can optimize. in many cases (especially on RISC) the emit functions will do all that is necessary.
- decreased register pressure on architectures that do not support CONST operations. (Because the constant is loaded directly into the reserved register by the emit function).
more variants are possible, for example IADD with the first operand constant.
- no restriction of constant values by the instruction format.
- more suitable for general constant folding
- less initial work when a codegen is ported. CONST optimizations can be added later.
The codegen can easily add extra checks, for example taking the const path only if the constant is zero, etc.