From 9487bd9acf3bd4c8d18a40a429334eb3cbc2f8a9 Mon Sep 17 00:00:00 2001 From: Motiejus Date: Sat, 7 Mar 2026 09:18:22 +0000 Subject: [PATCH] sema: add comptime float folding to analyzeArithmetic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- stage0/sema.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/stage0/sema.c b/stage0/sema.c index c161a23ced..aede17444f 100644 --- 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;