Patchwork [v2,12/27] tcg-ppc64: Improve and_i32 with constant

login
register
mail settings
Submitter Richard Henderson
Date March 5, 2013, 12:32 a.m.
Message ID <1362443590-28191-13-git-send-email-rth@twiddle.net>
Download mbox | patch
Permalink /patch/224867/
State New
Headers show

Comments

Richard Henderson - March 5, 2013, 12:32 a.m.
Use RLWINM

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/ppc64/tcg-target.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)
Aurelien Jarno - April 1, 2013, 2:55 p.m.
On Mon, Mar 04, 2013 at 04:32:55PM -0800, Richard Henderson wrote:
> Use RLWINM
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  tcg/ppc64/tcg-target.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
> index 9718ef6..ad6db6c 100644
> --- a/tcg/ppc64/tcg-target.c
> +++ b/tcg/ppc64/tcg-target.c
> @@ -527,6 +527,48 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
>      }
>  }
>  
> +static inline bool mask_operand(uint32_t c, int *mb, int *me)
> +{
> +    uint32_t lsb, test;
> +
> +    /* Accept a bit pattern like:
> +           0....01....1
> +           1....10....0
> +           0..01..10..0
> +       Keep track of the transitions.  */
> +    if (c == 0 || c == -1) {
> +        return false;
> +    }
> +    test = c;
> +    lsb = test & -test;
> +    test += lsb;
> +    if (test & (test - 1)) {
> +        return false;
> +    }
> +
> +    *me = clz32(lsb);
> +    *mb = test ? clz32(test & -test) + 1 : 0;
> +    return true;
> +}
> +
> +static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
> +{
> +    int mb, me;
> +
> +    if ((c & 0xffff) == c) {
> +        tcg_out32(s, ANDI | SAI(src, dst, c));
> +        return;
> +    } else if ((c & 0xffff0000) == c) {
> +        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
> +        return;
> +    } else if (mask_operand(c, &mb, &me)) {
> +        tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
> +    } else {
> +        tcg_out_movi(s, TCG_TYPE_I32, 0, c);
> +        tcg_out32(s, AND | SAB(src, dst, 0));

Give it's a 32-bit constant, wouldn't it be better to use ANDI + 
ANDIS here?

> +    }
> +}
> +
>  static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
>                             int op_lo, int op_hi)
>  {
> @@ -1346,9 +1388,15 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
>          }
>          break;
>  
> -    case INDEX_op_and_i64:
>      case INDEX_op_and_i32:
>          if (const_args[2]) {
> +            tcg_out_andi32(s, args[0], args[1], args[2]);
> +        } else {
> +            tcg_out32(s, AND | SAB(args[1], args[0], args[2]));
> +        }
> +        break;
> +    case INDEX_op_and_i64:
> +        if (const_args[2]) {
>              if ((args[2] & 0xffff) == args[2]) {
>                  tcg_out32(s, ANDI | SAI(args[1], args[0], args[2]));
>              } else if ((args[2] & 0xffff0000) == args[2]) {
> -- 
> 1.8.1.2
> 
> 
>
Richard Henderson - April 1, 2013, 3:43 p.m.
On 2013-04-01 07:55, Aurelien Jarno wrote:
>> >+static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
>> >+{
>> >+    int mb, me;
>> >+
>> >+    if ((c & 0xffff) == c) {
>> >+        tcg_out32(s, ANDI | SAI(src, dst, c));
>> >+        return;
>> >+    } else if ((c & 0xffff0000) == c) {
>> >+        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
>> >+        return;
>> >+    } else if (mask_operand(c, &mb, &me)) {
>> >+        tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
>> >+    } else {
>> >+        tcg_out_movi(s, TCG_TYPE_I32, 0, c);
>> >+        tcg_out32(s, AND | SAB(src, dst, 0));
> Give it's a 32-bit constant, wouldn't it be better to use ANDI +
> ANDIS here?
>

x & 0xffff0000 & 0x0000ffff == 0.

Unlike IOR and XOR...


r~
Aurelien Jarno - April 1, 2013, 3:58 p.m.
On Mon, Apr 01, 2013 at 08:43:24AM -0700, Richard Henderson wrote:
> On 2013-04-01 07:55, Aurelien Jarno wrote:
> >>>+static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
> >>>+{
> >>>+    int mb, me;
> >>>+
> >>>+    if ((c & 0xffff) == c) {
> >>>+        tcg_out32(s, ANDI | SAI(src, dst, c));
> >>>+        return;
> >>>+    } else if ((c & 0xffff0000) == c) {
> >>>+        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
> >>>+        return;
> >>>+    } else if (mask_operand(c, &mb, &me)) {
> >>>+        tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
> >>>+    } else {
> >>>+        tcg_out_movi(s, TCG_TYPE_I32, 0, c);
> >>>+        tcg_out32(s, AND | SAB(src, dst, 0));
> >Give it's a 32-bit constant, wouldn't it be better to use ANDI +
> >ANDIS here?
> >
> 
> x & 0xffff0000 & 0x0000ffff == 0.
> 
> Unlike IOR and XOR...

Looks like I read it too quickly. Therefore:

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

Patch

diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 9718ef6..ad6db6c 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -527,6 +527,48 @@  static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
     }
 }
 
+static inline bool mask_operand(uint32_t c, int *mb, int *me)
+{
+    uint32_t lsb, test;
+
+    /* Accept a bit pattern like:
+           0....01....1
+           1....10....0
+           0..01..10..0
+       Keep track of the transitions.  */
+    if (c == 0 || c == -1) {
+        return false;
+    }
+    test = c;
+    lsb = test & -test;
+    test += lsb;
+    if (test & (test - 1)) {
+        return false;
+    }
+
+    *me = clz32(lsb);
+    *mb = test ? clz32(test & -test) + 1 : 0;
+    return true;
+}
+
+static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
+{
+    int mb, me;
+
+    if ((c & 0xffff) == c) {
+        tcg_out32(s, ANDI | SAI(src, dst, c));
+        return;
+    } else if ((c & 0xffff0000) == c) {
+        tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
+        return;
+    } else if (mask_operand(c, &mb, &me)) {
+        tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
+    } else {
+        tcg_out_movi(s, TCG_TYPE_I32, 0, c);
+        tcg_out32(s, AND | SAB(src, dst, 0));
+    }
+}
+
 static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
                            int op_lo, int op_hi)
 {
@@ -1346,9 +1388,15 @@  static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
         }
         break;
 
-    case INDEX_op_and_i64:
     case INDEX_op_and_i32:
         if (const_args[2]) {
+            tcg_out_andi32(s, args[0], args[1], args[2]);
+        } else {
+            tcg_out32(s, AND | SAB(args[1], args[0], args[2]));
+        }
+        break;
+    case INDEX_op_and_i64:
+        if (const_args[2]) {
             if ((args[2] & 0xffff) == args[2]) {
                 tcg_out32(s, ANDI | SAI(args[1], args[0], args[2]));
             } else if ((args[2] & 0xffff0000) == args[2]) {