From 135c9821e8806defa455a47208fb897fff1a3ff8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 23 Jun 2015 08:53:50 +0200
Subject: Make the 'r' operand type optional

The 'r' type is now mandatory. That means in order to handle
both of the following instructions:

  move x(0) y(7)
  move x(1) y(7)

we would need to define two specific operations in ops.tab:

  move r y
  move x y

We want to make 'r' operands optional. That is, if we have
only this specific instruction:

  move x y

it will match both of the following instructions:

  move x(0) y(7)
  move x(1) y(7)

Make 'r' optional allows us to save code space when we don't
want to make handling of x(0) a special case, but we can still
use 'r' to optimize commonly used instructions.
---
 erts/emulator/beam/beam_debug.c  |   6 -
 erts/emulator/beam/beam_emu.c    | 355 ++++++------------------------
 erts/emulator/beam/beam_load.c   |  66 ++++--
 erts/emulator/beam/erl_vm.h      |   1 +
 erts/emulator/beam/ops.tab       | 456 +++++++++++++--------------------------
 erts/emulator/utils/beam_makeops |  16 +-
 6 files changed, 282 insertions(+), 618 deletions(-)

(limited to 'erts')

diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 243ccb9afd..30e3765502 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -569,7 +569,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
     unpacked = ap;
     ap = addr + size;
     switch (op) {
-    case op_i_select_val_lins_rfI:
     case op_i_select_val_lins_xfI:
     case op_i_select_val_lins_yfI:
 	{
@@ -589,7 +588,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
 	    }
 	}
 	break;
-    case op_i_select_val_bins_rfI:
     case op_i_select_val_bins_xfI:
     case op_i_select_val_bins_yfI:
 	{
@@ -603,7 +601,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
 	    }
 	}
 	break;
-    case op_i_select_tuple_arity_rfI:
     case op_i_select_tuple_arity_xfI:
     case op_i_select_tuple_arity_yfI:
         {
@@ -628,7 +625,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
             }
         }
         break;
-    case op_i_jump_on_val_rfII:
     case op_i_jump_on_val_xfII:
     case op_i_jump_on_val_yfII:
 	{
@@ -640,7 +636,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
 	    }
 	}
 	break;
-    case op_i_jump_on_val_zero_rfI:
     case op_i_jump_on_val_zero_xfI:
     case op_i_jump_on_val_zero_yfI:
 	{
@@ -652,7 +647,6 @@ print_op(int to, void *to_arg, int op, int size, BeamInstr* addr)
 	    }
 	}
 	break;
-    case op_i_put_tuple_rI:
     case op_i_put_tuple_xI:
     case op_i_put_tuple_yI:
     case op_new_map_dII:
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index a74da2d872..e5179830de 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -556,12 +556,12 @@ void** beam_ops;
 #define Move2(S1, D1, S2, D2) D1 = (S1); D2 = (S2)
 #define Move3(S1, D1, S2, D2, S3, D3) D1 = (S1); D2 = (S2); D3 = (S3)
 
-#define MoveReturn(Src, Dest)       \
-    (Dest) = (Src);                 \
-    I = c_p->cp;                    \
-    ASSERT(VALID_INSTR(*c_p->cp));  \
-    c_p->cp = 0;                    \
-    CHECK_TERM(r(0));               \
+#define MoveReturn(Src)				\
+    x(0) = (Src);				\
+    I = c_p->cp;				\
+    ASSERT(VALID_INSTR(*c_p->cp));		\
+    c_p->cp = 0;				\
+    CHECK_TERM(r(0));				\
     Goto(*I)
 
 #define DeallocateReturn(Deallocate)       \
@@ -573,26 +573,26 @@ void** beam_ops;
     Goto(*I);                              \
   } while (0)
 
-#define MoveDeallocateReturn(Src, Dest, Deallocate)  \
-    (Dest) = (Src);                                  \
+#define MoveDeallocateReturn(Src, Deallocate)	\
+    x(0) = (Src);				\
     DeallocateReturn(Deallocate)
 
-#define MoveCall(Src, Dest, CallDest, Size)	\
-    (Dest) = (Src);				\
+#define MoveCall(Src, CallDest, Size)		\
+    x(0) = (Src);				\
     SET_CP(c_p, I+Size+1);			\
-    SET_I((BeamInstr *) CallDest);			\
+    SET_I((BeamInstr *) CallDest);		\
     Dispatch();
 
-#define MoveCallLast(Src, Dest, CallDest, Deallocate)	\
-    (Dest) = (Src);					\
-    RESTORE_CP(E);					\
-    E = ADD_BYTE_OFFSET(E, (Deallocate));		\
-    SET_I((BeamInstr *) CallDest);				\
+#define MoveCallLast(Src, CallDest, Deallocate)	\
+    x(0) = (Src);				\
+    RESTORE_CP(E);				\
+    E = ADD_BYTE_OFFSET(E, (Deallocate));	\
+    SET_I((BeamInstr *) CallDest);		\
     Dispatch();
 
-#define MoveCallOnly(Src, Dest, CallDest)	\
-    (Dest) = (Src);				\
-    SET_I((BeamInstr *) CallDest);			\
+#define MoveCallOnly(Src, CallDest)		\
+    x(0) = (Src);				\
+    SET_I((BeamInstr *) CallDest);		\
     Dispatch();
 
 #define MoveJump(Src)				\
@@ -676,8 +676,8 @@ void** beam_ops;
     if (is_not_list(Src)) { Fail; }                     \
     A(Need, Alive)
 
-#define IsNonemptyListTestHeap(Src, Need, Alive, Fail)  \
-    if (is_not_list(Src)) { Fail; }                     \
+#define IsNonemptyListTestHeap(Need, Alive, Fail)  \
+    if (is_not_list(x(0))) { Fail; }			\
     TestHeap(Need, Alive)
 
 #define IsTuple(X, Action) if (is_not_tuple(X)) Action
@@ -1316,17 +1316,13 @@ void process_main(void)
 	    Uint live;
 	    Eterm result;
 
-	OpCase(i_increment_yIId):
-	    increment_reg_val = yb(Arg(0));
-	    goto do_increment;
-
 	OpCase(i_increment_xIId):
 	    increment_reg_val = xb(Arg(0));
 	    goto do_increment;
 
-	OpCase(i_increment_rIId):
-	    increment_reg_val = r(0);
-	    I--;
+	OpCase(i_increment_yIId):
+	    increment_reg_val = yb(Arg(0));
+	    goto do_increment;
 
 	do_increment:
 	    increment_val = Arg(1);
@@ -1335,7 +1331,6 @@ void process_main(void)
 		ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i));
 		if (MY_IS_SSMALL(i)) {
 		    result = make_small(i);
-		store_result:
 		    StoreBifResult(3, result);
 		}
 	    }
@@ -1348,7 +1343,7 @@ void process_main(void)
 	    SWAPIN;
 	    ERTS_HOLE_CHECK(c_p);
 	    if (is_value(result)) {
-		goto store_result;
+		StoreBifResult(3, result);
 	    }
 	    ASSERT(c_p->freason != BADMATCH || is_value(c_p->fvalue));
 	    goto find_func_info;
@@ -1464,47 +1459,37 @@ void process_main(void)
     {
 	Eterm is_eq_exact_lit_val;
 
-    OpCase(i_is_eq_exact_literal_xfc):
-	is_eq_exact_lit_val = xb(Arg(0));
-	I++;
+    OpCase(i_is_eq_exact_literal_fxc):
+	is_eq_exact_lit_val = xb(Arg(1));
 	goto do_is_eq_exact_literal;
 
-    OpCase(i_is_eq_exact_literal_yfc):
-	is_eq_exact_lit_val = yb(Arg(0));
-	I++;
+    OpCase(i_is_eq_exact_literal_fyc):
+	is_eq_exact_lit_val = yb(Arg(1));
 	goto do_is_eq_exact_literal;
 
-    OpCase(i_is_eq_exact_literal_rfc):
-	is_eq_exact_lit_val = r(0);
-
     do_is_eq_exact_literal:
-	if (!eq(Arg(1), is_eq_exact_lit_val)) {
+	if (!eq(Arg(2), is_eq_exact_lit_val)) {
 	    ClauseFail();
 	}
-	Next(2);
+	Next(3);
     }
 
     {
 	Eterm is_ne_exact_lit_val;
 
-    OpCase(i_is_ne_exact_literal_xfc):
-	is_ne_exact_lit_val = xb(Arg(0));
-	I++;
+    OpCase(i_is_ne_exact_literal_fxc):
+	is_ne_exact_lit_val = xb(Arg(1));
 	goto do_is_ne_exact_literal;
 
-    OpCase(i_is_ne_exact_literal_yfc):
-	is_ne_exact_lit_val = yb(Arg(0));
-	I++;
+    OpCase(i_is_ne_exact_literal_fyc):
+	is_ne_exact_lit_val = yb(Arg(1));
 	goto do_is_ne_exact_literal;
 
-    OpCase(i_is_ne_exact_literal_rfc):
-	is_ne_exact_lit_val = r(0);
-
     do_is_ne_exact_literal:
-	if (eq(Arg(1), is_ne_exact_lit_val)) {
+	if (eq(Arg(2), is_ne_exact_lit_val)) {
 	    ClauseFail();
 	}
-	Next(2);
+	Next(3);
     }
 
  OpCase(move_window3_xxxy): {
@@ -1553,7 +1538,7 @@ void process_main(void)
      NextPF(6, next);
  }
 
- OpCase(i_move_call_only_fcr): {
+ OpCase(i_move_call_only_fc): {
      r(0) = Arg(1);
  }
  /* FALL THROUGH */
@@ -1563,7 +1548,7 @@ void process_main(void)
      Dispatch();
  }
 
- OpCase(i_move_call_last_fPcr): {
+ OpCase(i_move_call_last_fPc): {
      r(0) = Arg(2);
  }
  /* FALL THROUGH */
@@ -1575,7 +1560,7 @@ void process_main(void)
      Dispatch();
  }
 
- OpCase(i_move_call_crf): {
+ OpCase(i_move_call_cf): {
      r(0) = Arg(0);
      I++;
  }
@@ -1587,7 +1572,7 @@ void process_main(void)
      Dispatch();
  }
 
- OpCase(i_move_call_ext_last_ePcr): {
+ OpCase(i_move_call_ext_last_ePc): {
      r(0) = Arg(2);
  }
  /* FALL THROUGH */
@@ -1603,7 +1588,7 @@ void process_main(void)
     DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, Arg(0));
     Dispatchx();
 
- OpCase(i_move_call_ext_cre): {
+ OpCase(i_move_call_ext_ce): {
      r(0) = Arg(0);
      I++;
  }
@@ -1613,7 +1598,7 @@ void process_main(void)
     DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, Arg(0));
     Dispatchx();
 
- OpCase(i_move_call_ext_only_ecr): {
+ OpCase(i_move_call_ext_only_ec): {
      r(0) = Arg(1);
  }
  /* FALL THROUGH */
@@ -1707,29 +1692,23 @@ void process_main(void)
 	Eterm element_index;
 	Eterm element_tuple;
 
-    OpCase(i_element_xjsd):
-	element_tuple = xb(Arg(0));
-	I++;
+    OpCase(i_element_jxsd):
+	element_tuple = xb(Arg(1));
 	goto do_element;
 
-    OpCase(i_element_yjsd):
-	element_tuple = yb(Arg(0));
-	I++;
+    OpCase(i_element_jysd):
+	element_tuple = yb(Arg(1));
 	goto do_element;
 
-    OpCase(i_element_rjsd):
-	element_tuple = r(0);
-	/* Fall through */
-
     do_element:
-	GetArg1(1, element_index);
+	GetArg1(2, element_index);
 	if (is_small(element_index) && is_tuple(element_tuple)) {
 	    Eterm* tp = tuple_val(element_tuple);
 
 	    if ((signed_val(element_index) >= 1) &&
 		(signed_val(element_index) <= arityval(*tp))) {
 		Eterm result = tp[signed_val(element_index)];
-		StoreBifResult(2, result);
+		StoreBifResult(3, result);
 	    }
 	}
     }
@@ -1743,29 +1722,24 @@ void process_main(void)
     {
 	Eterm fast_element_tuple;
 
-    OpCase(i_fast_element_rjId):
-	fast_element_tuple = r(0);
+    OpCase(i_fast_element_jxId):
+     fast_element_tuple = xb(Arg(1));
+     goto do_fast_element;
+
+    OpCase(i_fast_element_jyId):
+     fast_element_tuple = yb(Arg(1));
+     goto do_fast_element;
 
     do_fast_element:
 	if (is_tuple(fast_element_tuple)) {
 	    Eterm* tp = tuple_val(fast_element_tuple);
-	    Eterm pos = Arg(1);	/* Untagged integer >= 1 */
+	    Eterm pos = Arg(2);	/* Untagged integer >= 1 */
 	    if (pos <= arityval(*tp)) {
 		Eterm result = tp[pos];
-		StoreBifResult(2, result);
+		StoreBifResult(3, result);
 	    }
 	}
      goto badarg;
-
-    OpCase(i_fast_element_xjId):
-     fast_element_tuple = xb(Arg(0));
-     I++;
-     goto do_fast_element;
-
-    OpCase(i_fast_element_yjId):
-     fast_element_tuple = yb(Arg(0));
-     I++;
-     goto do_fast_element;
  }
 
  OpCase(catch_yf):
@@ -1871,7 +1845,7 @@ void process_main(void)
      * Pick up the next message and place it in x(0).
      * If no message, jump to a wait or wait_timeout instruction.
      */
- OpCase(i_loop_rec_fr):
+ OpCase(i_loop_rec_f):
  {
      BeamInstr *next;
      ErlMessage* msgp;
@@ -2183,10 +2157,6 @@ void process_main(void)
      select_val2 = xb(Arg(0));
      goto do_select_tuple_arity2;
 
- OpCase(i_select_tuple_arity2_rfAAff):
-     select_val2 = r(0);
-     I--;
-
  do_select_tuple_arity2:
      if (is_not_tuple(select_val2)) {
 	 goto select_val2_fail;
@@ -2202,10 +2172,6 @@ void process_main(void)
      select_val2 = xb(Arg(0));
      goto do_select_val2;
 
- OpCase(i_select_val2_rfccff):
-     select_val2 = r(0);
-     I--;
-
  do_select_val2:
      if (select_val2 == Arg(2)) {
 	 I += 3;
@@ -2229,10 +2195,6 @@ void process_main(void)
      select_val = yb(Arg(0));
      goto do_select_tuple_arity;
 
- OpCase(i_select_tuple_arity_rfI):
-     select_val = r(0);
-     I--;
-
  do_select_tuple_arity:
      if (is_tuple(select_val)) {
 	 select_val = *tuple_val(select_val);
@@ -2249,10 +2211,6 @@ void process_main(void)
      select_val = yb(Arg(0));
      goto do_linear_search;
 
- OpCase(i_select_val_lins_rfI):
-     select_val = r(0);
-     I--;
-
  do_linear_search: {
      BeamInstr *vs = &Arg(3);
      int ix = 0;
@@ -2279,10 +2237,6 @@ void process_main(void)
      select_val = yb(Arg(0));
      goto do_binary_search;
      
- OpCase(i_select_val_bins_rfI):
-     select_val = r(0);
-     I--;
-
  do_binary_search:
  {
      struct Pairs {
@@ -2343,10 +2297,6 @@ void process_main(void)
      jump_on_val_zero_index = xb(Arg(0));
      goto do_jump_on_val_zero_index;
 
- OpCase(i_jump_on_val_zero_rfI):
-     jump_on_val_zero_index = r(0);
-     I--;
-
  do_jump_on_val_zero_index:
      if (is_small(jump_on_val_zero_index)) {
 	 jump_on_val_zero_index = signed_val(jump_on_val_zero_index);
@@ -2371,10 +2321,6 @@ void process_main(void)
      jump_on_val_index = xb(Arg(0));
      goto do_jump_on_val_index;
 
- OpCase(i_jump_on_val_rfII):
-     jump_on_val_index = r(0);
-     I--;
-
  do_jump_on_val_index:
      if (is_small(jump_on_val_index)) {
 	 jump_on_val_index = (Uint) (signed_val(jump_on_val_index) - Arg(3));
@@ -3441,18 +3387,8 @@ do {						\
     {
 	Eterm badmatch_val;
 
-    OpCase(badmatch_y):
-	badmatch_val = yb(Arg(0));
-	goto do_badmatch;
-
     OpCase(badmatch_x):
 	badmatch_val = xb(Arg(0));
-	goto do_badmatch;
-
-    OpCase(badmatch_r):
-	badmatch_val = r(0);
-
-    do_badmatch:
 	c_p->fvalue = badmatch_val;
 	c_p->freason = BADMATCH;
     }
@@ -3627,16 +3563,6 @@ do {						\
 
     OpCase(case_end_x):
 	case_end_val = xb(Arg(0));
-	goto do_case_end;
-
-    OpCase(case_end_y):
-	case_end_val = yb(Arg(0));
-	goto do_case_end;
-
-    OpCase(case_end_r):
-	case_end_val = r(0);
-
-    do_case_end:
 	c_p->fvalue = case_end_val;
 	c_p->freason = EXC_CASE_CLAUSE;
 	goto find_func_info;
@@ -3692,11 +3618,6 @@ do {						\
 	 goto do_bs_init_bits;
      }
 
-     OpCase(i_bs_init_bits_fail_rjId): {
-	 num_bits_term = r(0);
-	 alloc = 0;
-	 goto do_bs_init_bits;
-     }
      OpCase(i_bs_init_bits_fail_yjId): {
 	 num_bits_term = yb(Arg(0));
 	 I++;
@@ -3823,12 +3744,6 @@ do {						\
 	 goto do_bs_init;
      }
 
-     OpCase(i_bs_init_fail_rjId): {
-	 tmp_arg1 = r(0);
-	 tmp_arg2 = 0;
-	 goto do_bs_init;
-     }
-
      OpCase(i_bs_init_fail_yjId): {
 	 tmp_arg1 = yb(Arg(0));
 	 tmp_arg2 = 0;
@@ -4202,9 +4117,6 @@ do {						\
      Uint slots;
      Eterm context;
 
-     OpCase(i_bs_start_match2_rfIId): {
-	 context = r(0);
-
      do_start_match:
 	 slots = Arg(2);
 	 if (!is_boxed(context)) {
@@ -4251,7 +4163,7 @@ do {						\
 	     ClauseFail();
 	 }
 	 NextPF(4, next);
-     }
+
      OpCase(i_bs_start_match2_xfIId): {
 	 context = xb(Arg(0));
 	 I++;
@@ -4264,18 +4176,6 @@ do {						\
      }
  }
 
- OpCase(bs_test_zero_tail2_fr): {
-     BeamInstr *next;
-     ErlBinMatchBuffer *_mb;
-     
-     PreFetch(1, next);
-     _mb = (ErlBinMatchBuffer*) ms_matchbuffer(r(0));
-     if (_mb->size != _mb->offset) {
-	 ClauseFail();
-     }
-     NextPF(1, next);
- }
-
  OpCase(bs_test_zero_tail2_fx): {
      BeamInstr *next;
      ErlBinMatchBuffer *_mb;
@@ -4288,16 +4188,6 @@ do {						\
      NextPF(2, next);
  }
 
- OpCase(bs_test_tail_imm2_frI): {
-     BeamInstr *next;
-     ErlBinMatchBuffer *_mb;
-     PreFetch(2, next);
-     _mb = ms_matchbuffer(r(0));
-     if (_mb->size - _mb->offset != Arg(1)) {
-	 ClauseFail();
-     }
-     NextPF(2, next);
- }
  OpCase(bs_test_tail_imm2_fxI): {
      BeamInstr *next;
      ErlBinMatchBuffer *_mb;
@@ -4309,16 +4199,6 @@ do {						\
      NextPF(3, next);
  }
 
- OpCase(bs_test_unit_frI): {
-     BeamInstr *next;
-     ErlBinMatchBuffer *_mb;
-     PreFetch(2, next);
-     _mb = ms_matchbuffer(r(0));
-     if ((_mb->size - _mb->offset) % Arg(1)) {
-	 ClauseFail();
-     }
-     NextPF(2, next);
- }
  OpCase(bs_test_unit_fxI): {
      BeamInstr *next;
      ErlBinMatchBuffer *_mb;
@@ -4330,16 +4210,6 @@ do {						\
      NextPF(3, next);
  }
 
- OpCase(bs_test_unit8_fr): {
-     BeamInstr *next;
-     ErlBinMatchBuffer *_mb;
-     PreFetch(1, next);
-     _mb = ms_matchbuffer(r(0));
-     if ((_mb->size - _mb->offset) & 7) {
-	 ClauseFail();
-     }
-     NextPF(1, next);
- }
  OpCase(bs_test_unit8_fx): {
      BeamInstr *next;
      ErlBinMatchBuffer *_mb;
@@ -4354,19 +4224,11 @@ do {						\
  {
      Eterm bs_get_integer8_context;
 
- OpCase(i_bs_get_integer_8_rfd): {
-	 bs_get_integer8_context = r(0);
-	 goto do_bs_get_integer_8;
-     }
-
  OpCase(i_bs_get_integer_8_xfd): {
-	 bs_get_integer8_context = xb(Arg(0));
-	 I++;
-     }
-
- do_bs_get_integer_8: {
 	 ErlBinMatchBuffer *_mb;
 	 Eterm _result;
+	 bs_get_integer8_context = xb(Arg(0));
+	 I++;
 	 _mb = ms_matchbuffer(bs_get_integer8_context);
 	 if (_mb->size - _mb->offset < 8) {
 	     ClauseFail();
@@ -4384,15 +4246,10 @@ do {						\
  {
      Eterm bs_get_integer_16_context;
 
- OpCase(i_bs_get_integer_16_rfd):
-     bs_get_integer_16_context = r(0);
-     goto do_bs_get_integer_16;
-
  OpCase(i_bs_get_integer_16_xfd):
      bs_get_integer_16_context = xb(Arg(0));
      I++;
 
- do_bs_get_integer_16:
      {
 	 ErlBinMatchBuffer *_mb;
 	 Eterm _result;
@@ -4413,17 +4270,10 @@ do {						\
  {
      Eterm bs_get_integer_32_context;
 
- OpCase(i_bs_get_integer_32_rfId):
-     bs_get_integer_32_context = r(0);
-     goto do_bs_get_integer_32;
-
-     
  OpCase(i_bs_get_integer_32_xfId):
      bs_get_integer_32_context = xb(Arg(0));
      I++;
 
-
- do_bs_get_integer_32:
      {
 	 ErlBinMatchBuffer *_mb;
 	 Uint32 _integer;
@@ -4452,13 +4302,6 @@ do {						\
      }
  }
 
- /* Operands: Size Live Fail Flags Dst */
- OpCase(i_bs_get_integer_imm_rIIfId): {
-     tmp_arg1 = r(0);
-     /* Operands: Size Live Fail Flags Dst */
-     goto do_bs_get_integer_imm_test_heap;
- }
-
  /* Operands: x(Reg) Size Live Fail Flags Dst */
  OpCase(i_bs_get_integer_imm_xIIfId): {
      tmp_arg1 = xb(Arg(0));
@@ -4481,15 +4324,6 @@ do {						\
      goto do_bs_get_integer_imm;
  }
 
- /* Operands: Size Fail Flags Dst */
- OpCase(i_bs_get_integer_small_imm_rIfId): {
-     tmp_arg1 = r(0);
-     tmp_arg2 = Arg(0);
-     I++;
-     /* Operands: Fail Flags Dst */
-     goto do_bs_get_integer_imm;
- }
-
  /* Operands: x(Reg) Size Fail Flags Dst */
  OpCase(i_bs_get_integer_small_imm_xIfId): {
      tmp_arg1 = xb(Arg(0));
@@ -4563,11 +4397,6 @@ do {						\
      Eterm get_utf8_context;
 
      /* Operands: MatchContext Fail Dst */
- OpCase(i_bs_get_utf8_rfd): {
-	 get_utf8_context = r(0);
-	 goto do_bs_get_utf8;
-     }
-
  OpCase(i_bs_get_utf8_xfd): {
 	 get_utf8_context = xb(Arg(0));
 	 I++;
@@ -4578,7 +4407,7 @@ do {						\
       * Operands: Fail Dst
       */
 
- do_bs_get_utf8: {
+     {
 	 Eterm result = erts_bs_get_utf8(ms_matchbuffer(get_utf8_context));
 	 if (is_non_value(result)) {
 	     ClauseFail();
@@ -4591,12 +4420,7 @@ do {						\
      Eterm get_utf16_context;
 
      /* Operands: MatchContext Fail Flags Dst */
- OpCase(i_bs_get_utf16_rfId): {
-	 get_utf16_context = r(0);
-	 goto do_bs_get_utf16;
-     }
-
- OpCase(i_bs_get_utf16_xfId): {
+     OpCase(i_bs_get_utf16_xfId): {
 	 get_utf16_context = xb(Arg(0));
 	 I++;
      }
@@ -4605,7 +4429,7 @@ do {						\
       * get_utf16_context = match_context
       * Operands: Fail Flags Dst
       */
- do_bs_get_utf16: {
+     {
 	 Eterm result = erts_bs_get_utf16(ms_matchbuffer(get_utf16_context),
 					  Arg(1));
 	 if (is_non_value(result)) {
@@ -4624,26 +4448,10 @@ do {						\
      Uint orig;
      Uint hole_size;
 
-     OpCase(bs_context_to_binary_r): {
-	 context_to_binary_context = r(0);
-	 I -= 2;
-	 goto do_context_to_binary;
-     }
-
-     /* Unfortunately, inlining can generate this instruction. */
-     OpCase(bs_context_to_binary_y): {
-	 context_to_binary_context = yb(Arg(0));
-	 goto do_context_to_binary0;
-     }
-
-     OpCase(bs_context_to_binary_x): {
+     OpCase(bs_context_to_binary_x):
 	 context_to_binary_context = xb(Arg(0));
-     
-     do_context_to_binary0:
 	 I--;
-     }
 
- do_context_to_binary:
      if (is_boxed(context_to_binary_context) &&
 	 header_is_bin_matchstate(*boxed_val(context_to_binary_context))) {
 	 ErlBinMatchState* ms;
@@ -4655,17 +4463,11 @@ do {						\
      }
      Next(2);
 
-     OpCase(i_bs_get_binary_all_reuse_rfI): {
-	 context_to_binary_context = r(0);
-	 goto do_bs_get_binary_all_reuse;
-     }
-
      OpCase(i_bs_get_binary_all_reuse_xfI): {
 	 context_to_binary_context = xb(Arg(0));
 	 I++;
      }
 
- do_bs_get_binary_all_reuse:
      mb = ms_matchbuffer(context_to_binary_context);
      size = mb->size - mb->offset;
      if (size % Arg(1) != 0) {
@@ -4693,16 +4495,11 @@ do {						\
  {
      Eterm match_string_context;
 
-     OpCase(i_bs_match_string_rfII): {
-	 match_string_context = r(0);
-	 goto do_bs_match_string;
-     }
      OpCase(i_bs_match_string_xfII): {
 	 match_string_context = xb(Arg(0));
 	 I++;
      }
 
- do_bs_match_string:
      {
 	 BeamInstr *next;
 	 byte* bytes;
@@ -4730,14 +4527,6 @@ do {						\
      }
  }
 
- OpCase(i_bs_save2_rI): {
-     BeamInstr *next;
-     ErlBinMatchState *_ms;
-     PreFetch(1, next);
-     _ms = (ErlBinMatchState*) boxed_val((Eterm) r(0));
-     _ms->save_offset[Arg(0)] = _ms->mb.offset;
-     NextPF(1, next);
- }
  OpCase(i_bs_save2_xI): {
      BeamInstr *next;
      ErlBinMatchState *_ms;
@@ -4747,14 +4536,6 @@ do {						\
      NextPF(2, next);
  }
 
- OpCase(i_bs_restore2_rI): {
-     BeamInstr *next;
-     ErlBinMatchState *_ms;
-     PreFetch(1, next);
-     _ms = (ErlBinMatchState*) boxed_val((Eterm) r(0));
-     _ms->mb.offset = _ms->save_offset[Arg(0)];
-     NextPF(1, next);
- }
  OpCase(i_bs_restore2_xI): {
      BeamInstr *next;
      ErlBinMatchState *_ms;
@@ -5030,7 +4811,9 @@ do {						\
      switch( c_p->def_arg_reg[3] ) {
        case HIPE_MODE_SWITCH_RES_RETURN:
 	 ASSERT(is_value(reg[0]));
-	 MoveReturn(reg[0], r(0));
+	 SET_I(c_p->cp);
+	 c_p->cp = 0;
+	 Goto(*I);
        case HIPE_MODE_SWITCH_RES_CALL_EXPORTED:
 	 c_p->i = c_p->hipe.u.callee_exp->addressv[erts_active_code_ix()];
 	 /*fall through*/
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 3cd80c4ec2..3671baa552 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1847,9 +1847,7 @@ load_code(LoaderState* stp)
 	    case TAG_o:
 		break;
 	    case TAG_x:
-		if (last_op->a[arg].val == 0) {
-		    last_op->a[arg].type = TAG_r;
-		} else if (last_op->a[arg].val >= MAX_REG) {
+		if (last_op->a[arg].val >= MAX_REG) {
 		    LoadError1(stp, "invalid x register number: %u",
 			       last_op->a[arg].val);
 		}
@@ -2055,7 +2053,42 @@ load_code(LoaderState* stp)
 		if (((opc[specific].mask[0] & mask[0]) == mask[0]) &&
 		    ((opc[specific].mask[1] & mask[1]) == mask[1]) &&
 		    ((opc[specific].mask[2] & mask[2]) == mask[2])) {
-		    break;
+
+		    if (!opc[specific].involves_r) {
+			break;	/* No complications - match */
+		    }
+
+		    /*
+		     * The specific operation uses the 'r' operand,
+		     * which is shorthand for x(0). Now things
+		     * get complicated. First we must check whether
+		     * all operands that should be of type 'r' use
+		     * x(0) (as opposed to some other X register).
+		     */
+		    for (arg = 0; arg < arity; arg++) {
+			if (opc[specific].involves_r & (1 << arg) &&
+			    tmp_op->a[arg].type == TAG_x) {
+			    if (tmp_op->a[arg].val != 0) {
+				break; /* Other X register than 0 */
+			    }
+			}
+		    }
+
+		    if (arg == arity) {
+			/*
+			 * All 'r' operands use x(0) in the generic
+			 * operation. That means a match. Now we
+			 * will need to rewrite the generic instruction
+			 * to actually use 'r' instead of 'x(0)'.
+			 */
+			for (arg = 0; arg < arity; arg++) {
+			    if (opc[specific].involves_r & (1 << arg) &&
+				tmp_op->a[arg].type == TAG_x) {
+				tmp_op->a[arg].type = TAG_r;
+			    }
+			}
+			break;	/* Match */
+		    }
 		}
 		specific++;
 	    }
@@ -2166,9 +2199,6 @@ load_code(LoaderState* stp)
 		break;
 	    case 's':	/* Any source (tagged constant or register) */
 		switch (tag) {
-		case TAG_r:
-		    code[ci++] = make_loader_x_reg(0);
-		    break;
 		case TAG_x:
 		    code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
 		    break;
@@ -2196,9 +2226,6 @@ load_code(LoaderState* stp)
 		break;
 	    case 'd':	/* Destination (x(0), x(N), y(N) */
 		switch (tag) {
-		case TAG_r:
-		    code[ci++] = make_loader_x_reg(0);
-		    break;
 		case TAG_x:
 		    code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
 		    break;
@@ -2360,7 +2387,6 @@ load_code(LoaderState* stp)
 		stp->labels[tmp_op->a[arg].val].patches = ci;
 		ci++;
 		break;
-	    case TAG_r:
 	    case TAG_x:
 		CodeNeed(1);
 		code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
@@ -2455,7 +2481,6 @@ load_code(LoaderState* stp)
 	    stp->on_load = ci;
 	    break;
 	case op_bs_put_string_II:
-	case op_i_bs_match_string_rfII:
 	case op_i_bs_match_string_xfII:
 	    new_string_patch(stp, ci-1);
 	    break;
@@ -2693,17 +2718,17 @@ gen_element(LoaderState* stp, GenOpArg Fail, GenOpArg Index,
     op->next = NULL;
 
     if (Index.type == TAG_i && Index.val > 0 &&
-	(Tuple.type == TAG_r || Tuple.type == TAG_x || Tuple.type == TAG_y)) {
+	(Tuple.type == TAG_x || Tuple.type == TAG_y)) {
 	op->op = genop_i_fast_element_4;
-	op->a[0] = Tuple;
-	op->a[1] = Fail;
+	op->a[0] = Fail;
+	op->a[1] = Tuple;
 	op->a[2].type = TAG_u;
 	op->a[2].val = Index.val;
 	op->a[3] = Dst;
     } else {
 	op->op = genop_i_element_4;
-	op->a[0] = Tuple;
-	op->a[1] = Fail;
+	op->a[0] = Fail;
+	op->a[1] = Tuple;
 	op->a[2] = Index;
 	op->a[3] = Dst;
     }
@@ -4798,7 +4823,8 @@ transform_engine(LoaderState* st)
 	    if (var[i].type != instr->a[ap].type)
 		goto restart;
 	    switch (var[i].type) {
-	    case TAG_r: case TAG_n: break;
+	    case TAG_n:
+		break;
 	    default:
 		if (var[i].val != instr->a[ap].val)
 		    goto restart;
@@ -5865,7 +5891,7 @@ make_stub(BeamInstr* fp, Eterm mod, Eterm func, Uint arity, Uint native, BeamIns
     fp[4] = arity;
 #ifdef HIPE
     if (native) {
-	fp[5] = BeamOpCode(op_move_return_nr);
+	fp[5] = BeamOpCode(op_move_return_n);
 	hipe_mfa_save_orig_beam_op(mod, func, arity, fp+5);
     }
 #endif
@@ -6301,7 +6327,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
 #ifdef HIPE
 	op = (Eterm) BeamOpCode(op_hipe_trap_call); /* Might be changed later. */
 #else
-	op = (Eterm) BeamOpCode(op_move_return_nr);
+	op = (Eterm) BeamOpCode(op_move_return_n);
 #endif
 	fp = make_stub(fp, Mod, func, arity, (Uint)native_address, op);
     }
diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h
index cfc978b5a5..98f27a1725 100644
--- a/erts/emulator/beam/erl_vm.h
+++ b/erts/emulator/beam/erl_vm.h
@@ -141,6 +141,7 @@
 typedef struct op_entry {
    char* name;			/* Name of instruction. */
    Uint32 mask[3];		/* Signature mask. */
+   unsigned involves_r;		/* Needs special attention when matching. */
    int sz;			/* Number of loaded words. */
    char* pack;			/* Instructions for packing engine. */
    char* sign;			/* Signature string. */
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 4fa6a087e2..335f8e2db5 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -39,8 +39,8 @@ too_old_compiler | never() =>
 # necessary.) Since the instructions don't work correctly in R12B, simply
 # refuse to load the module.
 
-func_info M=a a==am_module_info A=u==0 | label L | move n r => too_old_compiler
-func_info M=a a==am_module_info A=u==1 | label L | move n r => too_old_compiler
+func_info M=a a==am_module_info A=u==0 | label L | move n x==0 => too_old_compiler
+func_info M=a a==am_module_info A=u==1 | label L | move n x==0 => too_old_compiler
 
 # The undocumented and unsupported guard BIF is_constant/1 was removed
 # in R13. The is_constant/2 operation is marked as obsolete in genop.tab,
@@ -77,14 +77,14 @@ return
 # there is no line/1 instruction between the move and the call.
 #
 
-move S r | line Loc | call_ext Ar Func => \
-     line Loc | move S r | call_ext Ar Func
-move S r | line Loc | call_ext_last Ar Func=u$is_bif D => \
-     line Loc | move S r | call_ext_last Ar Func D
-move S r | line Loc | call_ext_only Ar Func=u$is_bif => \
-     line Loc | move S r | call_ext_only Ar Func
-move S r | line Loc | call Ar Func => \
-     line Loc | move S r | call Ar Func
+move S X0=x==0 | line Loc | call_ext Ar Func => \
+     line Loc | move S X0 | call_ext Ar Func
+move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_bif D => \
+     line Loc | move S X0 | call_ext_last Ar Func D
+move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_bif => \
+     line Loc | move S X0 | call_ext_only Ar Func
+move S X0=x==0 | line Loc | call Ar Func => \
+     line Loc | move S X0 | call Ar Func
 
 #
 # A tail-recursive call to an external function (non-BIF) will
@@ -167,31 +167,24 @@ is_tuple Fail=f S | select_tuple_arity S=d Fail=f Size=u Rest=* => \
 select_tuple_arity S=d Fail=f Size=u Rest=* => \
   gen_select_tuple_arity(S, Fail, Size, Rest)
 
-i_select_val_bins r f I
 i_select_val_bins x f I
 i_select_val_bins y f I
 
-i_select_val_lins r f I
 i_select_val_lins x f I
 i_select_val_lins y f I
 
-i_select_val2 r f c c f f
 i_select_val2 x f c c f f
 i_select_val2 y f c c f f
 
-i_select_tuple_arity r f I
 i_select_tuple_arity x f I
 i_select_tuple_arity y f I
 
-i_select_tuple_arity2 r f A A f f
 i_select_tuple_arity2 x f A A f f
 i_select_tuple_arity2 y f A A f f
 
-i_jump_on_val_zero r f I
 i_jump_on_val_zero x f I
 i_jump_on_val_zero y f I
 
-i_jump_on_val r f I I
 i_jump_on_val x f I I
 i_jump_on_val y f I I
 
@@ -203,30 +196,13 @@ is_ne_exact L1 S1 S2 | jump Fail | label L2 | same_label(L1, L2) => \
 %macro: get_list GetList -pack
 get_list x x x
 get_list x x y
-get_list x x r
 get_list x y x
 get_list x y y
-get_list x y r
-get_list x r x
-get_list x r y
 
 get_list y x x
 get_list y x y
-get_list y x r
 get_list y y x
 get_list y y y
-get_list y y r
-get_list y r x
-get_list y r y
-
-get_list r x x
-get_list r x y
-get_list r x r
-get_list r y x
-get_list r y y
-get_list r y r
-get_list r r x
-get_list r r y
 
 # Old-style catch.
 catch y f
@@ -247,21 +223,15 @@ set_tuple_element s d P
 
 %macro: i_get_tuple_element GetTupleElement -pack
 i_get_tuple_element x P x
-i_get_tuple_element r P x
 i_get_tuple_element y P x
-i_get_tuple_element x P r
-i_get_tuple_element y P r
 
 %cold
-i_get_tuple_element r P r
 i_get_tuple_element x P y
-i_get_tuple_element r P y
 i_get_tuple_element y P y
 %hot
 
 %macro: is_number IsNumber -fail_action
 %cold
-is_number f r
 is_number f x
 is_number f y
 %hot
@@ -271,16 +241,12 @@ is_number Fail Literal=q => move Literal x | is_number Fail x
 
 jump f
 
-case_end Literal=c => move Literal x | case_end x
-badmatch Literal=c => move Literal x | badmatch x
+case_end NotInX=cy => move NotInX x | case_end x
+badmatch NotInX=cy => move NotInX x | badmatch x
 
-case_end r
 case_end x
-case_end y
 
-badmatch r
 badmatch x
-badmatch y
 
 if_end
 raise s s
@@ -289,7 +255,7 @@ raise s s
 badarg j
 system_limit j
 
-move C=cxy r | jump Lbl => move_jump Lbl C
+move C=cxy x==0 | jump Lbl => move_jump Lbl C
 
 %macro: move_jump MoveJump -nonext
 move_jump f n
@@ -307,8 +273,6 @@ move_window/6
 
 # x -> y
 
-move S1=r S2=y | move X1=x Y1=y => move2 S1 S2 X1 Y1
-
 move X1=x Y1=y | move X2=x Y2=y | move X3=x Y3=y | succ(Y1,Y2) | succ(Y2,Y3) => \
     move_window X1 X2 X3 Y1 Y3
 
@@ -329,12 +293,13 @@ move X1=x Y1=y | move X2=x Y2=y => move2 X1 Y1 X2 Y2
 move Y1=y X1=x | move Y2=y X2=x => move2 Y1 X1 Y2 X2
 move X1=x X2=x | move X3=x X4=x => move2 X1 X2 X3 X4
 
-move S1=x S2=r | move S3=x S4=x => move2 S1 S2 S3 S4
-move S1=x S2=r | move X1=x Y1=y => move2 S1 S2 X1 Y1
-move S1=y S2=r | move X1=x Y1=y => move2 S1 S2 X1 Y1
+move X1=x X2=x | move X3=x Y1=y => move2 X1 X2 X3 Y1
+
+move S1=x S2=x | move X1=x Y1=y => move2 S1 S2 X1 Y1
+move S1=y S2=x | move X1=x Y1=y => move2 S1 S2 X1 Y1
 
-move Y1=y X1=x | move S1=r D1=x => move2 Y1 X1 S1 D1
-move S1=r D1=x | move Y1=y X1=x => move2 S1 D1 Y1 X1
+move Y1=y X1=x | move S1=x D1=x => move2 Y1 X1 S1 D1
+move S1=x D1=x | move Y1=y X1=x => move2 S1 D1 Y1 X1
 
 move2 X1=x Y1=y X2=x Y2=y | move X3=x Y3=y => move3 X1 Y1 X2 Y2 X3 Y3
 move2 Y1=y X1=x Y2=y X2=x | move Y3=y X3=x => move3 Y1 X1 Y2 X2 Y3 X3
@@ -351,14 +316,13 @@ move2 x y x y
 move2 y x y x
 move2 x x x x
 
-move2 x r x x
+move2 x x x y
 
-move2 x r x y
-move2 r y x y
-move2 y r x y
+move2 x y x y
+move2 y x x y
 
-move2 r x y x
-move2 y x r x
+move2 x x y x
+move2 y x x x
 
 %macro: move3 Move3
 move3 x y x y x y
@@ -373,20 +337,14 @@ move S=c D=y => move S x | move x D
 %macro:move Move -pack -gen_dest
 move x x
 move x y
-move x r
 move y x
-move y r
-move r x
-move r y
-move c r
 move c x
 move n x
-move n r
 move y y
 
 # Receive operations.
 
-loop_rec Fail Src | smp_mark_target_label(Fail) => i_loop_rec Fail Src
+loop_rec Fail x==0 | smp_mark_target_label(Fail) => i_loop_rec Fail
 
 label L | wait_timeout Fail Src | smp_already_locked(L) => label L | i_wait_timeout_locked Fail Src
 wait_timeout Fail Src => i_wait_timeout Fail Src
@@ -401,7 +359,7 @@ label L | timeout | smp_already_locked(L) => label L | timeout_locked
 remove_message
 timeout
 timeout_locked
-i_loop_rec f r
+i_loop_rec f
 loop_rec_end f
 wait f
 wait_locked f
@@ -419,29 +377,25 @@ send
 # Optimized comparisons with one immediate/literal operand.
 #
 
-is_eq_exact Lbl R=rxy C=ian => i_is_eq_exact_immed Lbl R C
-is_eq_exact Lbl R=rxy C=q => i_is_eq_exact_literal R Lbl C
+is_eq_exact Lbl R=xy C=ian => i_is_eq_exact_immed Lbl R C
+is_eq_exact Lbl R=xy C=q => i_is_eq_exact_literal Lbl R C
 
-is_ne_exact Lbl R=rxy C=ian => i_is_ne_exact_immed Lbl R C
-is_ne_exact Lbl R=rxy C=q => i_is_ne_exact_literal R Lbl C
+is_ne_exact Lbl R=xy C=ian => i_is_ne_exact_immed Lbl R C
+is_ne_exact Lbl R=xy C=q => i_is_ne_exact_literal Lbl R C
 
 %macro: i_is_eq_exact_immed EqualImmed -fail_action
-i_is_eq_exact_immed f r c
 i_is_eq_exact_immed f x c
 i_is_eq_exact_immed f y c
 
-i_is_eq_exact_literal r f c
-i_is_eq_exact_literal x f c
-i_is_eq_exact_literal y f c
+i_is_eq_exact_literal f x c
+i_is_eq_exact_literal f y c
 
 %macro: i_is_ne_exact_immed NotEqualImmed -fail_action
-i_is_ne_exact_immed f r c
 i_is_ne_exact_immed f x c
 i_is_ne_exact_immed f y c
 
-i_is_ne_exact_literal r f c
-i_is_ne_exact_literal x f c
-i_is_ne_exact_literal y f c
+i_is_ne_exact_literal f x c
+i_is_ne_exact_literal f y c
 
 #
 # Common Compare Specializations
@@ -449,31 +403,21 @@ i_is_ne_exact_literal y f c
 # to keep the instruction set small-ish
 #
 
-is_eq_exact Lbl S1=xy S2=r => is_eq_exact Lbl S2 S1
-is_eq_exact Lbl S1=rx S2=xy => i_is_eq_exact_spec Lbl S1 S2
+is_eq_exact Lbl S1=y S2=x => is_eq_exact Lbl S2 S1
+is_eq_exact Lbl S1=x S2=xy => i_is_eq_exact_spec Lbl S1 S2
 %macro: i_is_eq_exact_spec EqualExact -fail_action
 
 i_is_eq_exact_spec f x x
 i_is_eq_exact_spec f x y
-i_is_eq_exact_spec f r x
-i_is_eq_exact_spec f r y
-%cold
-i_is_eq_exact_spec f r r
-%hot
 
-is_lt Lbl S1=rxc S2=rxc  => i_is_lt_spec Lbl S1 S2
+is_lt Lbl S1=xc S2=xc  => i_is_lt_spec Lbl S1 S2
 
 %macro: i_is_lt_spec IsLessThan -fail_action
 
 i_is_lt_spec f x x
-i_is_lt_spec f x r
 i_is_lt_spec f x c
-i_is_lt_spec f r x
-i_is_lt_spec f r c
 i_is_lt_spec f c x
-i_is_lt_spec f c r
 %cold
-i_is_lt_spec f r r
 i_is_lt_spec f c c
 %hot
 
@@ -523,7 +467,6 @@ i_put_tuple Dst Arity Puts=* | put S => \
 i_put_tuple/2
 
 %macro:i_put_tuple PutTuple -pack -goto:do_put_tuple
-i_put_tuple r I
 i_put_tuple x I
 i_put_tuple y I
 
@@ -540,48 +483,25 @@ put_list x n x
 put_list y n x
 put_list x x x
 put_list y x x
-put_list x x r
-put_list y r r
 
 put_list y y x
 put_list x y x
-put_list r x x
-put_list r y x
-put_list r x r
-put_list y y r
-put_list y r x
-put_list r n x
-
-put_list x r x
-put_list x y r
-put_list y x r
-put_list y x x
 
-put_list x r r
+put_list y x x
 
 # put_list SrcReg Constant Dst
-put_list r c r
-put_list r c x
-put_list r c y
 
-put_list x c r
 put_list x c x
 put_list x c y
 
-put_list y c r
 put_list y c x
 put_list y c y
 
 # put_list Constant SrcReg Dst
-put_list c r r
-put_list c r x
-put_list c r y
 
-put_list c x r
 put_list c x x
 put_list c x y
 
-put_list c y r
 put_list c y x
 put_list c y y
 
@@ -590,18 +510,12 @@ put_list s s d
 %hot
 
 %macro: i_fetch FetchArgs -pack
-i_fetch c r
 i_fetch c x
 i_fetch c y
-i_fetch r c
-i_fetch r x
-i_fetch r y
 i_fetch x c
-i_fetch x r
 i_fetch x x
 i_fetch x y
 i_fetch y c
-i_fetch y r
 i_fetch y x
 i_fetch y y
 
@@ -629,27 +543,27 @@ return_trace
 # Note: There is no 'move_return y r', since there never are any y registers
 # when we do move_return (if we have y registers, we must do move_deallocate_return).
 
-move S r | return => move_return S r
+move S x==0 | return => move_return S
 
 %macro: move_return MoveReturn -nonext
-move_return x r
-move_return c r
-move_return n r
+move_return x
+move_return c
+move_return n
 
-move S r | deallocate D | return => move_deallocate_return S r D
+move S x==0 | deallocate D | return => move_deallocate_return S D
 
 %macro: move_deallocate_return MoveDeallocateReturn -pack -nonext
-move_deallocate_return x r Q
-move_deallocate_return y r Q
-move_deallocate_return c r Q
-move_deallocate_return n r Q
+move_deallocate_return x Q
+move_deallocate_return y Q
+move_deallocate_return c Q
+move_deallocate_return n Q
 
 deallocate D | return => deallocate_return D
 
 %macro: deallocate_return DeallocateReturn -nonext
 deallocate_return Q
 
-test_heap Need u==1 | put_list Y=y r r => test_heap_1_put_list Need Y
+test_heap Need u==1 | put_list Y=y x==0 x==0 => test_heap_1_put_list Need Y
 
 %macro: test_heap_1_put_list TestHeapPutList -pack
 test_heap_1_put_list I y
@@ -658,18 +572,16 @@ test_heap_1_put_list I y
 
 is_tuple Fail Literal=q => move Literal x | is_tuple Fail x
 is_tuple Fail=f c => jump Fail
-is_tuple Fail=f S=rxy | test_arity Fail=f S=rxy Arity => is_tuple_of_arity Fail S Arity
+is_tuple Fail=f S=xy | test_arity Fail=f S=xy Arity => is_tuple_of_arity Fail S Arity
 
 %macro:is_tuple_of_arity IsTupleOfArity -fail_action
 
 is_tuple_of_arity f x A
 is_tuple_of_arity f y A
-is_tuple_of_arity f r A
 
 %macro: is_tuple IsTuple -fail_action
 is_tuple f x
 is_tuple f y
-is_tuple f r
 
 test_arity Fail Literal=q Arity => move Literal x | test_arity Fail x Arity
 test_arity Fail=f c Arity => jump Fail
@@ -677,7 +589,6 @@ test_arity Fail=f c Arity => jump Fail
 %macro: test_arity IsArity -fail_action
 test_arity f x A
 test_arity f y A
-test_arity f r A
 
 is_tuple_of_arity Fail=f Reg Arity | get_tuple_element Reg P=u==0 Dst=xy => \
   is_tuple_of_arity Fail Reg Arity | extract_next_element Dst | original_reg Reg P
@@ -726,46 +637,40 @@ is_integer Fail=f i =>
 is_integer Fail=f an => jump Fail
 is_integer Fail Literal=q => move Literal x | is_integer Fail x
 
-is_integer Fail=f S=rx | allocate Need Regs => is_integer_allocate Fail S Need Regs
+is_integer Fail=f S=x | allocate Need Regs => is_integer_allocate Fail S Need Regs
 
 %macro: is_integer_allocate IsIntegerAllocate -fail_action
 is_integer_allocate f x I I
-is_integer_allocate f r I I
 
 %macro: is_integer IsInteger -fail_action
 is_integer f x
 is_integer f y
-is_integer f r
 
 is_list Fail=f n =>
 is_list Fail Literal=q => move Literal x | is_list Fail x
 is_list Fail=f c => jump Fail
 %macro: is_list IsList -fail_action
-is_list f r
 is_list f x
 %cold
 is_list f y
 %hot
 
-is_nonempty_list Fail=f S=rx | allocate Need Rs => is_nonempty_list_allocate Fail S Need Rs
+is_nonempty_list Fail=f S=x | allocate Need Rs => is_nonempty_list_allocate Fail S Need Rs
 
 %macro:is_nonempty_list_allocate IsNonemptyListAllocate -fail_action -pack
 is_nonempty_list_allocate f x I t
-is_nonempty_list_allocate f r I t
 
-is_nonempty_list F=f r | test_heap I1 I2 => is_non_empty_list_test_heap F r I1 I2
+is_nonempty_list F=f x==0 | test_heap I1 I2 => is_non_empty_list_test_heap F I1 I2
 
 %macro: is_non_empty_list_test_heap IsNonemptyListTestHeap -fail_action -pack
-is_non_empty_list_test_heap f r I t
+is_non_empty_list_test_heap f I t
 
 %macro: is_nonempty_list IsNonemptyList -fail_action
 is_nonempty_list f x
 is_nonempty_list f y
-is_nonempty_list f r
 
 %macro: is_atom IsAtom -fail_action
 is_atom f x
-is_atom f r
 %cold
 is_atom f y
 %hot
@@ -773,7 +678,6 @@ is_atom Fail=f a =>
 is_atom Fail=f niq => jump Fail
 
 %macro: is_float IsFloat -fail_action
-is_float f r
 is_float f x
 %cold
 is_float f y
@@ -787,12 +691,10 @@ is_nil Fail=f qia => jump Fail
 %macro: is_nil IsNil -fail_action
 is_nil f x
 is_nil f y
-is_nil f r
 
 is_binary Fail Literal=q => move Literal x | is_binary Fail x
 is_binary Fail=f c => jump Fail
 %macro: is_binary IsBinary -fail_action
-is_binary f r
 is_binary f x
 %cold
 is_binary f y
@@ -804,7 +706,6 @@ is_bitstr Fail Term => is_bitstring Fail Term
 is_bitstring Fail Literal=q => move Literal x | is_bitstring Fail x
 is_bitstring Fail=f c => jump Fail
 %macro: is_bitstring IsBitstring -fail_action
-is_bitstring f r
 is_bitstring f x
 %cold
 is_bitstring f y
@@ -812,7 +713,6 @@ is_bitstring f y
 
 is_reference Fail=f cq => jump Fail
 %macro: is_reference IsRef -fail_action
-is_reference f r
 is_reference f x
 %cold
 is_reference f y
@@ -820,7 +720,6 @@ is_reference f y
 
 is_pid Fail=f cq => jump Fail
 %macro: is_pid IsPid -fail_action
-is_pid f r
 is_pid f x
 %cold
 is_pid f y
@@ -828,7 +727,6 @@ is_pid f y
 
 is_port Fail=f cq => jump Fail
 %macro: is_port IsPort -fail_action
-is_port f r
 is_port f x
 %cold
 is_port f y
@@ -840,7 +738,6 @@ is_boolean Fail=f ac => jump Fail
 
 %cold
 %macro: is_boolean IsBoolean -fail_action
-is_boolean f r
 is_boolean f x
 is_boolean f y
 %hot
@@ -986,76 +883,76 @@ call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate
 %unless USE_VM_PROBES
 
 call_ext Arity u$func:erlang:dt_get_tag/0 => \
-    move a=am_undefined r
+    move a=am_undefined x=0
 call_ext_last Arity u$func:erlang:dt_get_tag/0 D => \
-    move a=am_undefined r | deallocate D | return
+    move a=am_undefined x=0 | deallocate D | return
 call_ext_only Arity u$func:erlang:dt_get_tag/0 => \
-    move a=am_undefined r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_put_tag/1 => \
-    move a=am_undefined r
-move Any r | call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
-    move a=am_undefined r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
-    move a=am_undefined r | return
+    move a=am_undefined x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_put_tag/1 => \
+    move a=am_undefined x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
+    move a=am_undefined x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
+    move a=am_undefined x=0 | return
 call_ext Arity u$func:erlang:dt_put_tag/1 => \
-    move a=am_undefined r
+    move a=am_undefined x=0
 call_ext_last Arity u$func:erlang:dt_put_tag/1 D => \
-    move a=am_undefined r | deallocate D | return
+    move a=am_undefined x=0 | deallocate D | return
 call_ext_only Arity u$func:erlang:dt_put_tag/1 => \
-    move a=am_undefined r | return
+    move a=am_undefined x=0 | return
 
 call_ext Arity u$func:erlang:dt_get_tag_data/0 => \
-    move a=am_undefined r
+    move a=am_undefined x=0
 call_ext_last Arity u$func:erlang:dt_get_tag_data/0 D => \
-    move a=am_undefined r | deallocate D | return
+    move a=am_undefined x=0 | deallocate D | return
 call_ext_only Arity u$func:erlang:dt_get_tag_data/0 => \
-    move a=am_undefined r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_spread_tag/1 => \
-    move a=am_true r
-move Any r | call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
-    move a=am_true r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
-    move a=am_true r | return
+    move a=am_undefined x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_spread_tag/1 => \
+    move a=am_true x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
+    move a=am_true x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
+    move a=am_true x=0 | return
 call_ext Arity u$func:erlang:dt_spread_tag/1 => \
-    move a=am_true r
+    move a=am_true x=0
 call_ext_last Arity u$func:erlang:dt_spread_tag/1 D => \
-    move a=am_true r | deallocate D | return
+    move a=am_true x=0 | deallocate D | return
 call_ext_only Arity u$func:erlang:dt_spread_tag/1 => \
-    move a=am_true r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_restore_tag/1 => \
-    move a=am_true r
-move Any r | call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
-    move a=am_true r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
-    move a=am_true r | return
+    move a=am_true x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_restore_tag/1 => \
+    move a=am_true x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
+    move a=am_true x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
+    move a=am_true x=0 | return
 call_ext Arity u$func:erlang:dt_restore_tag/1 => \
-    move a=am_true r
+    move a=am_true x=0
 call_ext_last Arity u$func:erlang:dt_restore_tag/1 D => \
-    move a=am_true r | deallocate D | return
+    move a=am_true x=0 | deallocate D | return
 call_ext_only Arity u$func:erlang:dt_restore_tag/1 => \
-    move a=am_true r | return
-
-move Any r | call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
-    move Any r
-move Any r | call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
-    move Any r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
-    move Any r | return
+    move a=am_true x=0 | return
+
+move Any x==0 | call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+    move Any x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
+    move Any x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
+    move Any x=0 | return
 call_ext Arity u$func:erlang:dt_prepend_vm_tag_data/1 =>
 call_ext_last Arity u$func:erlang:dt_prepend_vm_tag_data/1 D => \
     deallocate D | return
 call_ext_only Arity u$func:erlang:dt_prepend_vm_tag_data/1 => \
     return
 
-move Any r | call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => \
-    move Any r
-move Any r | call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
-    move Any r | deallocate D | return
-move Any r | call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
-    move Any r | return
+move Any x==0 | call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+    move Any x=0
+move Any x==0 | call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
+    move Any x=0 | deallocate D | return
+move Any x==0 | call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
+    move Any x=0 | return
 call_ext Arity u$func:erlang:dt_append_vm_tag_data/1 =>
 call_ext_last Arity u$func:erlang:dt_append_vm_tag_data/1 D => \
     deallocate D | return
@@ -1063,7 +960,7 @@ call_ext_only Arity u$func:erlang:dt_append_vm_tag_data/1 => \
     return
 
 # Can happen after one of the transformations above.
-move Discarded r | move Something r => move Something r
+move Discarded x==0 | move Something x==0 => move Something x=0
 
 %endif
 
@@ -1088,9 +985,9 @@ call_ext_only Ar=u Bif=u$is_bif => \
 # with call instructions.
 #
 
-move S=c r | call_ext Ar=u Func=u$is_not_bif => i_move_call_ext S r Func
-move S=c r | call_ext_last Ar=u Func=u$is_not_bif D => i_move_call_ext_last Func D S r
-move S=c r | call_ext_only Ar=u Func=u$is_not_bif => i_move_call_ext_only Func S r 
+move S=c x==0 | call_ext Ar=u Func=u$is_not_bif => i_move_call_ext S Func
+move S=c x==0 | call_ext_last Ar=u Func=u$is_not_bif D => i_move_call_ext_last Func D S
+move S=c x==0 | call_ext_only Ar=u Func=u$is_not_bif => i_move_call_ext_only Func S
 
 call_ext Ar Func        => i_call_ext Func
 call_ext_last Ar Func D => i_call_ext_last Func D
@@ -1117,7 +1014,7 @@ bif0 u$bif:erlang:node/0 Dst=d => node Dst
 
 bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => i_get Src Dst
 
-bif2 Jump=j u$bif:erlang:element/2 S1=s S2=rxy Dst=d => gen_element(Jump, S1, S2, Dst)
+bif2 Jump=j u$bif:erlang:element/2 S1=s S2=xy Dst=d => gen_element(Jump, S1, S2, Dst)
 
 bif1 p Bif S1 Dst => bif1_body Bif S1 Dst
 
@@ -1127,24 +1024,20 @@ bif2 Fail Bif S1 S2 Dst => i_fetch S1 S2 | i_bif2 Fail Bif Dst
 i_get s d
 
 %macro: self Self
-self r
 self x
 self y
 
 %macro: node Node
-node r
 node x
 %cold
 node y
 %hot
 
-i_fast_element r j I d
-i_fast_element x j I d
-i_fast_element y j I d
+i_fast_element j x I d
+i_fast_element j y I d
 
-i_element r j s d
-i_element x j s d
-i_element y j s d
+i_element j x s d
+i_element j y s d
 
 bif1 f b s d
 bif1_body b s d
@@ -1155,37 +1048,37 @@ i_bif2_body b d
 # Internal calls.
 #
 
-move S=c r | call Ar P=f => i_move_call S r P
-move S=s r | call Ar P=f => move_call S r P
+move S=c x==0 | call Ar P=f => i_move_call S P
+move S=s x==0 | call Ar P=f => move_call S P
 
-i_move_call c r f
+i_move_call c f
 
 %macro:move_call MoveCall -arg_f -size -nonext
-move_call/3
+move_call/2
 
-move_call x r f
-move_call y r f
+move_call x f
+move_call y f
 
-move S=c r | call_last Ar P=f D => i_move_call_last P D S r
-move S r | call_last Ar P=f D => move_call_last S r P D
+move S=c x==0 | call_last Ar P=f D => i_move_call_last P D S
+move S x==0 | call_last Ar P=f D => move_call_last S P D
 
-i_move_call_last f P c r
+i_move_call_last f P c
 
 %macro:move_call_last MoveCallLast -arg_f -nonext -pack
 
-move_call_last/4
-move_call_last x r f Q
-move_call_last y r f Q
+move_call_last/3
+move_call_last x f Q
+move_call_last y f Q
 
-move S=c r | call_only Ar P=f => i_move_call_only P S r
-move S=x r | call_only Ar P=f => move_call_only S r P
+move S=c x==0 | call_only Ar P=f => i_move_call_only P S
+move S=x x==0 | call_only Ar P=f => move_call_only S P
 
-i_move_call_only f c r
+i_move_call_only f c
 
 %macro:move_call_only MoveCallOnly -arg_f -nonext
-move_call_only/3
+move_call_only/2
 
-move_call_only x r f
+move_call_only x f
 
 call Ar Func        => i_call Func
 call_last Ar Func D => i_call_last Func D
@@ -1199,9 +1092,9 @@ i_call_ext e
 i_call_ext_last e P
 i_call_ext_only e
 
-i_move_call_ext c r e
-i_move_call_ext_last e P c r
-i_move_call_ext_only e c r
+i_move_call_ext c e
+i_move_call_ext_last e P c
+i_move_call_ext_only e c
 
 # Fun calls.
 
@@ -1221,7 +1114,6 @@ i_make_fun I t
 %macro: is_function IsFunction -fail_action
 is_function f x
 is_function f y
-is_function f r
 is_function Fail=f c => jump Fail
 
 func_info M F A => i_func_info u M F A
@@ -1233,126 +1125,102 @@ func_info M F A => i_func_info u M F A
 %cold
 bs_start_match2 Fail=f ica X Y D => jump Fail
 bs_start_match2 Fail Bin X Y D => i_bs_start_match2 Bin Fail X Y D
-i_bs_start_match2 r f I I d
 i_bs_start_match2 x f I I d
 i_bs_start_match2 y f I I d
 
 bs_save2 Reg Index => gen_bs_save(Reg, Index)
-i_bs_save2 r I
 i_bs_save2 x I
 
 bs_restore2 Reg Index => gen_bs_restore(Reg, Index)
-i_bs_restore2 r I
 i_bs_restore2 x I
 
 # Matching integers
 bs_match_string Fail Ms Bits Val => i_bs_match_string Ms Fail Bits Val
 
-i_bs_match_string r f I I
 i_bs_match_string x f I I
 
 # Fetching integers from binaries.
-bs_get_integer2 Fail=f Ms=rx Live=u Sz=sq Unit=u Flags=u Dst=d => \
+bs_get_integer2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
 			gen_get_integer2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
 
-i_bs_get_integer_small_imm r I f I d
 i_bs_get_integer_small_imm x I f I d
-i_bs_get_integer_imm r I I f I d
 i_bs_get_integer_imm x I I f I d
 i_bs_get_integer f I I d
-i_bs_get_integer_8 r f d
 i_bs_get_integer_8 x f d
-i_bs_get_integer_16 r f d
 i_bs_get_integer_16 x f d
-i_bs_get_integer_32 r f I d
 i_bs_get_integer_32 x f I d
 
 # Fetching binaries from binaries.
-bs_get_binary2 Fail=f Ms=rx Live=u Sz=sq Unit=u Flags=u Dst=d => \
+bs_get_binary2 Fail=f Ms=x Live=u Sz=sq Unit=u Flags=u Dst=d => \
 			gen_get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
 
 %macro: i_bs_get_binary_imm2 BsGetBinaryImm_2 -fail_action -gen_dest
 %macro: i_bs_get_binary2 BsGetBinary_2 -fail_action -gen_dest
 %macro: i_bs_get_binary_all2 BsGetBinaryAll_2 -fail_action -gen_dest
 
-i_bs_get_binary_imm2 f r I I I d
 i_bs_get_binary_imm2 f x I I I d
-i_bs_get_binary2 f r I s I d
 i_bs_get_binary2 f x I s I d
-i_bs_get_binary_all2 f r I I d
 i_bs_get_binary_all2 f x I I d
-i_bs_get_binary_all_reuse r f I
 i_bs_get_binary_all_reuse x f I
 
 # Fetching float from binaries.
-bs_get_float2 Fail=f Ms=rx Live=u Sz=s Unit=u Flags=u Dst=d => \
+bs_get_float2 Fail=f Ms=x Live=u Sz=s Unit=u Flags=u Dst=d => \
 		gen_get_float2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
 
-bs_get_float2 Fail=f Ms=rx Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
+bs_get_float2 Fail=f Ms=x Live=u Sz=q Unit=u Flags=u Dst=d => jump Fail
 
 %macro: i_bs_get_float2 BsGetFloat2 -fail_action -gen_dest
-i_bs_get_float2 f r I s I d
 i_bs_get_float2 f x I s I d
 
 # Miscellanous
 
-bs_skip_bits2 Fail=f Ms=rx Sz=s Unit=u Flags=u => \
-			gen_skip_bits2(Fail, Ms, Sz, Unit, Flags)
-bs_skip_bits2 Fail=f Ms=rx Sz=q Unit=u Flags=u => \
+bs_skip_bits2 Fail=f Ms=x Sz=sq Unit=u Flags=u => \
 			gen_skip_bits2(Fail, Ms, Sz, Unit, Flags)
 
 %macro: i_bs_skip_bits_imm2 BsSkipBitsImm2 -fail_action
-i_bs_skip_bits_imm2 f r I
 i_bs_skip_bits_imm2 f x I
 
 %macro: i_bs_skip_bits2 BsSkipBits2 -fail_action
-i_bs_skip_bits2 f r x I
-i_bs_skip_bits2 f r y I
 i_bs_skip_bits2 f x x I
-i_bs_skip_bits2 f x r I
 i_bs_skip_bits2 f x y I
 
 %macro: i_bs_skip_bits_all2 BsSkipBitsAll2 -fail_action
-i_bs_skip_bits_all2 f r I
 i_bs_skip_bits_all2 f x I 
 
-bs_test_tail2 Fail=f Ms=rx Bits=u==0 => bs_test_zero_tail2 Fail Ms
-bs_test_tail2 Fail=f Ms=rx Bits=u => bs_test_tail_imm2 Fail Ms Bits
-bs_test_zero_tail2 f r
+bs_test_tail2 Fail=f Ms=x Bits=u==0 => bs_test_zero_tail2 Fail Ms
+bs_test_tail2 Fail=f Ms=x Bits=u => bs_test_tail_imm2 Fail Ms Bits
 bs_test_zero_tail2 f x
-bs_test_tail_imm2 f r I
 bs_test_tail_imm2 f x I
 
 bs_test_unit F Ms Unit=u==8 => bs_test_unit8 F Ms
-bs_test_unit f r I
 bs_test_unit f x I
-bs_test_unit8 f r
 bs_test_unit8 f x
 
-bs_context_to_binary r
+# An y register operand for bs_context_to_binary is rare,
+# but can happen because of inlining.
+
+bs_context_to_binary Y=y => move Y x | bs_context_to_binary x
+
 bs_context_to_binary x
-bs_context_to_binary y
 
 #
 # Utf8/utf16/utf32 support. (R12B-5)
 #
-bs_get_utf8 Fail=f Ms=rx u u Dst=d => i_bs_get_utf8 Ms Fail Dst
-i_bs_get_utf8 r f d
+bs_get_utf8 Fail=f Ms=x u u Dst=d => i_bs_get_utf8 Ms Fail Dst
 i_bs_get_utf8 x f d
 
-bs_skip_utf8 Fail=f Ms=rx u u => i_bs_get_utf8 Ms Fail x
+bs_skip_utf8 Fail=f Ms=x u u => i_bs_get_utf8 Ms Fail x
 
-bs_get_utf16 Fail=f Ms=rx u Flags=u Dst=d => i_bs_get_utf16 Ms Fail Flags Dst
-bs_skip_utf16 Fail=f Ms=rx u Flags=u => i_bs_get_utf16 Ms Fail Flags x
+bs_get_utf16 Fail=f Ms=x u Flags=u Dst=d => i_bs_get_utf16 Ms Fail Flags Dst
+bs_skip_utf16 Fail=f Ms=x u Flags=u => i_bs_get_utf16 Ms Fail Flags x
 
-i_bs_get_utf16 r f I d
 i_bs_get_utf16 x f I d
 
-bs_get_utf32 Fail=f Ms=rx Live=u Flags=u Dst=d => \
+bs_get_utf32 Fail=f Ms=x Live=u Flags=u Dst=d => \
 	bs_get_integer2 Fail Ms Live i=32 u=1 Flags Dst | \
 	i_fetch Dst Ms | \
 	i_bs_validate_unicode_retract Fail
-bs_skip_utf32 Fail=f Ms=rx Live=u Flags=u => \
+bs_skip_utf32 Fail=f Ms=x Live=u Flags=u => \
 	bs_get_integer2 Fail Ms Live i=32 u=1 Flags x | \
 	i_fetch x Ms | \
 	i_bs_validate_unicode_retract Fail
@@ -1379,9 +1247,8 @@ bs_init2 Fail Sz=u Words Regs Flags Dst => \
 bs_init2 Fail Sz Words=u==0 Regs Flags Dst => \
   i_bs_init_fail Sz Fail Regs Dst
 bs_init2 Fail Sz Words Regs Flags Dst => \
-  i_fetch Sz r | i_bs_init_fail_heap Words Fail Regs Dst
+  i_fetch Sz x=0 | i_bs_init_fail_heap Words Fail Regs Dst
 
-i_bs_init_fail r j I d
 i_bs_init_fail x j I d
 i_bs_init_fail y j I d
 
@@ -1402,9 +1269,8 @@ bs_init_bits Fail Sz=u Words Regs Flags Dst =>  i_bs_init_bits_heap Sz Words Reg
 bs_init_bits Fail Sz Words=u==0 Regs Flags Dst => \
   i_bs_init_bits_fail Sz Fail Regs Dst
 bs_init_bits Fail Sz Words Regs Flags Dst => \
-  i_fetch Sz r | i_bs_init_bits_fail_heap Words Fail Regs Dst
+  i_fetch Sz x=0 | i_bs_init_bits_fail_heap Words Fail Regs Dst
 
-i_bs_init_bits_fail r j I d
 i_bs_init_bits_fail x j I d
 i_bs_init_bits_fail y j I d
 
@@ -1577,7 +1443,6 @@ is_map Fail Lit=q | literal_is_map(Lit) =>
 is_map Fail cq => jump Fail
 
 %macro: is_map IsMap -fail_action
-is_map f r
 is_map f x
 is_map f y
 
@@ -1588,35 +1453,25 @@ has_map_fields Fail Src Size Rest=* => \
 
 ## Transform get_map_elements(s) #{ K1 := V1, K2 := V2 }
 
-get_map_elements Fail Src=rxy Size=u==2 Rest=* => \
+get_map_elements Fail Src=xy Size=u==2 Rest=* => \
     gen_get_map_element(Fail, Src, Size, Rest)
 get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) => \
    gen_get_map_elements(Fail, Src, Size, Rest)
 
 i_get_map_elements f s I
 
-i_get_map_element Fail Src=rxy Key=ry Dst => \
+i_get_map_element Fail Src=xy Key=y Dst => \
     move Key x | i_get_map_element Fail Src x Dst
 
 %macro: i_get_map_element_hash GetMapElementHash -fail_action
-i_get_map_element_hash f r c I r
-i_get_map_element_hash f x c I r
-i_get_map_element_hash f y c I r
-i_get_map_element_hash f r c I x
 i_get_map_element_hash f x c I x
 i_get_map_element_hash f y c I x
-i_get_map_element_hash f r c I y
 i_get_map_element_hash f x c I y
 i_get_map_element_hash f y c I y
 
 %macro: i_get_map_element GetMapElement -fail_action
-i_get_map_element f r x r
-i_get_map_element f x x r
-i_get_map_element f y x r
-i_get_map_element f r x x
 i_get_map_element f x x x
 i_get_map_element f y x x
-i_get_map_element f r x y
 i_get_map_element f x x y
 i_get_map_element f y x y
 
@@ -1625,9 +1480,9 @@ i_get_map_element f y x y
 # the i_increment/4 instruction (in bodies, not in guards).
 #
 
-gc_bif2 p Live u$bif:erlang:splus/2 Int=i Reg=d Dst => \
+gc_bif2 p Live u$bif:erlang:splus/2 Int=i Reg=x Dst => \
 	gen_increment(Reg, Int, Live, Dst)
-gc_bif2 p Live u$bif:erlang:splus/2 Reg=d Int=i Dst => \
+gc_bif2 p Live u$bif:erlang:splus/2 Reg=x Int=i Dst => \
 	gen_increment(Reg, Int, Live, Dst)
 
 gc_bif2 p Live u$bif:erlang:sminus/2 Reg=d Int=i Dst | \
@@ -1662,7 +1517,6 @@ gc_bif1 Fail I u$bif:erlang:bnot/1 Src Dst=d => i_int_bnot Fail Src I Dst
 gc_bif1 Fail I u$bif:erlang:sminus/1 Src Dst=d => i_fetch i Src | i_minus Fail I Dst
 gc_bif1 Fail I u$bif:erlang:splus/1 Src Dst=d => i_fetch i Src | i_plus Fail I Dst
 
-i_increment r I I d
 i_increment x I I d
 i_increment y I I d
 
diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops
index 00b0df5b73..e61096355c 100755
--- a/erts/emulator/utils/beam_makeops
+++ b/erts/emulator/utils/beam_makeops
@@ -176,7 +176,7 @@ sub define_type_bit {
     }
 
     # Composed types.
-    define_type_bit('d', $type_bit{'x'} | $type_bit{'y'} | $type_bit{'r'});
+    define_type_bit('d', $type_bit{'x'} | $type_bit{'y'});
     define_type_bit('c', $type_bit{'i'} | $type_bit{'a'} |
 		    $type_bit{'n'} | $type_bit{'q'});
     define_type_bit('s', $type_bit{'d'} | $type_bit{'i'} |
@@ -528,12 +528,16 @@ sub emulator_output {
 
 	    my(@bits) = (0) x ($max_spec_operands/2);
 	    my($i);
+	    my $involves_r = 0;
 	    for ($i = 0; $i < $max_spec_operands && defined $args[$i]; $i++) {
 		my $t = $args[$i];
-		if (defined $type_bit{$t}) {
-		    my $shift = $max_genop_types * ($i % 2);
-		    $bits[int($i/2)] |= $type_bit{$t} << $shift;
+		my $bits = $type_bit{$t};
+		if ($t eq 'r') {
+		    $bits |= $type_bit{'x'};
+		    $involves_r |= 1 << $i;
 		}
+		my $shift = $max_genop_types * ($i % 2);
+		$bits[int($i/2)] |= $bits << $shift;
 	    }
 
 	    printf "/* %3d */  ", $spec_opnum;
@@ -545,7 +549,7 @@ sub emulator_output {
 		$sep = ",";
 	    }
 	    $init .= "}";
-	    &init_item($print_name, $init, $size, $pack, $sign, 0);
+	    init_item($print_name, $init, $involves_r, $size, $pack, $sign, 0);
 	    $op_to_name[$spec_opnum] = $instr;
 	    $spec_opnum++;
 	}
@@ -1310,6 +1314,8 @@ sub tr_parse_op {
 	foreach (split('', $type)) {
 	    &error("bad type in $op")
 		unless defined $type_bit{$_} or $type eq '*';
+	    $_ eq 'r' and
+		error("$op: 'r' is not allowed in transformations")
 	}
     }
 
-- 
cgit v1.2.3