* [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE}
@ 2023-10-25 7:26 Richard Henderson
2023-10-25 7:26 ` [PATCH 01/29] " Richard Henderson
` (28 more replies)
0 siblings, 29 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Inspired by some other patch review this week, expose a pair
of comparison operators that map to the "test" comparison
that is available on many architectures.
Convert target/alpha to use this as an exemplar.
r~
Richard Henderson (29):
tcg: Introduce TCG_COND_TST{EQ,NE}
tcg/optimize: Split out arg_is_const_val
tcg/optimize: Split out do_constant_folding_cond1
tcg/optimize: Do swap_commutative2 in do_constant_folding_cond2
tcg/optimize: Split out arg_new_constant
tcg/optimize: Handle TCG_COND_TST{EQ,NE}
tcg/aarch64: Support TCG_COND_TST{EQ,NE}
tcg/aarch64: Generate TBZ, TBNZ
tcg/arm: Support TCG_COND_TST{EQ,NE}
tcg/i386: Pass x86 condition codes to tcg_out_cmov
tcg/i386: Move tcg_cond_to_jcc[] into tcg_out_cmp
tcg/i386: Add rexw argument to tcg_out_testi
tcg/i386: Support TCG_COND_TST{EQ,NE}
tcg/loongarch64: Support TCG_COND_TST{EQ,NE}
tcg/mips: Support TCG_COND_TST{EQ,NE}
tcg/riscv: Support TCG_COND_TST{EQ,NE}
tcg/sparc64: Implement tcg_out_extrl_i64_i32
tcg/sparc64: Hoist read of tcg_cond_to_rcond
tcg/sparc64: Pass TCGCond to tcg_out_cmp
tcg/sparc64: Support TCG_COND_TST{EQ,NE}
tcg/ppc: Sink tcg_to_bc usage into tcg_out_bc
tcg/ppc: Use cr0 in tcg_to_bc and tcg_to_isel
tcg/ppc: Create tcg_out_and_rc
tcg/ppc: Support TCG_COND_TST{EQ,NE}
tcg/s390x: Support TCG_COND_TST{EQ,NE}
tcg/tci: Support TCG_COND_TST{EQ,NE}
target/alpha: Use TCG_COND_TST{EQ,NE} for BLB{C,S}
target/alpha: Use TCG_COND_TST{EQ,NE} for CMOVLB{C,S}
target/alpha: Use TCG_COND_TSTNE for gen_fold_mzero
include/tcg/tcg-cond.h | 49 +++-
tcg/aarch64/tcg-target-con-set.h | 4 +-
target/alpha/translate.c | 94 +++----
tcg/optimize.c | 444 ++++++++++++++++++++++---------
tcg/tcg.c | 4 +-
tcg/tci.c | 14 +
docs/devel/tcg-ops.rst | 2 +
tcg/aarch64/tcg-target.c.inc | 156 ++++++++---
tcg/arm/tcg-target.c.inc | 59 ++--
tcg/i386/tcg-target.c.inc | 111 ++++----
tcg/loongarch64/tcg-target.c.inc | 56 ++--
tcg/mips/tcg-target.c.inc | 41 +++
tcg/ppc/tcg-target.c.inc | 213 ++++++++-------
tcg/riscv/tcg-target.c.inc | 20 +-
tcg/s390x/tcg-target.c.inc | 127 ++++++---
tcg/sparc64/tcg-target.c.inc | 67 +++--
16 files changed, 998 insertions(+), 463 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 01/29] tcg: Introduce TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 02/29] tcg/optimize: Split out arg_is_const_val Richard Henderson
` (27 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Add the enumerators, adjust the helpers to match, and dump.
Not supported anywhere else just yet.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/tcg/tcg-cond.h | 49 ++++++++++++++++++++++++++++++++----------
tcg/tcg.c | 4 +++-
docs/devel/tcg-ops.rst | 2 ++
3 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/include/tcg/tcg-cond.h b/include/tcg/tcg-cond.h
index 2a38a386d4..bf3fcf5968 100644
--- a/include/tcg/tcg-cond.h
+++ b/include/tcg/tcg-cond.h
@@ -49,6 +49,9 @@ typedef enum {
TCG_COND_GEU = 0 | 4 | 0 | 1,
TCG_COND_LEU = 8 | 4 | 0 | 0,
TCG_COND_GTU = 8 | 4 | 0 | 1,
+ /* "test" i.e. and then compare vs 0 */
+ TCG_COND_TSTEQ = 8 | 4 | 2 | 0,
+ TCG_COND_TSTNE = 8 | 4 | 2 | 1,
} TCGCond;
/* Invert the sense of the comparison. */
@@ -60,25 +63,49 @@ static inline TCGCond tcg_invert_cond(TCGCond c)
/* Swap the operands in a comparison. */
static inline TCGCond tcg_swap_cond(TCGCond c)
{
- return c & 6 ? (TCGCond)(c ^ 9) : c;
+ return (c + 2) & 4 ? (TCGCond)(c ^ 9) : c;
}
-/* Create an "unsigned" version of a "signed" comparison. */
-static inline TCGCond tcg_unsigned_cond(TCGCond c)
+/* Must a comparison be considered signed? */
+static inline bool is_signed_cond(TCGCond c)
{
- return c & 2 ? (TCGCond)(c ^ 6) : c;
-}
-
-/* Create a "signed" version of an "unsigned" comparison. */
-static inline TCGCond tcg_signed_cond(TCGCond c)
-{
- return c & 4 ? (TCGCond)(c ^ 6) : c;
+ return (c & 6) == 2;
}
/* Must a comparison be considered unsigned? */
static inline bool is_unsigned_cond(TCGCond c)
{
- return (c & 4) != 0;
+ return (c & 6) == 4;
+}
+
+/* Must a comparison be considered a test? */
+static inline bool is_tst_cond(TCGCond c)
+{
+ return (c | 1) == 0xf;
+}
+
+/* Create an "unsigned" version of a "signed" comparison. */
+static inline TCGCond tcg_unsigned_cond(TCGCond c)
+{
+ return is_signed_cond(c) ? (TCGCond)(c ^ 6) : c;
+}
+
+/* Create a "signed" version of an "unsigned" comparison. */
+static inline TCGCond tcg_signed_cond(TCGCond c)
+{
+ return is_unsigned_cond(c) ? (TCGCond)(c ^ 6) : c;
+}
+
+/* Create the eq/ne version of a tsteq/tstne comparison. */
+static inline TCGCond tcg_tst_eqne_cond(TCGCond c)
+{
+ return is_tst_cond(c) ? (TCGCond)(c ^ 6) : c;
+}
+
+/* Create the lt/ge version of a tstne/tsteq comparison of the sign. */
+static inline TCGCond tcg_tst_ltge_cond(TCGCond c)
+{
+ return is_tst_cond(c) ? (TCGCond)(c ^ (8 | 4 | 1)) : c;
}
/*
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 35158a0846..57d0583fe7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2378,7 +2378,9 @@ static const char * const cond_name[] =
[TCG_COND_LTU] = "ltu",
[TCG_COND_GEU] = "geu",
[TCG_COND_LEU] = "leu",
- [TCG_COND_GTU] = "gtu"
+ [TCG_COND_GTU] = "gtu",
+ [TCG_COND_TSTEQ] = "tsteq",
+ [TCG_COND_TSTNE] = "tstne",
};
static const char * const ldst_name[(MO_BSWAP | MO_SSIZE) + 1] =
diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst
index 8ae59ea02b..d46b625e0e 100644
--- a/docs/devel/tcg-ops.rst
+++ b/docs/devel/tcg-ops.rst
@@ -253,6 +253,8 @@ Jumps/Labels
| ``TCG_COND_GEU /* unsigned */``
| ``TCG_COND_LEU /* unsigned */``
| ``TCG_COND_GTU /* unsigned */``
+ | ``TCG_COND_TSTEQ /* t1 & t2 == 0 */``
+ | ``TCG_COND_TSTNE /* t1 & t2 != 0 */``
Arithmetic
----------
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 02/29] tcg/optimize: Split out arg_is_const_val
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 01/29] " Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 16:20 ` Philippe Mathieu-Daudé
2023-10-25 7:26 ` [PATCH 03/29] tcg/optimize: Split out do_constant_folding_cond1 Richard Henderson
` (26 subsequent siblings)
28 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/optimize.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 2db5177c32..e8a13fedb5 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -112,11 +112,22 @@ static inline bool ts_is_const(TCGTemp *ts)
return ts_info(ts)->is_const;
}
+static inline bool ts_is_const_val(TCGTemp *ts, uint64_t val)
+{
+ TempOptInfo *ti = ts_info(ts);
+ return ti->is_const && ti->val == val;
+}
+
static inline bool arg_is_const(TCGArg arg)
{
return ts_is_const(arg_temp(arg));
}
+static inline bool arg_is_const_val(TCGArg arg, uint64_t val)
+{
+ return ts_is_const_val(arg_temp(arg), val);
+}
+
static inline bool ts_is_copy(TCGTemp *ts)
{
return ts_info(ts)->next_copy != ts;
@@ -565,7 +576,7 @@ static int do_constant_folding_cond(TCGType type, TCGArg x,
}
} else if (args_are_copies(x, y)) {
return do_constant_folding_cond_eq(c);
- } else if (arg_is_const(y) && arg_info(y)->val == 0) {
+ } else if (arg_is_const_val(y, 0)) {
switch (c) {
case TCG_COND_LTU:
return 0;
@@ -831,7 +842,7 @@ static bool fold_to_not(OptContext *ctx, TCGOp *op, int idx)
/* If the binary operation has first argument @i, fold to @i. */
static bool fold_ix_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
{
- if (arg_is_const(op->args[1]) && arg_info(op->args[1])->val == i) {
+ if (arg_is_const_val(op->args[1], i)) {
return tcg_opt_gen_movi(ctx, op, op->args[0], i);
}
return false;
@@ -840,7 +851,7 @@ static bool fold_ix_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
/* If the binary operation has first argument @i, fold to NOT. */
static bool fold_ix_to_not(OptContext *ctx, TCGOp *op, uint64_t i)
{
- if (arg_is_const(op->args[1]) && arg_info(op->args[1])->val == i) {
+ if (arg_is_const_val(op->args[1], i)) {
return fold_to_not(ctx, op, 2);
}
return false;
@@ -849,7 +860,7 @@ static bool fold_ix_to_not(OptContext *ctx, TCGOp *op, uint64_t i)
/* If the binary operation has second argument @i, fold to @i. */
static bool fold_xi_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
{
- if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == i) {
+ if (arg_is_const_val(op->args[2], i)) {
return tcg_opt_gen_movi(ctx, op, op->args[0], i);
}
return false;
@@ -858,7 +869,7 @@ static bool fold_xi_to_i(OptContext *ctx, TCGOp *op, uint64_t i)
/* If the binary operation has second argument @i, fold to identity. */
static bool fold_xi_to_x(OptContext *ctx, TCGOp *op, uint64_t i)
{
- if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == i) {
+ if (arg_is_const_val(op->args[2], i)) {
return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
}
return false;
@@ -867,7 +878,7 @@ static bool fold_xi_to_x(OptContext *ctx, TCGOp *op, uint64_t i)
/* If the binary operation has second argument @i, fold to NOT. */
static bool fold_xi_to_not(OptContext *ctx, TCGOp *op, uint64_t i)
{
- if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == i) {
+ if (arg_is_const_val(op->args[2], i)) {
return fold_to_not(ctx, op, 1);
}
return false;
@@ -1083,8 +1094,8 @@ static bool fold_brcond2(OptContext *ctx, TCGOp *op)
* Simplify LT/GE comparisons vs zero to a single compare
* vs the high word of the input.
*/
- if (arg_is_const(op->args[2]) && arg_info(op->args[2])->val == 0 &&
- arg_is_const(op->args[3]) && arg_info(op->args[3])->val == 0) {
+ if (arg_is_const_val(op->args[2], 0) &&
+ arg_is_const_val(op->args[3], 0)) {
goto do_brcond_high;
}
break;
@@ -1303,9 +1314,7 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
}
/* Inserting a value into zero at offset 0. */
- if (arg_is_const(op->args[1])
- && arg_info(op->args[1])->val == 0
- && op->args[3] == 0) {
+ if (arg_is_const_val(op->args[1], 0) && op->args[3] == 0) {
uint64_t mask = MAKE_64BIT_MASK(0, op->args[4]);
op->opc = and_opc;
@@ -1316,8 +1325,7 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
}
/* Inserting zero into a value. */
- if (arg_is_const(op->args[2])
- && arg_info(op->args[2])->val == 0) {
+ if (arg_is_const_val(op->args[2], 0)) {
uint64_t mask = deposit64(-1, op->args[3], op->args[4], 0);
op->opc = and_opc;
@@ -1855,8 +1863,8 @@ static bool fold_setcond2(OptContext *ctx, TCGOp *op)
* Simplify LT/GE comparisons vs zero to a single compare
* vs the high word of the input.
*/
- if (arg_is_const(op->args[3]) && arg_info(op->args[3])->val == 0 &&
- arg_is_const(op->args[4]) && arg_info(op->args[4])->val == 0) {
+ if (arg_is_const_val(op->args[3], 0) &&
+ arg_is_const_val(op->args[4], 0)) {
goto do_setcond_high;
}
break;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 03/29] tcg/optimize: Split out do_constant_folding_cond1
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 01/29] " Richard Henderson
2023-10-25 7:26 ` [PATCH 02/29] tcg/optimize: Split out arg_is_const_val Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 04/29] tcg/optimize: Do swap_commutative2 in do_constant_folding_cond2 Richard Henderson
` (25 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Handle modifications to the arguments and condition
in a single place.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/optimize.c | 57 ++++++++++++++++++++++++--------------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index e8a13fedb5..89cc794d24 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -672,6 +672,23 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
return false;
}
+static int do_constant_folding_cond1(OptContext *ctx, TCGArg dest,
+ TCGArg *p1, TCGArg *p2, TCGArg *pcond)
+{
+ TCGCond cond;
+ bool swap;
+ int r;
+
+ swap = swap_commutative(dest, p1, p2);
+ cond = *pcond;
+ if (swap) {
+ *pcond = cond = tcg_swap_cond(cond);
+ }
+
+ r = do_constant_folding_cond(ctx->type, *p1, *p2, cond);
+ return r;
+}
+
static void init_arguments(OptContext *ctx, TCGOp *op, int nb_args)
{
for (int i = 0; i < nb_args; i++) {
@@ -1053,14 +1070,8 @@ static bool fold_andc(OptContext *ctx, TCGOp *op)
static bool fold_brcond(OptContext *ctx, TCGOp *op)
{
- TCGCond cond = op->args[2];
- int i;
-
- if (swap_commutative(NO_DEST, &op->args[0], &op->args[1])) {
- op->args[2] = cond = tcg_swap_cond(cond);
- }
-
- i = do_constant_folding_cond(ctx->type, op->args[0], op->args[1], cond);
+ int i = do_constant_folding_cond1(ctx, NO_DEST, &op->args[0],
+ &op->args[1], &op->args[2]);
if (i == 0) {
tcg_op_remove(ctx->tcg, op);
return true;
@@ -1550,21 +1561,18 @@ static bool fold_mov(OptContext *ctx, TCGOp *op)
static bool fold_movcond(OptContext *ctx, TCGOp *op)
{
- TCGCond cond = op->args[5];
int i;
- if (swap_commutative(NO_DEST, &op->args[1], &op->args[2])) {
- op->args[5] = cond = tcg_swap_cond(cond);
- }
/*
* Canonicalize the "false" input reg to match the destination reg so
* that the tcg backend can implement a "move if true" operation.
*/
if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
- op->args[5] = cond = tcg_invert_cond(cond);
+ op->args[5] = tcg_invert_cond(op->args[5]);
}
- i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
+ i = do_constant_folding_cond1(ctx, NO_DEST, &op->args[1],
+ &op->args[2], &op->args[5]);
if (i >= 0) {
return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[4 - i]);
}
@@ -1578,6 +1586,7 @@ static bool fold_movcond(OptContext *ctx, TCGOp *op)
uint64_t tv = arg_info(op->args[3])->val;
uint64_t fv = arg_info(op->args[4])->val;
TCGOpcode opc, negopc = 0;
+ TCGCond cond = op->args[5];
switch (ctx->type) {
case TCG_TYPE_I32:
@@ -1805,14 +1814,8 @@ static bool fold_remainder(OptContext *ctx, TCGOp *op)
static bool fold_setcond(OptContext *ctx, TCGOp *op)
{
- TCGCond cond = op->args[3];
- int i;
-
- if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
- op->args[3] = cond = tcg_swap_cond(cond);
- }
-
- i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
+ int i = do_constant_folding_cond1(ctx, op->args[0], &op->args[1],
+ &op->args[2], &op->args[3]);
if (i >= 0) {
return tcg_opt_gen_movi(ctx, op, op->args[0], i);
}
@@ -1824,14 +1827,8 @@ static bool fold_setcond(OptContext *ctx, TCGOp *op)
static bool fold_negsetcond(OptContext *ctx, TCGOp *op)
{
- TCGCond cond = op->args[3];
- int i;
-
- if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
- op->args[3] = cond = tcg_swap_cond(cond);
- }
-
- i = do_constant_folding_cond(ctx->type, op->args[1], op->args[2], cond);
+ int i = do_constant_folding_cond1(ctx, op->args[0], &op->args[1],
+ &op->args[2], &op->args[3]);
if (i >= 0) {
return tcg_opt_gen_movi(ctx, op, op->args[0], -i);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 04/29] tcg/optimize: Do swap_commutative2 in do_constant_folding_cond2
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (2 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 03/29] tcg/optimize: Split out do_constant_folding_cond1 Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 05/29] tcg/optimize: Split out arg_new_constant Richard Henderson
` (24 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Mirror the new do_constant_folding_cond1 by doing all
argument and condition adjustment within one helper.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/optimize.c | 107 ++++++++++++++++++++++++++-----------------------
1 file changed, 57 insertions(+), 50 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 89cc794d24..76be0fc337 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -589,43 +589,6 @@ static int do_constant_folding_cond(TCGType type, TCGArg x,
return -1;
}
-/*
- * Return -1 if the condition can't be simplified,
- * and the result of the condition (0 or 1) if it can.
- */
-static int do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
-{
- TCGArg al = p1[0], ah = p1[1];
- TCGArg bl = p2[0], bh = p2[1];
-
- if (arg_is_const(bl) && arg_is_const(bh)) {
- tcg_target_ulong blv = arg_info(bl)->val;
- tcg_target_ulong bhv = arg_info(bh)->val;
- uint64_t b = deposit64(blv, 32, 32, bhv);
-
- if (arg_is_const(al) && arg_is_const(ah)) {
- tcg_target_ulong alv = arg_info(al)->val;
- tcg_target_ulong ahv = arg_info(ah)->val;
- uint64_t a = deposit64(alv, 32, 32, ahv);
- return do_constant_folding_cond_64(a, b, c);
- }
- if (b == 0) {
- switch (c) {
- case TCG_COND_LTU:
- return 0;
- case TCG_COND_GEU:
- return 1;
- default:
- break;
- }
- }
- }
- if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
- return do_constant_folding_cond_eq(c);
- }
- return -1;
-}
-
/**
* swap_commutative:
* @dest: TCGArg of the destination argument, or NO_DEST.
@@ -672,6 +635,10 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
return false;
}
+/*
+ * Return -1 if the condition can't be simplified,
+ * and the result of the condition (0 or 1) if it can.
+ */
static int do_constant_folding_cond1(OptContext *ctx, TCGArg dest,
TCGArg *p1, TCGArg *p2, TCGArg *pcond)
{
@@ -689,6 +656,51 @@ static int do_constant_folding_cond1(OptContext *ctx, TCGArg dest,
return r;
}
+static int do_constant_folding_cond2(OptContext *ctx, TCGArg *args)
+{
+ TCGArg al, ah, bl, bh;
+ TCGCond c;
+ bool swap;
+
+ swap = swap_commutative2(args, args + 2);
+ c = args[4];
+ if (swap) {
+ args[4] = c = tcg_swap_cond(c);
+ }
+
+ al = args[0];
+ ah = args[1];
+ bl = args[2];
+ bh = args[3];
+
+ if (arg_is_const(bl) && arg_is_const(bh)) {
+ tcg_target_ulong blv = arg_info(bl)->val;
+ tcg_target_ulong bhv = arg_info(bh)->val;
+ uint64_t b = deposit64(blv, 32, 32, bhv);
+
+ if (arg_is_const(al) && arg_is_const(ah)) {
+ tcg_target_ulong alv = arg_info(al)->val;
+ tcg_target_ulong ahv = arg_info(ah)->val;
+ uint64_t a = deposit64(alv, 32, 32, ahv);
+ return do_constant_folding_cond_64(a, b, c);
+ }
+ if (b == 0) {
+ switch (c) {
+ case TCG_COND_LTU:
+ return 0;
+ case TCG_COND_GEU:
+ return 1;
+ default:
+ break;
+ }
+ }
+ }
+ if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
+ return do_constant_folding_cond_eq(c);
+ }
+ return -1;
+}
+
static void init_arguments(OptContext *ctx, TCGOp *op, int nb_args)
{
for (int i = 0; i < nb_args; i++) {
@@ -1085,15 +1097,13 @@ static bool fold_brcond(OptContext *ctx, TCGOp *op)
static bool fold_brcond2(OptContext *ctx, TCGOp *op)
{
- TCGCond cond = op->args[4];
- TCGArg label = op->args[5];
+ TCGCond cond;
+ TCGArg label;
int i, inv = 0;
- if (swap_commutative2(&op->args[0], &op->args[2])) {
- op->args[4] = cond = tcg_swap_cond(cond);
- }
-
- i = do_constant_folding_cond2(&op->args[0], &op->args[2], cond);
+ i = do_constant_folding_cond2(ctx, &op->args[0]);
+ cond = op->args[4];
+ label = op->args[5];
if (i >= 0) {
goto do_brcond_const;
}
@@ -1841,14 +1851,11 @@ static bool fold_negsetcond(OptContext *ctx, TCGOp *op)
static bool fold_setcond2(OptContext *ctx, TCGOp *op)
{
- TCGCond cond = op->args[5];
+ TCGCond cond;
int i, inv = 0;
- if (swap_commutative2(&op->args[1], &op->args[3])) {
- op->args[5] = cond = tcg_swap_cond(cond);
- }
-
- i = do_constant_folding_cond2(&op->args[1], &op->args[3], cond);
+ i = do_constant_folding_cond2(ctx, &op->args[1]);
+ cond = op->args[5];
if (i >= 0) {
goto do_setcond_const;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 05/29] tcg/optimize: Split out arg_new_constant
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (3 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 04/29] tcg/optimize: Do swap_commutative2 in do_constant_folding_cond2 Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 16:22 ` Philippe Mathieu-Daudé
2023-10-25 7:26 ` [PATCH 06/29] tcg/optimize: Handle TCG_COND_TST{EQ,NE} Richard Henderson
` (23 subsequent siblings)
28 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Fixes a bug wherein raw uses of tcg_constant_internal
do not have their TempOptInfo initialized.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/optimize.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 76be0fc337..2f2d1c3001 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -237,6 +237,21 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
}
+static TCGArg arg_new_constant(OptContext *ctx, uint64_t val)
+{
+ TCGType type = ctx->type;
+ TCGTemp *ts;
+
+ if (type == TCG_TYPE_I32) {
+ val = (int32_t)val;
+ }
+
+ ts = tcg_constant_internal(type, val);
+ init_ts_info(ctx, ts);
+
+ return temp_arg(ts);
+}
+
static bool tcg_opt_gen_mov(OptContext *ctx, TCGOp *op, TCGArg dst, TCGArg src)
{
TCGTemp *dst_ts = arg_temp(dst);
@@ -293,16 +308,8 @@ static bool tcg_opt_gen_mov(OptContext *ctx, TCGOp *op, TCGArg dst, TCGArg src)
static bool tcg_opt_gen_movi(OptContext *ctx, TCGOp *op,
TCGArg dst, uint64_t val)
{
- TCGTemp *tv;
-
- if (ctx->type == TCG_TYPE_I32) {
- val = (int32_t)val;
- }
-
/* Convert movi to mov with constant temp. */
- tv = tcg_constant_internal(ctx->type, val);
- init_ts_info(ctx, tv);
- return tcg_opt_gen_mov(ctx, op, dst, temp_arg(tv));
+ return tcg_opt_gen_mov(ctx, op, dst, arg_new_constant(ctx, val));
}
static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
@@ -1340,7 +1347,7 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
op->opc = and_opc;
op->args[1] = op->args[2];
- op->args[2] = temp_arg(tcg_constant_internal(ctx->type, mask));
+ op->args[2] = arg_new_constant(ctx, mask);
ctx->z_mask = mask & arg_info(op->args[1])->z_mask;
return false;
}
@@ -1350,7 +1357,7 @@ static bool fold_deposit(OptContext *ctx, TCGOp *op)
uint64_t mask = deposit64(-1, op->args[3], op->args[4], 0);
op->opc = and_opc;
- op->args[2] = temp_arg(tcg_constant_internal(ctx->type, mask));
+ op->args[2] = arg_new_constant(ctx, mask);
ctx->z_mask = mask & arg_info(op->args[1])->z_mask;
return false;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 06/29] tcg/optimize: Handle TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (4 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 05/29] tcg/optimize: Split out arg_new_constant Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 07/29] tcg/aarch64: Support TCG_COND_TST{EQ,NE} Richard Henderson
` (22 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Fold constant comparisons.
Canonicalize "tst x,x" to equality vs zero.
Canonicalize "tst x,sign" to sign test vs zero.
Fold double-word comparisons with zero parts.
Fold setcond of "tst x,pow2" to a bit extract.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/optimize.c | 225 ++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 205 insertions(+), 20 deletions(-)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 2f2d1c3001..27b1eaaa8d 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -508,9 +508,15 @@ static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
return x <= y;
case TCG_COND_GTU:
return x > y;
- default:
- g_assert_not_reached();
+ case TCG_COND_TSTEQ:
+ return (x & y) == 0;
+ case TCG_COND_TSTNE:
+ return (x & y) != 0;
+ case TCG_COND_ALWAYS:
+ case TCG_COND_NEVER:
+ break;
}
+ g_assert_not_reached();
}
static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
@@ -536,12 +542,18 @@ static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
return x <= y;
case TCG_COND_GTU:
return x > y;
- default:
- g_assert_not_reached();
+ case TCG_COND_TSTEQ:
+ return (x & y) == 0;
+ case TCG_COND_TSTNE:
+ return (x & y) != 0;
+ case TCG_COND_ALWAYS:
+ case TCG_COND_NEVER:
+ break;
}
+ g_assert_not_reached();
}
-static bool do_constant_folding_cond_eq(TCGCond c)
+static int do_constant_folding_cond_eq(TCGCond c)
{
switch (c) {
case TCG_COND_GT:
@@ -556,9 +568,14 @@ static bool do_constant_folding_cond_eq(TCGCond c)
case TCG_COND_LEU:
case TCG_COND_EQ:
return 1;
- default:
- g_assert_not_reached();
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ return -1;
+ case TCG_COND_ALWAYS:
+ case TCG_COND_NEVER:
+ break;
}
+ g_assert_not_reached();
}
/*
@@ -660,7 +677,27 @@ static int do_constant_folding_cond1(OptContext *ctx, TCGArg dest,
}
r = do_constant_folding_cond(ctx->type, *p1, *p2, cond);
- return r;
+ if (r >= 0) {
+ return r;
+ }
+ if (!is_tst_cond(cond)) {
+ return -1;
+ }
+
+ /* TSTNE x,x -> NE x,0 */
+ if (args_are_copies(*p1, *p2)) {
+ *p2 = arg_new_constant(ctx, 0);
+ *pcond = tcg_tst_eqne_cond(cond);
+ return -1;
+ }
+
+ /* TSTNE x,sign -> LT x,0 */
+ if (arg_is_const_val(*p2, (ctx->type == TCG_TYPE_I32
+ ? INT32_MIN : INT64_MIN))) {
+ *p2 = arg_new_constant(ctx, 0);
+ *pcond = tcg_tst_ltge_cond(cond);
+ }
+ return -1;
}
static int do_constant_folding_cond2(OptContext *ctx, TCGArg *args)
@@ -668,6 +705,7 @@ static int do_constant_folding_cond2(OptContext *ctx, TCGArg *args)
TCGArg al, ah, bl, bh;
TCGCond c;
bool swap;
+ int r;
swap = swap_commutative2(args, args + 2);
c = args[4];
@@ -689,8 +727,13 @@ static int do_constant_folding_cond2(OptContext *ctx, TCGArg *args)
tcg_target_ulong alv = arg_info(al)->val;
tcg_target_ulong ahv = arg_info(ah)->val;
uint64_t a = deposit64(alv, 32, 32, ahv);
- return do_constant_folding_cond_64(a, b, c);
+
+ r = do_constant_folding_cond_64(a, b, c);
+ if (r >= 0) {
+ return r;
+ }
}
+
if (b == 0) {
switch (c) {
case TCG_COND_LTU:
@@ -701,9 +744,28 @@ static int do_constant_folding_cond2(OptContext *ctx, TCGArg *args)
break;
}
}
+
+ /* TSTNE x,sign -> LT x,0 */
+ if (b == INT64_MIN && is_tst_cond(c)) {
+ /* bl must be 0, so copy that to bh */
+ args[3] = bl;
+ args[4] = tcg_tst_ltge_cond(c);
+ return -1;
+ }
}
+
if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
- return do_constant_folding_cond_eq(c);
+ r = do_constant_folding_cond_eq(c);
+ if (r >= 0) {
+ return r;
+ }
+
+ /* TSTNE x,x -> NE x,0 */
+ if (is_tst_cond(c)) {
+ args[3] = args[2] = arg_new_constant(ctx, 0);
+ args[4] = tcg_tst_eqne_cond(c);
+ return -1;
+ }
}
return -1;
}
@@ -1151,17 +1213,30 @@ static bool fold_brcond2(OptContext *ctx, TCGOp *op)
case 0:
goto do_brcond_const;
case 1:
- op->opc = INDEX_op_brcond_i32;
- op->args[1] = op->args[2];
- op->args[2] = cond;
- op->args[3] = label;
- break;
+ goto do_brcond_low;
+ }
+ break;
+
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ if (arg_is_const_val(op->args[2], 0)) {
+ goto do_brcond_high;
+ }
+ if (arg_is_const_val(op->args[3], 0)) {
+ goto do_brcond_low;
}
break;
default:
break;
+ do_brcond_low:
+ op->opc = INDEX_op_brcond_i32;
+ op->args[1] = op->args[2];
+ op->args[2] = cond;
+ op->args[3] = label;
+ break;
+
do_brcond_high:
op->opc = INDEX_op_brcond_i32;
op->args[0] = op->args[1];
@@ -1829,6 +1904,100 @@ static bool fold_remainder(OptContext *ctx, TCGOp *op)
return false;
}
+static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg)
+{
+ TCGOpcode and_opc, sub_opc, xor_opc, neg_opc, shr_opc, uext_opc, sext_opc;
+ TCGCond cond = op->args[3];
+ TCGArg ret, src1, src2;
+ TCGOp *op2;
+ uint64_t val;
+ int sh;
+ bool inv;
+
+ if (!is_tst_cond(cond) || !arg_is_const(op->args[2])) {
+ return;
+ }
+
+ src2 = op->args[2];
+ val = arg_info(src2)->val;
+ if (!is_power_of_2(val)) {
+ return;
+ }
+
+ switch (ctx->type) {
+ case TCG_TYPE_I32:
+ and_opc = INDEX_op_and_i32;
+ sub_opc = INDEX_op_sub_i32;
+ xor_opc = INDEX_op_xor_i32;
+ shr_opc = INDEX_op_shr_i32;
+ neg_opc = TCG_TARGET_HAS_neg_i32 ? INDEX_op_neg_i32 : 0;
+ uext_opc = TCG_TARGET_HAS_extract_i32 ? INDEX_op_extract_i32 : 0;
+ sext_opc = TCG_TARGET_HAS_sextract_i32 ? INDEX_op_sextract_i32 : 0;
+ break;
+ case TCG_TYPE_I64:
+ and_opc = INDEX_op_and_i64;
+ sub_opc = INDEX_op_sub_i64;
+ xor_opc = INDEX_op_xor_i64;
+ shr_opc = INDEX_op_shr_i64;
+ neg_opc = TCG_TARGET_HAS_neg_i64 ? INDEX_op_neg_i64 : 0;
+ uext_opc = TCG_TARGET_HAS_extract_i64 ? INDEX_op_extract_i64 : 0;
+ sext_opc = TCG_TARGET_HAS_sextract_i64 ? INDEX_op_sextract_i64 : 0;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ sh = ctz64(val);
+ ret = op->args[0];
+ src1 = op->args[1];
+ inv = cond == TCG_COND_TSTEQ;
+
+ if (neg && !inv && sext_opc) {
+ op->opc = sext_opc;
+ op->args[1] = src1;
+ op->args[2] = sh;
+ op->args[3] = 1;
+ neg = false;
+ } else if (uext_opc) {
+ op->opc = uext_opc;
+ op->args[1] = src1;
+ op->args[2] = sh;
+ op->args[3] = 1;
+ } else {
+ if (sh) {
+ op2 = tcg_op_insert_before(ctx->tcg, op, shr_opc, 3);
+ op2->args[0] = ret;
+ op2->args[1] = src1;
+ op2->args[2] = arg_new_constant(ctx, sh);
+ src1 = ret;
+ }
+ op->opc = and_opc;
+ op->args[1] = src1;
+ op->args[2] = arg_new_constant(ctx, 1);
+ }
+
+ if (neg && inv) {
+ op2 = tcg_op_insert_after(ctx->tcg, op, sub_opc, 3);
+ op2->args[0] = ret;
+ op2->args[1] = ret;
+ op2->args[2] = arg_new_constant(ctx, 1);
+ } else if (inv) {
+ op2 = tcg_op_insert_after(ctx->tcg, op, xor_opc, 3);
+ op2->args[0] = ret;
+ op2->args[1] = ret;
+ op2->args[2] = arg_new_constant(ctx, 1);
+ } else if (neg && neg_opc) {
+ op2 = tcg_op_insert_after(ctx->tcg, op, neg_opc, 2);
+ op2->args[0] = ret;
+ op2->args[1] = ret;
+ } else if (neg) {
+ op2 = tcg_op_insert_after(ctx->tcg, op, sub_opc, 3);
+ op2->args[0] = ret;
+ op2->args[1] = arg_new_constant(ctx, 0);
+ op2->args[2] = ret;
+ }
+}
+
static bool fold_setcond(OptContext *ctx, TCGOp *op)
{
int i = do_constant_folding_cond1(ctx, op->args[0], &op->args[1],
@@ -1836,6 +2005,7 @@ static bool fold_setcond(OptContext *ctx, TCGOp *op)
if (i >= 0) {
return tcg_opt_gen_movi(ctx, op, op->args[0], i);
}
+ fold_setcond_tst_pow2(ctx, op, false);
ctx->z_mask = 1;
ctx->s_mask = smask_from_zmask(1);
@@ -1849,13 +2019,13 @@ static bool fold_negsetcond(OptContext *ctx, TCGOp *op)
if (i >= 0) {
return tcg_opt_gen_movi(ctx, op, op->args[0], -i);
}
+ fold_setcond_tst_pow2(ctx, op, true);
/* Value is {0,-1} so all bits are repetitions of the sign. */
ctx->s_mask = -1;
return false;
}
-
static bool fold_setcond2(OptContext *ctx, TCGOp *op)
{
TCGCond cond;
@@ -1903,21 +2073,36 @@ static bool fold_setcond2(OptContext *ctx, TCGOp *op)
case 0:
goto do_setcond_const;
case 1:
- op->args[2] = op->args[3];
- op->args[3] = cond;
- op->opc = INDEX_op_setcond_i32;
- break;
+ goto do_setcond_low;
+ }
+ break;
+
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ if (arg_is_const_val(op->args[2], 0)) {
+ goto do_setcond_high;
+ }
+ if (arg_is_const_val(op->args[4], 0)) {
+ goto do_setcond_low;
}
break;
default:
break;
+ do_setcond_low:
+ op->args[2] = op->args[3];
+ op->args[3] = cond;
+ op->opc = INDEX_op_setcond_i32;
+ fold_setcond_tst_pow2(ctx, op, false);
+ break;
+
do_setcond_high:
op->args[1] = op->args[2];
op->args[2] = op->args[4];
op->args[3] = cond;
op->opc = INDEX_op_setcond_i32;
+ fold_setcond_tst_pow2(ctx, op, false);
break;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 07/29] tcg/aarch64: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (5 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 06/29] tcg/optimize: Handle TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 08/29] tcg/aarch64: Generate TBZ, TBNZ Richard Henderson
` (21 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/aarch64/tcg-target-con-set.h | 4 +--
tcg/aarch64/tcg-target.c.inc | 58 +++++++++++++++++++++-----------
2 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/tcg/aarch64/tcg-target-con-set.h b/tcg/aarch64/tcg-target-con-set.h
index 3fdee26a3d..a927cd11a2 100644
--- a/tcg/aarch64/tcg-target-con-set.h
+++ b/tcg/aarch64/tcg-target-con-set.h
@@ -10,7 +10,7 @@
* tcg-target-con-str.h; the constraint combination is inclusive or.
*/
C_O0_I1(r)
-C_O0_I2(r, rA)
+C_O0_I2(r, rAL)
C_O0_I2(rZ, r)
C_O0_I2(w, r)
C_O0_I3(rZ, rZ, r)
@@ -31,6 +31,6 @@ C_O1_I2(w, w, wN)
C_O1_I2(w, w, wO)
C_O1_I2(w, w, wZ)
C_O1_I3(w, w, w, w)
-C_O1_I4(r, r, rA, rZ, rZ)
+C_O1_I4(r, r, rAL, rZ, rZ)
C_O2_I1(r, r, r)
C_O2_I4(r, r, rZ, rZ, rA, rMZ)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index a3efa1e67a..2a748b3ee3 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -344,6 +344,9 @@ static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
[TCG_COND_GTU] = COND_HI,
[TCG_COND_GEU] = COND_HS,
[TCG_COND_LEU] = COND_LS,
+ /* bit test */
+ [TCG_COND_TSTEQ] = COND_EQ,
+ [TCG_COND_TSTNE] = COND_NE,
};
typedef enum {
@@ -1341,20 +1344,35 @@ static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
tcg_out_bfm(s, ext, rd, rn, a, b);
}
-static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
+static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGCond cond, TCGReg a,
tcg_target_long b, bool const_b)
{
- if (const_b) {
- /* Using CMP or CMN aliases. */
- if (b >= 0) {
- tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
- } else {
- tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
+ if (is_tst_cond(cond)) {
+ if (const_b) {
+ if (is_limm(b)) {
+ tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, a, b);
+ return;
+ }
+ tcg_out_movi(s, ext, TCG_REG_TMP0, b);
+ b = TCG_REG_TMP0;
}
- } else {
- /* Using CMP alias SUBS wzr, Wn, Wm */
- tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
+ tcg_out_insn(s, 3510, ANDS, ext, TCG_REG_XZR, a, b);
+ return;
}
+
+ if (const_b) {
+ if (is_aimm(b)) {
+ tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
+ return;
+ }
+ if (is_aimm(-b)) {
+ tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
+ return;
+ }
+ tcg_out_movi(s, ext, TCG_REG_TMP0, b);
+ b = TCG_REG_TMP0;
+ }
+ tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
}
static void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
@@ -1401,7 +1419,7 @@ static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond c, TCGArg a,
need_cmp = false;
} else {
need_cmp = true;
- tcg_out_cmp(s, ext, a, b, b_const);
+ tcg_out_cmp(s, ext, c, a, b, b_const);
}
if (!l->has_value) {
@@ -1574,7 +1592,7 @@ static void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d,
} else {
AArch64Insn sel = I3506_CSEL;
- tcg_out_cmp(s, ext, a0, 0, 1);
+ tcg_out_cmp(s, ext, TCG_COND_NE, a0, 0, 1);
tcg_out_insn(s, 3507, CLZ, ext, TCG_REG_TMP0, a1);
if (const_b) {
@@ -1719,7 +1737,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
addr_adj, compare_mask);
/* Perform the address comparison. */
- tcg_out_cmp(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2, 0);
+ tcg_out_cmp(s, addr_type, TCG_COND_NE, TCG_REG_TMP0, TCG_REG_TMP2, 0);
/* If not equal, we jump to the slow path. */
ldst->label_ptr[0] = s->code_ptr;
@@ -2275,7 +2293,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
a2 = (int32_t)a2;
/* FALLTHRU */
case INDEX_op_setcond_i64:
- tcg_out_cmp(s, ext, a1, a2, c2);
+ tcg_out_cmp(s, ext, args[3], a1, a2, c2);
/* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
TCG_REG_XZR, tcg_invert_cond(args[3]));
@@ -2285,7 +2303,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
a2 = (int32_t)a2;
/* FALLTHRU */
case INDEX_op_negsetcond_i64:
- tcg_out_cmp(s, ext, a1, a2, c2);
+ tcg_out_cmp(s, ext, args[3], a1, a2, c2);
/* Use CSETM alias of CSINV Wd, WZR, WZR, invert(cond). */
tcg_out_insn(s, 3506, CSINV, ext, a0, TCG_REG_XZR,
TCG_REG_XZR, tcg_invert_cond(args[3]));
@@ -2295,7 +2313,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
a2 = (int32_t)a2;
/* FALLTHRU */
case INDEX_op_movcond_i64:
- tcg_out_cmp(s, ext, a1, a2, c2);
+ tcg_out_cmp(s, ext, args[5], a1, a2, c2);
tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
break;
@@ -2895,11 +2913,13 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_add_i64:
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
+ return C_O1_I2(r, r, rA);
+
case INDEX_op_setcond_i32:
case INDEX_op_setcond_i64:
case INDEX_op_negsetcond_i32:
case INDEX_op_negsetcond_i64:
- return C_O1_I2(r, r, rA);
+ return C_O1_I2(r, r, rAL);
case INDEX_op_mul_i32:
case INDEX_op_mul_i64:
@@ -2949,11 +2969,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
- return C_O0_I2(r, rA);
+ return C_O0_I2(r, rAL);
case INDEX_op_movcond_i32:
case INDEX_op_movcond_i64:
- return C_O1_I4(r, r, rA, rZ, rZ);
+ return C_O1_I4(r, r, rAL, rZ, rZ);
case INDEX_op_qemu_ld_a32_i32:
case INDEX_op_qemu_ld_a64_i32:
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 08/29] tcg/aarch64: Generate TBZ, TBNZ
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (6 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 07/29] tcg/aarch64: Support TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 09/29] tcg/arm: Support TCG_COND_TST{EQ,NE} Richard Henderson
` (20 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Test the sign bit for LT/GE vs 0, and TSTNE/EQ vs a power of 2.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/aarch64/tcg-target.c.inc | 100 ++++++++++++++++++++++++++++-------
1 file changed, 81 insertions(+), 19 deletions(-)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 2a748b3ee3..e65fc415d2 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -105,6 +105,18 @@ static bool reloc_pc19(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
return false;
}
+static bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+{
+ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+ ptrdiff_t offset = target - src_rx;
+
+ if (offset == sextract64(offset, 0, 14)) {
+ *src_rw = deposit32(*src_rw, 5, 14, offset);
+ return true;
+ }
+ return false;
+}
+
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
intptr_t value, intptr_t addend)
{
@@ -115,6 +127,8 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
return reloc_pc26(code_ptr, (const tcg_insn_unit *)value);
case R_AARCH64_CONDBR19:
return reloc_pc19(code_ptr, (const tcg_insn_unit *)value);
+ case R_AARCH64_TSTBR14:
+ return reloc_pc14(code_ptr, (const tcg_insn_unit *)value);
default:
g_assert_not_reached();
}
@@ -369,6 +383,10 @@ typedef enum {
/* Conditional branch (immediate). */
I3202_B_C = 0x54000000,
+ /* Test and branch (immediate). */
+ I3205_TBZ = 0x36000000,
+ I3205_TBNZ = 0x37000000,
+
/* Unconditional branch (immediate). */
I3206_B = 0x14000000,
I3206_BL = 0x94000000,
@@ -649,6 +667,14 @@ static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
}
+static void tcg_out_insn_3205(TCGContext *s, AArch64Insn insn,
+ TCGReg rt, int imm6, int imm14)
+{
+ insn |= (imm6 & 0x20) << (31 - 5);
+ insn |= (imm6 & 0x1f) << 19;
+ tcg_out32(s, insn | (imm14 & 0x3fff) << 5 | rt);
+}
+
static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
{
tcg_out32(s, insn | (imm26 & 0x03ffffff));
@@ -1412,30 +1438,66 @@ static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond c, TCGArg a,
TCGArg b, bool b_const, TCGLabel *l)
{
- intptr_t offset;
- bool need_cmp;
+ int tbit = -1;
+ bool need_cmp = true;
- if (b_const && b == 0 && (c == TCG_COND_EQ || c == TCG_COND_NE)) {
- need_cmp = false;
- } else {
- need_cmp = true;
- tcg_out_cmp(s, ext, c, a, b, b_const);
- }
-
- if (!l->has_value) {
- tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
- offset = tcg_in32(s) >> 5;
- } else {
- offset = tcg_pcrel_diff(s, l->u.value_ptr) >> 2;
- tcg_debug_assert(offset == sextract64(offset, 0, 19));
+ switch (c) {
+ case TCG_COND_EQ:
+ case TCG_COND_NE:
+ if (b_const && b == 0) {
+ need_cmp = false;
+ }
+ break;
+ case TCG_COND_LT:
+ case TCG_COND_GE:
+ if (b_const && b == 0) {
+ c = (c == TCG_COND_LT ? TCG_COND_TSTNE : TCG_COND_TSTEQ);
+ tbit = ext ? 63 : 31;
+ need_cmp = false;
+ }
+ break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ if (b_const && is_power_of_2(b)) {
+ tbit = ctz64(b);
+ need_cmp = false;
+ }
+ break;
+ default:
+ break;
}
if (need_cmp) {
- tcg_out_insn(s, 3202, B_C, c, offset);
- } else if (c == TCG_COND_EQ) {
- tcg_out_insn(s, 3201, CBZ, ext, a, offset);
+ tcg_out_cmp(s, ext, c, a, b, b_const);
+ tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
+ tcg_out_insn(s, 3202, B_C, c, 0);
+ return;
+ }
+
+ if (tbit >= 0) {
+ tcg_out_reloc(s, s->code_ptr, R_AARCH64_TSTBR14, l, 0);
+ switch (c) {
+ case TCG_COND_TSTEQ:
+ tcg_out_insn(s, 3205, TBZ, a, tbit, 0);
+ break;
+ case TCG_COND_TSTNE:
+ tcg_out_insn(s, 3205, TBNZ, a, tbit, 0);
+ break;
+ default:
+ g_assert_not_reached();
+ }
} else {
- tcg_out_insn(s, 3201, CBNZ, ext, a, offset);
+ tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
+ switch (c) {
+ case TCG_COND_EQ:
+ tcg_out_insn(s, 3201, CBZ, ext, a, 0);
+ break;
+ case TCG_COND_NE:
+ tcg_out_insn(s, 3201, CBNZ, ext, a, 0);
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 09/29] tcg/arm: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (7 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 08/29] tcg/aarch64: Generate TBZ, TBNZ Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 10/29] tcg/i386: Pass x86 condition codes to tcg_out_cmov Richard Henderson
` (19 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/arm/tcg-target.c.inc | 59 ++++++++++++++++++++++++++++++----------
1 file changed, 44 insertions(+), 15 deletions(-)
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
index fc78566494..344143cd10 100644
--- a/tcg/arm/tcg-target.c.inc
+++ b/tcg/arm/tcg-target.c.inc
@@ -1190,6 +1190,33 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
}
}
+static TCGCond tcg_out_cmp(TCGContext *s, TCGCond cond, TCGReg a,
+ TCGArg b, int b_const)
+{
+ if (!is_tst_cond(cond)) {
+ tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0, a, b, b_const);
+ return cond;
+ }
+
+ cond = tcg_tst_eqne_cond(cond);
+ if (b_const) {
+ int imm12 = encode_imm(b);
+
+ /*
+ * The compare constraints allow rIN, but TST does not support N.
+ * Be prepared to load the constant into a scratch register.
+ */
+ if (imm12 >= 0) {
+ tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, a, imm12);
+ return cond;
+ }
+ tcg_out_movi32(s, COND_AL, TCG_REG_TMP, b);
+ b = TCG_REG_TMP;
+ }
+ tcg_out_dat_reg(s, COND_AL, ARITH_TST, 0, a, b, SHIFT_IMM_LSL(0));
+ return cond;
+}
+
static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
const int *const_args)
{
@@ -1217,6 +1244,13 @@ static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
tcg_out_dat_rI(s, COND_EQ, ARITH_CMP, 0, al, bl, const_bl);
return cond;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ /* Similar, but with TST instead of CMP. */
+ tcg_out_dat_rI(s, COND_AL, ARITH_TST, 0, ah, bh, const_bh);
+ tcg_out_dat_rI(s, COND_EQ, ARITH_TST, 0, al, bl, const_bl);
+ return tcg_tst_eqne_cond(cond);
+
case TCG_COND_LT:
case TCG_COND_GE:
/* We perform a double-word subtraction and examine the result.
@@ -1805,9 +1839,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
/* Constraints mean that v2 is always in the same register as dest,
* so we only need to do "if condition passed, move v1 to dest".
*/
- tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
- args[1], args[2], const_args[2]);
- tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
+ c = tcg_out_cmp(s, args[5], args[1], args[2], const_args[2]);
+ tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[c], ARITH_MOV,
ARITH_MVN, args[0], 0, args[3], const_args[3]);
break;
case INDEX_op_add_i32:
@@ -1957,25 +1990,21 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_brcond_i32:
- tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
- args[0], args[1], const_args[1]);
- tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]],
- arg_label(args[3]));
+ c = tcg_out_cmp(s, args[2], args[0], args[1], const_args[1]);
+ tcg_out_goto_label(s, tcg_cond_to_arm_cond[c], arg_label(args[3]));
break;
case INDEX_op_setcond_i32:
- tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
- args[1], args[2], const_args[2]);
- tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
+ c = tcg_out_cmp(s, args[3], args[1], args[2], const_args[2]);
+ tcg_out_dat_imm(s, tcg_cond_to_arm_cond[c],
ARITH_MOV, args[0], 0, 1);
- tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
+ tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(c)],
ARITH_MOV, args[0], 0, 0);
break;
case INDEX_op_negsetcond_i32:
- tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
- args[1], args[2], const_args[2]);
- tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
+ c = tcg_out_cmp(s, args[3], args[1], args[2], const_args[2]);
+ tcg_out_dat_imm(s, tcg_cond_to_arm_cond[c],
ARITH_MVN, args[0], 0, 0);
- tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
+ tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(c)],
ARITH_MOV, args[0], 0, 0);
break;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 10/29] tcg/i386: Pass x86 condition codes to tcg_out_cmov
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (8 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 09/29] tcg/arm: Support TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 11/29] tcg/i386: Move tcg_cond_to_jcc[] into tcg_out_cmp Richard Henderson
` (18 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Hoist the tcg_cond_to_jcc index outside the function.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/i386/tcg-target.c.inc | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index a83f8aab30..0daffb0e70 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1668,14 +1668,14 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
}
#endif
-static void tcg_out_cmov(TCGContext *s, TCGCond cond, int rexw,
+static void tcg_out_cmov(TCGContext *s, int jcc, int rexw,
TCGReg dest, TCGReg v1)
{
if (have_cmov) {
- tcg_out_modrm(s, OPC_CMOVCC | tcg_cond_to_jcc[cond] | rexw, dest, v1);
+ tcg_out_modrm(s, OPC_CMOVCC | jcc | rexw, dest, v1);
} else {
TCGLabel *over = gen_new_label();
- tcg_out_jxx(s, tcg_cond_to_jcc[tcg_invert_cond(cond)], over, 1);
+ tcg_out_jxx(s, jcc ^ 1, over, 1);
tcg_out_mov(s, TCG_TYPE_I32, dest, v1);
tcg_out_label(s, over);
}
@@ -1686,7 +1686,7 @@ static void tcg_out_movcond(TCGContext *s, int rexw, TCGCond cond,
TCGReg v1)
{
tcg_out_cmp(s, c1, c2, const_c2, rexw);
- tcg_out_cmov(s, cond, rexw, dest, v1);
+ tcg_out_cmov(s, tcg_cond_to_jcc[cond], rexw, dest, v1);
}
static void tcg_out_ctz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
@@ -1698,12 +1698,12 @@ static void tcg_out_ctz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
tcg_debug_assert(arg2 == (rexw ? 64 : 32));
} else {
tcg_debug_assert(dest != arg2);
- tcg_out_cmov(s, TCG_COND_LTU, rexw, dest, arg2);
+ tcg_out_cmov(s, JCC_JB, rexw, dest, arg2);
}
} else {
tcg_debug_assert(dest != arg2);
tcg_out_modrm(s, OPC_BSF + rexw, dest, arg1);
- tcg_out_cmov(s, TCG_COND_EQ, rexw, dest, arg2);
+ tcg_out_cmov(s, JCC_JE, rexw, dest, arg2);
}
}
@@ -1716,7 +1716,7 @@ static void tcg_out_clz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
tcg_debug_assert(arg2 == (rexw ? 64 : 32));
} else {
tcg_debug_assert(dest != arg2);
- tcg_out_cmov(s, TCG_COND_LTU, rexw, dest, arg2);
+ tcg_out_cmov(s, JCC_JB, rexw, dest, arg2);
}
} else {
tcg_debug_assert(!const_a2);
@@ -1729,7 +1729,7 @@ static void tcg_out_clz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
/* Since we have destroyed the flags from BSR, we have to re-test. */
tcg_out_cmp(s, arg1, 0, 1, rexw);
- tcg_out_cmov(s, TCG_COND_EQ, rexw, dest, arg2);
+ tcg_out_cmov(s, JCC_JE, rexw, dest, arg2);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 11/29] tcg/i386: Move tcg_cond_to_jcc[] into tcg_out_cmp
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (9 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 10/29] tcg/i386: Pass x86 condition codes to tcg_out_cmov Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 12/29] tcg/i386: Add rexw argument to tcg_out_testi Richard Henderson
` (17 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Return the x86 condition codes to use after the compare.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/i386/tcg-target.c.inc | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 0daffb0e70..6e8af1fcf6 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1418,8 +1418,8 @@ static void tcg_out_jxx(TCGContext *s, int opc, TCGLabel *l, bool small)
}
}
-static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
- int const_arg2, int rexw)
+static int tcg_out_cmp(TCGContext *s, TCGCond cond, TCGArg arg1,
+ TCGArg arg2, int const_arg2, int rexw)
{
if (const_arg2) {
if (arg2 == 0) {
@@ -1431,14 +1431,15 @@ static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
} else {
tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
}
+ return tcg_cond_to_jcc[cond];
}
static void tcg_out_brcond(TCGContext *s, int rexw, TCGCond cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
TCGLabel *label, bool small)
{
- tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
- tcg_out_jxx(s, tcg_cond_to_jcc[cond], label, small);
+ int jcc = tcg_out_cmp(s, cond, arg1, arg2, const_arg2, rexw);
+ tcg_out_jxx(s, jcc, label, small);
}
#if TCG_TARGET_REG_BITS == 32
@@ -1530,6 +1531,7 @@ static void tcg_out_setcond(TCGContext *s, int rexw, TCGCond cond,
{
bool inv = false;
bool cleared;
+ int jcc;
switch (cond) {
case TCG_COND_NE:
@@ -1566,7 +1568,7 @@ static void tcg_out_setcond(TCGContext *s, int rexw, TCGCond cond,
* We can then use NEG or INC to produce the desired result.
* This is always smaller than the SETCC expansion.
*/
- tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
+ tcg_out_cmp(s, TCG_COND_LTU, arg1, arg2, const_arg2, rexw);
/* X - X - C = -C = (C ? -1 : 0) */
tgen_arithr(s, ARITH_SBB + (neg ? rexw : 0), dest, dest);
@@ -1613,8 +1615,8 @@ static void tcg_out_setcond(TCGContext *s, int rexw, TCGCond cond,
cleared = true;
}
- tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
- tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
+ jcc = tcg_out_cmp(s, cond, arg1, arg2, const_arg2, rexw);
+ tcg_out_modrm(s, OPC_SETCC | jcc, 0, dest);
if (!cleared) {
tcg_out_ext8u(s, dest, dest);
@@ -1685,8 +1687,8 @@ static void tcg_out_movcond(TCGContext *s, int rexw, TCGCond cond,
TCGReg dest, TCGReg c1, TCGArg c2, int const_c2,
TCGReg v1)
{
- tcg_out_cmp(s, c1, c2, const_c2, rexw);
- tcg_out_cmov(s, tcg_cond_to_jcc[cond], rexw, dest, v1);
+ int jcc = tcg_out_cmp(s, cond, c1, c2, const_c2, rexw);
+ tcg_out_cmov(s, jcc, rexw, dest, v1);
}
static void tcg_out_ctz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
@@ -1728,8 +1730,8 @@ static void tcg_out_clz(TCGContext *s, int rexw, TCGReg dest, TCGReg arg1,
tgen_arithi(s, ARITH_XOR + rexw, dest, rexw ? 63 : 31, 0);
/* Since we have destroyed the flags from BSR, we have to re-test. */
- tcg_out_cmp(s, arg1, 0, 1, rexw);
- tcg_out_cmov(s, JCC_JE, rexw, dest, arg2);
+ int jcc = tcg_out_cmp(s, TCG_COND_EQ, arg1, 0, 1, rexw);
+ tcg_out_cmov(s, jcc, rexw, dest, arg2);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 12/29] tcg/i386: Add rexw argument to tcg_out_testi
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (10 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 11/29] tcg/i386: Move tcg_cond_to_jcc[] into tcg_out_cmp Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 13/29] tcg/i386: Support TCG_COND_TST{EQ,NE} Richard Henderson
` (16 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Move up above tcg_out_cmp, where it will be used.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/i386/tcg-target.c.inc | 36 ++++++++++++++++--------------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 6e8af1fcf6..f4f456a2c0 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -1418,6 +1418,19 @@ static void tcg_out_jxx(TCGContext *s, int opc, TCGLabel *l, bool small)
}
}
+/* Test register R vs immediate bits I, setting Z flag for EQ/NE. */
+static void __attribute__((unused))
+tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i, int rexw)
+{
+ if (i <= 0xff && (TCG_TARGET_REG_BITS == 64 || r < 4)) {
+ tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, r);
+ tcg_out8(s, i);
+ } else {
+ tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_TESTi, r);
+ tcg_out32(s, i);
+ }
+}
+
static int tcg_out_cmp(TCGContext *s, TCGCond cond, TCGArg arg1,
TCGArg arg2, int const_arg2, int rexw)
{
@@ -1796,23 +1809,6 @@ static void tcg_out_nopn(TCGContext *s, int n)
tcg_out8(s, 0x90);
}
-/* Test register R vs immediate bits I, setting Z flag for EQ/NE. */
-static void __attribute__((unused))
-tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i)
-{
- /*
- * This is used for testing alignment, so we can usually use testb.
- * For i686, we have to use testl for %esi/%edi.
- */
- if (i <= 0xff && (TCG_TARGET_REG_BITS == 64 || r < 4)) {
- tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, r);
- tcg_out8(s, i);
- } else {
- tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_TESTi, r);
- tcg_out32(s, i);
- }
-}
-
typedef struct {
TCGReg base;
int index;
@@ -2080,7 +2076,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->addrlo_reg = addrlo;
ldst->addrhi_reg = addrhi;
- tcg_out_testi(s, addrlo, a_mask);
+ tcg_out_testi(s, addrlo, a_mask, false);
/* jne slow_path */
tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
ldst->label_ptr[0] = s->code_ptr;
@@ -2229,7 +2225,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
- tcg_out_testi(s, h.base, 15);
+ tcg_out_testi(s, h.base, 15, false);
tcg_out_jxx(s, JCC_JNE, l1, true);
tcg_out_vex_modrm_sib_offset(s, OPC_MOVDQA_VxWx + h.seg,
@@ -2357,7 +2353,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
- tcg_out_testi(s, h.base, 15);
+ tcg_out_testi(s, h.base, 15, false);
tcg_out_jxx(s, JCC_JNE, l1, true);
tcg_out_vex_modrm_sib_offset(s, OPC_MOVDQA_WxVx + h.seg,
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 13/29] tcg/i386: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (11 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 12/29] tcg/i386: Add rexw argument to tcg_out_testi Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 14/29] tcg/loongarch64: " Richard Henderson
` (15 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/i386/tcg-target.c.inc | 43 +++++++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index f4f456a2c0..0d97864174 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -504,6 +504,8 @@ static const uint8_t tcg_cond_to_jcc[] = {
[TCG_COND_GEU] = JCC_JAE,
[TCG_COND_LEU] = JCC_JBE,
[TCG_COND_GTU] = JCC_JA,
+ [TCG_COND_TSTEQ] = JCC_JE,
+ [TCG_COND_TSTNE] = JCC_JNE,
};
#if TCG_TARGET_REG_BITS == 64
@@ -1419,12 +1421,14 @@ static void tcg_out_jxx(TCGContext *s, int opc, TCGLabel *l, bool small)
}
/* Test register R vs immediate bits I, setting Z flag for EQ/NE. */
-static void __attribute__((unused))
-tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i, int rexw)
+static void tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i, int rexw)
{
if (i <= 0xff && (TCG_TARGET_REG_BITS == 64 || r < 4)) {
tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, r);
tcg_out8(s, i);
+ } else if ((i & ~0xff00) == 0 && r < 4) {
+ tcg_out_modrm(s, OPC_GRP3_Eb, EXT3_TESTi, r);
+ tcg_out8(s, i >> 8);
} else {
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_TESTi, r);
tcg_out32(s, i);
@@ -1434,15 +1438,25 @@ tcg_out_testi(TCGContext *s, TCGReg r, uint32_t i, int rexw)
static int tcg_out_cmp(TCGContext *s, TCGCond cond, TCGArg arg1,
TCGArg arg2, int const_arg2, int rexw)
{
- if (const_arg2) {
- if (arg2 == 0) {
- /* test r, r */
+ if (is_tst_cond(cond)) {
+ if (!const_arg2) {
+ tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg2);
+ } else {
+ if (!rexw) {
+ arg2 = (uint32_t)arg2;
+ } else if ((arg2 >> 31 >> 1) == 0) {
+ rexw = 0;
+ }
+ tcg_out_testi(s, arg1, arg2, rexw);
+ }
+ } else {
+ if (!const_arg2) {
+ tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
+ } else if (arg2 == 0) {
tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
} else {
tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
}
- } else {
- tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
}
return tcg_cond_to_jcc[cond];
}
@@ -1461,18 +1475,21 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
{
TCGLabel *label_next = gen_new_label();
TCGLabel *label_this = arg_label(args[5]);
+ TCGCond cond = args[4];
- switch(args[4]) {
+ switch (cond) {
case TCG_COND_EQ:
- tcg_out_brcond(s, 0, TCG_COND_NE, args[0], args[2], const_args[2],
- label_next, 1);
- tcg_out_brcond(s, 0, TCG_COND_EQ, args[1], args[3], const_args[3],
+ case TCG_COND_TSTEQ:
+ tcg_out_brcond(s, 0, tcg_invert_cond(cond),
+ args[0], args[2], const_args[2], label_next, 1);
+ tcg_out_brcond(s, 0, cond, args[1], args[3], const_args[3],
label_this, small);
break;
case TCG_COND_NE:
- tcg_out_brcond(s, 0, TCG_COND_NE, args[0], args[2], const_args[2],
+ case TCG_COND_TSTNE:
+ tcg_out_brcond(s, 0, cond, args[0], args[2], const_args[2],
label_this, small);
- tcg_out_brcond(s, 0, TCG_COND_NE, args[1], args[3], const_args[3],
+ tcg_out_brcond(s, 0, cond, args[1], args[3], const_args[3],
label_this, small);
break;
case TCG_COND_LT:
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 14/29] tcg/loongarch64: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (12 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 13/29] tcg/i386: Support TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 15/29] tcg/mips: " Richard Henderson
` (14 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/loongarch64/tcg-target.c.inc | 56 ++++++++++++++++++++++----------
1 file changed, 38 insertions(+), 18 deletions(-)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index ccf133db4b..4e850a29e5 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -555,6 +555,7 @@ static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
case TCG_COND_GEU: /* -> LTU */
case TCG_COND_GT: /* -> LE */
case TCG_COND_GTU: /* -> LEU */
+ case TCG_COND_TSTEQ: /* -> TSTNE */
cond = tcg_invert_cond(cond);
flags ^= SETCOND_INV;
break;
@@ -611,6 +612,18 @@ static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
}
break;
+ case TCG_COND_TSTNE:
+ flags |= SETCOND_NEZ;
+ if (!c2) {
+ tcg_out_opc_and(s, ret, arg1, arg2);
+ } else if (arg2 >= 0 && arg2 <= 0xfff) {
+ tcg_out_opc_andi(s, ret, arg1, arg2);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
+ tcg_out_opc_and(s, ret, arg1, TCG_REG_TMP0);
+ }
+ break;
+
case TCG_COND_LT:
case TCG_COND_LTU:
if (c2) {
@@ -695,29 +708,36 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
* Branch helpers
*/
-static const struct {
- LoongArchInsn op;
- bool swap;
-} tcg_brcond_to_loongarch[] = {
- [TCG_COND_EQ] = { OPC_BEQ, false },
- [TCG_COND_NE] = { OPC_BNE, false },
- [TCG_COND_LT] = { OPC_BGT, true },
- [TCG_COND_GE] = { OPC_BLE, true },
- [TCG_COND_LE] = { OPC_BLE, false },
- [TCG_COND_GT] = { OPC_BGT, false },
- [TCG_COND_LTU] = { OPC_BGTU, true },
- [TCG_COND_GEU] = { OPC_BLEU, true },
- [TCG_COND_LEU] = { OPC_BLEU, false },
- [TCG_COND_GTU] = { OPC_BGTU, false }
-};
-
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
TCGReg arg2, TCGLabel *l)
{
- LoongArchInsn op = tcg_brcond_to_loongarch[cond].op;
+ static const struct {
+ LoongArchInsn op;
+ bool swap;
+ } tcg_brcond_to_loongarch[16] = {
+ [TCG_COND_EQ] = { OPC_BEQ, false },
+ [TCG_COND_NE] = { OPC_BNE, false },
+ [TCG_COND_LT] = { OPC_BGT, true },
+ [TCG_COND_GE] = { OPC_BLE, true },
+ [TCG_COND_LE] = { OPC_BLE, false },
+ [TCG_COND_GT] = { OPC_BGT, false },
+ [TCG_COND_LTU] = { OPC_BGTU, true },
+ [TCG_COND_GEU] = { OPC_BLEU, true },
+ [TCG_COND_LEU] = { OPC_BLEU, false },
+ [TCG_COND_GTU] = { OPC_BGTU, false }
+ };
+ LoongArchInsn op;
+
+ if (is_tst_cond(cond)) {
+ tcg_out_opc_and(s, TCG_REG_TMP0, arg1, arg2);
+ arg1 = TCG_REG_TMP0;
+ arg2 = TCG_REG_ZERO;
+ cond = tcg_tst_eqne_cond(cond);
+ }
+
+ op = tcg_brcond_to_loongarch[cond].op
tcg_debug_assert(op != 0);
-
if (tcg_brcond_to_loongarch[cond].swap) {
TCGReg t = arg1;
arg1 = arg2;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 15/29] tcg/mips: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (13 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 14/29] tcg/loongarch64: " Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 16/29] tcg/riscv: " Richard Henderson
` (13 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/mips/tcg-target.c.inc | 41 +++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 328984ccff..739a0f60b7 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -909,6 +909,16 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
break;
+ case TCG_COND_TSTEQ:
+ tcg_out_opc_reg(s, OPC_AND, ret, arg1, arg2);
+ tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
+ break;
+
+ case TCG_COND_TSTNE:
+ tcg_out_opc_reg(s, OPC_AND, ret, arg1, arg2);
+ tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
+ break;
+
case TCG_COND_LT:
case TCG_COND_GE:
case TCG_COND_LE:
@@ -989,6 +999,14 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
arg2 = TCG_REG_ZERO;
break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP0, arg1, arg2);
+ arg1 = TCG_TMP0;
+ arg2 = TCG_REG_ZERO;
+ b_opc = cond == TCG_COND_TSTEQ ? OPC_BEQ : OPC_BNE;
+ break;
+
default:
g_assert_not_reached();
break;
@@ -1052,6 +1070,14 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP0, al, bl);
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, ah, bh);
+ tcg_out_opc_reg(s, OPC_OR, ret, TCG_TMP0, TCG_TMP1);
+ tcg_out_setcond(s, tcg_eqne_cond(cond), ret, tmp1, TCG_REG_ZERO);
+ break;
+
default:
tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
@@ -1078,6 +1104,13 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP0, al, bl);
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, ah, bh);
+ tcg_out_opc_reg(s, OPC_OR, TCG_TMP1, TCG_TMP1, TCG_TMP0);
+ break;
+
default:
/* Minimize code size by preferring a compare not requiring INV. */
if (mips_cmp_map[cond] & MIPS_CMP_INV) {
@@ -1114,6 +1147,14 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
}
break;
+ case TCG_COND_TSTEQ:
+ eqz = true;
+ /* FALLTHRU */
+ case TCG_COND_TSTNE:
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP0, c1, c2);
+ c1 = TCG_TMP0;
+ break;
+
default:
/* Minimize code size by preferring a compare not requiring INV. */
if (mips_cmp_map[cond] & MIPS_CMP_INV) {
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 16/29] tcg/riscv: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (14 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 15/29] tcg/mips: " Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 17/29] tcg/sparc64: Implement tcg_out_extrl_i64_i32 Richard Henderson
` (12 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/riscv/tcg-target.c.inc | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 34e10e77d9..3997e2f274 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -798,8 +798,14 @@ static const struct {
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
TCGReg arg2, TCGLabel *l)
{
- RISCVInsn op = tcg_brcond_to_riscv[cond].op;
+ RISCVInsn op;
+ if (is_tst_cond(cond)) {
+ tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP0, arg1, arg2);
+ cond = tcg_tst_eqne_cond(cond);
+ }
+
+ op = tcg_brcond_to_riscv[cond].op;
tcg_debug_assert(op != 0);
if (tcg_brcond_to_riscv[cond].swap) {
@@ -827,6 +833,7 @@ static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
case TCG_COND_GEU: /* -> LTU */
case TCG_COND_GT: /* -> LE */
case TCG_COND_GTU: /* -> LEU */
+ case TCG_COND_TSTEQ: /* -> TSTNE */
cond = tcg_invert_cond(cond);
flags ^= SETCOND_INV;
break;
@@ -886,6 +893,15 @@ static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
}
break;
+ case TCG_COND_TSTNE:
+ flags |= SETCOND_NEZ;
+ if (c2) {
+ tcg_out_opc_imm(s, OPC_ANDI, ret, arg1, arg2);
+ } else {
+ tcg_out_opc_reg(s, OPC_AND, ret, arg1, arg2);
+ }
+ break;
+
case TCG_COND_LT:
if (c2) {
tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
@@ -1079,7 +1095,7 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
int tmpflags;
TCGReg t;
- if (!have_zicond && (!c_cmp2 || cmp2 == 0)) {
+ if (!have_zicond && (!c_cmp2 || cmp2 == 0) && !is_tst_cond(cond)) {
tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
val1, c_val1, val2, c_val2);
return;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 17/29] tcg/sparc64: Implement tcg_out_extrl_i64_i32
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (15 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 16/29] tcg/riscv: " Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 18/29] tcg/sparc64: Hoist read of tcg_cond_to_rcond Richard Henderson
` (11 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd, qemu-stable
Build fix for missing symbol.
Cc: qemu-stable@nongnu.org
Fixes: b8b94ac6753 ("tcg: Split out tcg_out_extrl_i64_i32")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/sparc64/tcg-target.c.inc | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index 19d9df4a09..a91defd0ac 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -529,6 +529,11 @@ static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
tcg_out_ext32u(s, rd, rs);
}
+static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
+{
+ tcg_out_ext32u(s, rd, rs);
+}
+
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
{
return false;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 18/29] tcg/sparc64: Hoist read of tcg_cond_to_rcond
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (16 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 17/29] tcg/sparc64: Implement tcg_out_extrl_i64_i32 Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 19/29] tcg/sparc64: Pass TCGCond to tcg_out_cmp Richard Henderson
` (10 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Use a non-zero value here (an illegal encoding) as a better
condition than is_unsigned_cond for when MOVR/BPR is usable.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/sparc64/tcg-target.c.inc | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index a91defd0ac..13ad92b9b6 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -619,7 +619,7 @@ static const uint8_t tcg_cond_to_bcond[] = {
[TCG_COND_GTU] = COND_GU,
};
-static const uint8_t tcg_cond_to_rcond[] = {
+static const uint8_t tcg_cond_to_rcond[16] = {
[TCG_COND_EQ] = RCOND_Z,
[TCG_COND_NE] = RCOND_NZ,
[TCG_COND_LT] = RCOND_LZ,
@@ -678,7 +678,8 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
int32_t arg2, int const_arg2, TCGLabel *l)
{
/* For 64-bit signed comparisons vs zero, we can avoid the compare. */
- if (arg2 == 0 && !is_unsigned_cond(cond)) {
+ int rcond = tcg_cond_to_rcond[cond];
+ if (arg2 == 0 && rcond) {
int off16 = 0;
if (l->has_value) {
@@ -687,7 +688,7 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, l, 0);
}
tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
- | INSN_COND(tcg_cond_to_rcond[cond]) | off16);
+ | INSN_COND(rcond) | off16);
} else {
tcg_out_cmp(s, arg1, arg2, const_arg2);
tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, l);
@@ -695,11 +696,10 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
tcg_out_nop(s);
}
-static void tcg_out_movr(TCGContext *s, TCGCond cond, TCGReg ret, TCGReg c1,
+static void tcg_out_movr(TCGContext *s, int rcond, TCGReg ret, TCGReg c1,
int32_t v1, int v1const)
{
- tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1)
- | (tcg_cond_to_rcond[cond] << 10)
+ tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1) | (rcond << 10)
| (v1const ? INSN_IMM10(v1) : INSN_RS2(v1)));
}
@@ -710,9 +710,9 @@ static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
/* For 64-bit signed comparisons vs zero, we can avoid the compare.
Note that the immediate range is one bit smaller, so we must check
for that as well. */
- if (c2 == 0 && !is_unsigned_cond(cond)
- && (!v1const || check_fit_i32(v1, 10))) {
- tcg_out_movr(s, cond, ret, c1, v1, v1const);
+ int rcond = tcg_cond_to_rcond[cond];
+ if (c2 == 0 && rcond && (!v1const || check_fit_i32(v1, 10))) {
+ tcg_out_movr(s, rcond, ret, c1, v1, v1const);
} else {
tcg_out_cmp(s, c1, c2, c2const);
tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
@@ -787,6 +787,8 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg c1, int32_t c2, int c2const, bool neg)
{
+ int rcond;
+
if (use_vis3_instructions && !neg) {
switch (cond) {
case TCG_COND_NE:
@@ -806,9 +808,10 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
/* For 64-bit signed comparisons vs zero, we can avoid the compare
if the input does not overlap the output. */
- if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) {
+ rcond = tcg_cond_to_rcond[cond];
+ if (c2 == 0 && rcond && c1 != ret) {
tcg_out_movi_s13(s, ret, 0);
- tcg_out_movr(s, cond, ret, c1, neg ? -1 : 1, 1);
+ tcg_out_movr(s, rcond, ret, c1, neg ? -1 : 1, 1);
} else {
tcg_out_cmp(s, c1, c2, c2const);
tcg_out_movi_s13(s, ret, 0);
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 19/29] tcg/sparc64: Pass TCGCond to tcg_out_cmp
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (17 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 18/29] tcg/sparc64: Hoist read of tcg_cond_to_rcond Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 20/29] tcg/sparc64: Support TCG_COND_TST{EQ,NE} Richard Henderson
` (9 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/sparc64/tcg-target.c.inc | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index 13ad92b9b6..e958e3c242 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -645,7 +645,8 @@ static void tcg_out_bpcc(TCGContext *s, int scond, int flags, TCGLabel *l)
tcg_out_bpcc0(s, scond, flags, off19);
}
-static void tcg_out_cmp(TCGContext *s, TCGReg c1, int32_t c2, int c2const)
+static void tcg_out_cmp(TCGContext *s, TCGCond cond,
+ TCGReg c1, int32_t c2, int c2const)
{
tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
}
@@ -653,7 +654,7 @@ static void tcg_out_cmp(TCGContext *s, TCGReg c1, int32_t c2, int c2const)
static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGReg arg1,
int32_t arg2, int const_arg2, TCGLabel *l)
{
- tcg_out_cmp(s, arg1, arg2, const_arg2);
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2);
tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, l);
tcg_out_nop(s);
}
@@ -670,7 +671,7 @@ static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg c1, int32_t c2, int c2const,
int32_t v1, int v1const)
{
- tcg_out_cmp(s, c1, c2, c2const);
+ tcg_out_cmp(s, cond, c1, c2, c2const);
tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const);
}
@@ -690,7 +691,7 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
| INSN_COND(rcond) | off16);
} else {
- tcg_out_cmp(s, arg1, arg2, const_arg2);
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2);
tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, l);
}
tcg_out_nop(s);
@@ -714,7 +715,7 @@ static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
if (c2 == 0 && rcond && (!v1const || check_fit_i32(v1, 10))) {
tcg_out_movr(s, rcond, ret, c1, v1, v1const);
} else {
- tcg_out_cmp(s, c1, c2, c2const);
+ tcg_out_cmp(s, cond, c1, c2, c2const);
tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
}
}
@@ -758,13 +759,13 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
/* FALLTHRU */
default:
- tcg_out_cmp(s, c1, c2, c2const);
+ tcg_out_cmp(s, cond, c1, c2, c2const);
tcg_out_movi_s13(s, ret, 0);
tcg_out_movcc(s, cond, MOVCC_ICC, ret, neg ? -1 : 1, 1);
return;
}
- tcg_out_cmp(s, c1, c2, c2const);
+ tcg_out_cmp(s, cond, c1, c2, c2const);
if (cond == TCG_COND_LTU) {
if (neg) {
/* 0 - 0 - C = -C = (C ? -1 : 0) */
@@ -798,7 +799,7 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
c2 = c1, c2const = 0, c1 = TCG_REG_G0;
/* FALLTHRU */
case TCG_COND_LTU:
- tcg_out_cmp(s, c1, c2, c2const);
+ tcg_out_cmp(s, cond, c1, c2, c2const);
tcg_out_arith(s, ret, TCG_REG_G0, TCG_REG_G0, ARITH_ADDXC);
return;
default:
@@ -813,7 +814,7 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
tcg_out_movi_s13(s, ret, 0);
tcg_out_movr(s, rcond, ret, c1, neg ? -1 : 1, 1);
} else {
- tcg_out_cmp(s, c1, c2, c2const);
+ tcg_out_cmp(s, cond, c1, c2, c2const);
tcg_out_movi_s13(s, ret, 0);
tcg_out_movcc(s, cond, MOVCC_XCC, ret, neg ? -1 : 1, 1);
}
@@ -1101,7 +1102,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out_movi_s32(s, TCG_REG_T3, compare_mask);
tcg_out_arith(s, TCG_REG_T3, addr_reg, TCG_REG_T3, ARITH_AND);
}
- tcg_out_cmp(s, TCG_REG_T2, TCG_REG_T3, 0);
+ tcg_out_cmp(s, TCG_COND_NE, TCG_REG_T2, TCG_REG_T3, 0);
ldst = new_ldst_label(s);
ldst->is_ld = is_ld;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 20/29] tcg/sparc64: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (18 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 19/29] tcg/sparc64: Pass TCGCond to tcg_out_cmp Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:26 ` [PATCH 21/29] tcg/ppc: Sink tcg_to_bc usage into tcg_out_bc Richard Henderson
` (8 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/sparc64/tcg-target.c.inc | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index e958e3c242..feeb318c39 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -606,9 +606,11 @@ static void tcg_out_div32(TCGContext *s, TCGReg rd, TCGReg rs1,
uns ? ARITH_UDIV : ARITH_SDIV);
}
-static const uint8_t tcg_cond_to_bcond[] = {
+static const uint8_t tcg_cond_to_bcond[16] = {
[TCG_COND_EQ] = COND_E,
[TCG_COND_NE] = COND_NE,
+ [TCG_COND_TSTEQ] = COND_E,
+ [TCG_COND_TSTNE] = COND_NE,
[TCG_COND_LT] = COND_L,
[TCG_COND_GE] = COND_GE,
[TCG_COND_LE] = COND_LE,
@@ -648,7 +650,8 @@ static void tcg_out_bpcc(TCGContext *s, int scond, int flags, TCGLabel *l)
static void tcg_out_cmp(TCGContext *s, TCGCond cond,
TCGReg c1, int32_t c2, int c2const)
{
- tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
+ tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const,
+ is_tst_cond(cond) ? ARITH_ANDCC : ARITH_SUBCC);
}
static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGReg arg1,
@@ -743,6 +746,15 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU);
break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ /* Transform to inequality vs zero. */
+ tcg_out_arithc(s, TCG_REG_T1, c1, c2, c2const, ARITH_AND);
+ c1 = TCG_REG_G0;
+ c2 = TCG_REG_T1, c2const = 0;
+ cond = (cond == TCG_COND_TSTEQ ? TCG_COND_GEU : TCG_COND_LTU);
+ break;
+
case TCG_COND_GTU:
case TCG_COND_LEU:
/* If we don't need to load a constant into a register, we can
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 21/29] tcg/ppc: Sink tcg_to_bc usage into tcg_out_bc
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (19 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 20/29] tcg/sparc64: Support TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:26 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 22/29] tcg/ppc: Use cr0 in tcg_to_bc and tcg_to_isel Richard Henderson
` (7 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:26 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Rename the current tcg_out_bc function to tcg_out_bc_lab, and
create a new function that takes an integer displacement + link.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/ppc/tcg-target.c.inc | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 856c3b18f5..666d480e86 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -1945,14 +1945,20 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
}
}
-static void tcg_out_bc(TCGContext *s, int bc, TCGLabel *l)
+static void tcg_out_bc(TCGContext *s, TCGCond cond, int bd)
{
+ tcg_out32(s, tcg_to_bc[cond] | bd);
+}
+
+static void tcg_out_bc_lab(TCGContext *s, TCGCond cond, TCGLabel *l)
+{
+ int bd = 0;
if (l->has_value) {
- bc |= reloc_pc14_val(tcg_splitwx_to_rx(s->code_ptr), l->u.value_ptr);
+ bd = reloc_pc14_val(tcg_splitwx_to_rx(s->code_ptr), l->u.value_ptr);
} else {
tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, l, 0);
}
- tcg_out32(s, bc);
+ tcg_out_bc(s, cond, bd);
}
static void tcg_out_brcond(TCGContext *s, TCGCond cond,
@@ -1960,7 +1966,7 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond,
TCGLabel *l, TCGType type)
{
tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
- tcg_out_bc(s, tcg_to_bc[cond], l);
+ tcg_out_bc_lab(s, cond, l);
}
static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
@@ -2002,7 +2008,7 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
}
}
/* Branch forward over one insn */
- tcg_out32(s, tcg_to_bc[cond] | 8);
+ tcg_out_bc(s, cond, 8);
if (v2 == 0) {
tcg_out_movi(s, type, dest, 0);
} else {
@@ -2023,11 +2029,11 @@ static void tcg_out_cntxz(TCGContext *s, TCGType type, uint32_t opc,
tcg_out32(s, opc | RA(TCG_REG_R0) | RS(a1));
tcg_out32(s, tcg_to_isel[TCG_COND_EQ] | TAB(a0, a2, TCG_REG_R0));
} else if (!const_a2 && a0 == a2) {
- tcg_out32(s, tcg_to_bc[TCG_COND_EQ] | 8);
+ tcg_out_bc(s, TCG_COND_EQ, 8);
tcg_out32(s, opc | RA(a0) | RS(a1));
} else {
tcg_out32(s, opc | RA(a0) | RS(a1));
- tcg_out32(s, tcg_to_bc[TCG_COND_NE] | 8);
+ tcg_out_bc(s, TCG_COND_NE, 8);
if (const_a2) {
tcg_out_movi(s, type, a0, 0);
} else {
@@ -2107,11 +2113,11 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, 31, 31, 31);
}
-static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
- const int *const_args)
+static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
+ const int *const_args)
{
tcg_out_cmp2(s, args, const_args);
- tcg_out_bc(s, BC | BI(7, CR_EQ) | BO_COND_TRUE, arg_label(args[5]));
+ tcg_out_bc_lab(s, TCG_COND_EQ, arg_label(args[5]));
}
static void tcg_out_mb(TCGContext *s, TCGArg a0)
@@ -2445,7 +2451,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
/* Load a pointer into the current opcode w/conditional branch-link. */
ldst->label_ptr[0] = s->code_ptr;
- tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
+ tcg_out_bc(s, TCG_COND_NE, LK);
h->base = TCG_REG_TMP1;
} else {
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 22/29] tcg/ppc: Use cr0 in tcg_to_bc and tcg_to_isel
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (20 preceding siblings ...)
2023-10-25 7:26 ` [PATCH 21/29] tcg/ppc: Sink tcg_to_bc usage into tcg_out_bc Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 23/29] tcg/ppc: Create tcg_out_and_rc Richard Henderson
` (6 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Using cr0 means we could choose to use rc=1 to compute the condition.
Adjust the tables and tcg_out_cmp that feeds them.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/ppc/tcg-target.c.inc | 68 ++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 666d480e86..3c2ec4db4b 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -670,30 +670,30 @@ enum {
};
static const uint32_t tcg_to_bc[] = {
- [TCG_COND_EQ] = BC | BI(7, CR_EQ) | BO_COND_TRUE,
- [TCG_COND_NE] = BC | BI(7, CR_EQ) | BO_COND_FALSE,
- [TCG_COND_LT] = BC | BI(7, CR_LT) | BO_COND_TRUE,
- [TCG_COND_GE] = BC | BI(7, CR_LT) | BO_COND_FALSE,
- [TCG_COND_LE] = BC | BI(7, CR_GT) | BO_COND_FALSE,
- [TCG_COND_GT] = BC | BI(7, CR_GT) | BO_COND_TRUE,
- [TCG_COND_LTU] = BC | BI(7, CR_LT) | BO_COND_TRUE,
- [TCG_COND_GEU] = BC | BI(7, CR_LT) | BO_COND_FALSE,
- [TCG_COND_LEU] = BC | BI(7, CR_GT) | BO_COND_FALSE,
- [TCG_COND_GTU] = BC | BI(7, CR_GT) | BO_COND_TRUE,
+ [TCG_COND_EQ] = BC | BI(0, CR_EQ) | BO_COND_TRUE,
+ [TCG_COND_NE] = BC | BI(0, CR_EQ) | BO_COND_FALSE,
+ [TCG_COND_LT] = BC | BI(0, CR_LT) | BO_COND_TRUE,
+ [TCG_COND_GE] = BC | BI(0, CR_LT) | BO_COND_FALSE,
+ [TCG_COND_LE] = BC | BI(0, CR_GT) | BO_COND_FALSE,
+ [TCG_COND_GT] = BC | BI(0, CR_GT) | BO_COND_TRUE,
+ [TCG_COND_LTU] = BC | BI(0, CR_LT) | BO_COND_TRUE,
+ [TCG_COND_GEU] = BC | BI(0, CR_LT) | BO_COND_FALSE,
+ [TCG_COND_LEU] = BC | BI(0, CR_GT) | BO_COND_FALSE,
+ [TCG_COND_GTU] = BC | BI(0, CR_GT) | BO_COND_TRUE,
};
/* The low bit here is set if the RA and RB fields must be inverted. */
static const uint32_t tcg_to_isel[] = {
- [TCG_COND_EQ] = ISEL | BC_(7, CR_EQ),
- [TCG_COND_NE] = ISEL | BC_(7, CR_EQ) | 1,
- [TCG_COND_LT] = ISEL | BC_(7, CR_LT),
- [TCG_COND_GE] = ISEL | BC_(7, CR_LT) | 1,
- [TCG_COND_LE] = ISEL | BC_(7, CR_GT) | 1,
- [TCG_COND_GT] = ISEL | BC_(7, CR_GT),
- [TCG_COND_LTU] = ISEL | BC_(7, CR_LT),
- [TCG_COND_GEU] = ISEL | BC_(7, CR_LT) | 1,
- [TCG_COND_LEU] = ISEL | BC_(7, CR_GT) | 1,
- [TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
+ [TCG_COND_EQ] = ISEL | BC_(0, CR_EQ),
+ [TCG_COND_NE] = ISEL | BC_(0, CR_EQ) | 1,
+ [TCG_COND_LT] = ISEL | BC_(0, CR_LT),
+ [TCG_COND_GE] = ISEL | BC_(0, CR_LT) | 1,
+ [TCG_COND_LE] = ISEL | BC_(0, CR_GT) | 1,
+ [TCG_COND_GT] = ISEL | BC_(0, CR_GT),
+ [TCG_COND_LTU] = ISEL | BC_(0, CR_LT),
+ [TCG_COND_GEU] = ISEL | BC_(0, CR_LT) | 1,
+ [TCG_COND_LEU] = ISEL | BC_(0, CR_GT) | 1,
+ [TCG_COND_GTU] = ISEL | BC_(0, CR_GT),
};
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
@@ -1826,7 +1826,7 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
if (have_isa_3_10) {
tcg_insn_unit bi, opc;
- tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 0, type);
/* Re-use tcg_to_bc for BI and BO_COND_{TRUE,FALSE}. */
bi = tcg_to_bc[cond] & (0x1f << 16);
@@ -1879,7 +1879,7 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
if (have_isel) {
int isel, tab;
- tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 0, type);
isel = tcg_to_isel[cond];
@@ -1965,7 +1965,7 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond,
TCGArg arg1, TCGArg arg2, int const_arg2,
TCGLabel *l, TCGType type)
{
- tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
+ tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 0, type);
tcg_out_bc_lab(s, cond, l);
}
@@ -1979,7 +1979,7 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
return;
}
- tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
+ tcg_out_cmp(s, cond, c1, c2, const_c2, 0, type);
if (have_isel) {
int isel = tcg_to_isel[cond];
@@ -2023,7 +2023,7 @@ static void tcg_out_cntxz(TCGContext *s, TCGType type, uint32_t opc,
if (const_a2 && a2 == (type == TCG_TYPE_I32 ? 32 : 64)) {
tcg_out32(s, opc | RA(a0) | RS(a1));
} else {
- tcg_out_cmp(s, TCG_COND_EQ, a1, 0, 1, 7, type);
+ tcg_out_cmp(s, TCG_COND_EQ, a1, 0, 1, 0, type);
/* Note that the only other valid constant for a2 is 0. */
if (have_isel) {
tcg_out32(s, opc | RA(TCG_REG_R0) | RS(a1));
@@ -2078,7 +2078,7 @@ static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
do_equality:
tcg_out_cmp(s, cond, al, bl, blconst, 6, TCG_TYPE_I32);
tcg_out_cmp(s, cond, ah, bh, bhconst, 7, TCG_TYPE_I32);
- tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+ tcg_out32(s, op | BT(0, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
break;
case TCG_COND_LT:
@@ -2096,8 +2096,8 @@ static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
tcg_out_cmp(s, cond, ah, bh, bhconst, 6, TCG_TYPE_I32);
tcg_out_cmp(s, cond2, al, bl, blconst, 7, TCG_TYPE_I32);
- tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, bit2));
- tcg_out32(s, CROR | BT(7, CR_EQ) | BA(6, bit1) | BB(7, CR_EQ));
+ tcg_out32(s, op | BT(0, CR_EQ) | BA(6, CR_EQ) | BB(7, bit2));
+ tcg_out32(s, CROR | BT(0, CR_EQ) | BA(6, bit1) | BB(0, CR_EQ));
break;
default:
@@ -2109,8 +2109,8 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
const int *const_args)
{
tcg_out_cmp2(s, args + 1, const_args + 1);
- tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
- tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, 31, 31, 31);
+ tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(0));
+ tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, CR_EQ + 0*4 + 1, 31, 31);
}
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
@@ -2441,12 +2441,12 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_TMP2,
0, 6, TCG_TYPE_I32);
- /* Combine comparisons into cr7. */
- tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
+ /* Combine comparisons into cr0. */
+ tcg_out32(s, CRAND | BT(0, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
} else {
- /* Full comparison into cr7. */
+ /* Full comparison into cr0. */
tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP2,
- 0, 7, addr_type);
+ 0, 0, addr_type);
}
/* Load a pointer into the current opcode w/conditional branch-link. */
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 23/29] tcg/ppc: Create tcg_out_and_rc
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (21 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 22/29] tcg/ppc: Use cr0 in tcg_to_bc and tcg_to_isel Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 24/29] tcg/ppc: Support TCG_COND_TST{EQ,NE} Richard Henderson
` (5 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Merge tcg_out_andi32, tcg_out_andi64, and code to handle
two register inputs.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/ppc/tcg-target.c.inc | 86 +++++++++++++++++++---------------------
1 file changed, 40 insertions(+), 46 deletions(-)
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 3c2ec4db4b..fe141a26f9 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -1363,44 +1363,44 @@ static bool mask64_operand(uint64_t c, int *mb, int *me)
return false;
}
-static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
+static void tcg_out_and_rc(TCGContext *s, TCGType type, TCGReg dst,
+ TCGReg arg1, TCGArg arg2, bool const_arg2, bool rc)
{
- int mb, me;
-
- if (mask_operand(c, &mb, &me)) {
- tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
- } else if ((c & 0xffff) == c) {
- tcg_out32(s, ANDI | SAI(src, dst, c));
+ if (!const_arg2) {
+ tcg_out32(s, AND | SAB(arg1, dst, arg2) | rc);
return;
- } else if ((c & 0xffff0000) == c) {
- tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
- return;
- } else {
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R0, c);
- tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
}
-}
-static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
-{
- int mb, me;
+ if (!rc) {
+ int mb, me;
- tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
- if (mask64_operand(c, &mb, &me)) {
- if (mb == 0) {
- tcg_out_rld(s, RLDICR, dst, src, 0, me);
+ if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
+ if (mask_operand(arg2, &mb, &me)) {
+ tcg_out_rlw(s, RLWINM, dst, arg1, 0, mb, me);
+ return;
+ }
} else {
- tcg_out_rld(s, RLDICL, dst, src, 0, mb);
+ if (mask64_operand(arg2, &mb, &me)) {
+ if (mb == 0) {
+ tcg_out_rld(s, RLDICR, dst, arg1, 0, me);
+ } else {
+ tcg_out_rld(s, RLDICL, dst, arg1, 0, mb);
+ }
+ return;
+ }
}
- } else 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;
+ }
+
+ if (type == TCG_TYPE_I32) {
+ arg2 = (uint32_t)arg2;
+ }
+ if ((arg2 & 0xffff) == arg2) {
+ tcg_out32(s, ANDI | SAI(arg1, dst, arg2));
+ } else if ((arg2 & 0xffff0000u) == arg2) {
+ tcg_out32(s, ANDIS | SAI(arg1, dst, arg2 >> 16));
} else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, c);
- tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
+ tcg_out_movi(s, type, TCG_REG_R0, arg2);
+ tcg_out32(s, AND | SAB(arg1, dst, TCG_REG_R0) | rc);
}
}
@@ -2892,20 +2892,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_and_i32:
- a0 = args[0], a1 = args[1], a2 = args[2];
- if (const_args[2]) {
- tcg_out_andi32(s, a0, a1, a2);
- } else {
- tcg_out32(s, AND | SAB(a1, a0, a2));
- }
+ tcg_out_and_rc(s, TCG_TYPE_I32, args[0], args[1],
+ args[2], const_args[2], false);
break;
case INDEX_op_and_i64:
- a0 = args[0], a1 = args[1], a2 = args[2];
- if (const_args[2]) {
- tcg_out_andi64(s, a0, a1, a2);
- } else {
- tcg_out32(s, AND | SAB(a1, a0, a2));
- }
+ tcg_out_and_rc(s, TCG_TYPE_I64, args[0], args[1],
+ args[2], const_args[2], false);
break;
case INDEX_op_or_i64:
case INDEX_op_or_i32:
@@ -2928,7 +2920,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_andc_i32:
a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[2]) {
- tcg_out_andi32(s, a0, a1, ~a2);
+ tcg_out_and_rc(s, TCG_TYPE_I32, a0, a1, ~a2, true, false);
} else {
tcg_out32(s, ANDC | SAB(a1, a0, a2));
}
@@ -2936,7 +2928,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_andc_i64:
a0 = args[0], a1 = args[1], a2 = args[2];
if (const_args[2]) {
- tcg_out_andi64(s, a0, a1, ~a2);
+ tcg_out_and_rc(s, TCG_TYPE_I64, a0, a1, ~a2, true, false);
} else {
tcg_out32(s, ANDC | SAB(a1, a0, a2));
}
@@ -3270,7 +3262,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_deposit_i32:
if (const_args[2]) {
uint32_t mask = ((2u << (args[4] - 1)) - 1) << args[3];
- tcg_out_andi32(s, args[0], args[0], ~mask);
+ tcg_out_and_rc(s, TCG_TYPE_I32, args[0], args[0],
+ ~mask, true, false);
} else {
tcg_out_rlw(s, RLWIMI, args[0], args[2], args[3],
32 - args[3] - args[4], 31 - args[3]);
@@ -3279,7 +3272,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_deposit_i64:
if (const_args[2]) {
uint64_t mask = ((2ull << (args[4] - 1)) - 1) << args[3];
- tcg_out_andi64(s, args[0], args[0], ~mask);
+ tcg_out_and_rc(s, TCG_TYPE_I64, args[0], args[0],
+ ~mask, true, false);
} else {
tcg_out_rld(s, RLDIMI, args[0], args[2], args[3],
64 - args[3] - args[4]);
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 24/29] tcg/ppc: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (22 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 23/29] tcg/ppc: Create tcg_out_and_rc Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 25/29] tcg/s390x: " Richard Henderson
` (4 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/ppc/tcg-target.c.inc | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index fe141a26f9..5a316f364d 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -669,9 +669,11 @@ enum {
CR_SO
};
-static const uint32_t tcg_to_bc[] = {
+static const uint32_t tcg_to_bc[16] = {
[TCG_COND_EQ] = BC | BI(0, CR_EQ) | BO_COND_TRUE,
[TCG_COND_NE] = BC | BI(0, CR_EQ) | BO_COND_FALSE,
+ [TCG_COND_TSTEQ] = BC | BI(0, CR_EQ) | BO_COND_TRUE,
+ [TCG_COND_TSTNE] = BC | BI(0, CR_EQ) | BO_COND_FALSE,
[TCG_COND_LT] = BC | BI(0, CR_LT) | BO_COND_TRUE,
[TCG_COND_GE] = BC | BI(0, CR_LT) | BO_COND_FALSE,
[TCG_COND_LE] = BC | BI(0, CR_GT) | BO_COND_FALSE,
@@ -683,9 +685,11 @@ static const uint32_t tcg_to_bc[] = {
};
/* The low bit here is set if the RA and RB fields must be inverted. */
-static const uint32_t tcg_to_isel[] = {
+static const uint32_t tcg_to_isel[16] = {
[TCG_COND_EQ] = ISEL | BC_(0, CR_EQ),
[TCG_COND_NE] = ISEL | BC_(0, CR_EQ) | 1,
+ [TCG_COND_TSTEQ] = ISEL | BC_(0, CR_EQ),
+ [TCG_COND_TSTNE] = ISEL | BC_(0, CR_EQ) | 1,
[TCG_COND_LT] = ISEL | BC_(0, CR_LT),
[TCG_COND_GE] = ISEL | BC_(0, CR_LT) | 1,
[TCG_COND_LE] = ISEL | BC_(0, CR_GT) | 1,
@@ -1699,6 +1703,12 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
imm = 0;
break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ tcg_debug_assert(cr == 0);
+ tcg_out_and_rc(s, type, TCG_REG_R0, arg1, arg2, const_arg2, true);
+ return;
+
case TCG_COND_LT:
case TCG_COND_GE:
case TCG_COND_LE:
@@ -1909,6 +1919,16 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
tcg_out_setcond_ne0(s, type, arg0, arg1, neg);
break;
+ case TCG_COND_TSTEQ:
+ tcg_out_and_rc(s, type, TCG_REG_R0, arg1, arg2, const_arg2, false);
+ tcg_out_setcond_eq0(s, type, arg0, TCG_REG_R0, neg);
+ break;
+
+ case TCG_COND_TSTNE:
+ tcg_out_and_rc(s, type, TCG_REG_R0, arg1, arg2, const_arg2, false);
+ tcg_out_setcond_ne0(s, type, arg0, TCG_REG_R0, neg);
+ break;
+
case TCG_COND_LE:
case TCG_COND_LEU:
inv = true;
@@ -2081,6 +2101,13 @@ static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
tcg_out32(s, op | BT(0, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
break;
+ case TCG_COND_TSTEQ:
+ case TCG_COND_TSTNE:
+ tcg_out_and_rc(s, TCG_TYPE_I32, TCG_REG_R0, al, bl, blconst, false);
+ tcg_out_and_rc(s, TCG_TYPE_I32, TCG_REG_TMP1, ah, bh, bhconst, false);
+ tcg_out32(s, OR | SAB(TCG_REG_R0, TCG_REG_R0, TCG_REG_TMP1) | 1);
+ break;
+
case TCG_COND_LT:
case TCG_COND_LE:
case TCG_COND_GT:
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 25/29] tcg/s390x: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (23 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 24/29] tcg/ppc: Support TCG_COND_TST{EQ,NE} Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 26/29] tcg/tci: " Richard Henderson
` (3 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/s390x/tcg-target.c.inc | 127 +++++++++++++++++++++++++------------
1 file changed, 88 insertions(+), 39 deletions(-)
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index fbee43d3b0..ef3cb87e9f 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -111,6 +111,9 @@ typedef enum S390Opcode {
RI_OILH = 0xa50a,
RI_OILL = 0xa50b,
RI_TMLL = 0xa701,
+ RI_TMLH = 0xa700,
+ RI_TMHL = 0xa703,
+ RI_TMHH = 0xa702,
RIEb_CGRJ = 0xec64,
RIEb_CLGRJ = 0xec65,
@@ -403,10 +406,15 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
#define S390_CC_NEVER 0
#define S390_CC_ALWAYS 15
+#define S390_TM_EQ 8 /* CC == 0 */
+#define S390_TM_NE 7 /* CC in {1,2,3} */
+
/* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
-static const uint8_t tcg_cond_to_s390_cond[] = {
+static const uint8_t tcg_cond_to_s390_cond[16] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
+ [TCG_COND_TSTEQ] = S390_CC_EQ,
+ [TCG_COND_TSTNE] = S390_CC_NE,
[TCG_COND_LT] = S390_CC_LT,
[TCG_COND_LE] = S390_CC_LE,
[TCG_COND_GT] = S390_CC_GT,
@@ -420,9 +428,11 @@ static const uint8_t tcg_cond_to_s390_cond[] = {
/* Condition codes that result from a LOAD AND TEST. Here, we have no
unsigned instruction variation, however since the test is vs zero we
can re-map the outcomes appropriately. */
-static const uint8_t tcg_cond_to_ltr_cond[] = {
+static const uint8_t tcg_cond_to_ltr_cond[16] = {
[TCG_COND_EQ] = S390_CC_EQ,
[TCG_COND_NE] = S390_CC_NE,
+ [TCG_COND_TSTEQ] = S390_CC_ALWAYS,
+ [TCG_COND_TSTNE] = S390_CC_NEVER,
[TCG_COND_LT] = S390_CC_LT,
[TCG_COND_LE] = S390_CC_LE,
[TCG_COND_GT] = S390_CC_GT,
@@ -843,6 +853,9 @@ static const S390Opcode oi_insns[4] = {
static const S390Opcode lif_insns[2] = {
RIL_LLILF, RIL_LLIHF,
};
+static const S390Opcode tm_insns[4] = {
+ RI_TMLL, RI_TMLH, RI_TMHL, RI_TMHH
+};
/* load a register with an immediate value */
static void tcg_out_movi(TCGContext *s, TCGType type,
@@ -1203,6 +1216,40 @@ static int tgen_cmp2(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
TCGCond inv_c = tcg_invert_cond(c);
S390Opcode op;
+ if (is_tst_cond(c)) {
+ tcg_debug_assert(!need_carry);
+
+ if (c2const) {
+ int i;
+
+ if (type == TCG_TYPE_I32) {
+ c2 = (uint32_t)c2;
+ }
+
+ i = is_const_p16(c2);
+ if (i >= 0) {
+ tcg_out_insn_RI(s, tm_insns[i], r1, c2 >> (i * 16));
+ *inv_cc = TCG_COND_TSTEQ ? S390_TM_NE : S390_TM_EQ;
+ return *inv_cc ^ 15;
+ }
+
+ if (risbg_mask(c2)) {
+ tgen_andi_risbg(s, TCG_REG_R0, r1, c2);
+ goto exit;
+ }
+
+ tcg_out_movi(s, type, TCG_REG_R0, c2);
+ c2 = TCG_REG_R0;
+ }
+
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn(s, RRFa, NRK, TCG_REG_R0, r1, c2);
+ } else {
+ tcg_out_insn(s, RRFa, NGRK, TCG_REG_R0, r1, c2);
+ }
+ goto exit;
+ }
+
if (c2const) {
if (c2 == 0) {
if (!(is_unsigned && need_carry)) {
@@ -1516,46 +1563,49 @@ static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
TCGReg r1, TCGArg c2, int c2const, TCGLabel *l)
{
int cc;
- bool is_unsigned = is_unsigned_cond(c);
- bool in_range;
- S390Opcode opc;
- cc = tcg_cond_to_s390_cond[c];
+ if (!is_tst_cond(c)) {
+ bool is_unsigned = is_unsigned_cond(c);
+ bool in_range;
+ S390Opcode opc;
- if (!c2const) {
- opc = (type == TCG_TYPE_I32
- ? (is_unsigned ? RIEb_CLRJ : RIEb_CRJ)
- : (is_unsigned ? RIEb_CLGRJ : RIEb_CGRJ));
- tgen_compare_branch(s, opc, cc, r1, c2, l);
- return;
- }
+ cc = tcg_cond_to_s390_cond[c];
- /*
- * COMPARE IMMEDIATE AND BRANCH RELATIVE has an 8-bit immediate field.
- * If the immediate we've been given does not fit that range, we'll
- * fall back to separate compare and branch instructions using the
- * larger comparison range afforded by COMPARE IMMEDIATE.
- */
- if (type == TCG_TYPE_I32) {
- if (is_unsigned) {
- opc = RIEc_CLIJ;
- in_range = (uint32_t)c2 == (uint8_t)c2;
- } else {
- opc = RIEc_CIJ;
- in_range = (int32_t)c2 == (int8_t)c2;
+ if (!c2const) {
+ opc = (type == TCG_TYPE_I32
+ ? (is_unsigned ? RIEb_CLRJ : RIEb_CRJ)
+ : (is_unsigned ? RIEb_CLGRJ : RIEb_CGRJ));
+ tgen_compare_branch(s, opc, cc, r1, c2, l);
+ return;
}
- } else {
- if (is_unsigned) {
- opc = RIEc_CLGIJ;
- in_range = (uint64_t)c2 == (uint8_t)c2;
+
+ /*
+ * COMPARE IMMEDIATE AND BRANCH RELATIVE has an 8-bit immediate field.
+ * If the immediate we've been given does not fit that range, we'll
+ * fall back to separate compare and branch instructions using the
+ * larger comparison range afforded by COMPARE IMMEDIATE.
+ */
+ if (type == TCG_TYPE_I32) {
+ if (is_unsigned) {
+ opc = RIEc_CLIJ;
+ in_range = (uint32_t)c2 == (uint8_t)c2;
+ } else {
+ opc = RIEc_CIJ;
+ in_range = (int32_t)c2 == (int8_t)c2;
+ }
} else {
- opc = RIEc_CGIJ;
- in_range = (int64_t)c2 == (int8_t)c2;
+ if (is_unsigned) {
+ opc = RIEc_CLGIJ;
+ in_range = (uint64_t)c2 == (uint8_t)c2;
+ } else {
+ opc = RIEc_CGIJ;
+ in_range = (int64_t)c2 == (int8_t)c2;
+ }
+ }
+ if (in_range) {
+ tgen_compare_imm_branch(s, opc, cc, r1, c2, l);
+ return;
}
- }
- if (in_range) {
- tgen_compare_imm_branch(s, opc, cc, r1, c2, l);
- return;
}
cc = tgen_cmp(s, type, c, r1, c2, c2const, false);
@@ -1834,11 +1884,10 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
ldst->oi = oi;
ldst->addrlo_reg = addr_reg;
- /* We are expecting a_bits to max out at 7, much lower than TMLL. */
tcg_debug_assert(a_mask <= 0xffff);
tcg_out_insn(s, RI, TMLL, addr_reg, a_mask);
- tcg_out16(s, RI_BRC | (7 << 4)); /* CC in {1,2,3} */
+ tcg_out16(s, RI_BRC | (S390_TM_NE << 4));
ldst->label_ptr[0] = s->code_ptr++;
}
@@ -1919,7 +1968,7 @@ static void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg datalo, TCGReg datahi,
l2 = gen_new_label();
tcg_out_insn(s, RI, TMLL, addr_reg, 15);
- tgen_branch(s, 7, l1); /* CC in {1,2,3} */
+ tgen_branch(s, S390_TM_NE, l1);
}
tcg_debug_assert(!need_bswap);
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 26/29] tcg/tci: Support TCG_COND_TST{EQ,NE}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (24 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 25/29] tcg/s390x: " Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 27/29] target/alpha: Use TCG_COND_TST{EQ,NE} for BLB{C,S} Richard Henderson
` (2 subsequent siblings)
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/tci.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tcg/tci.c b/tcg/tci.c
index 4640902c88..5e1c4a491d 100644
--- a/tcg/tci.c
+++ b/tcg/tci.c
@@ -228,6 +228,12 @@ static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
case TCG_COND_GTU:
result = (u0 > u1);
break;
+ case TCG_COND_TSTEQ:
+ result = (u0 & u1) == 0;
+ break;
+ case TCG_COND_TSTNE:
+ result = (u0 & u1) != 0;
+ break;
default:
g_assert_not_reached();
}
@@ -270,6 +276,12 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
case TCG_COND_GTU:
result = (u0 > u1);
break;
+ case TCG_COND_TSTEQ:
+ result = (u0 & u1) == 0;
+ break;
+ case TCG_COND_TSTNE:
+ result = (u0 & u1) != 0;
+ break;
default:
g_assert_not_reached();
}
@@ -1043,6 +1055,8 @@ static const char *str_c(TCGCond c)
[TCG_COND_GEU] = "geu",
[TCG_COND_LEU] = "leu",
[TCG_COND_GTU] = "gtu",
+ [TCG_COND_TSTEQ] = "tsteq",
+ [TCG_COND_TSTNE] = "tstne",
};
assert((unsigned)c < ARRAY_SIZE(cond));
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 27/29] target/alpha: Use TCG_COND_TST{EQ,NE} for BLB{C,S}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (25 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 26/29] tcg/tci: " Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 28/29] target/alpha: Use TCG_COND_TST{EQ,NE} for CMOVLB{C,S} Richard Henderson
2023-10-25 7:27 ` [PATCH 29/29] target/alpha: Use TCG_COND_TSTNE for gen_fold_mzero Richard Henderson
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/alpha/translate.c | 39 ++++++++++++++++-----------------------
1 file changed, 16 insertions(+), 23 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 32333081d8..49e6a7b62d 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -453,13 +453,13 @@ static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
}
static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
- TCGv cmp, int32_t disp)
+ TCGv cmp, uint64_t imm, int32_t disp)
{
uint64_t dest = ctx->base.pc_next + (disp << 2);
TCGLabel *lab_true = gen_new_label();
if (use_goto_tb(ctx, dest)) {
- tcg_gen_brcondi_i64(cond, cmp, 0, lab_true);
+ tcg_gen_brcondi_i64(cond, cmp, imm, lab_true);
tcg_gen_goto_tb(0);
tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
@@ -472,27 +472,20 @@ static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
return DISAS_NORETURN;
} else {
- TCGv_i64 z = load_zero(ctx);
+ TCGv_i64 i = tcg_constant_i64(imm);
TCGv_i64 d = tcg_constant_i64(dest);
TCGv_i64 p = tcg_constant_i64(ctx->base.pc_next);
- tcg_gen_movcond_i64(cond, cpu_pc, cmp, z, d, p);
+ tcg_gen_movcond_i64(cond, cpu_pc, cmp, i, d, p);
return DISAS_PC_UPDATED;
}
}
static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
- int32_t disp, int mask)
+ int32_t disp)
{
- if (mask) {
- TCGv tmp = tcg_temp_new();
- DisasJumpType ret;
-
- tcg_gen_andi_i64(tmp, load_gpr(ctx, ra), 1);
- ret = gen_bcond_internal(ctx, cond, tmp, disp);
- return ret;
- }
- return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra), disp);
+ return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra),
+ is_tst_cond(cond), disp);
}
/* Fold -0.0 for comparison with COND. */
@@ -533,7 +526,7 @@ static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
DisasJumpType ret;
gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
- ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp);
+ ret = gen_bcond_internal(ctx, cond, cmp_tmp, 0, disp);
return ret;
}
@@ -2827,35 +2820,35 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x38:
/* BLBC */
- ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1);
+ ret = gen_bcond(ctx, TCG_COND_TSTEQ, ra, disp21);
break;
case 0x39:
/* BEQ */
- ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 0);
+ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21);
break;
case 0x3A:
/* BLT */
- ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, 0);
+ ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21);
break;
case 0x3B:
/* BLE */
- ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, 0);
+ ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21);
break;
case 0x3C:
/* BLBS */
- ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1);
+ ret = gen_bcond(ctx, TCG_COND_TSTNE, ra, disp21);
break;
case 0x3D:
/* BNE */
- ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 0);
+ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21);
break;
case 0x3E:
/* BGE */
- ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, 0);
+ ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21);
break;
case 0x3F:
/* BGT */
- ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, 0);
+ ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21);
break;
invalid_opc:
ret = gen_invalid(ctx);
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 28/29] target/alpha: Use TCG_COND_TST{EQ,NE} for CMOVLB{C,S}
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (26 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 27/29] target/alpha: Use TCG_COND_TST{EQ,NE} for BLB{C,S} Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
2023-10-25 7:27 ` [PATCH 29/29] target/alpha: Use TCG_COND_TSTNE for gen_fold_mzero Richard Henderson
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/alpha/translate.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 49e6a7b62d..c7daf46de7 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -1676,16 +1676,12 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x14:
/* CMOVLBS */
- tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, va, 1);
- tcg_gen_movcond_i64(TCG_COND_NE, vc, tmp, load_zero(ctx),
+ tcg_gen_movcond_i64(TCG_COND_TSTNE, vc, va, tcg_constant_i64(1),
vb, load_gpr(ctx, rc));
break;
case 0x16:
/* CMOVLBC */
- tmp = tcg_temp_new();
- tcg_gen_andi_i64(tmp, va, 1);
- tcg_gen_movcond_i64(TCG_COND_EQ, vc, tmp, load_zero(ctx),
+ tcg_gen_movcond_i64(TCG_COND_TSTEQ, vc, va, tcg_constant_i64(1),
vb, load_gpr(ctx, rc));
break;
case 0x20:
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH 29/29] target/alpha: Use TCG_COND_TSTNE for gen_fold_mzero
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
` (27 preceding siblings ...)
2023-10-25 7:27 ` [PATCH 28/29] target/alpha: Use TCG_COND_TST{EQ,NE} for CMOVLB{C,S} Richard Henderson
@ 2023-10-25 7:27 ` Richard Henderson
28 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-25 7:27 UTC (permalink / raw)
To: qemu-devel; +Cc: philmd
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/alpha/translate.c | 49 +++++++++++++++++++---------------------
1 file changed, 23 insertions(+), 26 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index c7daf46de7..c68c2bcd21 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -490,56 +490,53 @@ static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
/* Fold -0.0 for comparison with COND. */
-static void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src)
+static TCGv_i64 gen_fold_mzero(TCGCond *pcond, uint64_t *pimm, TCGv_i64 src)
{
- uint64_t mzero = 1ull << 63;
+ TCGv_i64 tmp;
- switch (cond) {
+ *pimm = 0;
+ switch (*pcond) {
case TCG_COND_LE:
case TCG_COND_GT:
/* For <= or >, the -0.0 value directly compares the way we want. */
- tcg_gen_mov_i64(dest, src);
- break;
+ return src;
case TCG_COND_EQ:
case TCG_COND_NE:
- /* For == or !=, we can simply mask off the sign bit and compare. */
- tcg_gen_andi_i64(dest, src, mzero - 1);
- break;
+ /* For == or !=, we can compare without the sign bit. */
+ *pcond = *pcond == TCG_COND_EQ ? TCG_COND_TSTEQ : TCG_COND_TSTNE;
+ *pimm = INT64_MAX;
+ return src;
case TCG_COND_GE:
case TCG_COND_LT:
/* For >= or <, map -0.0 to +0.0. */
- tcg_gen_movcond_i64(TCG_COND_NE, dest, src, tcg_constant_i64(mzero),
- src, tcg_constant_i64(0));
- break;
+ tmp = tcg_temp_new_i64();
+ tcg_gen_movcond_i64(TCG_COND_EQ, tmp,
+ src, tcg_constant_i64(INT64_MIN),
+ tcg_constant_i64(0), src);
+ return tmp;
default:
- abort();
+ g_assert_not_reached();
}
}
static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
int32_t disp)
{
- TCGv cmp_tmp = tcg_temp_new();
- DisasJumpType ret;
-
- gen_fold_mzero(cond, cmp_tmp, load_fpr(ctx, ra));
- ret = gen_bcond_internal(ctx, cond, cmp_tmp, 0, disp);
- return ret;
+ uint64_t imm;
+ TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra));
+ return gen_bcond_internal(ctx, cond, tmp, imm, disp);
}
static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
{
- TCGv_i64 va, vb, z;
-
- z = load_zero(ctx);
- vb = load_fpr(ctx, rb);
- va = tcg_temp_new();
- gen_fold_mzero(cond, va, load_fpr(ctx, ra));
-
- tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc), va, z, vb, load_fpr(ctx, rc));
+ uint64_t imm;
+ TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra));
+ tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc),
+ tmp, tcg_constant_i64(imm),
+ load_fpr(ctx, rb), load_fpr(ctx, rc));
}
#define QUAL_RM_N 0x080 /* Round mode nearest even */
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH 02/29] tcg/optimize: Split out arg_is_const_val
2023-10-25 7:26 ` [PATCH 02/29] tcg/optimize: Split out arg_is_const_val Richard Henderson
@ 2023-10-25 16:20 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-25 16:20 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 25/10/23 09:26, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tcg/optimize.c | 38 +++++++++++++++++++++++---------------
> 1 file changed, 23 insertions(+), 15 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 05/29] tcg/optimize: Split out arg_new_constant
2023-10-25 7:26 ` [PATCH 05/29] tcg/optimize: Split out arg_new_constant Richard Henderson
@ 2023-10-25 16:22 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-25 16:22 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 25/10/23 09:26, Richard Henderson wrote:
> Fixes a bug wherein raw uses of tcg_constant_internal
> do not have their TempOptInfo initialized.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tcg/optimize.c | 29 ++++++++++++++++++-----------
> 1 file changed, 18 insertions(+), 11 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 16/29] tcg/riscv: Support TCG_COND_TST{EQ,NE}
2023-10-26 0:13 [PULL 00/94] target/sparc: Convert to decodetree Richard Henderson
@ 2023-10-26 0:14 ` Richard Henderson
0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2023-10-26 0:14 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/riscv/tcg-target.c.inc | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
index 34e10e77d9..3997e2f274 100644
--- a/tcg/riscv/tcg-target.c.inc
+++ b/tcg/riscv/tcg-target.c.inc
@@ -798,8 +798,14 @@ static const struct {
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
TCGReg arg2, TCGLabel *l)
{
- RISCVInsn op = tcg_brcond_to_riscv[cond].op;
+ RISCVInsn op;
+ if (is_tst_cond(cond)) {
+ tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP0, arg1, arg2);
+ cond = tcg_tst_eqne_cond(cond);
+ }
+
+ op = tcg_brcond_to_riscv[cond].op;
tcg_debug_assert(op != 0);
if (tcg_brcond_to_riscv[cond].swap) {
@@ -827,6 +833,7 @@ static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
case TCG_COND_GEU: /* -> LTU */
case TCG_COND_GT: /* -> LE */
case TCG_COND_GTU: /* -> LEU */
+ case TCG_COND_TSTEQ: /* -> TSTNE */
cond = tcg_invert_cond(cond);
flags ^= SETCOND_INV;
break;
@@ -886,6 +893,15 @@ static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
}
break;
+ case TCG_COND_TSTNE:
+ flags |= SETCOND_NEZ;
+ if (c2) {
+ tcg_out_opc_imm(s, OPC_ANDI, ret, arg1, arg2);
+ } else {
+ tcg_out_opc_reg(s, OPC_AND, ret, arg1, arg2);
+ }
+ break;
+
case TCG_COND_LT:
if (c2) {
tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
@@ -1079,7 +1095,7 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
int tmpflags;
TCGReg t;
- if (!have_zicond && (!c_cmp2 || cmp2 == 0)) {
+ if (!have_zicond && (!c_cmp2 || cmp2 == 0) && !is_tst_cond(cond)) {
tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
val1, c_val1, val2, c_val2);
return;
--
2.34.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
end of thread, other threads:[~2023-10-26 0:17 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-25 7:26 [PATCH 00/29] tcg: Introduce TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 01/29] " Richard Henderson
2023-10-25 7:26 ` [PATCH 02/29] tcg/optimize: Split out arg_is_const_val Richard Henderson
2023-10-25 16:20 ` Philippe Mathieu-Daudé
2023-10-25 7:26 ` [PATCH 03/29] tcg/optimize: Split out do_constant_folding_cond1 Richard Henderson
2023-10-25 7:26 ` [PATCH 04/29] tcg/optimize: Do swap_commutative2 in do_constant_folding_cond2 Richard Henderson
2023-10-25 7:26 ` [PATCH 05/29] tcg/optimize: Split out arg_new_constant Richard Henderson
2023-10-25 16:22 ` Philippe Mathieu-Daudé
2023-10-25 7:26 ` [PATCH 06/29] tcg/optimize: Handle TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 07/29] tcg/aarch64: Support TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 08/29] tcg/aarch64: Generate TBZ, TBNZ Richard Henderson
2023-10-25 7:26 ` [PATCH 09/29] tcg/arm: Support TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 10/29] tcg/i386: Pass x86 condition codes to tcg_out_cmov Richard Henderson
2023-10-25 7:26 ` [PATCH 11/29] tcg/i386: Move tcg_cond_to_jcc[] into tcg_out_cmp Richard Henderson
2023-10-25 7:26 ` [PATCH 12/29] tcg/i386: Add rexw argument to tcg_out_testi Richard Henderson
2023-10-25 7:26 ` [PATCH 13/29] tcg/i386: Support TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 14/29] tcg/loongarch64: " Richard Henderson
2023-10-25 7:26 ` [PATCH 15/29] tcg/mips: " Richard Henderson
2023-10-25 7:26 ` [PATCH 16/29] tcg/riscv: " Richard Henderson
2023-10-25 7:26 ` [PATCH 17/29] tcg/sparc64: Implement tcg_out_extrl_i64_i32 Richard Henderson
2023-10-25 7:26 ` [PATCH 18/29] tcg/sparc64: Hoist read of tcg_cond_to_rcond Richard Henderson
2023-10-25 7:26 ` [PATCH 19/29] tcg/sparc64: Pass TCGCond to tcg_out_cmp Richard Henderson
2023-10-25 7:26 ` [PATCH 20/29] tcg/sparc64: Support TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:26 ` [PATCH 21/29] tcg/ppc: Sink tcg_to_bc usage into tcg_out_bc Richard Henderson
2023-10-25 7:27 ` [PATCH 22/29] tcg/ppc: Use cr0 in tcg_to_bc and tcg_to_isel Richard Henderson
2023-10-25 7:27 ` [PATCH 23/29] tcg/ppc: Create tcg_out_and_rc Richard Henderson
2023-10-25 7:27 ` [PATCH 24/29] tcg/ppc: Support TCG_COND_TST{EQ,NE} Richard Henderson
2023-10-25 7:27 ` [PATCH 25/29] tcg/s390x: " Richard Henderson
2023-10-25 7:27 ` [PATCH 26/29] tcg/tci: " Richard Henderson
2023-10-25 7:27 ` [PATCH 27/29] target/alpha: Use TCG_COND_TST{EQ,NE} for BLB{C,S} Richard Henderson
2023-10-25 7:27 ` [PATCH 28/29] target/alpha: Use TCG_COND_TST{EQ,NE} for CMOVLB{C,S} Richard Henderson
2023-10-25 7:27 ` [PATCH 29/29] target/alpha: Use TCG_COND_TSTNE for gen_fold_mzero Richard Henderson
-- strict thread matches above, loose matches on Subject: below --
2023-10-26 0:13 [PULL 00/94] target/sparc: Convert to decodetree Richard Henderson
2023-10-26 0:14 ` [PATCH 16/29] tcg/riscv: Support TCG_COND_TST{EQ,NE} Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).