aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/ops.tab
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-06-25 13:21:14 +0200
committerBjörn Gustavsson <[email protected]>2015-07-03 14:34:58 +0200
commit62473daf8169a04a07409f344d938bc51a4536c3 (patch)
tree153bf43a5833103f6d368de318288aad692fcedf /erts/emulator/beam/ops.tab
parent3dc2bee53b4d36f41821a6ab512cf01c958c11f9 (diff)
downloadotp-62473daf8169a04a07409f344d938bc51a4536c3.tar.gz
otp-62473daf8169a04a07409f344d938bc51a4536c3.tar.bz2
otp-62473daf8169a04a07409f344d938bc51a4536c3.zip
Introduce swap_temp/3 and swap/2
Sequences of three move instructionst that effectively swap the contents of two registers are fairly common. We can replace them with a swap_temp/3 instruction. The third operand is the temporary register to be used for swapping, since the temporary register may actually be used. If swap_temp/3 instruction is followed by a call, the temporary register will often (but not always) be killed by the call. If it is killed, we can replace the swap_temp/3 instruction with a slightly cheaper swap/2 instruction.
Diffstat (limited to 'erts/emulator/beam/ops.tab')
-rw-r--r--erts/emulator/beam/ops.tab28
1 files changed, 28 insertions, 0 deletions
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 97525c3b72..386de0a658 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -303,6 +303,34 @@ move_window3 x x x y
move_window4 x x x x y
move_window5 x x x x x y
+# Swap registers.
+move R1=x Tmp=x | move R2=xy R1 | move Tmp R2 => swap_temp R1 R2 Tmp
+
+swap_temp R1 R2 Tmp | line Loc | apply Live | is_killed(Tmp, Live) => \
+ swap R1 R2 | line Loc | apply Live
+
+swap_temp R1 R2 Tmp | line Loc | call Live Addr | is_killed(Tmp, Live) => \
+ swap R1 R2 | line Loc | call Live Addr
+swap_temp R1 R2 Tmp | call_only Live Addr | \
+ is_killed(Tmp, Live) => swap R1 R2 | call_only Live Addr
+swap_temp R1 R2 Tmp | call_last Live Addr D | \
+ is_killed(Tmp, Live) => swap R1 R2 | call_last Live Addr D
+
+swap_temp R1 R2 Tmp | line Loc | call_ext Live Addr | is_killed(Tmp, Live) => \
+ swap R1 R2 | line Loc | call_ext Live Addr
+swap_temp R1 R2 Tmp | line Loc | call_ext_only Live Addr | \
+ is_killed(Tmp, Live) => swap R1 R2 | line Loc | call_ext_only Live Addr
+swap_temp R1 R2 Tmp | line Loc | call_ext_last Live Addr D | \
+ is_killed(Tmp, Live) => swap R1 R2 | line Loc | call_ext_last Live Addr D
+
+%macro: swap_temp SwapTemp -pack
+swap_temp x x x
+swap_temp x y x
+
+%macro: swap Swap -pack
+swap x x
+swap x y
+
move Src=x D1=x | move Src=x D2=x => move_dup Src D1 D2
move Src=x SD=x | move SD=x D=x => move_dup Src SD D
move Src=x D1=x | move Src=x D2=y => move_dup Src D1 D2