diff mbox series

[v2,08/48] tcg/optimize: Split out fold_call

Message ID 20211007195456.1168070-9-richard.henderson@linaro.org
State New
Headers show
Series tcg: optimize redundant sign extensions | expand

Commit Message

Richard Henderson Oct. 7, 2021, 7:54 p.m. UTC
Calls are special in that they have a variable number
of arguments, and need to be able to clobber globals.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/optimize.c | 63 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 41 insertions(+), 22 deletions(-)

Comments

Alex Bennée Oct. 20, 2021, 4:05 p.m. UTC | #1
Richard Henderson <richard.henderson@linaro.org> writes:

> Calls are special in that they have a variable number
> of arguments, and need to be able to clobber globals.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  tcg/optimize.c | 63 ++++++++++++++++++++++++++++++++------------------
>  1 file changed, 41 insertions(+), 22 deletions(-)
>
> diff --git a/tcg/optimize.c b/tcg/optimize.c
> index fad6f5de1f..74b9aa025a 100644
> --- a/tcg/optimize.c
> +++ b/tcg/optimize.c
> @@ -624,10 +624,42 @@ static void copy_propagate(OptContext *ctx, TCGOp *op,
>      }
>  }
>  
> +static bool fold_call(OptContext *ctx, TCGOp *op)
> +{
> +    TCGContext *s = ctx->tcg;
> +    int nb_oargs = TCGOP_CALLO(op);
> +    int nb_iargs = TCGOP_CALLI(op);
> +    int flags, i;
> +
> +    init_arguments(ctx, op, nb_oargs + nb_iargs);
> +    copy_propagate(ctx, op, nb_oargs, nb_iargs);
> +
> +    /* If the function reads or writes globals, reset temp data. */
> +    flags = tcg_call_flags(op);
> +    if (!(flags & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
> +        int nb_globals = s->nb_globals;

Aren't we missing a trick here?

If the helper is going to read global registers we need to ensure any
temps holding their data is written but we don't need to throw the
existing temps away if the helper is TCG_CALL_NO_WRITE_GLOBALS?

I guess we have to handle the case of temps that are about to get smahed
by the call though....

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Luis Fernando Fujita Pires Oct. 20, 2021, 10:27 p.m. UTC | #2
From: Richard Henderson <richard.henderson@linaro.org>
> Calls are special in that they have a variable number of arguments, and need to
> be able to clobber globals.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  tcg/optimize.c | 63 ++++++++++++++++++++++++++++++++------------------
>  1 file changed, 41 insertions(+), 22 deletions(-)

Reviewed-by: Luis Pires <luis.pires@eldorado.org.br>

--
Luis Pires
Instituto de Pesquisas ELDORADO
Aviso Legal - Disclaimer <https://www.eldorado.org.br/disclaimer.html>
Richard Henderson Oct. 21, 2021, 2:04 a.m. UTC | #3
On 10/20/21 9:05 AM, Alex Bennée wrote:
> 
> Richard Henderson <richard.henderson@linaro.org> writes:
> 
>> Calls are special in that they have a variable number
>> of arguments, and need to be able to clobber globals.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   tcg/optimize.c | 63 ++++++++++++++++++++++++++++++++------------------
>>   1 file changed, 41 insertions(+), 22 deletions(-)
>>
>> diff --git a/tcg/optimize.c b/tcg/optimize.c
>> index fad6f5de1f..74b9aa025a 100644
>> --- a/tcg/optimize.c
>> +++ b/tcg/optimize.c
>> @@ -624,10 +624,42 @@ static void copy_propagate(OptContext *ctx, TCGOp *op,
>>       }
>>   }
>>   
>> +static bool fold_call(OptContext *ctx, TCGOp *op)
>> +{
>> +    TCGContext *s = ctx->tcg;
>> +    int nb_oargs = TCGOP_CALLO(op);
>> +    int nb_iargs = TCGOP_CALLI(op);
>> +    int flags, i;
>> +
>> +    init_arguments(ctx, op, nb_oargs + nb_iargs);
>> +    copy_propagate(ctx, op, nb_oargs, nb_iargs);
>> +
>> +    /* If the function reads or writes globals, reset temp data. */
>> +    flags = tcg_call_flags(op);
>> +    if (!(flags & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
>> +        int nb_globals = s->nb_globals;
> 
> Aren't we missing a trick here?
> 
> If the helper is going to read global registers we need to ensure any
> temps holding their data is written but we don't need to throw the
> existing temps away if the helper is TCG_CALL_NO_WRITE_GLOBALS?

Hmm, if NO_WRITE_GLOBALS, then yes, we should be able to preserve the information about 
the current contents.  There must be some quirk, though; I just don't recall what it is. 
This patch preserves existing behaviour.


r~
diff mbox series

Patch

diff --git a/tcg/optimize.c b/tcg/optimize.c
index fad6f5de1f..74b9aa025a 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -624,10 +624,42 @@  static void copy_propagate(OptContext *ctx, TCGOp *op,
     }
 }
 
+static bool fold_call(OptContext *ctx, TCGOp *op)
+{
+    TCGContext *s = ctx->tcg;
+    int nb_oargs = TCGOP_CALLO(op);
+    int nb_iargs = TCGOP_CALLI(op);
+    int flags, i;
+
+    init_arguments(ctx, op, nb_oargs + nb_iargs);
+    copy_propagate(ctx, op, nb_oargs, nb_iargs);
+
+    /* If the function reads or writes globals, reset temp data. */
+    flags = tcg_call_flags(op);
+    if (!(flags & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
+        int nb_globals = s->nb_globals;
+
+        for (i = 0; i < nb_globals; i++) {
+            if (test_bit(i, ctx->temps_used.l)) {
+                reset_ts(&ctx->tcg->temps[i]);
+            }
+        }
+    }
+
+    /* Reset temp data for outputs. */
+    for (i = 0; i < nb_oargs; i++) {
+        reset_temp(op->args[i]);
+    }
+
+    /* Stop optimizing MB across calls. */
+    ctx->prev_mb = NULL;
+    return true;
+}
+
 /* Propagate constants and copies, fold constant expressions. */
 void tcg_optimize(TCGContext *s)
 {
-    int nb_temps, nb_globals, i;
+    int nb_temps, i;
     TCGOp *op, *op_next;
     OptContext ctx = { .tcg = s };
 
@@ -637,8 +669,6 @@  void tcg_optimize(TCGContext *s)
        available through the doubly linked circular list. */
 
     nb_temps = s->nb_temps;
-    nb_globals = s->nb_globals;
-
     for (i = 0; i < nb_temps; ++i) {
         s->temps[i].state_ptr = NULL;
     }
@@ -647,17 +677,17 @@  void tcg_optimize(TCGContext *s)
         uint64_t z_mask, partmask, affected, tmp;
         int nb_oargs, nb_iargs;
         TCGOpcode opc = op->opc;
-        const TCGOpDef *def = &tcg_op_defs[opc];
+        const TCGOpDef *def;
 
-        /* Count the arguments, and initialize the temps that are
-           going to be used */
+        /* Calls are special. */
         if (opc == INDEX_op_call) {
-            nb_oargs = TCGOP_CALLO(op);
-            nb_iargs = TCGOP_CALLI(op);
-        } else {
-            nb_oargs = def->nb_oargs;
-            nb_iargs = def->nb_iargs;
+            fold_call(&ctx, op);
+            continue;
         }
+
+        def = &tcg_op_defs[opc];
+        nb_oargs = def->nb_oargs;
+        nb_iargs = def->nb_iargs;
         init_arguments(&ctx, op, nb_oargs + nb_iargs);
         copy_propagate(&ctx, op, nb_oargs, nb_iargs);
 
@@ -1549,16 +1579,6 @@  void tcg_optimize(TCGContext *s)
         if (def->flags & TCG_OPF_BB_END) {
             memset(&ctx.temps_used, 0, sizeof(ctx.temps_used));
         } else {
-            if (opc == INDEX_op_call &&
-                !(tcg_call_flags(op)
-                  & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
-                for (i = 0; i < nb_globals; i++) {
-                    if (test_bit(i, ctx.temps_used.l)) {
-                        reset_ts(&s->temps[i]);
-                    }
-                }
-            }
-
             for (i = 0; i < nb_oargs; i++) {
                 reset_temp(op->args[i]);
                 /* Save the corresponding known-zero bits mask for the
@@ -1599,7 +1619,6 @@  void tcg_optimize(TCGContext *s)
             case INDEX_op_qemu_st_i32:
             case INDEX_op_qemu_st8_i32:
             case INDEX_op_qemu_st_i64:
-            case INDEX_op_call:
                 /* Opcodes that touch guest memory stop the optimization.  */
                 ctx.prev_mb = NULL;
                 break;