@@ -601,6 +601,82 @@ bool algebraic_simplification(ph2_ir_t *ph2_ir)
601601 return false;
602602}
603603
604+ /* Division/modulo strength reduction: Optimize division and modulo by
605+ * power-of-2
606+ *
607+ * This pattern is unique to peephole optimizer.
608+ * SSA cannot perform this optimization because it works on virtual registers
609+ * before actual constant values are loaded.
610+ *
611+ * Returns true if optimization was applied
612+ */
613+ bool strength_reduction (ph2_ir_t * ph2_ir )
614+ {
615+ if (!ph2_ir || !ph2_ir -> next )
616+ return false;
617+
618+ ph2_ir_t * next = ph2_ir -> next ;
619+
620+ /* Check for constant load followed by division or modulo */
621+ if (ph2_ir -> op != OP_load_constant )
622+ return false;
623+
624+ int value = ph2_ir -> src0 ;
625+
626+ /* Check if value is a power of 2 */
627+ if (value <= 0 || (value & (value - 1 )) != 0 )
628+ return false;
629+
630+ /* Calculate shift amount for power of 2 */
631+ int shift = 0 ;
632+ int tmp = value ;
633+ while (tmp > 1 ) {
634+ shift ++ ;
635+ tmp >>= 1 ;
636+ }
637+
638+ /* Pattern 1: Division by power of 2 → right shift
639+ * x / 2^n = x >> n (for unsigned)
640+ */
641+ if (next -> op == OP_div && next -> src1 == ph2_ir -> dest ) {
642+ /* Convert division to right shift */
643+ ph2_ir -> src0 = shift ; /* Load shift amount instead */
644+ next -> op = OP_rshift ;
645+ return true;
646+ }
647+
648+ /* Pattern 2: Modulo by power of 2 → bitwise AND
649+ * x % 2^n = x & (2^n - 1)
650+ */
651+ if (next -> op == OP_mod && next -> src1 == ph2_ir -> dest ) {
652+ /* Convert modulo to bitwise AND */
653+ ph2_ir -> src0 = value - 1 ; /* Load mask (2^n - 1) */
654+ next -> op = OP_bit_and ;
655+ return true;
656+ }
657+
658+ /* Pattern 3: Multiplication by power of 2 → left shift
659+ * x * 2^n = x << n
660+ */
661+ if (next -> op == OP_mul ) {
662+ if (next -> src0 == ph2_ir -> dest ) {
663+ /* 2^n * x = x << n */
664+ ph2_ir -> src0 = shift ; /* Load shift amount */
665+ next -> op = OP_lshift ;
666+ next -> src0 = next -> src1 ; /* Move x to src0 */
667+ next -> src1 = ph2_ir -> dest ; /* Shift amount in src1 */
668+ return true;
669+ } else if (next -> src1 == ph2_ir -> dest ) {
670+ /* x * 2^n = x << n */
671+ ph2_ir -> src0 = shift ; /* Load shift amount */
672+ next -> op = OP_lshift ;
673+ return true;
674+ }
675+ }
676+
677+ return false;
678+ }
679+
604680/* Main peephole optimization driver.
605681 * It iterates through all functions, basic blocks, and IR instructions to apply
606682 * local optimizations on adjacent instruction pairs.
0 commit comments