Skip to content

Commit ebb0cbf

Browse files
committed
Improve cmm peephole optimizations
This will be used by a future pr to simplify casting without impacting performance as much
1 parent 434f596 commit ebb0cbf

File tree

1 file changed

+77
-47
lines changed

1 file changed

+77
-47
lines changed

backend/cmm_helpers.ml

+77-47
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,13 @@ let rec add_const c n dbg =
334334
Cop (Csubi, [Cconst_int (n + x, dbg); c], dbg)
335335
| Cop (Csubi, [c; Cconst_int (x, _)], _) when Misc.no_overflow_sub n x ->
336336
add_const c (n - x) dbg
337+
| Cop
338+
( Cor,
339+
[(Cop (Clsl, [_; Cconst_int (1, _)], _) as inner); Cconst_int (1, _)],
340+
_ )
341+
when n = -1 ->
342+
(* undo setting the tag bit *)
343+
inner
337344
| c -> Cop (Caddi, [c; Cconst_int (n, dbg)], dbg)
338345

339346
let incr_int c dbg = add_const c 1 dbg
@@ -360,38 +367,6 @@ let rec sub_int c1 c2 dbg =
360367

361368
let neg_int c dbg = sub_int (Cconst_int (0, dbg)) c dbg
362369

363-
let rec lsl_int c1 c2 dbg =
364-
match c1, c2 with
365-
| c1, Cconst_int (0, _) -> c1
366-
| Cop (Clsl, [c; Cconst_int (n1, _)], _), Cconst_int (n2, _)
367-
when n1 > 0 && n2 > 0 && n1 + n2 < size_int * 8 ->
368-
Cop (Clsl, [c; Cconst_int (n1 + n2, dbg)], dbg)
369-
| Cop (Caddi, [c1; Cconst_int (n1, _)], _), Cconst_int (n2, _)
370-
when Misc.no_overflow_lsl n1 n2 ->
371-
add_const (lsl_int c1 c2 dbg) (n1 lsl n2) dbg
372-
| _, _ -> Cop (Clsl, [c1; c2], dbg)
373-
374-
let lsl_const c n dbg = lsl_int c (Cconst_int (n, dbg)) dbg
375-
376-
let is_power2 n = n = 1 lsl Misc.log2 n
377-
378-
and mult_power2 c n dbg = lsl_int c (Cconst_int (Misc.log2 n, dbg)) dbg
379-
380-
let rec mul_int c1 c2 dbg =
381-
match c1, c2 with
382-
| c, Cconst_int (0, _) | Cconst_int (0, _), c ->
383-
Csequence (c, Cconst_int (0, dbg))
384-
| c, Cconst_int (1, _) | Cconst_int (1, _), c -> c
385-
| c, Cconst_int (-1, _) | Cconst_int (-1, _), c ->
386-
sub_int (Cconst_int (0, dbg)) c dbg
387-
| c, Cconst_int (n, _) when is_power2 n -> mult_power2 c n dbg
388-
| Cconst_int (n, _), c when is_power2 n -> mult_power2 c n dbg
389-
| Cop (Caddi, [c; Cconst_int (n, _)], _), Cconst_int (k, _)
390-
| Cconst_int (k, _), Cop (Caddi, [c; Cconst_int (n, _)], _)
391-
when Misc.no_overflow_mul n k ->
392-
add_const (mul_int c (Cconst_int (k, dbg)) dbg) (n * k) dbg
393-
| c1, c2 -> Cop (Cmuli, [c1; c2], dbg)
394-
395370
(* identify cmm operations whose result is guaranteed to be small integers (e.g.
396371
in the range [min_int / 4; max_int / 4]) *)
397372
let guaranteed_to_be_small_int = function
@@ -410,7 +385,7 @@ let ignore_low_bit_int = function
410385
| Cop (Cor, [c; Cconst_int (1, _)], _) -> c
411386
| c -> c
412387

413-
let lsr_int c1 c2 dbg =
388+
let rec lsr_int c1 c2 dbg =
414389
match c1, c2 with
415390
| c1, Cconst_int (0, _) -> c1
416391
| Cop (Clsr, [c; Cconst_int (n1, _)], _), Cconst_int (n2, _)
@@ -420,46 +395,97 @@ let lsr_int c1 c2 dbg =
420395
Cop (Clsr, [ignore_low_bit_int c1; c2], dbg)
421396
| _ -> Cop (Clsr, [c1; c2], dbg)
422397

423-
let lsr_const c n dbg = lsr_int c (Cconst_int (n, dbg)) dbg
424-
425-
let asr_int c1 c2 dbg =
426-
match c2 with
427-
| Cconst_int (0, _) -> c1
428-
| Cconst_int (n, _) when n > 0 -> (
398+
and asr_int c1 c2 dbg =
399+
match c1, c2 with
400+
| c1, Cconst_int (0, _) -> c1
401+
| c1, Cconst_int (n, _) when n > 0 -> (
429402
match ignore_low_bit_int c1 with
430403
(* some operations always return small enough integers that it is safe and
431404
correct to optimise [asr (lsl x 1) 1] into [x]. *)
432405
| Cop (Clsl, [c; Cconst_int (1, _)], _)
433406
when n = 1 && guaranteed_to_be_small_int c ->
434407
c
408+
| Cop (Cor, [inner; Cconst_int (x, _)], _) when n < Sys.int_size ->
409+
let inner = asr_const inner n dbg in
410+
let x = x asr n in
411+
if x = 0 then inner else Cop (Cor, [inner; Cconst_int (x, dbg)], dbg)
435412
| c1' -> Cop (Casr, [c1'; c2], dbg))
413+
| Cop (Casr, [x; (Cconst_int _ as y)], z), c2 ->
414+
(* prefer putting the constant shift on the outside to help enable further
415+
peephole optimizations *)
416+
Cop (Casr, [Cop (Casr, [x; c2], dbg); y], z)
436417
| _ -> Cop (Casr, [c1; c2], dbg)
437418

438-
let asr_const c n dbg = asr_int c (Cconst_int (n, dbg)) dbg
419+
and lsl_int c1 c2 dbg =
420+
match c1, c2 with
421+
| c1, Cconst_int (0, _) -> c1
422+
| Cop (Clsl, [c; Cconst_int (n1, _)], _), Cconst_int (n2, _)
423+
when n1 > 0 && n2 > 0 && n1 + n2 < size_int * 8 ->
424+
Cop (Clsl, [c; Cconst_int (n1 + n2, dbg)], dbg)
425+
| Cop (Caddi, [c1; Cconst_int (n1, _)], _), Cconst_int (n2, _)
426+
when Misc.no_overflow_lsl n1 n2 ->
427+
add_const (lsl_int c1 c2 dbg) (n1 lsl n2) dbg
428+
| Cop (Cor, [c1; Cconst_int (n1, _)], _), Cconst_int (n2, _)
429+
when Misc.no_overflow_lsl n1 n2 ->
430+
Cop (Cor, [lsl_int c1 c2 dbg; Cconst_int (n1 lsl n2, dbg)], dbg)
431+
| Cop (Clsl, [x; (Cconst_int _ as y)], z), c2 ->
432+
(* prefer putting the constant shift on the outside to help enable further
433+
peephole optimizations *)
434+
Cop (Clsl, [Cop (Clsl, [x; c2], dbg); y], z)
435+
| _, _ -> Cop (Clsl, [c1; c2], dbg)
436+
437+
and lsl_const c n dbg = lsl_int c (Cconst_int (n, dbg)) dbg
438+
439+
and asr_const c n dbg = asr_int c (Cconst_int (n, dbg)) dbg
440+
441+
and lsr_const c n dbg = lsr_int c (Cconst_int (n, dbg)) dbg
442+
443+
let is_power2 n = n = 1 lsl Misc.log2 n
444+
445+
and mult_power2 c n dbg = lsl_int c (Cconst_int (Misc.log2 n, dbg)) dbg
446+
447+
let rec mul_int c1 c2 dbg =
448+
match c1, c2 with
449+
| c, Cconst_int (0, _) | Cconst_int (0, _), c ->
450+
Csequence (c, Cconst_int (0, dbg))
451+
| c, Cconst_int (1, _) | Cconst_int (1, _), c -> c
452+
| c, Cconst_int (-1, _) | Cconst_int (-1, _), c ->
453+
sub_int (Cconst_int (0, dbg)) c dbg
454+
| c, Cconst_int (n, _) when is_power2 n -> mult_power2 c n dbg
455+
| Cconst_int (n, _), c when is_power2 n -> mult_power2 c n dbg
456+
| Cop (Caddi, [c; Cconst_int (n, _)], _), Cconst_int (k, _)
457+
| Cconst_int (k, _), Cop (Caddi, [c; Cconst_int (n, _)], _)
458+
when Misc.no_overflow_mul n k ->
459+
add_const (mul_int c (Cconst_int (k, dbg)) dbg) (n * k) dbg
460+
| c1, c2 -> Cop (Cmuli, [c1; c2], dbg)
439461

440462
let tag_int i dbg =
441463
match i with
442464
| Cconst_int (n, _) -> int_const dbg n
443465
| Cop (Casr, [c; Cconst_int (n, _)], _) when n > 0 ->
444466
Cop
445467
(Cor, [asr_int c (Cconst_int (n - 1, dbg)) dbg; Cconst_int (1, dbg)], dbg)
468+
| Cop (Clsr, [c; Cconst_int (n, _)], _) when n > 0 ->
469+
Cop (Cor, [lsr_const c (n - 1) dbg; Cconst_int (1, dbg)], dbg)
446470
| c -> incr_int (lsl_int c (Cconst_int (1, dbg)) dbg) dbg
447471

448472
let untag_int i dbg =
449473
match i with
450474
| Cconst_int (n, _) -> Cconst_int (n asr 1, dbg)
451475
| Cop (Cor, [Cop (Casr, [c; Cconst_int (n, _)], _); Cconst_int (1, _)], _)
452476
when n > 0 && n < (size_int * 8) - 1 ->
453-
Cop (Casr, [c; Cconst_int (n + 1, dbg)], dbg)
477+
asr_const c (n + 1) dbg
454478
| Cop (Cor, [Cop (Clsr, [c; Cconst_int (n, _)], _); Cconst_int (1, _)], _)
455479
when n > 0 && n < (size_int * 8) - 1 ->
456480
Cop (Clsr, [c; Cconst_int (n + 1, dbg)], dbg)
457481
| c -> asr_int c (Cconst_int (1, dbg)) dbg
458482

459483
let mk_not dbg cmm =
460484
match cmm with
461-
| Cop (Caddi, [Cop (Clsl, [c; Cconst_int (1, _)], _); Cconst_int (1, _)], dbg')
462-
-> (
485+
| Cop
486+
( (Caddi | Cor),
487+
[Cop (Clsl, [c; Cconst_int (1, _)], _); Cconst_int (1, _)],
488+
dbg' ) -> (
463489
match c with
464490
| Cop (Ccmpi cmp, [c1; c2], dbg'') ->
465491
tag_int
@@ -799,8 +825,10 @@ let mod_int ?dividend_cannot_be_min_int c1 c2 dbg =
799825

800826
let test_bool dbg cmm =
801827
match cmm with
802-
| Cop (Caddi, [Cop (Clsl, [c; Cconst_int (1, _)], _); Cconst_int (1, _)], _)
803-
->
828+
| Cop
829+
( (Caddi | Cor),
830+
[Cop (Clsl, [c; Cconst_int (1, _)], _); Cconst_int (1, _)],
831+
_ ) ->
804832
c
805833
| Cconst_int (n, dbg) ->
806834
if n = 1 then Cconst_int (0, dbg) else Cconst_int (1, dbg)
@@ -1035,8 +1063,10 @@ let array_indexing ?typ log2size ptr ofs dbg =
10351063
if i = 0
10361064
then ptr
10371065
else Cop (add, [ptr; Cconst_int (i lsl log2size, dbg)], dbg)
1038-
| Cop (Caddi, [Cop (Clsl, [c; Cconst_int (1, _)], _); Cconst_int (1, _)], dbg')
1039-
->
1066+
| Cop
1067+
( (Caddi | Cor),
1068+
[Cop (Clsl, [c; Cconst_int (1, _)], _); Cconst_int (1, _)],
1069+
dbg' ) ->
10401070
Cop (add, [ptr; lsl_const c log2size dbg], dbg')
10411071
| Cop (Caddi, [c; Cconst_int (n, _)], dbg') when log2size = 0 ->
10421072
Cop

0 commit comments

Comments
 (0)