mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-01 07:40:42 -04:00
phase-36: S104 s104_e5 — func_8018AD74 banked at 0 through the whole-object gate + propagated — launder → a marked empty do-while (cse1 block end, cse.c:8054; sched.c:2428) — Drew ruling (a)
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
void func_80187DD0(s32 param_1)
|
||||
{
|
||||
s32 t1 = *(s32 *)(param_1 + 0x64);
|
||||
s32 pad[2];
|
||||
|
||||
if (*(s16 *)(t1 + 0x36) != *(s16 *)(param_1 + 0x10A)) {
|
||||
func_8012C218((void *)param_1);
|
||||
return;
|
||||
}
|
||||
{
|
||||
if ((*(u32 *)(t1 + 0xE0) & 4) != 0) {
|
||||
func_8012E8A8((u8 *)param_1);
|
||||
return;
|
||||
}
|
||||
{
|
||||
s32 a2 = *(s32 *)(*(s32 *)(t1 + 0x20) + 0x20);
|
||||
s32 a3 = param_1 + 0xFC;
|
||||
|
||||
if (a2 != 0) {
|
||||
if ((a2 & 0x1000000) != 0) {
|
||||
s32 a1 = a2 & 0xFEFFFFFF;
|
||||
u32 v0;
|
||||
u32 a0;
|
||||
u32 v1;
|
||||
|
||||
*(u16 *)(param_1 + 0x102) = *(u16 *)(a1 + 0x66);
|
||||
|
||||
v0 = *(u32 *)(a1 + 0x60);
|
||||
a0 = *(u8 *)(a1 + 0x61) | ((v0 & 0xF) << 8);
|
||||
v1 = (((s32)v0 >> 16) & 0xFF) | ((v0 & 0xF0) << 4);
|
||||
do { // !FAKE: do-while — flow counts the stores' refs at loop depth 2 (flow.c:1440-1449, :2711 reg_n_refs += loop_depth), which lifts a0's quantity over a1's in qty_compare_1 (local-alloc.c:1598); its LOOP notes also keep sched1 from moving the 0x104 store above v1's or (sched.c:2053-2074), so w's quantity ties the (w & 0xF) one at 13333 and wins on qty number (P36 S104 e5 minimum-lever)
|
||||
*(u16 *)(param_1 + 0x104) = a0;
|
||||
*(u16 *)(param_1 + 0x106) = v1;
|
||||
} while (0);
|
||||
|
||||
*(s16 *)(param_1 + 0xFC) = (s8)*(u8 *)(a1 + 0x63);
|
||||
*(s16 *)(param_1 + 0xFE) = (s8)*(u8 *)(a1 + 0x64);
|
||||
*(s16 *)(param_1 + 0x100) = (s8)*(u8 *)(a1 + 0x65);
|
||||
} else {
|
||||
*(UAlign12 *)(param_1 + 0xFC) = *(UAlign12 *)(a2 + 0x90);
|
||||
}
|
||||
*(s32 *)(*(s32 *)(param_1 + 0x20) + 0x20) = a3;
|
||||
}
|
||||
|
||||
if ((*(u32 *)(t1 + 0xE0) & 0x80) != 0) {
|
||||
if (*(u16 *)(param_1 + 0x34) == 0) {
|
||||
s16 sVar2 = *(u16 *)(param_1 + 0x108) + 0x40;
|
||||
*(s16 *)(param_1 + 0x108) = sVar2;
|
||||
if (sVar2 > 0x200) {
|
||||
*(u16 *)(param_1 + 0x108) = 0x200;
|
||||
*(s16 *)(param_1 + 0x34) = *(s16 *)(param_1 + 0x34) + 1;
|
||||
}
|
||||
} else {
|
||||
u16 uVar3 = *(u16 *)(param_1 + 0x108) - 0x80;
|
||||
*(u16 *)(param_1 + 0x108) = uVar3;
|
||||
if ((s16)uVar3 < 0) {
|
||||
*(u16 *)(param_1 + 0x108) = 0;
|
||||
*(u16 *)(param_1 + 0x34) = 0;
|
||||
*(u32 *)(t1 + 0xE0) = *(u32 *)(t1 + 0xE0) & ~0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*(u16 *)(a3 + 6) = *(u16 *)(a3 + 6) + *(u16 *)(param_1 + 0x108);
|
||||
|
||||
*(u32 *)(param_1 + 4) = *(u32 *)(t1 + 4);
|
||||
*(u32 *)(param_1 + 8) = *(u32 *)(t1 + 8);
|
||||
*(u32 *)(param_1 + 0xC) = *(u32 *)(t1 + 0xC);
|
||||
|
||||
*(UAlign8 *)(param_1 + 0x50) = *(UAlign8 *)(t1 + 0x50);
|
||||
|
||||
{
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
*(UAlign8 *)(dst + 0x10) = *(UAlign8 *)(src + 0x10);
|
||||
}
|
||||
{
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
*(UAlign8 *)(dst + 0x18) = *(UAlign8 *)(src + 0x18);
|
||||
}
|
||||
{
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
*(u32 *)(dst + 4) = *(u32 *)(src + 4);
|
||||
}
|
||||
{
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
*(u16 *)(dst + 0x2C) = *(u16 *)(src + 0x2C);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
void func_80187DD0(s32 param_1)
|
||||
{
|
||||
s32 t1 = *(s32 *)(param_1 + 0x64);
|
||||
s32 pad[2];
|
||||
|
||||
if (*(s16 *)(t1 + 0x36) != *(s16 *)(param_1 + 0x10A)) {
|
||||
func_8012C218((void *)param_1);
|
||||
return;
|
||||
}
|
||||
{
|
||||
if ((*(u32 *)(t1 + 0xE0) & 4) != 0) {
|
||||
func_8012E8A8((u8 *)param_1);
|
||||
return;
|
||||
}
|
||||
{
|
||||
s32 a2 = *(s32 *)(*(s32 *)(t1 + 0x20) + 0x20);
|
||||
s32 a3 = param_1 + 0xFC;
|
||||
|
||||
if (a2 != 0) {
|
||||
if ((a2 & 0x1000000) != 0) {
|
||||
s32 a1 = a2 & 0xFEFFFFFF;
|
||||
u32 v0;
|
||||
u32 a0;
|
||||
u32 v1b;
|
||||
u32 v1;
|
||||
|
||||
*(u16 *)(param_1 + 0x102) = *(u16 *)(a1 + 0x66);
|
||||
|
||||
v0 = *(u32 *)(a1 + 0x60);
|
||||
a0 = *(u8 *)(a1 + 0x61) | ((v0 & 0xF) << 8);
|
||||
v1b = ((s32)v0 >> 16) & 0xFF;
|
||||
v1 = ((v0 & 0xF0) << 4) | v1b;
|
||||
*(u16 *)(param_1 + 0x104) = (u16)a0;
|
||||
*(u16 *)(param_1 + 0x106) = (u16)v1;
|
||||
|
||||
*(s16 *)(param_1 + 0xFC) = (s8)*(u8 *)(a1 + 0x63);
|
||||
*(s16 *)(param_1 + 0xFE) = (s8)*(u8 *)(a1 + 0x64);
|
||||
*(s16 *)(param_1 + 0x100) = (s8)*(u8 *)(a1 + 0x65);
|
||||
} else {
|
||||
*(UAlign12 *)(param_1 + 0xFC) = *(UAlign12 *)(a2 + 0x90);
|
||||
}
|
||||
*(s32 *)(*(s32 *)(param_1 + 0x20) + 0x20) = a3;
|
||||
}
|
||||
|
||||
if ((*(u32 *)(t1 + 0xE0) & 0x80) != 0) {
|
||||
if (*(u16 *)(param_1 + 0x34) == 0) {
|
||||
s16 sVar2 = *(u16 *)(param_1 + 0x108) + 0x40;
|
||||
*(s16 *)(param_1 + 0x108) = sVar2;
|
||||
if (sVar2 > 0x200) {
|
||||
*(u16 *)(param_1 + 0x108) = 0x200;
|
||||
*(s16 *)(param_1 + 0x34) = *(s16 *)(param_1 + 0x34) + 1;
|
||||
}
|
||||
} else {
|
||||
u16 uVar3 = *(u16 *)(param_1 + 0x108) - 0x80;
|
||||
*(u16 *)(param_1 + 0x108) = uVar3;
|
||||
if ((s16)uVar3 < 0) {
|
||||
*(u16 *)(param_1 + 0x108) = 0;
|
||||
*(u16 *)(param_1 + 0x34) = 0;
|
||||
*(u32 *)(t1 + 0xE0) = *(u32 *)(t1 + 0xE0) & ~0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*(u16 *)(a3 + 6) = *(u16 *)(a3 + 6) + *(u16 *)(param_1 + 0x108);
|
||||
|
||||
*(u32 *)(param_1 + 4) = *(u32 *)(t1 + 4);
|
||||
*(u32 *)(param_1 + 8) = *(u32 *)(t1 + 8);
|
||||
*(u32 *)(param_1 + 0xC) = *(u32 *)(t1 + 0xC);
|
||||
|
||||
*(UAlign8 *)(param_1 + 0x50) = *(UAlign8 *)(t1 + 0x50);
|
||||
|
||||
{
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
*(UAlign8 *)(dst + 0x10) = *(UAlign8 *)(src + 0x10);
|
||||
}
|
||||
{
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
*(UAlign8 *)(dst + 0x18) = *(UAlign8 *)(src + 0x18);
|
||||
}
|
||||
{
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
*(u32 *)(dst + 4) = *(u32 *)(src + 4);
|
||||
}
|
||||
{
|
||||
s32 src = *(s32 *)(t1 + 0x20);
|
||||
s32 dst = *(s32 *)(param_1 + 0x20);
|
||||
*(u16 *)(dst + 0x2C) = *(u16 *)(src + 0x2C);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
# func_80187DD0 (src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c), e5, P36 T7 S104: MINIMUM-LEVER at 0
|
||||
|
||||
**Final: score 0 (174/174 ins, byte-identical).** Lever count 1 → 1, but the kind changes: the `register u32 v0 __asm__("$2")`
|
||||
pin becomes ONE marked `do { … } while (0);` around the two halfword stores, which is ordinary C (step 8). No pin, no asm,
|
||||
no volatile. The best lever-free text scores **2** (below). The nibble-packing block now reads:
|
||||
|
||||
v0 = *(u32 *)(a1 + 0x60);
|
||||
a0 = *(u8 *)(a1 + 0x61) | ((v0 & 0xF) << 8);
|
||||
v1 = (((s32)v0 >> 16) & 0xFF) | ((v0 & 0xF0) << 4);
|
||||
do { // !FAKE: do-while — …
|
||||
*(u16 *)(param_1 + 0x104) = a0;
|
||||
*(u16 *)(param_1 + 0x106) = v1;
|
||||
} while (0);
|
||||
|
||||
**The same block closes all five other copies of the class, each `--try` at 0** (`scratch/copy_<fn>.c`, built by
|
||||
`scratch/port.py`, which swaps only this block into the tree's text): func_80181F40 (ov_SC06_020), func_80185E64 (ov_SC06_022),
|
||||
func_8018833C (ov_SC06_024), func_80182B74 (ov_SC06_032), func_80186858 (ov_SC06_033). That is 6 pins → 6 marked do-whiles.
|
||||
|
||||
## (a) The residual
|
||||
Same count, a register permutation in one block (local-alloc). The target has the loaded word `w` in v0 and the `(w&0xF)<<8`
|
||||
temp in v1. The lever-free text swaps them (and the or's result with them).
|
||||
|
||||
## (b) The pass and the decision (local-alloc, proved with `lsim3.py` on every candidate's `.lreg`, 0 mismatches)
|
||||
Quantities in the block (numbers are local-alloc's birth/death indices, 2 per insn). The target needs this assignment:
|
||||
q2 = {w, w&0xF0, <<4} → v0, q3 = {w&0xF, <<8} → v1, q5 = {>>16, &0xFF, the second or} → v1, q4 = {lbu 0x61, the first
|
||||
or} → a0, q0 = {mask, a1} → a1. `qty_compare_1` (local-alloc.c:1598) ranks by `floor_log2(refs)·refs/(death−birth)`,
|
||||
with ties going to the lower qty number:
|
||||
- q2 (8 refs) against q3 (4 refs): **24/L2 ≥ 8/L3**. That holds only when sched1's order is `lw, andi 0xf, lbu, sll 8, or,
|
||||
<group 2>, sh, sh`: L2 = 18, L3 = 6, a 13333 tie that q2 wins on number. If the 0x104 store is scheduled inside q2's range
|
||||
(the lever-free default: sched1 puts it right after the first or because the group-2 insns are birthing-boosted,
|
||||
sched.c:2507-2545), then L2 = 20, q3 wins, and w loses v0. That is the residual.
|
||||
- q4 (4 refs, L4 = 16 when the store sits after group 2) against q0 (9 refs, L0 = 50): 0.50 < 0.54, so q0 takes a0 and
|
||||
the lbu gets a1. Fixing the first condition alone turns the v0/v1 residual into an a0/a1 one (score 11,
|
||||
`e3/u16u16_aa.c`: u16 result variables make the ors SUBREG-destination sets that fail `birthing_insn_p`, which moves
|
||||
the store late). L4 cannot drop to 14 without a barrier (the lbu→or load latency queues the lbu behind the `sll`,
|
||||
sched.c:2583-2600), so q4 needs a fifth ref.
|
||||
- **The do-while supplies both.** flow counts a ref at `loop_depth` (2 inside the loop; propagate_block tracks the LOOP notes, flow.c:1440-1449, and mark_used_regs adds `reg_n_refs += loop_depth`, flow.c:2711), so the store's use of a0 makes
|
||||
q4 5 refs: 10/16 = 0.625 > 0.54. The LOOP notes are a full sched barrier (sched.c:2053-2074), so the stores cannot
|
||||
be hoisted into q2's range: L2 = 18. `lsim3` on `scratch/dumps_b9/`: q2 13333, q3 13333, q5 11666, q4 **6250**, q0
|
||||
5400. That is exactly the target assignment. In sched2 the barrier only keeps the stores where the target has them.
|
||||
|
||||
## (c) The move
|
||||
Inline the two packed values into one expression each (`a0 = lbu | ((w & 0xF) << 8)`, so the lbu's destination is set
|
||||
once and stays birthing-boosted, which puts it between `andi` and `sll`) and wrap the two stores in `do { } while (0)`.
|
||||
Each piece is needed. Body_free + the do-while alone scores 10, because `a0` is set twice there, the lbu is not
|
||||
boosted and it is scheduled first.
|
||||
|
||||
## (d) GENERATOR PROPOSAL
|
||||
For a local-alloc permutation where `lsim3` shows the loser short by one ref or by 2 in live length, try (1) a
|
||||
`do { <the store that is the losing quantity's last use> } while (0)`, which doubles that ref (flow loop_depth) and pins
|
||||
the store after everything above it. Also try (2) inlining a two-statement `x = load; x |= y;` into one expression so the load's
|
||||
destination is set once (it becomes birthing-boosted). Score the pair, and each alone. Mark (1) as `!FAKE: do-while`.
|
||||
|
||||
## (e) What did not work (all `--try`, ~1,100 candidates in `scratch/e1`..`e9`)
|
||||
| family | best | why |
|
||||
|---|---|---|
|
||||
| inline / operand order / statement order of the 7 temps (`e1`, 160) | **2** (`u32_a1101_s01_o0.c`, in `body_plain_best.c`) | the second or's result ties to `(w&0xF0)<<4` (q2 13636 > q3), so w gets v0, but the or result lands in v0, not v1 |
|
||||
| variable reuse / compound assignment (`e2`, 256) | 3 | the same tie structures |
|
||||
| u16/s16 result variables (`e3`, 180) | 11 | v0/v1 right, a0/a1 swapped (q4 0.50 < q0 0.54, above) |
|
||||
| extra copies to add refs (`e4`/`e5`, 330) | 3 | cse folds the copies before flow counts the refs |
|
||||
| `const` reads to relax the store→load dependences (`e6`/`e7`) | 2 | RTX_UNCHANGING_P reorders everything (up to 93 worse) |
|
||||
| barrier between `sll` and `lbu` (`e8`) | 9 | the allocation is exactly right, but the barrier survives into sched2, the lbu cannot fill the lw delay slot, +2 nops |
|
||||
|
||||
## (f) Where the method fell short
|
||||
- `lsim3.py` was decisive: every hypothesis was two numbers on its table. It needs a documented home (it lives in
|
||||
another agent's scratch). It should also print each qty's registers' refs, which is how the loop-depth ref showed up.
|
||||
- Nothing in the method says flow's `reg_n_refs` is **weighted by loop depth**, so a `do { } while (0)` changes
|
||||
allocation priorities as well as the schedule. That is a second, independent effect of the same marked construct (d4 used only the barrier).
|
||||
- A two-sided allocation constraint (q2≥q3 AND q4>q0) where every plain-C single move fixes one side and breaks the
|
||||
other is a case for an exhaustive search over the priority arithmetic, not for more spellings.
|
||||
|
||||
- Interpretation (not proven): two stores wrapped in `do { … } while (0)` is the shape of a C statement macro
|
||||
(`#define SET_PAIR(p, a, b) do { … } while (0)`), so this may be the original text rather than a lever. The sibling
|
||||
in 800.c (`local[1] = a1[3].b1 | ((w & 0xF) << 8); local[2] = …`) is lever-free because it sits inside a real
|
||||
`while` loop, which again points to loop depth as the missing fact.
|
||||
|
||||
## (g) Structs answer
|
||||
Unlikely to remove this lever. The deciding quantities are refs and live lengths in local-alloc, plus sched1's
|
||||
placement of the 0x104 store. Struct field access would make the reads and stores `MEM_IN_STRUCT_P`, and they already
|
||||
are (every `*(T *)(p + K)` is a PLUS_EXPR address, expr.c:4568-4577). `true_dependence` (sched.c:817-842) disambiguates
|
||||
only against a fixed address, and both sides here are register-based, so the dependences cannot change. Tested the only
|
||||
aliasing channel that could move the store, `const` (RTX_UNCHANGING_P): it makes things worse. What a struct *could*
|
||||
supply is the original's shape of this block, e.g. a colour struct written through a pointer inside a loop over parts. If
|
||||
the original sits in a real loop, the do-while stands in for real loop depth, and that information lives in the caller's
|
||||
structure, not in a type.
|
||||
|
||||
Files: `body.c` (min-lever text), `body_plain_best.c` (best lever-free text, 2), `scratch/copy_<fn>.c` (5 class copies
|
||||
at 0), `scratch/port.py`, `scratch/an.sh` (dump + lsim3 + sched order for one candidate), `scratch/dumps_b9/` (the close),
|
||||
`scratch/dumps_u16aa/` (the a0/a1 case), `scratch/e1`..`e9` (candidate families with `eN_scores.txt`).
|
||||
@@ -0,0 +1,28 @@
|
||||
void func_8018AD74(s32 p1, s32 p2, s32 p3, s32 p4)
|
||||
{
|
||||
/* [T51] block-scoped decls (house idiom in this TU, cf. func_8018AF88): a file-scope
|
||||
decl of these symbols would constrain every LATER function in the object. */
|
||||
extern Blk20_8018AF88 D_800AE620;
|
||||
extern s32 func_8012C658(s32, s32, s32);
|
||||
extern void RotMatrixY(s32 a0, void *a1);
|
||||
extern void func_800484EC(s32, s32, s32);
|
||||
extern u8 D_801CD468[];
|
||||
|
||||
Blk20_8018AF88 local_30; /* sp+0x10 */
|
||||
Blk20_8018AF88 *m;
|
||||
s32 obj;
|
||||
s32 out[3]; /* sp+0x30, only [0] and [2] used */
|
||||
|
||||
local_30 = D_800AE620;
|
||||
obj = func_8012C658((s16)p2, (s16)p3, p1);
|
||||
do { } while (0); // !FAKE: do-while — its NOTE_INSN_LOOP_END ends cse1's extended block (cse.c:8054), so m below is not folded onto the struct copy's address pseudo (cse.c:846-862) and is set AFTER obj's copy: sched1 then ranks it last by LUID (sched.c:2428) (P36 S104 e5 minimum-lever)
|
||||
m = &local_30;
|
||||
if (obj != 0) {
|
||||
*(u16 *)(obj + 0xA) = *(u16 *)(obj + 0xA) - 0x80;
|
||||
RotMatrixY((s16)p4, m);
|
||||
func_800484EC((s32)m, (s32)&D_801CD468, (s32)out);
|
||||
*(s32 *)(obj + 0x10) = out[0];
|
||||
*(s32 *)(obj + 0x14) = 0xFFD80000;
|
||||
*(s32 *)(obj + 0x18) = out[2];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
# func_8018AD74 (src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c), e5, P36 T7 S104: MINIMUM-LEVER at 0
|
||||
|
||||
**Final: score 0 (60/60 ins, byte-identical).** Lever count 1 → 1, but the kind changes: the tree's `__asm__` launder
|
||||
on `obj` becomes ONE marked empty `do { } while (0);`, which is ordinary C (step 8). No pin, no asm, no volatile. I found no
|
||||
lever-free spelling (below). The move against `body_free.c`:
|
||||
|
||||
- obj = func_8012C658((s16)p2, (s16)p3, p1);
|
||||
- if (obj != 0) {
|
||||
- m = &local_30;
|
||||
+ obj = func_8012C658((s16)p2, (s16)p3, p1);
|
||||
+ do { } while (0); // !FAKE: do-while — …
|
||||
+ m = &local_30;
|
||||
+ if (obj != 0) {
|
||||
|
||||
The class's other copy closes with the same text: **func_80185F4C** (src/ov_SC06_032/ov_SC06_032_jr_80182890.c) scores
|
||||
**0** (`scratch/copy_func_80185F4C.c`).
|
||||
|
||||
## (a) The residual
|
||||
Same count, one instruction in the wrong place. The target is `jal; [move s1,a3]; move s0,v0; beqz s0; [addiu s2,sp,16]`.
|
||||
The free text is `move s1,a3; jal; [addiu s2,sp,16]; move s0,v0; beqz; [sll a0,s1,16]`. The `m = &local_30` address
|
||||
(`addiu s2,sp,16`) sits before the call instead of between the call-result copy and the branch.
|
||||
|
||||
## (b) The pass and the decision (proved on dumps, `scratch/dumps_free/`, `scratch/dumps_tree/`)
|
||||
1. **cse1 hoists `m` into block 0.** `local_30 = D_800AE620` expands through `expand_block_move`, which copies the
|
||||
destination address into a pseudo (`.rtl` insn 17, `reg 78 = fp+16`). `m = &local_30` in the if-body is the same
|
||||
`(plus fp 16)`, so cse finds reg 78 in the table. m's own pseudo is not made the class head (it does not outlive the
|
||||
extended block, `make_regs_eqv`, cse.c:846-862), so every use of m becomes reg 78 and m's set is deleted. The
|
||||
struct copy's own address is folded back to `fp+16`, so reg 78 now exists only to be m. It is set at insn 17, before the call.
|
||||
2. **sched1 ranks it before the call.** At T-2 (just before the branch) the ready list is {17 (reg 78), 35 (`obj = v0`)}.
|
||||
Both are birthing insns, boosted to `max_priority` (`adjust_priority`, sched.c:2507-2545; `birthing_insn_p` needs
|
||||
`reg_n_sets == 1`, :2469-2490). Both are class 3. The tie goes to the higher LUID (`rank_for_schedule`, sched.c:2428),
|
||||
which is 35, so 35 is placed last and 17 falls before the `jal`. reorg then fills the `jal` slot with it.
|
||||
3. **The tree's launder** makes obj's pseudo `reg_n_sets == 2`. 35 is then not a birthing insn (priority 1 against 17's
|
||||
boost), and 17 lands between 35 and the branch (`.sched` of the tree: `T-2: 17 (7f000001) 35 (1), now 17`).
|
||||
|
||||
## (c) The move (minimum lever)
|
||||
Assign `m = &local_30;` in block 0 after the call, behind an empty `do { } while (0);`. The loop's `NOTE_INSN_LOOP_END`
|
||||
ends cse1's extended basic block (`cse_end_of_basic_block`, cse.c:8054). m's `(plus fp 16)` is then never looked up
|
||||
against reg 78. Reg 78 goes dead once the movstr address is folded, and cse deletes it, so cse2 (which ignores the note)
|
||||
has nothing to merge. m keeps its own pseudo, set after 35. At T-2 both are boosted and the LUID tie now picks m's set.
|
||||
It lands between `move s0,v0` and `beqz`, and reorg puts it in the branch delay slot. The note is also a sched barrier
|
||||
(sched.c:2053-2074), but between 35 and m's set that is harmless.
|
||||
Placement matters (all `--try`): the empty loop **between the call and `m =`** scores **0**. `do { m = &local_30; } while (0)`
|
||||
scores 5, because the LOOP_END comes after m and the fold still happens. Wrapping the call scores 7: its LOOP_BEG pins
|
||||
`move s1,a3` before the argument setup and flips the s1/s2 allocation. Wrapping the struct copy scores 21.
|
||||
|
||||
## (d) GENERATOR PROPOSAL
|
||||
When the only residual is an `addiu sK,sp,N` (a local's address) sitting in a `jal` delay slot where the target has it in
|
||||
the following branch's slot, and the source takes that local's address inside the if-body after a struct copy into the
|
||||
same local: hoist `p = &local;` to just before the `if`, behind an empty `do { } while (0);` (marked). The mechanical
|
||||
test: `.cse` shows the address pseudo created by `expand_block_move` standing in for the pointer variable.
|
||||
|
||||
## (e) What did not work (all `--try`)
|
||||
| spelling | score | why |
|
||||
|---|---|---|
|
||||
| body_free (start) | 5 | above |
|
||||
| `&local_30` direct at both calls, no `m` | 5 | same fold onto reg 78 |
|
||||
| `m = &local_30;` before / instead of the struct copy (`*m = D_800AE620`) | 5 / 5 | m is set first, LUID lowest |
|
||||
| `m = &local_30;` between the call and `if`, no loop | 5 | cse1 folds it onto reg 78 again |
|
||||
| `if (obj == 0) return;` form | 5 | the same extended block |
|
||||
| `p1 = func(…, p1)` / `p2 = func(…)` to give obj a second set | 5 / 5 | expand puts the call value in a fresh temp; cse deletes the param copy, so the temp still has `n_sets == 1` |
|
||||
| the sweep's R18/R7 bests | 2 (history) | never below 2 |
|
||||
|
||||
## (f) Where the method fell short
|
||||
- A plausible origin for an EMPTY `do { } while (0)` in 1990s game code is a debug macro compiled out
|
||||
(`#define DPRINTF(...) do { } while (0)`). That is an interpretation, not proven. It would make this text the original
|
||||
rather than a lever, and it is why I prefer it to the asm. Three distinct effects of a do-while(0) are now on record:
|
||||
a sched barrier (d4), a cse1 extended-block end (this one, cse.c:8054), and a loop-depth ref weight (e5's
|
||||
func_80187DD0, flow.c:2711). A generator that inserts `do { } while (0);` at each statement boundary and scores all of
|
||||
them would have found this in about 20 compiles.
|
||||
- The method has the birthing boost (S104 d8) but no rule for **cse moving a variable's definition to another block**
|
||||
by folding it onto an earlier pseudo that holds the same address. That fold is what put `m` in block 0 in the first place.
|
||||
"Read `.cse` for a user variable that vanished" belongs in step 3.
|
||||
- I looked for a plain-C second set of `obj` (a natural `reg_n_sets == 2`) and did not find one. Every reuse of a
|
||||
parameter goes through a call-value temp.
|
||||
|
||||
## (g) Structs answer
|
||||
Struct typing would not remove this lever. The deciding facts are cse's value equivalence of two `(plus fp 16)`
|
||||
computations and sched1's LUID tie. Neither involves memory aliasing (`expr.c:4568-4577` → `sched.c` true_dependence
|
||||
is not on the path: the two contenders are register copies). `local_30` is already a struct. What would matter is the
|
||||
original's **statement placement** (where `&m` is formed) or a second assignment of `obj`, which is information a
|
||||
struct definition does not supply.
|
||||
|
||||
Files: `body.c` (the min-lever text), `scratch/copy_func_80185F4C.c` (SC06_032 copy, 0), `scratch/d/` (do-while
|
||||
placements), `scratch/dumps_free/`, `scratch/dumps_tree/`, `scratch/dumps_v2/`, `scratch/dumps_v7/`.
|
||||
@@ -0,0 +1,35 @@
|
||||
void func_8018B9D4(s32 param_1)
|
||||
{
|
||||
struct { u16 a; u16 b; s16 c; u16 d; } t1;
|
||||
struct { u16 a; u16 b; s16 c; u16 d; } t2;
|
||||
|
||||
func_8018BCC4((void *)param_1, 0, (u16 *)(param_1 + 0xE8), 0x81818);
|
||||
func_8018BCC4((void *)param_1, 1, (u16 *)(param_1 + 0xE8), 0x204040);
|
||||
t1.b = 0;
|
||||
t1.a = 0;
|
||||
t1.c = -*(u16 *)(param_1 + 0xE8);
|
||||
t2.b = 0;
|
||||
t2.a = 0;
|
||||
t2.c = -*(u16 *)(param_1 + 0xEA);
|
||||
if (func_8012DEB8(param_1, &t1, &t2) != 0) {
|
||||
D_80126B96 = 0x4018;
|
||||
D_80126B98 = 0x96;
|
||||
}
|
||||
if (*(s16 *)(param_1 + 0xEA) < *(s16 *)(param_1 + 0xFE)) {
|
||||
*(s16 *)(param_1 + 0xEA) += 0x40;
|
||||
if (*(s16 *)(param_1 + 0xEA) >= *(s16 *)(param_1 + 0xFE)) {
|
||||
*(s16 *)(param_1 + 0xEA) = *(s16 *)(param_1 + 0xFE);
|
||||
func_8018BC40(param_1);
|
||||
}
|
||||
} else {
|
||||
*(s16 *)(param_1 + 0xE8) += 0x40;
|
||||
if (*(s16 *)(param_1 + 0xE8) < *(s16 *)(param_1 + 0xFE)) {
|
||||
return;
|
||||
}
|
||||
if (*(s32 *)(param_1 + 0xCC) != 0) {
|
||||
func_80016714((void *)*(s32 *)(param_1 + 0xCC), 0x38);
|
||||
}
|
||||
*(s32 *)(*(s32 *)(param_1 + 0x64) + 0xD0) = 0;
|
||||
func_8012C218((void *)param_1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
# func_8018B9D4 (src/ov_SC06_018/ov_SC06_018_jr_80187AEC.c), e5, P36 T7 S104: CLOSED at 0, zero levers
|
||||
|
||||
**Final: score 0 (81/81 ins, byte-identical, frame included), plain C.** Lever count 1 → 0 (the `$0` pin), and the
|
||||
`s32 pad[2]` and `r1..r4` keepalives are gone as well. The whole change from `body_free.c`: the `var_ea/var_fe/var_a0/var_v0`
|
||||
temp chain is replaced by direct field arithmetic on memory:
|
||||
|
||||
if (*(s16 *)(param_1 + 0xEA) < *(s16 *)(param_1 + 0xFE)) {
|
||||
*(s16 *)(param_1 + 0xEA) += 0x40;
|
||||
if (*(s16 *)(param_1 + 0xEA) >= *(s16 *)(param_1 + 0xFE)) { ... }
|
||||
} else {
|
||||
*(s16 *)(param_1 + 0xE8) += 0x40;
|
||||
if (*(s16 *)(param_1 + 0xE8) < *(s16 *)(param_1 + 0xFE)) return;
|
||||
...
|
||||
|
||||
The class's other copy closes with the same text (callees renamed): **func_80186BAC**
|
||||
(src/ov_SC06_032/ov_SC06_032_jr_80182890.c) scores **0** (`scratch/copy_func_80186BAC.c`).
|
||||
|
||||
## (a) The residual
|
||||
Same count (81/81). The target has `lh v0,234(s1); lh v1,254(s1); move a0,v0; slt v0,v0,v1; beqz; addiu v0,a0,64`. The
|
||||
lever-free text has `lh v1; lh v0; nop; slt v0,v1,v0; addiu v0,v1,64`. The target keeps a **copy** of the loaded 0xEA value
|
||||
(`move a0,v0`) that lives past the compare. The free text has no copy, and the compare and the add read one register.
|
||||
|
||||
## (b) The pass and the decision (proved on dumps, `scratch/dumps_n2e/`, `dumps_c1/`, `dumps_c5/`)
|
||||
The copy comes from **combine's narrow-load split**, `combine.c:1887-1940`: when a 3-insn combination builds
|
||||
`(parallel [(set A (sign_extend (mem:HI))) (set P (mem:HI))])` because the narrow load's destination P is still
|
||||
needed, combine splits it into `A = sign_extend(mem)` (= `lh`) plus `P:HI = (subreg:HI A)`, a register copy.
|
||||
- P is still needed because `*(s16 *)(p+0xEA) += 0x40` re-reads the halfword, and cse1 forwards that read to the
|
||||
HImode load pseudo P (`.cse` insn 104: `(plus:SI (subreg:SI (reg:HI 83)) 64)`). So P has two readers: the extension
|
||||
for the compare, and the add.
|
||||
- `.combine` insns 92/93: `(set (reg:SI 85) (sign_extend:SI (mem:HI …234)))` and `(set (reg:HI 83) (subreg:HI (reg:SI 85) 0))`.
|
||||
- The copy's source is a **SUBREG**, so local-alloc's `optimize_reg_copy_1` does not touch it. That function rewrites a
|
||||
later use of the source onto the copy so the two can be tied, and it is only called for `GET_CODE (SET_SRC) == REG`
|
||||
(`local-alloc.c:1003-1007`). A85 dies at the `slt` and not at the copy, so `combine_regs` cannot tie them either →
|
||||
two registers → `move a0,v0`.
|
||||
|
||||
Why each temp spelling fails (bytes + dumps):
|
||||
- `var_a0 = var_ea` (s32): a REG-REG copy. cse canonicalises it onto var_ea and deletes it.
|
||||
- `var_a0 = (s16)var_ea` (`c1`): cse keeps the re-extension, combine reduces it to `(set 79 77)` (sign-bit copies), and then
|
||||
**local-alloc's `optimize_reg_copy_1` rewrites the `slt` to read 79** (`.lreg` insn 103) and ties them. Score 5.
|
||||
- `s16 var_a0; var_a0 = var_ea` (`c5`): a SUBREG copy, but cse `fold_rtx` SUBREG case (paradoxical subreg of a reg
|
||||
equivalent to a lowpart subreg → the inner reg) folds the add's `(subreg:SI (reg:HI 79))` back to 77. The copy dies. Score 5.
|
||||
- So the copy has to be created **after** cse by combine, and with a SUBREG source. That is the 1887 split, and only
|
||||
a second READ of the same halfword creates it. A temp chain never does.
|
||||
|
||||
## (c) The move
|
||||
Spell the field update as the original almost certainly wrote it, `*(s16 *)(p + 0xEA) += 0x40;`, and re-read the field
|
||||
in the following test instead of reusing a temp: `if (*(s16 *)(p + 0xEA) >= …)`. The else arm takes the same spelling on
|
||||
0xE8 (`+= 0x40` as `s16` or `u16`, both 0). The re-read after the store is forwarded by cse (store-to-load), and
|
||||
the target's `sll/sra` of the stored value is exactly that forwarded extension. The frame also came out right with no
|
||||
pad: `.frame vars=32` in both.
|
||||
|
||||
## (d) GENERATOR PROPOSAL
|
||||
When the target keeps a `move rX,rY` right after an `lh rY` (or `lb`) and rX is used later only in an `addiu`/`sh` back
|
||||
to the same field, rewrite the decompiler's temp chain `t = *(s16 *)(p+K); u = t; if (t < …) { v = u + C; *(s16 *)(p+K) = v;
|
||||
if ((v << 16) >> 16 …` as `if (*(s16 *)(p+K) < …) { *(s16 *)(p+K) += C; if (*(s16 *)(p+K) …`. That is, **collapse the temps into
|
||||
compound assignment on the memory lvalue and re-read the field at each test**. The tell is mechanical: a `move` whose
|
||||
source was just loaded by `lh`/`lb` and which the text spells with a `+ zr` / `$0` pin or a launder.
|
||||
|
||||
## (e) What did not work (all `--try`)
|
||||
| spelling | score |
|
||||
|---|---|
|
||||
| body_free (start) | 5 |
|
||||
| all 81 width combinations of var_ea/var_fe/var_a0/var_v0 ∈ {s32,s16,u16} (`scratch/w/`) | best 4 (`u16 var_a0`: copy kept but an extra `andi 0xffff`) |
|
||||
| `var_a0 = (s16)var_ea` | 5 (optimize_reg_copy_1 ties it, above) |
|
||||
| `var_ea` kept, `var_v0 = var_ea + 0x40`, `(s16)var_v0` test | 5 |
|
||||
| `+= 0x40` text but with `pad[2]` kept | 8 (the frame is 8 bytes too big, the body is identical) |
|
||||
| `+= 0x40` text, pad and `r1..r4` deleted | **0** |
|
||||
|
||||
## (f) Where the method fell short
|
||||
- Counting said "same count, one `nop` vs `move`": that is a copy the target keeps. Step 3's listed causes are all
|
||||
about copies that **cse** deletes (R20/R21 width or distance). This one is deleted by **local-alloc
|
||||
`optimize_reg_copy_1`** (`local-alloc.c:700`, caller `:1003`), a pass the method never names. Worth a line in step 3:
|
||||
"a copy that survives cse and combine can still be folded by optimize_reg_copy_1 when its source is a REG that dies
|
||||
later in the same block with no jump in between; a SUBREG-source copy (combine.c:1887 split) is exempt."
|
||||
- The pad and the keepalives were part of the lever: the temp spelling needed a `pad[2]` to make the frame right. A
|
||||
close that deletes the temps has to delete the pad too. Otherwise it scores 8 and looks worse than the start.
|
||||
- No generator reaches "replace a temp chain with a compound assignment on the lvalue". R6 (inline) inlines one temp
|
||||
at a time, and the first step alone does not create the second read.
|
||||
|
||||
## (g) Structs answer
|
||||
A struct would help the READABILITY, not the decision: `e->ea += 0x40; if (e->ea >= e->fe)` gives the same RTL as the
|
||||
cast spelling (the field reads are `mem:HI` either way). The deciding facts are the second read of the same `s16`
|
||||
location, the combine split and the SUBREG copy, and none of them involve aliasing. The struct is the natural way to
|
||||
write the re-read, and that is likely why the original has it. Not tested separately. The cast text already closes.
|
||||
|
||||
Files: `body.c` (the closed text), `scratch/copy_func_80186BAC.c` (the SC06_032 copy, 0), dumps in `scratch/dumps_n2e/`
|
||||
(close), `scratch/dumps_c1/` and `scratch/dumps_c5/` (the two refuted copy spellings), `scratch/w/` (the width sweep).
|
||||
+179
-179
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"head": "b591697b8",
|
||||
"head": "a1a0a80e2",
|
||||
"stamp": "15956e4a96c4",
|
||||
"generated": "2026-09-11 01:50",
|
||||
"generated": "2026-09-11 01:54",
|
||||
"aliases": [
|
||||
"main",
|
||||
"ov_SC03_014",
|
||||
@@ -21,206 +21,206 @@
|
||||
"main": {
|
||||
"objects": 85,
|
||||
"identical": 85,
|
||||
"seconds": 6.521999999999999,
|
||||
"mean_s": 0.077
|
||||
"seconds": 6.381999999999998,
|
||||
"mean_s": 0.075
|
||||
},
|
||||
"ov_SC03_014": {
|
||||
"objects": 32,
|
||||
"identical": 32,
|
||||
"seconds": 4.517,
|
||||
"mean_s": 0.141
|
||||
"seconds": 4.442,
|
||||
"mean_s": 0.139
|
||||
},
|
||||
"ov_SC03_015": {
|
||||
"objects": 32,
|
||||
"identical": 32,
|
||||
"seconds": 4.3549999999999995,
|
||||
"mean_s": 0.136
|
||||
"seconds": 4.295999999999999,
|
||||
"mean_s": 0.134
|
||||
},
|
||||
"ov_SC04_011": {
|
||||
"objects": 28,
|
||||
"identical": 28,
|
||||
"seconds": 3.813,
|
||||
"mean_s": 0.136
|
||||
"seconds": 3.727,
|
||||
"mean_s": 0.133
|
||||
}
|
||||
},
|
||||
"per_object_seconds": {
|
||||
"build/src/800.o": 0.699,
|
||||
"build/src/800_b.o": 0.071,
|
||||
"build/src/800_b_2.o": 0.304,
|
||||
"build/src/800_b_o0a.o": 0.081,
|
||||
"build/src/800_c.o": 0.183,
|
||||
"build/src/800b2.o": 0.073,
|
||||
"build/src/apicard1.o": 0.068,
|
||||
"build/src/apicard2.o": 0.064,
|
||||
"build/src/apicard3.o": 0.063,
|
||||
"build/src/apicard4.o": 0.088,
|
||||
"build/src/apicard5.o": 0.062,
|
||||
"build/src/apicard6.o": 0.087,
|
||||
"build/src/apicard7.o": 0.062,
|
||||
"build/src/boot.o": 0.104,
|
||||
"build/src/gap.o": 0.074,
|
||||
"build/src/libapi1.o": 0.081,
|
||||
"build/src/libapi2.o": 0.057,
|
||||
"build/src/libc2_1.o": 0.06,
|
||||
"build/src/libc2_2.o": 0.058,
|
||||
"build/src/libcd1.o": 0.064,
|
||||
"build/src/libcd2.o": 0.058,
|
||||
"build/src/libetc.o": 0.066,
|
||||
"build/src/libgpu.o": 0.059,
|
||||
"build/src/libgpu2.o": 0.077,
|
||||
"build/src/libgs1.o": 0.048,
|
||||
"build/src/libgs2.o": 0.061,
|
||||
"build/src/libgs3.o": 0.059,
|
||||
"build/src/libgs4.o": 0.061,
|
||||
"build/src/libgs5.o": 0.061,
|
||||
"build/src/libgs6.o": 0.068,
|
||||
"build/src/800.o": 0.711,
|
||||
"build/src/800_b.o": 0.078,
|
||||
"build/src/800_b_2.o": 0.277,
|
||||
"build/src/800_b_o0a.o": 0.064,
|
||||
"build/src/800_c.o": 0.189,
|
||||
"build/src/800b2.o": 0.075,
|
||||
"build/src/apicard1.o": 0.061,
|
||||
"build/src/apicard2.o": 0.072,
|
||||
"build/src/apicard3.o": 0.065,
|
||||
"build/src/apicard4.o": 0.08,
|
||||
"build/src/apicard5.o": 0.065,
|
||||
"build/src/apicard6.o": 0.081,
|
||||
"build/src/apicard7.o": 0.063,
|
||||
"build/src/boot.o": 0.08,
|
||||
"build/src/gap.o": 0.067,
|
||||
"build/src/libapi1.o": 0.068,
|
||||
"build/src/libapi2.o": 0.055,
|
||||
"build/src/libc2_1.o": 0.058,
|
||||
"build/src/libc2_2.o": 0.055,
|
||||
"build/src/libcd1.o": 0.066,
|
||||
"build/src/libcd2.o": 0.057,
|
||||
"build/src/libetc.o": 0.061,
|
||||
"build/src/libgpu.o": 0.057,
|
||||
"build/src/libgpu2.o": 0.064,
|
||||
"build/src/libgs1.o": 0.058,
|
||||
"build/src/libgs2.o": 0.057,
|
||||
"build/src/libgs3.o": 0.064,
|
||||
"build/src/libgs4.o": 0.069,
|
||||
"build/src/libgs5.o": 0.053,
|
||||
"build/src/libgs6.o": 0.075,
|
||||
"build/src/libgs7.o": 0.061,
|
||||
"build/src/libgs8.o": 0.061,
|
||||
"build/src/libgte1.o": 0.063,
|
||||
"build/src/libgte10.o": 0.063,
|
||||
"build/src/libgs8.o": 0.057,
|
||||
"build/src/libgte1.o": 0.065,
|
||||
"build/src/libgte10.o": 0.062,
|
||||
"build/src/libgte11.o": 0.061,
|
||||
"build/src/libgte12.o": 0.058,
|
||||
"build/src/libgte12.o": 0.062,
|
||||
"build/src/libgte13.o": 0.064,
|
||||
"build/src/libgte14.o": 0.069,
|
||||
"build/src/libgte15.o": 0.05,
|
||||
"build/src/libgte16.o": 0.057,
|
||||
"build/src/libgte17.o": 0.07,
|
||||
"build/src/libgte18.o": 0.061,
|
||||
"build/src/libgte19.o": 0.059,
|
||||
"build/src/libgte2.o": 0.064,
|
||||
"build/src/libgte20.o": 0.063,
|
||||
"build/src/libgte21.o": 0.061,
|
||||
"build/src/libgte22.o": 0.053,
|
||||
"build/src/libgte23.o": 0.057,
|
||||
"build/src/libgte24.o": 0.064,
|
||||
"build/src/libgte25.o": 0.059,
|
||||
"build/src/libgte26.o": 0.063,
|
||||
"build/src/libgte27.o": 0.067,
|
||||
"build/src/libgte28.o": 0.053,
|
||||
"build/src/libgte29.o": 0.06,
|
||||
"build/src/libgte3.o": 0.059,
|
||||
"build/src/libgte30.o": 0.06,
|
||||
"build/src/libgte4.o": 0.061,
|
||||
"build/src/libgte5.o": 0.063,
|
||||
"build/src/libgte6.o": 0.062,
|
||||
"build/src/libgte7.o": 0.069,
|
||||
"build/src/libgte8.o": 0.061,
|
||||
"build/src/libgte9.o": 0.069,
|
||||
"build/src/libmcrd1.o": 0.071,
|
||||
"build/src/libmcrd2.o": 0.064,
|
||||
"build/src/libpad1.o": 0.06,
|
||||
"build/src/libpad2.o": 0.075,
|
||||
"build/src/sgap.o": 0.067,
|
||||
"build/src/sgap_2.o": 0.062,
|
||||
"build/src/libgte14.o": 0.063,
|
||||
"build/src/libgte15.o": 0.062,
|
||||
"build/src/libgte16.o": 0.054,
|
||||
"build/src/libgte17.o": 0.061,
|
||||
"build/src/libgte18.o": 0.063,
|
||||
"build/src/libgte19.o": 0.058,
|
||||
"build/src/libgte2.o": 0.059,
|
||||
"build/src/libgte20.o": 0.068,
|
||||
"build/src/libgte21.o": 0.058,
|
||||
"build/src/libgte22.o": 0.063,
|
||||
"build/src/libgte23.o": 0.054,
|
||||
"build/src/libgte24.o": 0.077,
|
||||
"build/src/libgte25.o": 0.079,
|
||||
"build/src/libgte26.o": 0.055,
|
||||
"build/src/libgte27.o": 0.061,
|
||||
"build/src/libgte28.o": 0.052,
|
||||
"build/src/libgte29.o": 0.049,
|
||||
"build/src/libgte3.o": 0.063,
|
||||
"build/src/libgte30.o": 0.069,
|
||||
"build/src/libgte4.o": 0.055,
|
||||
"build/src/libgte5.o": 0.059,
|
||||
"build/src/libgte6.o": 0.064,
|
||||
"build/src/libgte7.o": 0.063,
|
||||
"build/src/libgte8.o": 0.06,
|
||||
"build/src/libgte9.o": 0.059,
|
||||
"build/src/libmcrd1.o": 0.073,
|
||||
"build/src/libmcrd2.o": 0.061,
|
||||
"build/src/libpad1.o": 0.065,
|
||||
"build/src/libpad2.o": 0.056,
|
||||
"build/src/sgap.o": 0.061,
|
||||
"build/src/sgap_2.o": 0.064,
|
||||
"build/src/sgap_3.o": 0.064,
|
||||
"build/src/sgap_4.o": 0.073,
|
||||
"build/src/sgap_5.o": 0.064,
|
||||
"build/src/sgap_6.o": 0.07,
|
||||
"build/src/sgap_8.o": 0.072,
|
||||
"build/src/snd1.o": 0.072,
|
||||
"build/src/snd10.o": 0.061,
|
||||
"build/src/snd11.o": 0.055,
|
||||
"build/src/snd12.o": 0.067,
|
||||
"build/src/snd2.o": 0.071,
|
||||
"build/src/snd3.o": 0.064,
|
||||
"build/src/snd4.o": 0.061,
|
||||
"build/src/snd5.o": 0.072,
|
||||
"build/src/snd6.o": 0.071,
|
||||
"build/src/snd7.o": 0.066,
|
||||
"build/src/snd8.o": 0.065,
|
||||
"build/src/snd9.o": 0.069,
|
||||
"build/src/ov_SC03_014/ov_SC03_014.o": 0.125,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_after.o": 0.5,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.388,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.065,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.057,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.117,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.148,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.129,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.075,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.066,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.174,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.07,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.188,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.097,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.061,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.075,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.089,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.441,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.261,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.094,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.182,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.054,
|
||||
"build/src/sgap_4.o": 0.082,
|
||||
"build/src/sgap_5.o": 0.062,
|
||||
"build/src/sgap_6.o": 0.062,
|
||||
"build/src/sgap_8.o": 0.07,
|
||||
"build/src/snd1.o": 0.064,
|
||||
"build/src/snd10.o": 0.063,
|
||||
"build/src/snd11.o": 0.069,
|
||||
"build/src/snd12.o": 0.059,
|
||||
"build/src/snd2.o": 0.065,
|
||||
"build/src/snd3.o": 0.059,
|
||||
"build/src/snd4.o": 0.059,
|
||||
"build/src/snd5.o": 0.068,
|
||||
"build/src/snd6.o": 0.068,
|
||||
"build/src/snd7.o": 0.063,
|
||||
"build/src/snd8.o": 0.06,
|
||||
"build/src/snd9.o": 0.06,
|
||||
"build/src/ov_SC03_014/ov_SC03_014.o": 0.128,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_after.o": 0.499,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8012ACE0.o": 0.38,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80135888.o": 0.072,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80135A4C.o": 0.058,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80135D20.o": 0.116,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801380E0.o": 0.15,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8013C98C.o": 0.112,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8013F350.o": 0.077,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8013FFD8.o": 0.067,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80140608.o": 0.196,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015444C.o": 0.072,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80154C24.o": 0.169,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801588CC.o": 0.093,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80159C84.o": 0.064,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015A3C8.o": 0.073,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015AE2C.o": 0.091,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8015C32C.o": 0.427,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8016AB6C.o": 0.25,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80171B4C.o": 0.091,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801734BC.o": 0.183,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801789AC.o": 0.053,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80178D40.o": 0.095,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.065,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.153,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.19,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.048,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.276,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.056,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8017A4AC.o": 0.061,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8017AE2C.o": 0.15,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.o": 0.184,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_80184440.o": 0.044,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_jr_801848E4.o": 0.266,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0b.o": 0.05,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0c.o": 0.057,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.057,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.064,
|
||||
"build/src/ov_SC03_015/ov_SC03_015.o": 0.118,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_after.o": 0.518,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.369,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.051,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.051,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.122,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.143,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.112,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.076,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.063,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.166,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.068,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.163,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.084,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.067,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.07,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.094,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.421,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.254,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.094,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.181,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.056,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.099,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.056,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.156,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.165,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.05,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.257,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.05,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.059,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.055,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.067,
|
||||
"build/src/ov_SC04_011/ov_SC04_011.o": 0.123,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_after.o": 0.415,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.332,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.055,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.048,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.105,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.153,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.104,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.072,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.059,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.168,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.074,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0d.o": 0.048,
|
||||
"build/src/ov_SC03_014/ov_SC03_014_o0e.o": 0.066,
|
||||
"build/src/ov_SC03_015/ov_SC03_015.o": 0.119,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_after.o": 0.472,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8012ACE0.o": 0.345,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80135888.o": 0.045,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80135A4C.o": 0.054,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80135D20.o": 0.121,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801380E0.o": 0.134,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8013C98C.o": 0.103,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8013F350.o": 0.063,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8013FFD8.o": 0.059,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80140608.o": 0.151,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015444C.o": 0.063,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80154C24.o": 0.165,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801588CC.o": 0.088,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80159C84.o": 0.063,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015A3C8.o": 0.062,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015AE2C.o": 0.09,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8015C32C.o": 0.435,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8016AB6C.o": 0.253,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80171B4C.o": 0.1,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801734BC.o": 0.191,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801789AC.o": 0.052,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80178D40.o": 0.097,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8017A4AC.o": 0.062,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8017AE2C.o": 0.157,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_8017EB7C.o": 0.191,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_80184440.o": 0.052,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_jr_801848E4.o": 0.268,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0b.o": 0.06,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0c.o": 0.053,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0d.o": 0.057,
|
||||
"build/src/ov_SC03_015/ov_SC03_015_o0e.o": 0.071,
|
||||
"build/src/ov_SC04_011/ov_SC04_011.o": 0.127,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_after.o": 0.411,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8012ACE0.o": 0.326,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80135888.o": 0.046,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80135A4C.o": 0.053,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80135D20.o": 0.102,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801380E0.o": 0.148,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8013C98C.o": 0.106,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8013F350.o": 0.069,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8013FFD8.o": 0.051,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80140608.o": 0.165,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015444C.o": 0.063,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80154C24.o": 0.152,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801588CC.o": 0.087,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.064,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.061,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.093,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.377,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.215,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.098,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.156,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.056,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.081,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.063,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.093,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.406,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.051,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.052
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80159C84.o": 0.065,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015A3C8.o": 0.063,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015AE2C.o": 0.095,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8015C32C.o": 0.335,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8016AB6C.o": 0.217,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80171B4C.o": 0.087,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801734BC.o": 0.155,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_801789AC.o": 0.055,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_80178D40.o": 0.086,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8017A4AC.o": 0.061,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8017AE2C.o": 0.105,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_jr_8017D494.o": 0.404,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_o0b.o": 0.044,
|
||||
"build/src/ov_SC04_011/ov_SC04_011_o0c.o": 0.049
|
||||
},
|
||||
"ok": true,
|
||||
"seconds": 2.2
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5386,9 +5386,9 @@ void func_8018AD74(s32 p1, s32 p2, s32 p3, s32 p4)
|
||||
|
||||
local_30 = D_800AE620;
|
||||
obj = func_8012C658((s16)p2, (s16)p3, p1);
|
||||
do { } while (0); // !FAKE: do-while — its NOTE_INSN_LOOP_END ends cse1's extended block (cse.c:8054), so m below is not folded onto the struct copy's address pseudo (cse.c:846-862) and is set AFTER obj's copy: sched1 then ranks it last by LUID (sched.c:2428) (P36 S104 e5 minimum-lever)
|
||||
m = &local_30;
|
||||
if (obj != 0) {
|
||||
__asm__("" : "=r"(obj) : "0"(obj)); /* §350 birthing-boost kill; 0 bytes */ // !FAKE: launder — NEEDED DIFFERS (P36 rung B tus9)
|
||||
m = &local_30;
|
||||
*(u16 *)(obj + 0xA) = *(u16 *)(obj + 0xA) - 0x80;
|
||||
RotMatrixY((s16)p4, m);
|
||||
func_800484EC((s32)m, (s32)&D_801CD468, (s32)out);
|
||||
|
||||
Reference in New Issue
Block a user