Skip to content

Commit c093ffc

Browse files
committed
Add safe peephole optimizations
- Add comparison optimization for self-comparisons (x==x, x!=x, etc.) - Add strength reduction for multiplication by power-of-2 - Both optimizations are conservative and maintain bootstrap stability - Removed problematic dead instruction elimination that broke bootstrap
1 parent ee97fef commit c093ffc

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

src/peephole.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)