commit 9487bd9acf3bd4c8d18a40a429334eb3cbc2f8a9 (tree)
parent fad25d34f91f0cb44d4ca9e45bc853937885b1f8
Author: Motiejus <motiejus@jakstys.lt>
Date: Sat, 7 Mar 2026 09:18:22 +0000
sema: add comptime float folding to analyzeArithmetic
When both operands are comptime-known floats (IP_KEY_FLOAT entries,
including comptime_float and concrete float types), fold the result
at comptime instead of emitting a runtime AIR instruction.
Ported from Sema.zig analyzeArithmetic: resolveValue(casted_lhs/rhs)
path which evaluates comptime values via arith.add/sub/mul.
Handles ADD, SUB, MUL variants (including wrap/sat) for both
comptime_float × comptime_float and concrete float × float. Result
type is the wider of the two float types.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
| M | stage0/sema.c | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 48 insertions(+), 0 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -929,6 +929,54 @@ static void addSignedMag128(uint64_t a_lo, uint64_t a_hi, bool a_neg,
// Handles add/sub/mul and their wrap/sat variants.
static AirInstRef analyzeArithmetic(Sema* sema, SemaBlock* block,
AirInstTag air_tag, AirInstRef lhs, AirInstRef rhs) {
+ // Comptime folding for float operands (comptime_float or concrete float).
+ // Ported from Sema.zig analyzeArithmetic: resolveValue(casted_lhs/rhs).
+ if (AIR_REF_IS_IP(lhs) && AIR_REF_IS_IP(rhs)) {
+ InternPoolKey lk = ipIndexToKey(sema->ip, AIR_REF_TO_IP(lhs));
+ InternPoolKey rk = ipIndexToKey(sema->ip, AIR_REF_TO_IP(rhs));
+ if (lk.tag == IP_KEY_FLOAT && rk.tag == IP_KEY_FLOAT) {
+ double lv = lk.data.float_val.val;
+ double rv = rk.data.float_val.val;
+ double result;
+ switch (air_tag) {
+ case AIR_INST_ADD:
+ case AIR_INST_ADD_WRAP:
+ case AIR_INST_ADD_SAT:
+ result = lv + rv;
+ break;
+ case AIR_INST_SUB:
+ case AIR_INST_SUB_WRAP:
+ case AIR_INST_SUB_SAT:
+ result = lv - rv;
+ break;
+ case AIR_INST_MUL:
+ case AIR_INST_MUL_WRAP:
+ case AIR_INST_MUL_SAT:
+ result = lv * rv;
+ break;
+ default:
+ goto after_float_fold;
+ }
+ // Result type: pick the wider float (or comptime_float if both
+ // are).
+ TypeIndex result_ty
+ = (lk.data.float_val.ty == IP_INDEX_COMPTIME_FLOAT_TYPE
+ && rk.data.float_val.ty == IP_INDEX_COMPTIME_FLOAT_TYPE)
+ ? IP_INDEX_COMPTIME_FLOAT_TYPE
+ : (floatBits(lk.data.float_val.ty)
+ >= floatBits(rk.data.float_val.ty)
+ ? lk.data.float_val.ty
+ : rk.data.float_val.ty);
+ InternPoolKey key;
+ memset(&key, 0, sizeof(key));
+ key.tag = IP_KEY_FLOAT;
+ key.data.float_val.ty = result_ty;
+ key.data.float_val.val = result;
+ return AIR_REF_FROM_IP(ipIntern(sema->ip, key));
+ }
+ }
+after_float_fold:;
+
// Comptime folding: if both operands are comptime integers,
// compute the result at comptime (128-bit).
uint64_t lhs_lo, lhs_hi, rhs_lo, rhs_hi;