Performance backlog#372
Open
kromych wants to merge 46 commits into
Open
Conversation
The RmwPlace::Slot exclusion of StoreKind::F32 dated from before the backends lowered fused F32 StoreLocal/LoadLocal; both do now, the SSA interpreter handles them, and the walker already narrows to single precision before every F32 store, so the slot promotes like the x = x op k form. Fixes #349 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ImmData offsets drifted with earlier header/runtime binding changes; the current compiler already produces these values, so this is regeneration only, no codegen change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
C99 6.4.4.2p4: an unsuffixed floating constant has type double, f/F float, l/L long double (which c5 represents as double). The lexer consumed the suffix and discarded it, so every floating constant was typed double: sizeof(1.0f) reported 8, and float arithmetic against an f-suffixed literal ran a widen / op-in-double / narrow hop. The lexer now records the f/F suffix and rounds the constant to single precision at the literal (6.4.4.2p5), keeping the value as f64 bits so the const-expression evaluator and static initializers consume it unchanged. The parser types the literal Ty::Float; the walker emits it through the new SsaBuilder::imm_f32, cached apart from integer imms of equal payload because the f32 mark changes the value's materialisation. The SSA interpreter widens an f32-marked imm at its definition to match its f64-pattern register convention. Fixes #348 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The badc -O / clang -O2 / cl /O2 rows of tests/perf/run.py and both -O legs of demos/python/compare_compilers.py now build with NDEBUG, matching release-build practice; unoptimized legs keep asserts live. Perf-table history is not comparable across this commit for the assert-carrying fixtures (sqlite, quickjs, compress, CPython). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The brace-element parser skipped a leading (TYPE) cast and recursed on the operand, so every intermediate conversion was lost: (long)(int)0x92492493 stored the unextended 0x92492493 in static and automatic arrays and structs, (int)2.75 kept the float bits, and a binary operator after the cast folded before it instead of after. Route a cast of an arithmetic operand through the constant-expression evaluator, which converts at each cast's width and signedness per C99 6.5.4/6.3.1.3 before the 6.7.8p11 conversion to the member type; only a cast of a relocation-bearing leaf keeps the skip-and-recurse path where the value is the leaf's address. The shared reloc-leaf probe now sees through grouping parens plus nested casts and restores string bytes it lexed while scanning. Fixes #366 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A static-local array initializer carrying a `&&` token (a `&&label` element, or logical AND inside a constant element) routes to emit_static_array_init_runtime, which emitted unguarded per-element stores at the declaration point: the initializer re-ran on every call, clobbering user writes to the table. C99 6.2.4p3 gives an object with static storage duration exactly one initialization, before program startup, for the whole program run. Wrap the stores in a hidden once-guard byte allocated directly after the array in the same data object (so data DCE and linker rebase move it with the array), lowered as the single statement `guard ? 0 : (stores..., guard = 1)`; the guard is ordinary loads, stores, and branches in the IR, so the native backends, the JIT, and the SSA interpreter all honor it. quickjs_bench -O on the arm64 host: 325.2 -> 207.7 ms median of 5 (-36%). The generic form -- resolving `&&label` elements in the data image via label relocations at translation time, removing the runtime stores entirely -- remains as follow-up work on the issue. Fixes #365 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A single -O now selects release semantics: the optimization passes plus NDEBUG=1 and __OPTIMIZE__=1 predefines, installed ahead of the CLI -D/-U lists so an explicit -D NDEBUG=<v> keeps the user's value and -U NDEBUG re-enables assert. Demo builds that compiled without optimization now pass -O on every badc compile (dual-lane demos keep both lanes); the perf harnesses drop the now-redundant -DNDEBUG from their badc rows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/snapshots/ssa/object_macro_to_fn_macro_rescan.ssa
compute_frame_base counted every LoadLocal / StoreLocal / LocalAddr as a local access, so a promotion-orphaned LoadLocal with no consumers -- which the per-inst emit dispatch skips via is_dead_pure and which produces no machine code -- still forced frame_bytes != 0 and a full prologue on an otherwise frameless leaf. Gate the scan with the same is_dead_pure predicate the emit uses, so the frame decision and the emit skip cannot diverge. The rewritten scan also counts locals-region references that reach the emit outside the slot-access instructions: AllocaInit's arena bookkeeping slot, a call's aggregate-return result temp (ret_slot_local), and the by-value aggregate parameter scatter into a body local (param_aggs / param_local_slots), alongside the existing indirect_result_slot case. Volatile slot accesses are not pure and keep the frame. Snapshot drift: 512 asm files, 616 functions; every change is a frame loss (424) or a frame allocation shrink (192), no function gains code. Fixes #352 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/snapshots/asm/object_macro_to_fn_macro_rescan.aarch64.asm # tests/snapshots/asm/object_macro_to_fn_macro_rescan.x64.asm
Regenerated with a binary built from the branch base; the recorded ImmData offsets were one byte behind the current front end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ParamRef entry sign-extension was gated on high_observed, which tracks reads of bits 32..63 only. An I8/I16 parameter conversion also rewrites bits 8..31, so a consumer reading the low word through a 32-bit truncation observed the caller's unconverted value; direct and indirect calls miscompiled alike under -O. Keep the gate for I32, whose sxtw/movsxd touches only bits 32..63. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
emit_call_indirect took the marshal branch only for variadic and aggregate cases; every non-variadic scalar-arg indirect call fell to the c5-stack push shape, spending 2n+2 memory operations per blr on pushes the callee never reads. The variadic disjunction is exhaustive on aarch64, so the push shape was reachable only for non-variadic scalar calls: widen the gate to marshal unconditionally and delete the push shape. A non-variadic call plans every argument as fixed, mirroring the direct-call path; x86_64 already marshals every indirect call. sqlite_bench -O on the macOS arm64 host: median 0.65s -> 0.60s. Fixes #351 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plain long is 32-bit on LLP64 targets and plain char is unsigned on AArch64 Linux/Windows, so the host-derived expected values failed there. Explicitly signed fixed-width types keep one expectation set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # src/c5/tests/jit.rs # src/c5/tests/native.rs # src/c5/tests/native_elf.rs # src/c5/tests/native_elf_x64.rs # src/c5/tests/native_pe_arm64.rs # src/c5/tests/native_pe_x64.rs # src/c5/tests/programs.rs # tests/snapshots/ssa/object_macro_to_fn_macro_rescan.ssa
…ossing flags promote_calls_after_def_to_classes re-derived call-crossing per phi class from a pc-interval test (first call pc between the class root's def and the class's combined last use). extend_last_use_across_blocks raises loop-resident values' last_use past call pcs whenever a call block is laid out at a lower pc than the loop body, so the interval covered calls the class never crosses in the CFG. Values the precise values_live_across_calls pass leaves unflagged were still forced into the callee bank; with more loop-live values than callee registers the hot induction variable spilled, carrying a store->reload through every loop iteration. The class flag is now the OR of the members' per-value flags from values_live_across_calls, which already models TlsAddr-as-call and the setjmp barrier. The pc-interval machinery and the class_last_use table it read become dead and are removed. On the recursive-partition fixture (linux-x64) the spill disappears (spill_count 1 -> 0, callee regs 5 -> 3) and the aarch64 prologue drops from 6 saves to 3. 59 fixture snapshots drift; every change is a pure register reassignment out of the callee bank, no snapshot gains stack traffic, net spill_count -4 corpus-wide. Fixes #355 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/snapshots/asm/block_scope_function_declaration.aarch64.asm # tests/snapshots/asm/block_scope_function_declaration.x64.asm # tests/snapshots/asm/c4.aarch64.asm # tests/snapshots/asm/c4.x64.asm # tests/snapshots/asm/comparison_imm_lhs_swap.x64.asm # tests/snapshots/asm/designator_override_and_braced_string.x64.asm # tests/snapshots/asm/dlopen_atoi.aarch64.asm # tests/snapshots/asm/fn_ptr_ternary_call_return.aarch64.asm # tests/snapshots/asm/global_init_midexpr_cast_narrow.aarch64.asm # tests/snapshots/asm/global_init_midexpr_cast_narrow.x64.asm # tests/snapshots/asm/inline_forward_ref_value.aarch64.asm # tests/snapshots/asm/inline_forward_ref_value.x64.asm # tests/snapshots/asm/integer_ops_exhaustive.aarch64.asm # tests/snapshots/asm/integer_ops_exhaustive.x64.asm # tests/snapshots/asm/mem2reg_value_across_call.aarch64.asm # tests/snapshots/asm/mmap_anonymous.aarch64.asm # tests/snapshots/asm/mmap_anonymous.x64.asm # tests/snapshots/asm/slot_coalesce_declared.x64.asm # tests/snapshots/asm/ssa_fp_compare_nan.aarch64.asm # tests/snapshots/asm/ssa_fp_compare_nan.x64.asm # tests/snapshots/asm/switch_nested_case_in_compound.aarch64.asm # tests/snapshots/asm/switch_nested_case_in_compound.x64.asm # tests/snapshots/asm/sysconf_pagesize.aarch64.asm # tests/snapshots/asm/sysconf_pagesize.x64.asm # tests/snapshots/asm/tentative_array_definition.aarch64.asm # tests/snapshots/asm/tentative_array_definition.x64.asm # tests/snapshots/asm/tentative_array_use_before_init.aarch64.asm # tests/snapshots/asm/tentative_array_use_before_init.x64.asm # tests/snapshots/asm/unsigned_char_array.aarch64.asm # tests/snapshots/asm/unsigned_char_array.x64.asm # tests/snapshots/asm/unsigned_compare.aarch64.asm # tests/snapshots/asm/unsigned_compare.x64.asm
store_forward cleared its tracking on every StoreLocal instead of recording the stored value, so a same-slot StoreLocal -> LoadLocal pair survived as a store plus a dependent reload. Track slots in a second intra-block table under the existing width / volatile / distance discipline. A slot participates only when nothing but LoadLocal / StoreLocal can reach it: mem2reg::promotable_slots (no LocalAddr, no volatile access, no alloca arena) minus the slots written through FunctionSsa fields or a call's ret_slot_local. Its entries survive pointer stores, Mcpy, and atomics -- the slot's address is never a value -- and die at a same-slot StoreLocal, at a call (forwarding across one holds the value live over the call, which spills), and at block boundaries. GotoIndirect targets now resolve through the redirect map so a forwarded slot load feeding a computed goto goes dead. Fixes #354 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/snapshots/asm/indirect_struct_return_outptr.x64.asm # tests/snapshots/asm/label_addr_array_init.aarch64.asm # tests/snapshots/asm/out_pointer_return_float_args.x64.asm # tests/snapshots/ssa/label_addr_array_init.ssa
Move apply_binop, round_if_f32, and the Extend / FpCast / Fneg / Fma arm bodies verbatim into a shared module so the interpreter and the compile-time constant folder use one implementation of the operator semantics. Division traps become the EvalTrap enum; the VM re-wraps the same message strings into C5Error::Runtime. Behavior-neutral. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Baseline regen: the merge of the ten mid-end changes did not refresh tests/snapshots, so the tree lagged the compiler's output (54 files; store-forwarded reload shapes and shorter block bodies). Generated with the pre-extraction compiler; no compiler change in this commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The inliner substitutes call-site immediates into callees and materialises callee-narrows extends on them, leaving Extend(Imm) / Binop(Imm, Imm) / BinopI(Imm, k) chains no stage re-folded, so the rotate matcher's constant arm and the immediate-form encoders never saw them. The new constfold pass (between struct_return_reg and rotate in both pipelines) folds those shapes through eval::fold_binop -- the interpreter's own evaluator -- and rewrites immediate-operand binops to BinopI when the op is immediate-safe in both emitters and the immediate either encodes without a per-use scratch materialisation or has no other use. Folds the evaluator computes but native code traps on (division by zero, i64::MIN / -1) are refused; f32-flagged and address-bearing immediates never fold. Corpus effect: 2815 instructions fold to Imm across 180 fixtures; snapshot text drops 12 percent of instructions with no function growing beyond padding artifacts; the crypto fixture's 21 register-count rotates become 20 immediate-form rotates plus the one genuine runtime count. Fixes #347 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…functions
A value dead on the first-return path of a setjmp-family or vfork call
is still read after the second return (C99 7.13.2.1p3; under vfork the
child writes the parent's shared stack), so slot reuse and frame-slot
coalescing clobber it; such bodies also stay out of line. The flag is
set for the setjmp intrinsic and the {vfork, setjmp, _setjmp, sigsetjmp,
__sigsetjmp} externs.
Fixes #374
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Saves and restores at contiguous offsets pair into stp/ldp; frames within the imm7 scaled range fold the locals allocation into a pre-indexed stp, keeping x29-relative addressing unchanged. Larger frames keep the split shape. The x86_64 push/pop form is deferred: PE UNWIND_INFO would need save codes the writer does not emit yet. Fixes #353 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/snapshots/asm/block_scope_function_declaration.x64.asm # tests/snapshots/asm/indirect_call_mixed_fp_int_args.x64.asm # tests/snapshots/asm/integer_ops_exhaustive.aarch64.asm # tests/snapshots/asm/integer_ops_exhaustive.x64.asm # tests/snapshots/asm/switch_nested_case_in_compound.x64.asm # tests/snapshots/asm/tentative_array_definition.x64.asm # tests/snapshots/asm/unsigned_compare.x64.asm
# Conflicts: # tests/snapshots/asm/binop_imm_chain_fold.aarch64.asm # tests/snapshots/asm/block_scope_function_declaration.aarch64.asm # tests/snapshots/asm/builtin_bswap_expect.aarch64.asm # tests/snapshots/asm/c4.aarch64.asm # tests/snapshots/asm/c99_arith_common_width.aarch64.asm # tests/snapshots/asm/comparison_imm_lhs_swap.aarch64.asm # tests/snapshots/asm/divmod_preserves_rdx.aarch64.asm # tests/snapshots/asm/dlopen_atoi.aarch64.asm # tests/snapshots/asm/float_pointer_basics.aarch64.asm # tests/snapshots/asm/fn_ptr_decay_inside_block.aarch64.asm # tests/snapshots/asm/fn_ptr_multi_deref.aarch64.asm # tests/snapshots/asm/fn_ptr_ternary_call_return.aarch64.asm # tests/snapshots/asm/function_type_typedef_declaration.aarch64.asm # tests/snapshots/asm/global_init_midexpr_cast_narrow.aarch64.asm # tests/snapshots/asm/gnu_extension_keyword.aarch64.asm # tests/snapshots/asm/include_macro_operand.aarch64.asm # tests/snapshots/asm/indirect_call_mixed_fp_int_args.aarch64.asm # tests/snapshots/asm/indirect_call_narrow_scalar_args.aarch64.asm # tests/snapshots/asm/indirect_call_ten_scalar_args.aarch64.asm # tests/snapshots/asm/indirect_call_variadic_fp_control.aarch64.asm # tests/snapshots/asm/inline_arg_count_mismatch.aarch64.asm # tests/snapshots/asm/inline_forward_ref_value.aarch64.asm # tests/snapshots/asm/integer_boundary_c99.aarch64.asm # tests/snapshots/asm/integer_ops_exhaustive.aarch64.asm # tests/snapshots/asm/mem2reg_value_across_call.aarch64.asm # tests/snapshots/asm/mmap_anonymous.aarch64.asm # tests/snapshots/asm/mul_pow2_to_shift.aarch64.asm # tests/snapshots/asm/parenthesized_function_declarator.aarch64.asm # tests/snapshots/asm/preinc_narrow_lvalue_wraps.aarch64.asm # tests/snapshots/asm/signed_cast_extends.aarch64.asm # tests/snapshots/asm/ssa_fp_compare_nan.aarch64.asm # tests/snapshots/asm/static_init_once_guard.x64.asm # tests/snapshots/asm/store_to_load_forward.aarch64.asm # tests/snapshots/asm/switch_nested_case_in_compound.aarch64.asm # tests/snapshots/asm/sysconf_pagesize.aarch64.asm # tests/snapshots/asm/tentative_array_definition.aarch64.asm # tests/snapshots/asm/type_warning_arity.aarch64.asm # tests/snapshots/asm/unsigned_char_array.aarch64.asm # tests/snapshots/asm/unsigned_compare.aarch64.asm # tests/snapshots/asm/unsigned_compound_assign.aarch64.asm # tests/snapshots/asm/zero_sign_extension_32bit.aarch64.asm
Cross-branch merges resolved snapshot conflicts by taking one side; this regen reflects the merged compiler. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The shape exposes a pre-existing Win64 positional-slot marshalling defect in indirect calls; tracked separately, re-enable with the fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pairing fold emits the x29/x30 pair pre-indexed or at a signed offset into an already-adjusted frame depending on pressure; the sentinel was pinned to the #-0x10 pre-indexed word. Dump the preamble on failure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pthread_attr_getstack and pthread_attr_getguardsize on both platforms, pthread_getattr_np on Linux (GNU extension). CPython's recursion guard derives real stack limits from these; without them it falls back to a 4 MB estimate from the current stack pointer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Define __GLIBC__ in the Linux target configs so CPython's guard takes the pthread_getattr_np path instead of estimating the stack from sp (flaky aborts under ASLR); raise _PyOS_LOG2_STACK_MARGIN to 2^13 words because the check-to-check stride must exceed one eval frame and badc's frames outsize the reference compilers' until live ranges split; keep the head of a failing slice's output where the fatal message lives. Verified: the tier2 slice went from ~50% SIGABRT to 8/8 green on linux-aarch64. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ells
The walker's callee entry reads a float parameter from its argument
cell as an f32 bit pattern (LoadLocal { F32 } for a stack-passed one,
matching what native callers store), but the SSA interpreter's call
path wrote the f64-pattern register convention into every cell, so a
float parameter past the FP argument registers read back as 0.0f.
Win64 assigns one argument slot per position (rcx/xmm0 .. r9/xmm3)
rather than SysV's independent int/FP banks, so the mixed int/fp
indirect-call fixture hit the divergence at argument position 4 on the
win-x64 host lane; SysV needs nine FP arguments to reach it. Narrow
f32-typed arguments at the cell boundary and widen them back in
ParamRef { F32 }; the emitted native code is unchanged.
Fixes #375
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… inversion The For lowering allocates (header, post, body, after) with the header's exit test branching over post, so every for / while iteration runs three taken branches, plus jmp-to-jmp chains where loops nest. Add a late layout pass to both pipelines, after store_forward, that only reorders blocks and remaps block ids; instructions never move between blocks: * thread edges through chains of empty Jmp blocks, stopping one hop short of a phi-carrying target (that hop holds the edge's moves); * place blocks depth-first with each natural loop's body contiguous; * rotate a loop whose header conditionally exits the loop to bottom-test form: header last in its chain, an unconditional latch directly before it so the back edge falls through; * invert a Bz / Bnz whose taken target is the next block in layout (successor set unchanged, so no new critical edges). Functions with a computed goto or an irreducible loop keep source order. Block-id remapping (terminator targets, phi incomings, BlockAddr, computed_goto_targets) lives in passes/remap_blocks.rs as a shared utility. The .ssa snapshots drift because the dump prints the new block order; the .asm snapshots drift because the emitters elide jumps to the new next block. Measured -O medians (7 runs): arm64 sieve -20.8%, crypto -25.1%, compress -12.1%, sqlite_bench -20.3%, qsort +2.6% (x64 qsort -1.4%; the static per-scan branch counts are equal, entry hops into the rotated scan loops offset the rotation win); x64 sieve -21.4%, crypto -45.5%, sqlite_bench -14.9%. A CFG-reconstructing checker over the emitted code shows no function gained an unconditional branch inside a loop body on either arch. Fixes #357 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A switch dispatcher previously lowered only to a balanced compare tree, so a many-case dense switch (a bytecode interpreter's opcode dispatch) paid O(log n) compare-and-branch levels per dispatch, each level reloading the scrutinee. A dense case set (>= 8 cases, span under twice the case count) now lowers to a bias subtract, a single unsigned bounds check to default, and Terminator::JumpTable -- an indexed branch through a per-function side table (Terminator stays Copy; the target lists live in FunctionSsa::jump_tables, the computed_goto_targets precedent). Sparse and small sets keep the tree. The table is emitted in .text right after the terminator and resolved by the per-function block-offset fixups; no object-writer or relocation changes. Entries are 32-bit offsets relative to the table base: aarch64 dispatches via adr / ldrsw scaled / add / br (the embedded table keeps adr trivially inside its +/-1 MiB reach), x86_64 via lea rip-relative / movsxd SIB / add / jmp. The bounds check proves the index in range, so out-of-range and negative scrutinees (including the promoted-width unsigned wrap cases) fall to default before the indexed branch. Every terminator consumer gains the arm: the VM interpreter (interp / JIT parity), liveness and the allocator's use walks treat the index as a terminator operand, mem2reg / slot_coalesce / the passes' successor enumeration read the table's distinct targets, constfold_branch folds a constant in-range index to Jmp, and the inliner rejects jump-table callees and skips multi-block splicing for jump-table callers (block ids shift; a shared BlockId remap utility can lift this later). split_crit_edges retargets table entries onto trampoline blocks: a dispatcher edge into a phi-carrying case block would otherwise emit every successor's phi moves at the dispatcher exit and clobber values live on the other edges. Perf (7-run medians, -O): sqlite_bench 602.0 -> 535.5 ms (-11.0%) on macOS arm64 and 715.1 -> 655.4 ms (-8.4%) on Linux x64; the compress canary is neutral on both. The clang oracle isolates the same cost: -fno-jump-tables slows its sqlite_bench build by 12.1%. Fixes #358 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/snapshots/asm/duff_switch_into_loop.aarch64.asm # tests/snapshots/asm/duff_switch_into_loop.x64.asm # tests/snapshots/ssa/duff_switch_into_loop.ssa
The chain builder enumerates JumpTable successors in table order and permute_blocks remaps the jump_tables target lists with the rest of the block-id surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…inery Models a natural loop's body as a pseudo-callee whose parameters are the header phis and whose returns are the latch back-edge values, then clones trip-count copies with the inliner's remap primitives; trip counts are evaluated with the shared VM evaluator. v1 unrolls single-block bodies (trip <= 16, size-capped) without scalar promotion, leaving the existing index_fold/store_forward/constfold to clean up. crypto 700 -> 310 ms (2.15x) on host arm64, checksum unchanged; compress unaffected. Refs #360 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The phi_join switch fixture also carries a const-trip loop that the unroll pass now expands; runtime behaviour is unchanged (suite green). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fixture computed a 64-bit golden value with 'long', which is 32-bit on LLP64 (Windows); the arithmetic overflowed there and the check failed. Use 'long long' for 64-bit width on every target. #358's jump-table codegen is unaffected (LP64 snapshot targets unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Perf-lever campaign round 1: the S/M-cost levers from the 2026-07 audit, plus every miscompile the campaign surfaced.
Codegen / mid-end
Loop/switch codegen
Miscompiles found and fixed
Closes #347
Closes #348
Closes #349
Closes #351
Closes #352
Closes #353
Closes #354
Closes #355
Closes #365
Closes #366
Closes #374
Closes #375
Closes #357
Closes #358
Found and filed, not fixed here: #373 (snapshot path dependence), #376 (GLIBC predefine policy), #377 (python demo obj-cache keying).
🤖 Generated with Claude Code