Repository navigation
Ci26 device fixes - #15
Merged
Merged
Conversation
…fall-through try_kill_rotated_loop dropped the back-edge of a pure counting loop once nothing the body computed was read outside, but a body exit to another label (`if (a[i] == x) goto found;`) fires on whichever trip its condition first holds, so the rewritten loop only ever tested element 0. Loop detection pulls an exit within 50 instructions into the loop's range, so only a far exit label reached the rewrite. This miscompiled tcc_ir_opt_dse's chain-op scan in the self-hosted native tcc: a SET_CHAIN/INIT_CHAIN_SLOT past the first instruction was never seen, so the parent frame's stores to variables captured by nested functions were deleted (device-only failures of the bug_nested_* and bug_r5_nested_inline_combined tests). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ly exit try_kill_rotated_loop checked the loop's entries but not its exits. A pure search loop whose body leaves early (an inlined `return 0`) was treated as a dead counting loop and lost its back-edge, so it ran one iteration. The loop_max_idx check only caught exits within detect_loops' 50-instruction padding; a far exit target slipped through. loop_relayout exposes the shape by placing the early-exit block inside the loop's index range. Self-host impact: the cross collapsed the consecutive-offset check in ssa_opt_load_combine, so the native tcc combined non-consecutive byte loads (870_readint_unroll_combine -O2 on the device). The rotated arm now requires the latch fall-through to be the only exit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he latch's try_kill_rotated_loop deleted the back-edge of a pure rotated loop as long as no value it computed was read afterwards, but a pure body still decides where control goes: a dedup search `for (i < s->count) if (hit) return;` leaves through its early return, so killing the back-edge compared only element 0. The early return is a jump to the epilogue (target == the instruction count), which has no CFG edge, so the successor checks never saw it. Once ssa:licm_field_ptr hoisted the s->count bound out of the loop, the bound was invariant and the kill fired; the self-hosted tcc's sccp_add_mem_dep then appended duplicate deps until "memory full" (device ir_tests/nested_struct_return.c and gcc nestfunc-7 at -O2). The rotated arm now requires every jump and CFG edge leaving the body to land on the latch's fall-through block (no return / computed jump), and dead_loop_body_hi treats a jump to the epilogue as an exit as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s another exit The rotated arm (try_kill_rotated_loop) dropped the latch JUMPIF of a pure counting loop once nothing varying escaped, but a search loop that leaves early (`found = 1; break`, `return`, a jump to the epilogue) escapes a per-edge constant: killing the back-edge ran the body once and looked at items[0] only. licm_field_ptr exposed it by hoisting the field bound out of the loop, which made the bound invariant and the loop eligible. Self-hosted, this miscompiled tcc_ir_tu_analyze_dead_statics, so the native tcc marked statics read by reachable functions as having no readers (bug_guard_head_partial_inline -O2 on the device). The arm now requires the latch's fall-through to be the only way out of the loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… follow every plain copy to a fixpoint tcc_ir_opt_dead_addrvar_elim tracked a local's address only through LEA -> STORE V=T -> ASSIGN T=V, in one linear scan. A VAR-to-VAR copy (V4 <-- T9; V6 <-- V4; T12 <-- V6; *T12 = x, from inlining sub/look into main in gcc 990128-1) hid the store through T12, so the LEA of the dead &pp was deleted while the store stayed and wrote through whatever register held T9 (argc on the device: HardFault MMFAR=0x1). The pass now computes, to a fixpoint over plain copies of TEMPs and VARs in any order, which local each value may point to. A value that may also hold anything else (another def, a second local, an address-taken VAR) is untracked and its locals escape, as does any use other than a tracked copy or a STORE/STORE_INDEXED base. When the local is dead the LEA, the stores through it and every copy of the address go together, so no copy is left reading the deleted TEMP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e destination registers
tcc_gen_machine_assign_mop_ex reads a 64-bit lvalue as [base] / [base+4].
The address scratch was allocated with no exclusions, so under pressure
(-fpic reserves r9, a nested function r10) at -O0 the picker handed out the
low half's own register and saved it around the use:
push {r0}; ldr r0,<&GA[1]>; ldr r0,[r0]; ldr.w ip,[r0,#4]; pop {r0}
The high word was read through the loaded low word (HardFault MMFAR=0x6 on
YasOS in bug_nested_static_chain_scratch_reg -O0) and the low word was then
popped away. The scratch now excludes the destination registers, and an
address that already sits in the low half's register is read for the high
word first.
Regression: bug_pic_ll_global_load_base_alias.c (runtime, all levels) and
test_pic_ll_load_codegen.py (the -fpic shape; red at -O0 before the fix).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…offset by the push th_offset_to_reg_ex materializes an out-of-range frame offset in a scratch register, and with every register busy it PUSHes one first. The caller had already computed the SP-relative offset, so the access landed 4 bytes below the slot. gcc pr28982b (256 KB frame, 60 live values) read a neighbouring spill slot at -O1/-O2 under the YasOS ABI, where R9 is reserved. The helper now takes the base register and adds 4 when it pushed and the base is SP. Regression: bug_far_spill_scratch_push_sp_bias.c (8 KB frame, 22 live pointer/float pairs), red at -O1/-O2/-Os before the fix. Co-Authored-By: Claude Opus 5.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.
No description provided.