@@ -242,6 +242,108 @@ bool insn_fusion(ph2_ir_t *ph2_ir)
242242 return false;
243243}
244244
245+ /* Comparison optimization for self-comparisons
246+ * Returns true if optimization was applied
247+ */
248+ bool comparison_optimization (ph2_ir_t * ph2_ir )
249+ {
250+ if (!ph2_ir )
251+ return false;
252+
253+ /* Self-comparisons that can be evaluated at compile time */
254+
255+ /* x != x → 0 (always false) */
256+ if (ph2_ir -> op == OP_neq && ph2_ir -> src0 == ph2_ir -> src1 ) {
257+ ph2_ir -> op = OP_load_constant ;
258+ ph2_ir -> src0 = 0 ;
259+ ph2_ir -> src1 = 0 ;
260+ return true;
261+ }
262+
263+ /* x == x → 1 (always true) */
264+ if (ph2_ir -> op == OP_eq && ph2_ir -> src0 == ph2_ir -> src1 ) {
265+ ph2_ir -> op = OP_load_constant ;
266+ ph2_ir -> src0 = 1 ;
267+ ph2_ir -> src1 = 0 ;
268+ return true;
269+ }
270+
271+ /* x < x → 0 (always false) */
272+ if (ph2_ir -> op == OP_lt && ph2_ir -> src0 == ph2_ir -> src1 ) {
273+ ph2_ir -> op = OP_load_constant ;
274+ ph2_ir -> src0 = 0 ;
275+ ph2_ir -> src1 = 0 ;
276+ return true;
277+ }
278+
279+ /* x > x → 0 (always false) */
280+ if (ph2_ir -> op == OP_gt && ph2_ir -> src0 == ph2_ir -> src1 ) {
281+ ph2_ir -> op = OP_load_constant ;
282+ ph2_ir -> src0 = 0 ;
283+ ph2_ir -> src1 = 0 ;
284+ return true;
285+ }
286+
287+ /* x <= x → 1 (always true) */
288+ if (ph2_ir -> op == OP_leq && ph2_ir -> src0 == ph2_ir -> src1 ) {
289+ ph2_ir -> op = OP_load_constant ;
290+ ph2_ir -> src0 = 1 ;
291+ ph2_ir -> src1 = 0 ;
292+ return true;
293+ }
294+
295+ /* x >= x → 1 (always true) */
296+ if (ph2_ir -> op == OP_geq && ph2_ir -> src0 == ph2_ir -> src1 ) {
297+ ph2_ir -> op = OP_load_constant ;
298+ ph2_ir -> src0 = 1 ;
299+ ph2_ir -> src1 = 0 ;
300+ return true;
301+ }
302+
303+ return false;
304+ }
305+
306+ /* Strength reduction optimization for power-of-2 operations
307+ * Returns true if optimization was applied
308+ */
309+ bool strength_reduction (ph2_ir_t * ph2_ir )
310+ {
311+ if (!ph2_ir || !ph2_ir -> next )
312+ return false;
313+
314+ ph2_ir_t * next = ph2_ir -> next ;
315+
316+ /* Check for constant load followed by mul/div/mod */
317+ if (ph2_ir -> op != OP_load_constant )
318+ return false;
319+
320+ int value = ph2_ir -> src0 ;
321+
322+ /* Check if value is a power of 2 (must be positive) */
323+ if (value <= 0 || (value & (value - 1 )) != 0 )
324+ return false;
325+
326+ /* Calculate shift amount for power of 2 */
327+ int shift = 0 ;
328+ int tmp = value ;
329+ while (tmp > 1 ) {
330+ shift ++ ;
331+ tmp >>= 1 ;
332+ }
333+
334+ /* Pattern: Multiplication by power of 2 → left shift */
335+ if (next -> op == OP_mul && next -> src1 == ph2_ir -> dest ) {
336+ ph2_ir -> src0 = shift ;
337+ next -> op = OP_lshift ;
338+ return true;
339+ }
340+
341+ /* Note: Division and modulo optimizations require handling signed values
342+ * which is more complex, so we skip them for safety */
343+
344+ return false;
345+ }
346+
245347/* Main peephole optimization driver.
246348 * It iterates through all functions, basic blocks, and IR instructions to apply
247349 * local optimizations on adjacent instruction pairs.
@@ -265,6 +367,15 @@ void peephole(void)
265367 continue ;
266368 }
267369
370+ /* Try comparison optimization for single instructions */
371+ if (comparison_optimization (ir ))
372+ continue ;
373+
374+ /* Try strength reduction for constant+op patterns */
375+ if (strength_reduction (ir ))
376+ continue ;
377+
378+ /* Try instruction fusion last */
268379 insn_fusion (ir );
269380 }
270381 }
0 commit comments