diff mbox series

[v2,20/30] tcg/loongarch64: Implement setcond ops

Message ID 20210921201915.601245-21-git@xen0n.name
State New
Headers show
Series LoongArch64 port of QEMU TCG | expand

Commit Message

WANG Xuerui Sept. 21, 2021, 8:19 p.m. UTC
Signed-off-by: WANG Xuerui <git@xen0n.name>
---
 tcg/loongarch64/tcg-target.c.inc | 74 ++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

Comments

Richard Henderson Sept. 22, 2021, 3:13 p.m. UTC | #1
On 9/21/21 1:19 PM, WANG Xuerui wrote:
> +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
> +                            TCGReg arg1, TCGReg arg2, bool c1, bool c2)
> +{
> +    TCGReg tmp;
> +
> +    if (c1) {
> +        tcg_debug_assert(arg1 == 0);
> +    }
> +    if (c2) {
> +        tcg_debug_assert(arg2 == 0);
> +    }

You don't need to work quite this hard.  Only the second argument will be constant.  If 
both are constant, we will have folded the operation away.  If the first argument was 
constant, we will swap the condition.

> +    switch (cond) {
> +    case TCG_COND_EQ:
> +        if (c1) {
> +            tmp = arg2;
> +        } else if (c2) {
> +            tmp = arg1;
> +        } else {
> +            tcg_out_opc_sub_d(s, ret, arg1, arg2);

     if (!c2) {
         ...
     }

Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~
WANG Xuerui Sept. 22, 2021, 5:26 p.m. UTC | #2
Hi Richard,

On 9/22/21 23:13, Richard Henderson wrote:
> On 9/21/21 1:19 PM, WANG Xuerui wrote:
>> +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
>> +                            TCGReg arg1, TCGReg arg2, bool c1, bool c2)
>> +{
>> +    TCGReg tmp;
>> +
>> +    if (c1) {
>> +        tcg_debug_assert(arg1 == 0);
>> +    }
>> +    if (c2) {
>> +        tcg_debug_assert(arg2 == 0);
>> +    }
>
> You don't need to work quite this hard.  Only the second argument will 
> be constant.  If both are constant, we will have folded the operation 
> away.  If the first argument was constant, we will swap the condition.
Thanks for the clarification; again something I didn't discover during 
my (often cursory) read of tcg middle-end code. I'll drop all the c1 
thing in v3.
diff mbox series

Patch

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index b0600a3dbd..08e6541dcf 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -386,6 +386,73 @@  static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
     tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
 }
 
+static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
+                            TCGReg arg1, TCGReg arg2, bool c1, bool c2)
+{
+    TCGReg tmp;
+
+    if (c1) {
+        tcg_debug_assert(arg1 == 0);
+    }
+    if (c2) {
+        tcg_debug_assert(arg2 == 0);
+    }
+
+    switch (cond) {
+    case TCG_COND_EQ:
+        if (c1) {
+            tmp = arg2;
+        } else if (c2) {
+            tmp = arg1;
+        } else {
+            tcg_out_opc_sub_d(s, ret, arg1, arg2);
+            tmp = ret;
+        }
+        tcg_out_opc_sltui(s, ret, tmp, 1);
+        break;
+    case TCG_COND_NE:
+        if (c1) {
+            tmp = arg2;
+        } else if (c2) {
+            tmp = arg1;
+        } else {
+            tcg_out_opc_sub_d(s, ret, arg1, arg2);
+            tmp = ret;
+        }
+        tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
+        break;
+    case TCG_COND_LT:
+        tcg_out_opc_slt(s, ret, arg1, arg2);
+        break;
+    case TCG_COND_GE:
+        tcg_out_opc_slt(s, ret, arg1, arg2);
+        tcg_out_opc_xori(s, ret, ret, 1);
+        break;
+    case TCG_COND_LE:
+        tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, c2, c1);
+        break;
+    case TCG_COND_GT:
+        tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, c2, c1);
+        break;
+    case TCG_COND_LTU:
+        tcg_out_opc_sltu(s, ret, arg1, arg2);
+        break;
+    case TCG_COND_GEU:
+        tcg_out_opc_sltu(s, ret, arg1, arg2);
+        tcg_out_opc_xori(s, ret, ret, 1);
+        break;
+    case TCG_COND_LEU:
+        tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, c2, c1);
+        break;
+    case TCG_COND_GTU:
+        tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, c2, c1);
+        break;
+    default:
+        g_assert_not_reached();
+        break;
+    }
+}
+
 /*
  * Branch helpers
  */
@@ -768,6 +835,11 @@  static void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_opc_mod_du(s, a0, a1, a2);
         break;
 
+    case INDEX_op_setcond_i32:
+    case INDEX_op_setcond_i64:
+        tcg_out_setcond(s, args[3], a0, a1, a2, const_args[1], c2);
+        break;
+
     case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
     case INDEX_op_mov_i64:
     default:
@@ -877,6 +949,8 @@  static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
     case INDEX_op_rem_i64:
     case INDEX_op_remu_i32:
     case INDEX_op_remu_i64:
+    case INDEX_op_setcond_i32:
+    case INDEX_op_setcond_i64:
         return C_O1_I2(r, rZ, rZ);
 
     default: