tcg: Optimize fence instructions

This commit optimizes fence instructions. Two optimizations are
currently implemented: (1) unnecessary duplicate fence instructions,
and (2) merging weaker fences into a stronger fence.

[rth: Merge tcg_optimize_mb back into tcg_optimize, so that we only
loop over the opcode stream once. Merge "unrelated" weaker barriers
into one stronger barrier.]

Backports commit 34f939218ce78163171addd63750e1e0300376ab from qemu
This commit is contained in:
Pranith Kumar 2018-02-26 03:29:56 -05:00 committed by Lioncash
parent 533e083495
commit 16d71f0f10
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -553,6 +553,7 @@ void tcg_optimize(TCGContext *s)
{
struct tcg_temp_info *temps = s->temps2;
int oi, oi_next, nb_temps, nb_globals;
TCGArg *prev_mb_args = NULL;
/* Array VALS has an element for each temp.
If this temp holds a constant then its value is kept in VALS' element.
@ -1306,5 +1307,43 @@ void tcg_optimize(TCGContext *s)
}
break;
}
/* Eliminate duplicate and redundant fence instructions. */
if (prev_mb_args) {
switch (opc) {
case INDEX_op_mb:
/* Merge two barriers of the same type into one,
* or a weaker barrier into a stronger one,
* or two weaker barriers into a stronger one.
* mb X; mb Y => mb X|Y
* mb; strl => mb; st
* ldaq; mb => ld; mb
* ldaq; strl => ld; mb; st
* Other combinations are also merged into a strong
* barrier. This is stricter than specified but for
* the purposes of TCG is better than not optimizing.
*/
prev_mb_args[0] |= args[0];
tcg_op_remove(s, op);
break;
default:
/* Opcodes that end the block stop the optimization. */
if ((def->flags & TCG_OPF_BB_END) == 0) {
break;
}
/* fallthru */
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_ld_i64:
case INDEX_op_qemu_st_i32:
case INDEX_op_qemu_st_i64:
case INDEX_op_call:
/* Opcodes that touch guest memory stop the optimization. */
prev_mb_args = NULL;
break;
}
} else if (opc == INDEX_op_mb) {
prev_mb_args = args;
}
}
}