+/* Emit code to copy in_ent to out_ent. Only uses l0. */
+static void memperm_emit_copy(const ir_node *node, ir_entity *in_ent,
+ ir_entity *out_ent)
+{
+ ir_graph *irg = get_irn_irg(node);
+ be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
+ int off_in = be_get_stack_entity_offset(layout, in_ent, 0);
+ int off_out = be_get_stack_entity_offset(layout, out_ent, 0);
+
+ /* Load from input entity. */
+ sparc_emitf(node, "ld [%%fp%+d], %%l0", off_in);
+ /* Store to output entity. */
+ sparc_emitf(node, "st %%l0, [%%fp%+d]", off_out);
+}
+
+/* Emit code to swap ent1 and ent2. Uses l0 and l1. */
+static void memperm_emit_swap(const ir_node *node, ir_entity *ent1,
+ ir_entity *ent2)
+{
+ ir_graph *irg = get_irn_irg(node);
+ be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
+ int off1 = be_get_stack_entity_offset(layout, ent1, 0);
+ int off2 = be_get_stack_entity_offset(layout, ent2, 0);
+
+ /* Load from first input entity. */
+ sparc_emitf(node, "ld [%%fp%+d], %%l0", off1);
+ /* Load from second input entity. */
+ sparc_emitf(node, "ld [%%fp%+d], %%l1", off2);
+ /* Store first value to second output entity. */
+ sparc_emitf(node, "st %%l0, [%%fp%+d]", off2);
+ /* Store second value to first output entity. */
+ sparc_emitf(node, "st %%l1, [%%fp%+d]", off1);
+}
+
+/* Find the index of ent in ents or return -1 if not found. */
+static int get_index(ir_entity **ents, int n, ir_entity *ent)
+{
+ for (int i = 0; i < n; ++i) {
+ if (ents[i] == ent)
+ return i;
+ }
+
+ return -1;
+}
+
+/*
+ * Emit code for a MemPerm node.
+ *
+ * Analyze MemPerm for copy chains and cyclic swaps and resolve them using
+ * loads and stores.
+ * This function is conceptually very similar to permute_values in
+ * beprefalloc.c.
+ */