diff options
author | Björn Gustavsson <[email protected]> | 2015-03-02 16:22:06 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2015-03-09 09:41:19 +0100 |
commit | 0d3be61f3a4b5aa3437d08603ea7565432e3a07b (patch) | |
tree | d2346a896cbc59ea1d442fd7476c325b46abd411 | |
parent | b8488349179410c449b591aad20f26814b85e115 (diff) | |
download | otp-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.erl | 16 |
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; |