aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/vmemitcodes.ml13
1 files changed, 13 insertions, 0 deletions
diff --git a/kernel/vmemitcodes.ml b/kernel/vmemitcodes.ml
index e70285d9ab..5849641c20 100644
--- a/kernel/vmemitcodes.ml
+++ b/kernel/vmemitcodes.ml
@@ -135,6 +135,16 @@ let out env opcode =
let is_immed i = Uint63.le (Uint63.of_int i) Uint63.maxuint31
+(* Detect whether the current value of the accu register is no longer
+ needed (i.e., the register is written before being read). If so, the
+ register can be used freely; no need to save and restore it. *)
+let is_accu_dead = function
+ | [] -> false
+ | c :: _ ->
+ match c with
+ | Kacc _ | Kenvacc _ | Kconst _ | Koffsetclosure _ | Kgetglobal _ -> true
+ | _ -> false
+
let out_int env n =
out_word env n (n asr 8) (n asr 16) (n asr 24)
@@ -399,6 +409,9 @@ let rec emit env insns remaining = match insns with
| Kpush :: Kconst const :: c ->
out env opPUSHGETGLOBAL; slot_for_const env const;
emit env c remaining
+ | Kpushfields 1 :: c when is_accu_dead c ->
+ out env opGETFIELD0;
+ emit env (Kpush :: c) remaining
| Kpop n :: Kjump :: c ->
out env opRETURN; out_int env n; emit env c remaining
| Ksequence c1 :: c ->