peephole.ml 3.0 KB

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