diff mbox series

[v4,25/27] tcg/s390x: Tighten constraints for 64-bit compare

Message ID 20221209020530.396391-26-richard.henderson@linaro.org (mailing list archive)
State New, archived
Headers show
Series tcg/s390x: misc patches | expand

Commit Message

Richard Henderson Dec. 9, 2022, 2:05 a.m. UTC
Give 64-bit comparison second operand a signed 33-bit immediate.
This is the smallest superset of uint32_t and int32_t, as used
by CLGFI and CGFI respectively.  The rest of the 33-bit space
can be loaded into TCG_TMP0.  Drop use of the constant pool.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/s390x/tcg-target-con-set.h |  3 +++
 tcg/s390x/tcg-target.c.inc     | 27 ++++++++++++++-------------
 2 files changed, 17 insertions(+), 13 deletions(-)

Comments

Ilya Leoshkevich Dec. 13, 2022, 4:25 p.m. UTC | #1
On Thu, Dec 08, 2022 at 08:05:28PM -0600, Richard Henderson wrote:
> Give 64-bit comparison second operand a signed 33-bit immediate.
> This is the smallest superset of uint32_t and int32_t, as used
> by CLGFI and CGFI respectively.  The rest of the 33-bit space
> can be loaded into TCG_TMP0.  Drop use of the constant pool.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  tcg/s390x/tcg-target-con-set.h |  3 +++
>  tcg/s390x/tcg-target.c.inc     | 27 ++++++++++++++-------------
>  2 files changed, 17 insertions(+), 13 deletions(-)

<...>
 
> --- a/tcg/s390x/tcg-target.c.inc
> +++ b/tcg/s390x/tcg-target.c.inc
> @@ -1249,22 +1249,20 @@ static int tgen_cmp2(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
>              tcg_out_insn_RIL(s, op, r1, c2);
>              goto exit;
>          }
> +
> +        /*
> +         * Constraints are for a signed 33-bit operand, which is a
> +         * convenient superset of this signed/unsigned test.
> +         */
>          if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) {
>              op = (is_unsigned ? RIL_CLGFI : RIL_CGFI);
>              tcg_out_insn_RIL(s, op, r1, c2);
>              goto exit;
>          }
>  
> -        /* Use the constant pool, but not for small constants.  */
> -        if (maybe_out_small_movi(s, type, TCG_TMP0, c2)) {
> -            c2 = TCG_TMP0;
> -            /* fall through to reg-reg */
> -        } else {
> -            op = (is_unsigned ? RIL_CLGRL : RIL_CGRL);
> -            tcg_out_insn_RIL(s, op, r1, 0);
> -            new_pool_label(s, c2, R_390_PC32DBL, s->code_ptr - 2, 2);
> -            goto exit;
> -        }
> +        /* Load everything else into a register. */
> +        tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, c2);
> +        c2 = TCG_TMP0;

What does tightening the constraint give us, if we have to handle the
"everything else" case anyway, even for values that match
TCG_CT_CONST_S33?

The example that I have in mind is:

- Comparison: r0_64 s<= -0xffffffffL;
- tcg_target_const_match(-0xffffffffL, TCG_TYPE_I64,
                         TCG_CT_CONST_S33) == true;
- (long)(int)-0xffffffffL != -0xffffffff;
- So we should end up in the "everything else" branch.

<...>

Best regards,
Ilya
Richard Henderson Dec. 13, 2022, 4:43 p.m. UTC | #2
On 12/13/22 10:25, Ilya Leoshkevich wrote:
> On Thu, Dec 08, 2022 at 08:05:28PM -0600, Richard Henderson wrote:
>> Give 64-bit comparison second operand a signed 33-bit immediate.
>> This is the smallest superset of uint32_t and int32_t, as used
>> by CLGFI and CGFI respectively.  The rest of the 33-bit space
>> can be loaded into TCG_TMP0.  Drop use of the constant pool.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   tcg/s390x/tcg-target-con-set.h |  3 +++
>>   tcg/s390x/tcg-target.c.inc     | 27 ++++++++++++++-------------
>>   2 files changed, 17 insertions(+), 13 deletions(-)
> 
> <...>
>   
>> --- a/tcg/s390x/tcg-target.c.inc
>> +++ b/tcg/s390x/tcg-target.c.inc
>> @@ -1249,22 +1249,20 @@ static int tgen_cmp2(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
>>               tcg_out_insn_RIL(s, op, r1, c2);
>>               goto exit;
>>           }
>> +
>> +        /*
>> +         * Constraints are for a signed 33-bit operand, which is a
>> +         * convenient superset of this signed/unsigned test.
>> +         */
>>           if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) {
>>               op = (is_unsigned ? RIL_CLGFI : RIL_CGFI);
>>               tcg_out_insn_RIL(s, op, r1, c2);
>>               goto exit;
>>           }
>>   
>> -        /* Use the constant pool, but not for small constants.  */
>> -        if (maybe_out_small_movi(s, type, TCG_TMP0, c2)) {
>> -            c2 = TCG_TMP0;
>> -            /* fall through to reg-reg */
>> -        } else {
>> -            op = (is_unsigned ? RIL_CLGRL : RIL_CGRL);
>> -            tcg_out_insn_RIL(s, op, r1, 0);
>> -            new_pool_label(s, c2, R_390_PC32DBL, s->code_ptr - 2, 2);
>> -            goto exit;
>> -        }
>> +        /* Load everything else into a register. */
>> +        tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, c2);
>> +        c2 = TCG_TMP0;
> 
> What does tightening the constraint give us, if we have to handle the
> "everything else" case anyway, even for values that match
> TCG_CT_CONST_S33?

Values outside const_s33 get loaded by the register allocator, which means the value in 
the register might get re-used.

> The example that I have in mind is:
> 
> - Comparison: r0_64 s<= -0xffffffffL;
> - tcg_target_const_match(-0xffffffffL, TCG_TYPE_I64,
>                           TCG_CT_CONST_S33) == true;
> - (long)(int)-0xffffffffL != -0xffffffff;
> - So we should end up in the "everything else" branch.

I suppose I could invent a new constraint that matches INT_MIN32 .. UINT32_MAX, which 
would exclude this particular case.  But it would still leave us loading INT32MIN .. -1 
for unsigned and INT32MAX+1 .. UINT32_MAX for signed.

Since S33 existed already, I thought I would just re-use it.


r~
Ilya Leoshkevich Dec. 13, 2022, 5:01 p.m. UTC | #3
On Tue, Dec 13, 2022 at 10:43:07AM -0600, Richard Henderson wrote:
> On 12/13/22 10:25, Ilya Leoshkevich wrote:
> > On Thu, Dec 08, 2022 at 08:05:28PM -0600, Richard Henderson wrote:
> > > Give 64-bit comparison second operand a signed 33-bit immediate.
> > > This is the smallest superset of uint32_t and int32_t, as used
> > > by CLGFI and CGFI respectively.  The rest of the 33-bit space
> > > can be loaded into TCG_TMP0.  Drop use of the constant pool.
> > > 
> > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> > > ---
> > >   tcg/s390x/tcg-target-con-set.h |  3 +++
> > >   tcg/s390x/tcg-target.c.inc     | 27 ++++++++++++++-------------
> > >   2 files changed, 17 insertions(+), 13 deletions(-)
> > 
> > <...>
> > > --- a/tcg/s390x/tcg-target.c.inc
> > > +++ b/tcg/s390x/tcg-target.c.inc
> > > @@ -1249,22 +1249,20 @@ static int tgen_cmp2(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
> > >               tcg_out_insn_RIL(s, op, r1, c2);
> > >               goto exit;
> > >           }
> > > +
> > > +        /*
> > > +         * Constraints are for a signed 33-bit operand, which is a
> > > +         * convenient superset of this signed/unsigned test.
> > > +         */
> > >           if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) {
> > >               op = (is_unsigned ? RIL_CLGFI : RIL_CGFI);
> > >               tcg_out_insn_RIL(s, op, r1, c2);
> > >               goto exit;
> > >           }
> > > -        /* Use the constant pool, but not for small constants.  */
> > > -        if (maybe_out_small_movi(s, type, TCG_TMP0, c2)) {
> > > -            c2 = TCG_TMP0;
> > > -            /* fall through to reg-reg */
> > > -        } else {
> > > -            op = (is_unsigned ? RIL_CLGRL : RIL_CGRL);
> > > -            tcg_out_insn_RIL(s, op, r1, 0);
> > > -            new_pool_label(s, c2, R_390_PC32DBL, s->code_ptr - 2, 2);
> > > -            goto exit;
> > > -        }
> > > +        /* Load everything else into a register. */
> > > +        tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, c2);
> > > +        c2 = TCG_TMP0;
> > 
> > What does tightening the constraint give us, if we have to handle the
> > "everything else" case anyway, even for values that match
> > TCG_CT_CONST_S33?
> 
> Values outside const_s33 get loaded by the register allocator, which means
> the value in the register might get re-used.

Thanks for the explanation!
I did not consider the reuse of already loaded large 64-bit values.

Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
diff mbox series

Patch

diff --git a/tcg/s390x/tcg-target-con-set.h b/tcg/s390x/tcg-target-con-set.h
index baf3bc9037..15f1c55103 100644
--- a/tcg/s390x/tcg-target-con-set.h
+++ b/tcg/s390x/tcg-target-con-set.h
@@ -13,6 +13,7 @@  C_O0_I1(r)
 C_O0_I2(L, L)
 C_O0_I2(r, r)
 C_O0_I2(r, ri)
+C_O0_I2(r, rA)
 C_O0_I2(v, r)
 C_O1_I1(r, L)
 C_O1_I1(r, r)
@@ -24,6 +25,7 @@  C_O1_I2(r, 0, rI)
 C_O1_I2(r, 0, rJ)
 C_O1_I2(r, r, r)
 C_O1_I2(r, r, ri)
+C_O1_I2(r, r, rA)
 C_O1_I2(r, r, rI)
 C_O1_I2(r, r, rJ)
 C_O1_I2(r, r, rK)
@@ -35,6 +37,7 @@  C_O1_I2(v, v, r)
 C_O1_I2(v, v, v)
 C_O1_I3(v, v, v, v)
 C_O1_I4(r, r, ri, rI, r)
+C_O1_I4(r, r, rA, rI, r)
 C_O2_I2(o, m, 0, r)
 C_O2_I2(o, m, r, r)
 C_O2_I3(o, m, 0, 1, r)
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index c0434fa2f8..4d113139e5 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -1249,22 +1249,20 @@  static int tgen_cmp2(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
             tcg_out_insn_RIL(s, op, r1, c2);
             goto exit;
         }
+
+        /*
+         * Constraints are for a signed 33-bit operand, which is a
+         * convenient superset of this signed/unsigned test.
+         */
         if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) {
             op = (is_unsigned ? RIL_CLGFI : RIL_CGFI);
             tcg_out_insn_RIL(s, op, r1, c2);
             goto exit;
         }
 
-        /* Use the constant pool, but not for small constants.  */
-        if (maybe_out_small_movi(s, type, TCG_TMP0, c2)) {
-            c2 = TCG_TMP0;
-            /* fall through to reg-reg */
-        } else {
-            op = (is_unsigned ? RIL_CLGRL : RIL_CGRL);
-            tcg_out_insn_RIL(s, op, r1, 0);
-            new_pool_label(s, c2, R_390_PC32DBL, s->code_ptr - 2, 2);
-            goto exit;
-        }
+        /* Load everything else into a register. */
+        tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, c2);
+        c2 = TCG_TMP0;
     }
 
     if (type == TCG_TYPE_I32) {
@@ -3105,8 +3103,9 @@  static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_rotr_i32:
     case INDEX_op_rotr_i64:
     case INDEX_op_setcond_i32:
-    case INDEX_op_setcond_i64:
         return C_O1_I2(r, r, ri);
+    case INDEX_op_setcond_i64:
+        return C_O1_I2(r, r, rA);
 
     case INDEX_op_clz_i64:
         return C_O1_I2(r, r, rI);
@@ -3154,8 +3153,9 @@  static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
         return C_O1_I2(r, r, ri);
 
     case INDEX_op_brcond_i32:
-    case INDEX_op_brcond_i64:
         return C_O0_I2(r, ri);
+    case INDEX_op_brcond_i64:
+        return C_O0_I2(r, rA);
 
     case INDEX_op_bswap16_i32:
     case INDEX_op_bswap16_i64:
@@ -3196,8 +3196,9 @@  static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
         return C_O1_I2(r, rZ, r);
 
     case INDEX_op_movcond_i32:
-    case INDEX_op_movcond_i64:
         return C_O1_I4(r, r, ri, rI, r);
+    case INDEX_op_movcond_i64:
+        return C_O1_I4(r, r, rA, rI, r);
 
     case INDEX_op_div2_i32:
     case INDEX_op_div2_i64: