aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-03-02 16:22:06 +0100
committerBjörn Gustavsson <[email protected]>2015-03-09 09:41:19 +0100
commit0d3be61f3a4b5aa3437d08603ea7565432e3a07b (patch)
treed2346a896cbc59ea1d442fd7476c325b46abd411
parentb8488349179410c449b591aad20f26814b85e115 (diff)
downloadotp-0d3be61f3a4b5aa3437d08603ea7565432e3a07b.tar.gz
otp-0d3be61f3a4b5aa3437d08603ea7565432e3a07b.tar.bz2
otp-0d3be61f3a4b5aa3437d08603ea7565432e3a07b.zip
v3_codegen: Teach the put_map_* instructions to reuse source registers
The put_map_assoc and put_map_exact instructions in the run-time system will support that the target register is the same as one of the source registers. Teach the code generator to take advantage of that. The disadvantages of not reusing register when possible is that the garbage collector may retain dead terms longer than necessary.
-rw-r--r--lib/compiler/src/v3_codegen.erl16
1 files changed, 10 insertions, 6 deletions
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
index 8c1a0c08ac..cbe50b93b0 100644
--- a/lib/compiler/src/v3_codegen.erl
+++ b/lib/compiler/src/v3_codegen.erl
@@ -1523,9 +1523,11 @@ set_cg([{var,R}], {map,Op,Map,[{map_pair,{var,_}=K,V}]}, Le, Vdb, Bef,
List = [cg_reg_arg(K,Int0),cg_reg_arg(V,Int0)],
Live = max_reg(Bef#sr.reg),
- Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
- Aft = clear_dead(Int1, Le#l.i, Vdb),
- Target = fetch_reg(R, Int1#sr.reg),
+
+ %% The target register can reuse one of the source registers.
+ Aft0 = clear_dead(Int0, Le#l.i, Vdb),
+ Aft = Aft0#sr{reg=put_reg(R, Aft0#sr.reg)},
+ Target = fetch_reg(R, Aft#sr.reg),
I = case Op of
assoc -> put_map_assoc;
@@ -1557,9 +1559,11 @@ set_cg([{var,R}], {map,Op,Map,Es}, Le, Vdb, Bef,
List = flatmap(fun({K,V}) -> [K,cg_reg_arg(V,Int0)] end, Pairs),
Live = max_reg(Bef#sr.reg),
- Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
- Aft = clear_dead(Int1, Le#l.i, Vdb),
- Target = fetch_reg(R, Int1#sr.reg),
+
+ %% The target register can reuse one of the source registers.
+ Aft0 = clear_dead(Int0, Le#l.i, Vdb),
+ Aft = Aft0#sr{reg=put_reg(R, Aft0#sr.reg)},
+ Target = fetch_reg(R, Aft#sr.reg),
I = case Op of
assoc -> put_map_assoc;