Skip to content

Commit 2cce7c3

Browse files
committed
Add bitwise operation optimizations to peephole
This implements bitwise identity and absorption patterns: - Double complement: ~(~x) → x - AND with all-ones: x & -1 → x - OR with zero: x | 0 → x - XOR with zero: x ^ 0 → x - AND with zero: x & 0 → 0 (absorption) - OR with all-ones: x | -1 → -1 (absorption) - Shift by zero: x << 0 → x, x >> 0 → x These patterns are not handled by SSA optimizer and provide significant optimization opportunities for bitwise operations.
1 parent 1753776 commit 2cce7c3

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

src/peephole.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,108 @@ bool comparison_optimization(ph2_ir_t *ph2_ir)
753753
return false;
754754
}
755755

756+
/* Bitwise operation optimization: Simplify bitwise patterns
757+
* Returns true if optimization was applied
758+
*/
759+
bool bitwise_optimization(ph2_ir_t *ph2_ir)
760+
{
761+
if (!ph2_ir || !ph2_ir->next)
762+
return false;
763+
764+
ph2_ir_t *next = ph2_ir->next;
765+
766+
/* Pattern 1: Double complement → identity
767+
* ~(~x) = x
768+
*/
769+
if (ph2_ir->op == OP_negate && next->op == OP_negate &&
770+
next->src0 == ph2_ir->dest) {
771+
/* Replace with simple assignment */
772+
ph2_ir->op = OP_assign;
773+
ph2_ir->dest = next->dest;
774+
ph2_ir->next = next->next;
775+
return true;
776+
}
777+
778+
/* Pattern 2: AND with all-ones mask → identity
779+
* x & 0xFFFFFFFF = x (for 32-bit)
780+
*/
781+
if (ph2_ir->op == OP_load_constant && ph2_ir->src0 == -1 &&
782+
next->op == OP_bit_and && next->src1 == ph2_ir->dest) {
783+
/* Replace AND with assignment */
784+
next->op = OP_assign;
785+
next->src1 = 0;
786+
ph2_ir->next = next->next;
787+
return true;
788+
}
789+
790+
/* Pattern 3: OR with zero → identity
791+
* x | 0 = x
792+
*/
793+
if (ph2_ir->op == OP_load_constant && ph2_ir->src0 == 0 &&
794+
next->op == OP_bit_or && next->src1 == ph2_ir->dest) {
795+
/* Replace OR with assignment */
796+
next->op = OP_assign;
797+
next->src1 = 0;
798+
ph2_ir->next = next->next;
799+
return true;
800+
}
801+
802+
/* Pattern 4: XOR with zero → identity
803+
* x ^ 0 = x
804+
*/
805+
if (ph2_ir->op == OP_load_constant && ph2_ir->src0 == 0 &&
806+
next->op == OP_bit_xor && next->src1 == ph2_ir->dest) {
807+
/* Replace XOR with assignment */
808+
next->op = OP_assign;
809+
next->src1 = 0;
810+
ph2_ir->next = next->next;
811+
return true;
812+
}
813+
814+
/* Pattern 5: AND with zero → zero
815+
* x & 0 = 0
816+
*/
817+
if (ph2_ir->op == OP_load_constant && ph2_ir->src0 == 0 &&
818+
next->op == OP_bit_and &&
819+
(next->src0 == ph2_ir->dest || next->src1 == ph2_ir->dest)) {
820+
/* Replace with constant load of 0 */
821+
next->op = OP_load_constant;
822+
next->src0 = 0;
823+
next->src1 = 0;
824+
ph2_ir->next = next->next;
825+
return true;
826+
}
827+
828+
/* Pattern 6: OR with all-ones → all-ones
829+
* x | 0xFFFFFFFF = 0xFFFFFFFF
830+
*/
831+
if (ph2_ir->op == OP_load_constant && ph2_ir->src0 == -1 &&
832+
next->op == OP_bit_or &&
833+
(next->src0 == ph2_ir->dest || next->src1 == ph2_ir->dest)) {
834+
/* Replace with constant load of -1 */
835+
next->op = OP_load_constant;
836+
next->src0 = -1;
837+
next->src1 = 0;
838+
ph2_ir->next = next->next;
839+
return true;
840+
}
841+
842+
/* Pattern 7: Shift by zero → identity
843+
* x << 0 = x, x >> 0 = x
844+
*/
845+
if (ph2_ir->op == OP_load_constant && ph2_ir->src0 == 0 &&
846+
(next->op == OP_lshift || next->op == OP_rshift) &&
847+
next->src1 == ph2_ir->dest) {
848+
/* Replace shift with assignment */
849+
next->op = OP_assign;
850+
next->src1 = 0;
851+
ph2_ir->next = next->next;
852+
return true;
853+
}
854+
855+
return false;
856+
}
857+
756858
/* Main peephole optimization driver.
757859
* It iterates through all functions, basic blocks, and IR instructions to apply
758860
* local optimizations on adjacent instruction pairs.

0 commit comments

Comments
 (0)