@@ -320,13 +320,129 @@ bool redundant_move_elim(ph2_ir_t *ph2_ir)
320
320
return false;
321
321
}
322
322
323
+ /* Simple dead instruction elimination within basic blocks.
324
+ * Removes instructions whose results are never used (dead stores).
325
+ * Works in conjunction with existing SSA-based DCE.
326
+ */
327
+ bool eliminate_dead_instructions (func_t * func )
328
+ {
329
+ if (!func || !func -> bbs )
330
+ return false;
331
+
332
+ bool changed = false;
333
+
334
+ for (basic_block_t * bb = func -> bbs ; bb ; bb = bb -> rpo_next ) {
335
+ ph2_ir_t * ir = bb -> ph2_ir_list .head ;
336
+ while (ir && ir -> next ) {
337
+ ph2_ir_t * next = ir -> next ;
338
+
339
+ /* Check if next instruction immediately overwrites this one's
340
+ * result */
341
+ if (ir -> op == OP_load_constant && next -> op == OP_load_constant &&
342
+ ir -> dest == next -> dest ) {
343
+ /* Consecutive constant loads to same register - first is dead
344
+ */
345
+ ir -> next = next -> next ;
346
+ if (next == bb -> ph2_ir_list .tail ) {
347
+ bb -> ph2_ir_list .tail = ir ;
348
+ }
349
+ changed = true;
350
+ continue ;
351
+ }
352
+
353
+ /* Check for dead arithmetic results */
354
+ if ((ir -> op == OP_add || ir -> op == OP_sub || ir -> op == OP_mul ) &&
355
+ next -> op == OP_assign && ir -> dest == next -> dest ) {
356
+ /* Arithmetic result immediately overwritten by assignment */
357
+ ir -> next = next -> next ;
358
+ if (next == bb -> ph2_ir_list .tail ) {
359
+ bb -> ph2_ir_list .tail = ir ;
360
+ }
361
+ changed = true;
362
+ continue ;
363
+ }
364
+
365
+ ir = ir -> next ;
366
+ }
367
+ }
368
+
369
+ return changed ;
370
+ }
371
+
372
+ /* Simple constant folding for branches after SCCP.
373
+ * Converts branches with obvious constant conditions to jumps.
374
+ * Very conservative to maintain bootstrap stability.
375
+ */
376
+ bool fold_constant_branches (func_t * func )
377
+ {
378
+ if (!func || !func -> bbs )
379
+ return false;
380
+
381
+ bool changed = false;
382
+
383
+ for (basic_block_t * bb = func -> bbs ; bb ; bb = bb -> rpo_next ) {
384
+ if (!bb -> ph2_ir_list .tail )
385
+ continue ;
386
+
387
+ ph2_ir_t * last = bb -> ph2_ir_list .tail ;
388
+
389
+ /* Only handle branches */
390
+ if (last -> op != OP_branch || last -> src0 < 0 )
391
+ continue ;
392
+
393
+ /* Look for immediately preceding constant load to the same register */
394
+ ph2_ir_t * prev = bb -> ph2_ir_list .head ;
395
+ ph2_ir_t * found = NULL ;
396
+
397
+ /* Find the most recent constant load to the branch condition register
398
+ */
399
+ while (prev && prev != last ) {
400
+ if (prev -> op == OP_load_constant && prev -> dest == last -> src0 ) {
401
+ found = prev ;
402
+ /* Keep looking - want the most recent load */
403
+ }
404
+ /* Stop if we see any other write to this register */
405
+ else if (prev -> dest == last -> src0 ) {
406
+ found = NULL ; /* Register was modified, can't fold */
407
+ }
408
+ prev = prev -> next ;
409
+ }
410
+
411
+ if (found ) {
412
+ /* Found constant condition - convert branch to jump */
413
+ int const_val = found -> src0 ;
414
+
415
+ /* Just change the opcode, don't modify CFG edges directly */
416
+ last -> op = OP_jump ;
417
+
418
+ if (const_val != 0 ) {
419
+ /* Always take then branch */
420
+ last -> next_bb = bb -> then_ ;
421
+ } else {
422
+ /* Always take else branch */
423
+ last -> next_bb = bb -> else_ ;
424
+ }
425
+
426
+ /* Don't modify src0 or CFG edges - let later passes handle it */
427
+ changed = true;
428
+ }
429
+ }
430
+
431
+ return changed ;
432
+ }
433
+
323
434
/* Main peephole optimization driver.
324
435
* It iterates through all functions, basic blocks, and IR instructions to apply
325
436
* local optimizations on adjacent instruction pairs.
326
437
*/
327
438
void peephole (void )
328
439
{
329
440
for (func_t * func = FUNC_LIST .head ; func ; func = func -> next ) {
441
+ /* Phase 1: Dead code elimination working with SCCP results */
442
+ eliminate_dead_instructions (func );
443
+ fold_constant_branches (func );
444
+
445
+ /* Phase 2: Local peephole optimizations */
330
446
for (basic_block_t * bb = func -> bbs ; bb ; bb = bb -> rpo_next ) {
331
447
for (ph2_ir_t * ir = bb -> ph2_ir_list .head ; ir ; ir = ir -> next ) {
332
448
ph2_ir_t * next = ir -> next ;
0 commit comments