peephole.ml 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. open Printf
  2. open Types
  3. open Util
  4. let rec strip_comments = function
  5. | Comment _ :: tl -> strip_comments tl
  6. | InlineComment (EmptyLine, _) :: tl -> strip_comments tl
  7. | InlineComment (instr, _) :: tl -> strip_comments (instr :: tl)
  8. | hd :: tl -> hd :: (strip_comments tl)
  9. | [] -> []
  10. let rec peephole = function
  11. (* Constant load before branch becomes a jump when the branch condition
  12. * matches the loaded value ... *)
  13. | LoadImm (BoolVal b) :: Branch (cond, tgt) :: tl when cond = b ->
  14. InlineComment (Jump tgt, "branch -> jump") :: (peephole tl)
  15. (* ... otherwise, both instructions can be removed *)
  16. | LoadImm (BoolVal _) :: Branch (_, tgt) :: tl ->
  17. InlineComment (EmptyLine, "load + branch removed") :: peephole tl
  18. (* Transform addition/subtraction by constant to increment/decrement:
  19. * iload L | iload L
  20. * iloadc[_ ]C | iloadc_1
  21. * i{add,sub} | i{add,sub}
  22. * istore L | istore L
  23. * | |
  24. * v v
  25. * i{inc,dec} L C | i{inc,dec}_1 L
  26. *)
  27. | Load (Int, Current, index) ::
  28. LoadConst (_, i) ::
  29. Op (Add, Int) ::
  30. Store (Int, Current, store) :: tl
  31. | LoadConst (_, i) ::
  32. Load (Int, Current, index) ::
  33. Op (Add, Int) ::
  34. Store (Int, Current, store) :: tl
  35. when store = index ->
  36. InlineComment (Inc (index, i), "add -> inc") :: (peephole tl)
  37. | Load (Int, Current, index) ::
  38. LoadConst (_, i) ::
  39. Op (Sub, Int) ::
  40. Store (Int, Current, store) :: tl
  41. | LoadConst (_, i) ::
  42. Load (Int, Current, index) ::
  43. Op (Sub, Int) ::
  44. Store (Int, Current, store) :: tl
  45. when store = index ->
  46. InlineComment (Dec (index, i), "sub -> dec") :: (peephole tl)
  47. | Load (Int, Current, index) ::
  48. LoadImm (IntVal 1) ::
  49. Op (Add, Int) ::
  50. Store (Int, Current, store) :: tl
  51. | LoadImm (IntVal 1) ::
  52. Load (Int, Current, index) ::
  53. Op (Add, Int) ::
  54. Store (Int, Current, store) :: tl
  55. when store = index ->
  56. InlineComment (IncOne index, "add -> inc") :: (peephole tl)
  57. | Load (Int, Current, index) :: LoadImm (IntVal 1) :: Op (Sub, Int) ::
  58. Store (Int, Current, store) :: tl
  59. | LoadImm (IntVal 1) ::
  60. Load (Int, Current, index) ::
  61. Op (Sub, Int) ::
  62. Store (Int, Current, store) :: tl
  63. when store = index ->
  64. InlineComment (DecOne index, "sub -> dec") :: (peephole tl)
  65. | hd :: tl -> hd :: (peephole tl)
  66. | [] -> []
  67. (* Count actual instructions, ignoring comments and labels *)
  68. let count_instrs instrs =
  69. let rec trav n = function
  70. | [] -> n
  71. | (Comment _ | Label _ | EmptyLine) :: tl -> trav n tl
  72. | InlineComment (hd, _) :: tl -> trav (trav n [hd]) tl
  73. | hd :: tl -> trav (n + 1) tl
  74. in trav 0 instrs
  75. let phase = function
  76. | Assembly instrs as input ->
  77. let oldcount = count_instrs instrs in
  78. let instrs = peephole (strip_comments instrs) in
  79. let newcount = count_instrs instrs in
  80. log_line 2 (sprintf
  81. "Optimized %d to %d instructions (%d fewer)"
  82. oldcount newcount (oldcount - newcount)
  83. );
  84. Assembly instrs
  85. | _ -> raise (InvalidInput "peephole")