peephole.ml 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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) :: LoadConst (_, i) :: Op (Add, Int) ::
  29. Store (Int, Current, store) :: tl
  30. | LoadConst (_, i) :: Load (Int, Current, index) :: Op (Add, Int) ::
  31. Store (Int, Current, store) :: tl) when store = index ->
  32. InlineComment (Inc (index, i), "add -> inc") :: (peephole tl)
  33. | (Load (Int, Current, index) :: LoadConst (_, i) :: Op (Sub, Int) ::
  34. Store (Int, Current, store) :: tl
  35. | LoadConst (_, i) :: Load (Int, Current, index) :: Op (Sub, Int) ::
  36. Store (Int, Current, store) :: tl) when store = index ->
  37. InlineComment (Dec (index, i), "sub -> dec") :: (peephole tl)
  38. | (Load (Int, Current, index) :: LoadImm (IntVal 1) :: Op (Add, Int) ::
  39. Store (Int, Current, store) :: tl
  40. | LoadImm (IntVal 1) :: Load (Int, Current, index) :: Op (Add, Int) ::
  41. Store (Int, Current, store) :: tl) when store = index ->
  42. InlineComment (IncOne index, "add -> inc") :: (peephole tl)
  43. | (Load (Int, Current, index) :: LoadImm (IntVal 1) :: Op (Sub, Int) ::
  44. Store (Int, Current, store) :: tl
  45. | LoadImm (IntVal 1) :: Load (Int, Current, index) :: Op (Sub, Int) ::
  46. Store (Int, Current, store) :: tl) when store = index ->
  47. InlineComment (DecOne index, "sub -> dec") :: (peephole tl)
  48. | hd :: tl -> hd :: (peephole tl)
  49. | [] -> []
  50. (* Count actual instructions, ignoring comments and labels *)
  51. let count_instrs instrs =
  52. let rec trav n = function
  53. | [] -> n
  54. | (Comment _ | Label _ | EmptyLine) :: tl -> trav n tl
  55. | InlineComment (hd, _) :: tl -> trav (trav n [hd]) tl
  56. | hd :: tl -> trav (n + 1) tl
  57. in trav 0 instrs
  58. let phase = function
  59. | Assembly instrs as input ->
  60. let oldcount = count_instrs instrs in
  61. let instrs = peephole (strip_comments instrs) in
  62. let newcount = count_instrs instrs in
  63. log_line 2 (sprintf
  64. "Optimized %d to %d instructions (%d fewer)"
  65. oldcount newcount (oldcount - newcount)
  66. );
  67. Assembly instrs
  68. | _ -> raise (InvalidInput "peephole")