@@ -601,6 +601,82 @@ bool algebraic_simplification(ph2_ir_t *ph2_ir)
601
601
return false;
602
602
}
603
603
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
+
604
680
/* Main peephole optimization driver.
605
681
* It iterates through all functions, basic blocks, and IR instructions to apply
606
682
* local optimizations on adjacent instruction pairs.
0 commit comments