From 954b01e1ac6189f4a8b5ad1b6accf6eb01261d1f Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Wed, 24 Aug 2016 11:11:29 +0200 Subject: PR#113, PR#122: Unspillable temporaries causing register allocation to fail The spilling strategy for 2-address operations was strange in the case where the first argument needs spilling but not (yet) the result: a Xreload instruction was generated which prevented future spilling of the result. Fixed by generating Xmove instead of Xreload in this case. --- backend/Regalloc.ml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'backend/Regalloc.ml') diff --git a/backend/Regalloc.ml b/backend/Regalloc.ml index e6e07339..0013d91a 100644 --- a/backend/Regalloc.ml +++ b/backend/Regalloc.ml @@ -915,7 +915,12 @@ let spill_instr tospill eqs instr = | false, true -> let eqs1 = add arg1 res (kill res eqs) in let (argl', c1, eqs2) = reload_vars tospill eqs1 argl in - (Xreload(arg1, res) :: c1 @ [Xop(op, res :: argl', res)], + (* PR#113, PR#122: [Xreload] here causes [res] to become + unspillable in the future. This is too strong, hence + the [Xmove]. Alternatively, this [false, true] + case could be removed and the [true, true] case + below used instead. *) + (Xmove(arg1, res) :: c1 @ [Xop(op, res :: argl', res)], kill res eqs2) | true, true -> let tmp = new_temp (typeof res) in -- cgit