@@ -1866,6 +1866,19 @@ bool eval_algebraic(insn_t *insn)
18661866 insn -> rs2 = NULL ;
18671867 return true;
18681868 }
1869+ /* x * -1 = -x */
1870+ if (insn -> rs2 && insn -> rs2 -> is_const && insn -> rs2 -> init_val == -1 ) {
1871+ insn -> opcode = OP_negate ;
1872+ insn -> rs2 = NULL ;
1873+ return true;
1874+ }
1875+ /* -1 * x = -x */
1876+ if (insn -> rs1 && insn -> rs1 -> is_const && insn -> rs1 -> init_val == -1 ) {
1877+ insn -> opcode = OP_negate ;
1878+ insn -> rs1 = insn -> rs2 ;
1879+ insn -> rs2 = NULL ;
1880+ return true;
1881+ }
18691882 /* Strength reduction: x * power-of-2 → x << shift */
18701883 if (insn -> rs2 && insn -> rs2 -> is_const ) {
18711884 int val = insn -> rs2 -> init_val ;
@@ -2501,39 +2514,16 @@ void optimize(void)
25012514 }
25022515 }
25032516
2504- /* Self-operation optimizations at SSA level */
2505- /* These patterns must be handled at SSA level for correct
2506- * self-hosting despite some duplication with peephole optimizer
2517+ /* SSA-specific self-operation optimizations */
2518+ /* Only handle patterns that peephole doesn't cover effectively:
2519+ * - Comparison operations (not in peephole)
2520+ * - Division/modulo (not in peephole)
2521+ * Note: Basic arithmetic (sub, xor, and, or) are handled by
2522+ * peephole after register allocation for better efficiency.
25072523 */
25082524 if (insn -> rs1 && insn -> rs2 && insn -> rs1 == insn -> rs2 ) {
2509- /* x - x = 0 */
2510- if (insn -> opcode == OP_sub && insn -> rd ) {
2511- insn -> opcode = OP_load_constant ;
2512- insn -> rd -> is_const = true;
2513- insn -> rd -> init_val = 0 ;
2514- insn -> rs1 = NULL ;
2515- insn -> rs2 = NULL ;
2516- }
2517- /* x ^ x = 0 */
2518- else if (insn -> opcode == OP_bit_xor && insn -> rd ) {
2519- insn -> opcode = OP_load_constant ;
2520- insn -> rd -> is_const = true;
2521- insn -> rd -> init_val = 0 ;
2522- insn -> rs1 = NULL ;
2523- insn -> rs2 = NULL ;
2524- }
2525- /* x & x = x */
2526- else if (insn -> opcode == OP_bit_and && insn -> rd ) {
2527- insn -> opcode = OP_assign ;
2528- insn -> rs2 = NULL ;
2529- }
2530- /* x | x = x */
2531- else if (insn -> opcode == OP_bit_or && insn -> rd ) {
2532- insn -> opcode = OP_assign ;
2533- insn -> rs2 = NULL ;
2534- }
2535- /* x / x = 1 (if x != 0) */
2536- else if (insn -> opcode == OP_div && insn -> rd ) {
2525+ /* x / x = 1 (assuming x != 0) */
2526+ if (insn -> opcode == OP_div && insn -> rd ) {
25372527 insn -> opcode = OP_load_constant ;
25382528 insn -> rd -> is_const = true;
25392529 insn -> rd -> init_val = 1 ;
@@ -2548,35 +2538,34 @@ void optimize(void)
25482538 insn -> rs1 = NULL ;
25492539 insn -> rs2 = NULL ;
25502540 }
2551- /* x == x = 1 */
2541+ /* Comparison self-operations */
25522542 else if (insn -> opcode == OP_eq && insn -> rd ) {
2543+ /* x == x = 1 */
25532544 insn -> opcode = OP_load_constant ;
25542545 insn -> rd -> is_const = true;
25552546 insn -> rd -> init_val = 1 ;
25562547 insn -> rs1 = NULL ;
25572548 insn -> rs2 = NULL ;
2558- }
2559- /* x != x = 0 */
2560- else if (insn -> opcode == OP_neq && insn -> rd ) {
2549+ } else if (insn -> opcode == OP_neq && insn -> rd ) {
2550+ /* x != x = 0 */
25612551 insn -> opcode = OP_load_constant ;
25622552 insn -> rd -> is_const = true;
25632553 insn -> rd -> init_val = 0 ;
25642554 insn -> rs1 = NULL ;
25652555 insn -> rs2 = NULL ;
2566- }
2567- /* x < x = 0, x > x = 0 */
2568- else if (( insn -> opcode == OP_lt || insn -> opcode == OP_gt ) &&
2569- insn -> rd ) {
2556+ } else if (( insn -> opcode == OP_lt ||
2557+ insn -> opcode == OP_gt ) &&
2558+ insn -> rd ) {
2559+ /* x < x = 0, x > x = 0 */
25702560 insn -> opcode = OP_load_constant ;
25712561 insn -> rd -> is_const = true;
25722562 insn -> rd -> init_val = 0 ;
25732563 insn -> rs1 = NULL ;
25742564 insn -> rs2 = NULL ;
2575- }
2576- /* x <= x = 1, x >= x = 1 */
2577- else if ((insn -> opcode == OP_leq ||
2578- insn -> opcode == OP_geq ) &&
2579- insn -> rd ) {
2565+ } else if ((insn -> opcode == OP_leq ||
2566+ insn -> opcode == OP_geq ) &&
2567+ insn -> rd ) {
2568+ /* x <= x = 1, x >= x = 1 */
25802569 insn -> opcode = OP_load_constant ;
25812570 insn -> rd -> is_const = true;
25822571 insn -> rd -> init_val = 1 ;
@@ -2585,107 +2574,9 @@ void optimize(void)
25852574 }
25862575 }
25872576
2588- /* Comprehensive algebraic simplifications with identity
2589- * operations */
2590- if (insn -> rs2 && insn -> rs2 -> is_const && insn -> rd ) {
2591- int val = insn -> rs2 -> init_val ;
2592-
2593- /* x + 0 = x, x - 0 = x, x | 0 = x, x ^ 0 = x */
2594- if (val == 0 ) {
2595- if (insn -> opcode == OP_add || insn -> opcode == OP_sub ||
2596- insn -> opcode == OP_bit_or ||
2597- insn -> opcode == OP_bit_xor ) {
2598- insn -> opcode = OP_assign ;
2599- insn -> rs2 = NULL ;
2600- }
2601- /* x * 0 = 0, x & 0 = 0 */
2602- else if (insn -> opcode == OP_mul ||
2603- insn -> opcode == OP_bit_and ) {
2604- insn -> opcode = OP_load_constant ;
2605- insn -> rd -> is_const = true;
2606- insn -> rd -> init_val = 0 ;
2607- insn -> rs1 = NULL ;
2608- insn -> rs2 = NULL ;
2609- }
2610- /* x << 0 = x, x >> 0 = x */
2611- else if (insn -> opcode == OP_lshift ||
2612- insn -> opcode == OP_rshift ) {
2613- insn -> opcode = OP_assign ;
2614- insn -> rs2 = NULL ;
2615- }
2616- }
2617- /* x * 1 = x, x / 1 = x */
2618- else if (val == 1 ) {
2619- if (insn -> opcode == OP_mul || insn -> opcode == OP_div ) {
2620- insn -> opcode = OP_assign ;
2621- insn -> rs2 = NULL ;
2622- }
2623- }
2624- /* x & -1 = x (all bits set) */
2625- else if (val == -1 ) {
2626- if (insn -> opcode == OP_bit_and ) {
2627- insn -> opcode = OP_assign ;
2628- insn -> rs2 = NULL ;
2629- }
2630- /* x | -1 = -1 */
2631- else if (insn -> opcode == OP_bit_or ) {
2632- insn -> opcode = OP_load_constant ;
2633- insn -> rd -> is_const = true;
2634- insn -> rd -> init_val = -1 ;
2635- insn -> rs1 = NULL ;
2636- insn -> rs2 = NULL ;
2637- }
2638- }
2639- /* x * -1 = -x */
2640- else if (val == -1 && insn -> opcode == OP_mul ) {
2641- insn -> opcode = OP_negate ;
2642- insn -> rs2 = NULL ;
2643- }
2644- }
2645-
2646- /* Simplifications with rs1 constant */
2647- if (insn -> rs1 && insn -> rs1 -> is_const && insn -> rd ) {
2648- int val = insn -> rs1 -> init_val ;
2649-
2650- /* 0 + x = x, 0 | x = x, 0 ^ x = x */
2651- if (val == 0 ) {
2652- if (insn -> opcode == OP_add ||
2653- insn -> opcode == OP_bit_or ||
2654- insn -> opcode == OP_bit_xor ) {
2655- insn -> opcode = OP_assign ;
2656- insn -> rs1 = insn -> rs2 ;
2657- insn -> rs2 = NULL ;
2658- }
2659- /* 0 * x = 0, 0 & x = 0, 0 / x = 0 */
2660- else if (insn -> opcode == OP_mul ||
2661- insn -> opcode == OP_bit_and ||
2662- insn -> opcode == OP_div ) {
2663- insn -> opcode = OP_load_constant ;
2664- insn -> rd -> is_const = true;
2665- insn -> rd -> init_val = 0 ;
2666- insn -> rs1 = NULL ;
2667- insn -> rs2 = NULL ;
2668- }
2669- /* 0 - x = -x */
2670- else if (insn -> opcode == OP_sub ) {
2671- insn -> opcode = OP_negate ;
2672- insn -> rs1 = insn -> rs2 ;
2673- insn -> rs2 = NULL ;
2674- }
2675- }
2676- /* 1 * x = x */
2677- else if (val == 1 && insn -> opcode == OP_mul ) {
2678- insn -> opcode = OP_assign ;
2679- insn -> rs1 = insn -> rs2 ;
2680- insn -> rs2 = NULL ;
2681- }
2682- /* -1 & x = x */
2683- else if (val == -1 && insn -> opcode == OP_bit_and ) {
2684- insn -> opcode = OP_assign ;
2685- insn -> rs1 = insn -> rs2 ;
2686- insn -> rs2 = NULL ;
2687- }
2688- }
2577+ /* Apply algebraic simplifications using eval_algebraic */
2578+ if (eval_algebraic (insn ))
2579+ continue ;
26892580
26902581 /* Phi node optimization - eliminate trivial phi nodes */
26912582 if (insn -> opcode == OP_phi && insn -> phi_ops ) {
0 commit comments