提交 78505279 编写于 作者: A Aurelien Jarno

tcg: rework TCG helper flags

The current helper flags, TCG_CALL_CONST and TCG_CALL_PURE might be
confusing and doesn't provide enough granularity for some helpers (FP
helpers for example).

This patch changes them into the following helpers flags:
- TCG_CALL_NO_READ_GLOBALS means that the helper does not read globals,
  either directly or via an exception. They will not be saved to their
  canonical location before calling the helper.
- TCG_CALL_NO_WRITE_GLOBALS means that the helper does not modify any
  globals. They will only be saved to their canonical locations before
  calling helpers, but they won't be reloaded afterwise.
- TCG_CALL_NO_SIDE_EFFECTS means that the call to the function is
  removed if the return value is not used.

It provides convenience flags, to avoid helper definitions longer than
80 characters. It also provides compatibility flags, and updates the
documentation.
Reviewed-by: NRichard Henderson <rth@twiddle.net>
Signed-off-by: NAurelien Jarno <aurelien@aurel32.net>
上级 3d5c5f87
...@@ -77,11 +77,20 @@ destroyed, but local temporaries and globals are preserved. ...@@ -77,11 +77,20 @@ destroyed, but local temporaries and globals are preserved.
Using the tcg_gen_helper_x_y it is possible to call any function Using the tcg_gen_helper_x_y it is possible to call any function
taking i32, i64 or pointer types. By default, before calling a helper, taking i32, i64 or pointer types. By default, before calling a helper,
all globals are stored at their canonical location and it is assumed all globals are stored at their canonical location and it is assumed
that the function can modify them. This can be overridden by the that the function can modify them. By default, the helper is allowed to
TCG_CALL_CONST function modifier. By default, the helper is allowed to modify the CPU state or raise an exception.
modify the CPU state or raise an exception. This can be overridden by
the TCG_CALL_PURE function modifier, in which case the call to the This can be overridden using the following function modifiers:
function is removed if the return value is not used. - TCG_CALL_NO_READ_GLOBALS means that the helper does not read globals,
either directly or via an exception. They will not be saved to their
canonical locations before calling the helper.
- TCG_CALL_NO_WRITE_GLOBALS means that the helper does not modify any globals.
They will only be saved to their canonical location before calling helpers,
but they won't be reloaded afterwise.
- TCG_CALL_NO_SIDE_EFFECTS means that the call to the function is removed if
the return value is not used.
Note that TCG_CALL_NO_READ_GLOBALS implies TCG_CALL_NO_WRITE_GLOBALS.
On some TCG targets (e.g. x86), several calling conventions are On some TCG targets (e.g. x86), several calling conventions are
supported. supported.
......
...@@ -915,7 +915,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, ...@@ -915,7 +915,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
case INDEX_op_call: case INDEX_op_call:
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { if (!(args[nb_call_args + 1] & (TCG_CALL_NO_READ_GLOBALS |
TCG_CALL_NO_WRITE_GLOBALS))) {
for (i = 0; i < nb_globals; i++) { for (i = 0; i < nb_globals; i++) {
reset_temp(i); reset_temp(i);
} }
......
...@@ -401,10 +401,10 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask, ...@@ -401,10 +401,10 @@ static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
} }
/* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently /* Note: Both tcg_gen_helper32() and tcg_gen_helper64() are currently
reserved for helpers in tcg-runtime.c. These helpers are all const reserved for helpers in tcg-runtime.c. These helpers all do not read
and pure, hence the call to tcg_gen_callN() with TCG_CALL_CONST | globals and do not have side effects, hence the call to tcg_gen_callN()
TCG_CALL_PURE. This may need to be adjusted if these functions with TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS. This may need
start to be used with other helpers. */ to be adjusted if these functions start to be used with other helpers. */
static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret, static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
TCGv_i32 a, TCGv_i32 b) TCGv_i32 a, TCGv_i32 b)
{ {
...@@ -413,8 +413,9 @@ static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret, ...@@ -413,8 +413,9 @@ static inline void tcg_gen_helper32(void *func, int sizemask, TCGv_i32 ret,
fn = tcg_const_ptr(func); fn = tcg_const_ptr(func);
args[0] = GET_TCGV_I32(a); args[0] = GET_TCGV_I32(a);
args[1] = GET_TCGV_I32(b); args[1] = GET_TCGV_I32(b);
tcg_gen_callN(&tcg_ctx, fn, TCG_CALL_CONST | TCG_CALL_PURE, sizemask, tcg_gen_callN(&tcg_ctx, fn,
GET_TCGV_I32(ret), 2, args); TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
sizemask, GET_TCGV_I32(ret), 2, args);
tcg_temp_free_ptr(fn); tcg_temp_free_ptr(fn);
} }
...@@ -426,8 +427,9 @@ static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret, ...@@ -426,8 +427,9 @@ static inline void tcg_gen_helper64(void *func, int sizemask, TCGv_i64 ret,
fn = tcg_const_ptr(func); fn = tcg_const_ptr(func);
args[0] = GET_TCGV_I64(a); args[0] = GET_TCGV_I64(a);
args[1] = GET_TCGV_I64(b); args[1] = GET_TCGV_I64(b);
tcg_gen_callN(&tcg_ctx, fn, TCG_CALL_CONST | TCG_CALL_PURE, sizemask, tcg_gen_callN(&tcg_ctx, fn,
GET_TCGV_I64(ret), 2, args); TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_SIDE_EFFECTS,
sizemask, GET_TCGV_I64(ret), 2, args);
tcg_temp_free_ptr(fn); tcg_temp_free_ptr(fn);
} }
......
...@@ -1251,7 +1251,7 @@ static void tcg_liveness_analysis(TCGContext *s) ...@@ -1251,7 +1251,7 @@ static void tcg_liveness_analysis(TCGContext *s)
/* pure functions can be removed if their result is not /* pure functions can be removed if their result is not
used */ used */
if (call_flags & TCG_CALL_PURE) { if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
for(i = 0; i < nb_oargs; i++) { for(i = 0; i < nb_oargs; i++) {
arg = args[i]; arg = args[i];
if (!dead_temps[arg] || mem_temps[arg]) { if (!dead_temps[arg] || mem_temps[arg]) {
...@@ -1277,11 +1277,15 @@ static void tcg_liveness_analysis(TCGContext *s) ...@@ -1277,11 +1277,15 @@ static void tcg_liveness_analysis(TCGContext *s)
dead_temps[arg] = 1; dead_temps[arg] = 1;
mem_temps[arg] = 0; mem_temps[arg] = 0;
} }
if (!(call_flags & TCG_CALL_CONST)) { if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
/* globals should be synced to memory */
memset(mem_temps, 1, s->nb_globals);
}
if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
TCG_CALL_NO_READ_GLOBALS))) {
/* globals should go back to memory */ /* globals should go back to memory */
memset(dead_temps, 1, s->nb_globals); memset(dead_temps, 1, s->nb_globals);
memset(mem_temps, 1, s->nb_globals);
} }
/* input args are live */ /* input args are live */
...@@ -2128,10 +2132,14 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, ...@@ -2128,10 +2132,14 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
tcg_reg_free(s, reg); tcg_reg_free(s, reg);
} }
} }
/* store globals and free associated registers (we assume the call /* Save globals if they might be written by the helper, sync them if
can modify any global. */ they might be read. */
if (!(flags & TCG_CALL_CONST)) { if (flags & TCG_CALL_NO_READ_GLOBALS) {
/* Nothing to do */
} else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
sync_globals(s, allocated_regs);
} else {
save_globals(s, allocated_regs); save_globals(s, allocated_regs);
} }
......
...@@ -253,14 +253,24 @@ typedef int TCGv_i64; ...@@ -253,14 +253,24 @@ typedef int TCGv_i64;
#define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1) #define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
/* call flags */ /* call flags */
/* A pure function only reads its arguments and TCG global variables /* Helper does not read globals (either directly or through an exception). It
and cannot raise exceptions. Hence a call to a pure function can be implies TCG_CALL_NO_WRITE_GLOBALS. */
safely suppressed if the return value is not used. */ #define TCG_CALL_NO_READ_GLOBALS 0x0010
#define TCG_CALL_PURE 0x0010 /* Helper does not write globals */
/* A const function only reads its arguments and does not use TCG #define TCG_CALL_NO_WRITE_GLOBALS 0x0020
global variables. Hence a call to such a function does not /* Helper can be safely suppressed if the return value is not used. */
save TCG global variables back to their canonical location. */ #define TCG_CALL_NO_SIDE_EFFECTS 0x0040
#define TCG_CALL_CONST 0x0020
/* convenience version of most used call flags */
#define TCG_CALL_NO_RWG TCG_CALL_NO_READ_GLOBALS
#define TCG_CALL_NO_WG TCG_CALL_NO_WRITE_GLOBALS
#define TCG_CALL_NO_SE TCG_CALL_NO_SIDE_EFFECTS
#define TCG_CALL_NO_RWG_SE (TCG_CALL_NO_RWG | TCG_CALL_NO_SE)
#define TCG_CALL_NO_WG_SE (TCG_CALL_NO_WG | TCG_CALL_NO_SE)
/* compatibility call flags, they should be eventually be removed */
#define TCG_CALL_PURE TCG_CALL_NO_SIDE_EFFECTS
#define TCG_CALL_CONST TCG_CALL_NO_READ_GLOBALS
/* used to align parameters */ /* used to align parameters */
#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1) #define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册