From 16d71f0f1043c2e5fabb92e94f6976201f1a86d5 Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Mon, 26 Feb 2018 03:29:56 -0500 Subject: [PATCH] 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 --- qemu/tcg/optimize.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/qemu/tcg/optimize.c b/qemu/tcg/optimize.c index 687ecbc6..58e88717 100644 --- a/qemu/tcg/optimize.c +++ b/qemu/tcg/optimize.c @@ -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; + } } }