zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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:
Mstage0/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;