{"action":"created","issue":{"url":"https://api.github.com/repos/ocaml/ocaml/issues/180","labels_url":"https://api.github.com/repos/ocaml/ocaml/issues/180/labels{/name}","comments_url":"https://api.github.com/repos/ocaml/ocaml/issues/180/comments","events_url":"https://api.github.com/repos/ocaml/ocaml/issues/180/events","html_url":"https://github.com/ocaml/ocaml/pull/180","id":72953454,"number":180,"title":"[RFC] [Spill] add an optimisation which reload early registers in branches","user":{"login":"bobot","id":102849,"avatar_url":"https://avatars.githubusercontent.com/u/102849?v=3","gravatar_id":"","url":"https://api.github.com/users/bobot","html_url":"https://github.com/bobot","followers_url":"https://api.github.com/users/bobot/followers","following_url":"https://api.github.com/users/bobot/following{/other_user}","gists_url":"https://api.github.com/users/bobot/gists{/gist_id}","starred_url":"https://api.github.com/users/bobot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bobot/subscriptions","organizations_url":"https://api.github.com/users/bobot/orgs","repos_url":"https://api.github.com/users/bobot/repos","events_url":"https://api.github.com/users/bobot/events{/privacy}","received_events_url":"https://api.github.com/users/bobot/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-05-04T08:09:55Z","updated_at":"2015-05-04T08:48:08Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ocaml/ocaml/pulls/180","html_url":"https://github.com/ocaml/ocaml/pull/180","diff_url":"https://github.com/ocaml/ocaml/pull/180.diff","patch_url":"https://github.com/ocaml/ocaml/pull/180.patch"},"body":"During the discussion of #162, it appears that a call in one branch will always hindered a fast path in another branch because all the live registers will have to be reloaded after the join point. The problem is particularly patent in ocaml since there is no callee saved registers.\r\n\r\nThis request for comment implements the analogous of this existing optimisation[1]. Instead of pushing later spillings in the branch that needs them, it pushes earlier reloadings in the branch that destroys the registers.\r\n\r\nWith this optimization the following (dumb) function use only registers in the case `x<y`, and as many spilling/reloading than previously :\r\n\r\n```ocaml\r\nlet fun_l (x:int) y =\r\n  let r = if x < y then y else max x y in\r\n  r + x + y\r\n```\r\n\r\nDeadcode elimination pass is added after the split pass because unneeded reloading can be added as in this function:\r\n\r\n```ocaml\r\n let fun_i (x:int) y z =\r\n  let r = if x < y then y else max x y in\r\n  let w = max r r in\r\n  w + r + x + y\r\n```\r\n\r\nThis optimization has similar bad cases than the previous one and the interaction with the previous one (spill late) could add a lot of spilling. In this function (where fun_l is automatically inlined) x is spilled once more (in the slow path) by call to `fun_l`:\r\n\r\n```ocaml\r\nlet fun_m x y =\r\n  let r = fun_l x y in\r\n  let r = fun_l r x in\r\n  let r = fun_l r x in\r\n  r\r\n```\r\n\r\nIf the previous optimization (spill late) is deactivated there are as many spilling/reloading as before.\r\n\r\nDoes this optimization have already been considered? Do you think it can be interesting to investigate it more? with macro-benchmarks?\r\n\r\nRegards,\r\n\r\n[1]:https://github.com/ocaml/ocaml/blob/d1c017c7cb77a0b4864f82805b4957e911041fef/asmcomp/spill.ml#L253"},"comment":{"url":"https://api.github.com/repos/ocaml/ocaml/issues/comments/98638946","html_url":"https://github.com/ocaml/ocaml/pull/180#issuecomment-98638946","issue_url":"https://api.github.com/repos/ocaml/ocaml/issues/180","id":98638946,"user":{"login":"gasche","id":426238,"avatar_url":"https://avatars.githubusercontent.com/u/426238?v=3","gravatar_id":"","url":"https://api.github.com/users/gasche","html_url":"https://github.com/gasche","followers_url":"https://api.github.com/users/gasche/followers","following_url":"https://api.github.com/users/gasche/following{/other_user}","gists_url":"https://api.github.com/users/gasche/gists{/gist_id}","starred_url":"https://api.github.com/users/gasche/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gasche/subscriptions","organizations_url":"https://api.github.com/users/gasche/orgs","repos_url":"https://api.github.com/users/gasche/repos","events_url":"https://api.github.com/users/gasche/events{/privacy}","received_events_url":"https://api.github.com/users/gasche/received_events","type":"User","site_admin":false},"created_at":"2015-05-04T08:48:08Z","updated_at":"2015-05-04T08:48:08Z","body":"For benchmarks you may want to try [operf-macro](https://github.com/OCamlPro/operf-macro) (macro benchmarks) and [operf-micro](https://github.com/OCamlPro/operf-micro) (micro benchmarks)."}}