* [PATCH 1/6] tcg/mips: Split out tcg_out_setcond_int
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
@ 2023-10-26 4:13 ` Richard Henderson
2023-10-26 4:14 ` [PATCH 2/6] tcg/mips: Always implement movcond Richard Henderson
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:13 UTC (permalink / raw)
To: qemu-devel
Return the temp and a set of flags, to be used as a
primitive for setcond, brcond, movcond.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/mips/tcg-target.c.inc | 356 ++++++++++++++------------------------
1 file changed, 132 insertions(+), 224 deletions(-)
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index 739a0f60b7..a5e6fe727b 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -871,81 +871,88 @@ static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
}
}
-/* Bit 0 set if inversion required; bit 1 set if swapping required. */
-#define MIPS_CMP_INV 1
-#define MIPS_CMP_SWAP 2
+#define SETCOND_INV TCG_TARGET_NB_REGS
+#define SETCOND_NEZ (SETCOND_INV << 1)
+#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ)
-static const uint8_t mips_cmp_map[16] = {
- [TCG_COND_LT] = 0,
- [TCG_COND_LTU] = 0,
- [TCG_COND_GE] = MIPS_CMP_INV,
- [TCG_COND_GEU] = MIPS_CMP_INV,
- [TCG_COND_LE] = MIPS_CMP_INV | MIPS_CMP_SWAP,
- [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
- [TCG_COND_GT] = MIPS_CMP_SWAP,
- [TCG_COND_GTU] = MIPS_CMP_SWAP,
-};
+static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
+ TCGReg arg1, TCGReg arg2)
+{
+ int flags = 0;
+
+ switch (cond) {
+ case TCG_COND_EQ: /* -> NE */
+ case TCG_COND_GE: /* -> LT */
+ case TCG_COND_GEU: /* -> LTU */
+ case TCG_COND_LE: /* -> GT */
+ case TCG_COND_LEU: /* -> GTU */
+ case TCG_COND_TSTEQ: /* -> TSTNE */
+ cond = tcg_invert_cond(cond);
+ flags ^= SETCOND_INV;
+ break;
+ default:
+ break;
+ }
+
+ switch (cond) {
+ case TCG_COND_NE:
+ flags |= SETCOND_NEZ;
+ if (arg2 == 0) {
+ return arg1 | flags;
+ }
+ tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
+ break;
+ case TCG_COND_TSTNE:
+ flags |= SETCOND_NEZ;
+ tcg_out_opc_reg(s, OPC_AND, ret, arg1, arg2);
+ break;
+ case TCG_COND_LT:
+ tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
+ break;
+ case TCG_COND_LTU:
+ tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
+ break;
+ case TCG_COND_GT:
+ tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
+ break;
+ case TCG_COND_GTU:
+ tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ return ret | flags;
+}
+
+static void tcg_out_setcond_end(TCGContext *s, TCGReg ret, int tmpflags)
+{
+ if (tmpflags != ret) {
+ TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
+
+ switch (tmpflags & SETCOND_FLAGS) {
+ case SETCOND_INV:
+ /* Intermediate result is boolean: simply invert. */
+ tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
+ break;
+ case SETCOND_NEZ:
+ /* Intermediate result is zero/non-zero: test != 0. */
+ tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
+ break;
+ case SETCOND_NEZ | SETCOND_INV:
+ /* Intermediate result is zero/non-zero: test == 0. */
+ tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg arg1, TCGReg arg2)
{
- MIPSInsn s_opc = OPC_SLTU;
- int cmp_map;
-
- switch (cond) {
- case TCG_COND_EQ:
- if (arg2 != 0) {
- tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
- arg1 = ret;
- }
- tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
- break;
-
- case TCG_COND_NE:
- if (arg2 != 0) {
- tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
- arg1 = 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:
- case TCG_COND_GT:
- s_opc = OPC_SLT;
- /* FALLTHRU */
-
- case TCG_COND_LTU:
- case TCG_COND_GEU:
- case TCG_COND_LEU:
- case TCG_COND_GTU:
- cmp_map = mips_cmp_map[cond];
- if (cmp_map & MIPS_CMP_SWAP) {
- TCGReg t = arg1;
- arg1 = arg2;
- arg2 = t;
- }
- tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
- if (cmp_map & MIPS_CMP_INV) {
- tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
- }
- break;
-
- default:
- g_assert_not_reached();
- break;
- }
+ int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2);
+ tcg_out_setcond_end(s, ret, tmpflags);
}
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
@@ -958,9 +965,7 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
[TCG_COND_GE] = OPC_BGEZ,
};
- MIPSInsn s_opc = OPC_SLTU;
- MIPSInsn b_opc;
- int cmp_map;
+ MIPSInsn b_opc = 0;
switch (cond) {
case TCG_COND_EQ:
@@ -969,7 +974,6 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
case TCG_COND_NE:
b_opc = OPC_BNE;
break;
-
case TCG_COND_LT:
case TCG_COND_GT:
case TCG_COND_LE:
@@ -978,156 +982,86 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
b_opc = b_zero[cond];
arg2 = arg1;
arg1 = 0;
- break;
}
- s_opc = OPC_SLT;
- /* FALLTHRU */
-
- case TCG_COND_LTU:
- case TCG_COND_GTU:
- case TCG_COND_LEU:
- case TCG_COND_GEU:
- cmp_map = mips_cmp_map[cond];
- if (cmp_map & MIPS_CMP_SWAP) {
- TCGReg t = arg1;
- arg1 = arg2;
- arg2 = t;
- }
- tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
- b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
- arg1 = TCG_TMP0;
- 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;
}
+ if (b_opc == 0) {
+ int tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, arg1, arg2);
+
+ arg2 = 0;
+ arg1 = tmpflags & ~SETCOND_FLAGS;
+ b_opc = tmpflags & SETCOND_INV ? OPC_BEQ : OPC_BNE;
+ }
+
tcg_out_opc_br(s, b_opc, arg1, arg2);
tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
tcg_out_nop(s);
}
-static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
- TCGReg al, TCGReg ah,
- TCGReg bl, TCGReg bh)
+static int tcg_out_setcond2_int(TCGContext *s, TCGCond cond, TCGReg ret,
+ TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
{
- /* Merge highpart comparison into AH. */
- if (bh != 0) {
- if (ah != 0) {
- tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
- ah = tmp0;
- } else {
- ah = bh;
- }
+ int flags = 0;
+
+ switch (cond) {
+ case TCG_COND_EQ:
+ flags |= SETCOND_INV;
+ /* fall through */
+ case TCG_COND_NE:
+ flags |= SETCOND_NEZ;
+ tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, al, bl);
+ tcg_out_opc_reg(s, OPC_XOR, TCG_TMP1, ah, bh);
+ tcg_out_opc_reg(s, OPC_OR, ret, TCG_TMP0, TCG_TMP1);
+ break;
+
+ case TCG_COND_TSTEQ:
+ flags |= SETCOND_INV;
+ /* fall through */
+ case TCG_COND_TSTNE:
+ flags |= SETCOND_NEZ;
+ 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);
+ break;
+
+ default:
+ tcg_out_setcond(s, TCG_COND_EQ, TCG_TMP0, ah, bh);
+ tcg_out_setcond(s, tcg_unsigned_cond(cond), TCG_TMP1, al, bl);
+ tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP0);
+ tcg_out_setcond(s, tcg_high_cond(cond), TCG_TMP0, ah, bh);
+ tcg_out_opc_reg(s, OPC_OR, ret, TCG_TMP0, TCG_TMP1);
+ break;
}
- /* Merge lowpart comparison into AL. */
- if (bl != 0) {
- if (al != 0) {
- tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
- al = tmp1;
- } else {
- al = bl;
- }
- }
- /* Merge high and low part comparisons into AL. */
- if (ah != 0) {
- if (al != 0) {
- tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
- al = tmp0;
- } else {
- al = ah;
- }
- }
- return al;
+ return ret | flags;
}
static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
{
- TCGReg tmp0 = TCG_TMP0;
- TCGReg tmp1 = ret;
-
- tcg_debug_assert(ret != TCG_TMP0);
- if (ret == ah || ret == bh) {
- tcg_debug_assert(ret != TCG_TMP1);
- tmp1 = TCG_TMP1;
- }
-
- switch (cond) {
- case TCG_COND_EQ:
- case TCG_COND_NE:
- tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
- 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);
- tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
- tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
- tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
- break;
- }
+ int tmpflags = tcg_out_setcond2_int(s, cond, ret, al, ah, bl, bh);
+ tcg_out_setcond_end(s, ret, tmpflags);
}
static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
TCGReg bl, TCGReg bh, TCGLabel *l)
{
- TCGCond b_cond = TCG_COND_NE;
- TCGReg tmp = TCG_TMP1;
+ int tmpflags = tcg_out_setcond2_int(s, cond, TCG_TMP0, al, ah, bl, bh);
+ TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
+ MIPSInsn b_opc = tmpflags & SETCOND_INV ? OPC_BEQ : OPC_BNE;
- /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
- With setcond, we emit between 3 and 10 insns and only 1 branch,
- which ought to get better branch prediction. */
- switch (cond) {
- case TCG_COND_EQ:
- case TCG_COND_NE:
- b_cond = cond;
- 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) {
- cond = tcg_invert_cond(cond);
- b_cond = TCG_COND_EQ;
- }
- tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
- break;
- }
-
- tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
+ tcg_out_opc_br(s, b_opc, tmp, TCG_REG_ZERO);
+ tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
+ tcg_out_nop(s);
}
static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
{
- bool eqz = false;
+ int tmpflags;
+ bool eqz;
/* If one of the values is zero, put it last to match SEL*Z instructions */
if (use_mips32r6_instructions && v1 == 0) {
@@ -1136,35 +1070,9 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
cond = tcg_invert_cond(cond);
}
- switch (cond) {
- case TCG_COND_EQ:
- eqz = true;
- /* FALLTHRU */
- case TCG_COND_NE:
- if (c2 != 0) {
- tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
- c1 = TCG_TMP0;
- }
- 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) {
- cond = tcg_invert_cond(cond);
- eqz = true;
- }
- tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
- c1 = TCG_TMP0;
- break;
- }
+ tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, c1, c2);
+ c1 = tmpflags & ~SETCOND_FLAGS;
+ eqz = tmpflags & SETCOND_INV;
if (use_mips32r6_instructions) {
MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/6] tcg/mips: Always implement movcond
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
2023-10-26 4:13 ` [PATCH 1/6] tcg/mips: Split out tcg_out_setcond_int Richard Henderson
@ 2023-10-26 4:14 ` Richard Henderson
2023-10-26 4:14 ` [PATCH 3/6] tcg: Remove TCG_TARGET_HAS_movcond_{i32,i64} Richard Henderson
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:14 UTC (permalink / raw)
To: qemu-devel
Expand as branch over move if not supported in the ISA.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/mips/tcg-target.h | 4 ++--
tcg/mips/tcg-target.c.inc | 19 ++++++++++++++-----
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index c0576f66d7..0a4083f0d9 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -154,7 +154,7 @@ extern bool use_mips32r2_instructions;
#endif
/* optional instructions detected at runtime */
-#define TCG_TARGET_HAS_movcond_i32 use_movnz_instructions
+#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions
#define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions
#define TCG_TARGET_HAS_extract_i32 use_mips32r2_instructions
@@ -169,7 +169,7 @@ extern bool use_mips32r2_instructions;
#define TCG_TARGET_HAS_qemu_st8_i32 0
#if TCG_TARGET_REG_BITS == 64
-#define TCG_TARGET_HAS_movcond_i64 use_movnz_instructions
+#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_bswap16_i64 use_mips32r2_instructions
#define TCG_TARGET_HAS_bswap32_i64 use_mips32r2_instructions
#define TCG_TARGET_HAS_bswap64_i64 use_mips32r2_instructions
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index a5e6fe727b..f9b790ed8a 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -1085,13 +1085,22 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
if (v2 != 0) {
tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
}
- } else {
+ return;
+ }
+
+ /* This should be guaranteed via constraints */
+ tcg_debug_assert(v2 == ret);
+
+ if (use_movnz_instructions) {
MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
-
tcg_out_opc_reg(s, m_opc, ret, v1, c1);
-
- /* This should be guaranteed via constraints */
- tcg_debug_assert(v2 == ret);
+ } else {
+ /* Invert the condition in order to branch over the move. */
+ MIPSInsn b_opc = eqz ? OPC_BNE : OPC_BEQ;
+ tcg_out_opc_imm(s, b_opc, c1, TCG_REG_ZERO, 2);
+ tcg_out_nop(s);
+ /* Open-code tcg_out_mov, without the nop-move check. */
+ tcg_out_opc_reg(s, OPC_OR, ret, v1, TCG_REG_ZERO);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] tcg: Remove TCG_TARGET_HAS_movcond_{i32,i64}
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
2023-10-26 4:13 ` [PATCH 1/6] tcg/mips: Split out tcg_out_setcond_int Richard Henderson
2023-10-26 4:14 ` [PATCH 2/6] tcg/mips: Always implement movcond Richard Henderson
@ 2023-10-26 4:14 ` Richard Henderson
2023-10-26 4:14 ` [PATCH 4/6] tcg/mips: Implement neg opcodes Richard Henderson
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:14 UTC (permalink / raw)
To: qemu-devel
The movcond opcode is now mandatory for backends to implement.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/tcg/tcg-opc.h | 4 +--
include/tcg/tcg.h | 1 -
tcg/aarch64/tcg-target.h | 2 --
tcg/arm/tcg-target.h | 1 -
tcg/i386/tcg-target.h | 2 --
tcg/loongarch64/tcg-target.h | 2 --
tcg/mips/tcg-target.h | 2 --
tcg/ppc/tcg-target.h | 2 --
tcg/riscv/tcg-target.h | 2 --
tcg/s390x/tcg-target.h | 2 --
tcg/sparc64/tcg-target.h | 2 --
tcg/tci/tcg-target.h | 2 --
tcg/tcg-op.c | 50 ++++++++----------------------------
tcg/tcg.c | 6 ++---
14 files changed, 14 insertions(+), 66 deletions(-)
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 6eff3d9106..ecd08db0de 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -47,7 +47,7 @@ DEF(mb, 0, 0, 1, 0)
DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
DEF(setcond_i32, 1, 2, 1, 0)
DEF(negsetcond_i32, 1, 2, 1, IMPL(TCG_TARGET_HAS_negsetcond_i32))
-DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
+DEF(movcond_i32, 1, 4, 1, 0)
/* load/store */
DEF(ld8u_i32, 1, 1, 1, 0)
DEF(ld8s_i32, 1, 1, 1, 0)
@@ -113,7 +113,7 @@ DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32))
DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
DEF(setcond_i64, 1, 2, 1, IMPL64)
DEF(negsetcond_i64, 1, 2, 1, IMPL64 | IMPL(TCG_TARGET_HAS_negsetcond_i64))
-DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
+DEF(movcond_i64, 1, 4, 1, IMPL64)
/* load/store */
DEF(ld8u_i64, 1, 1, 1, IMPL64)
DEF(ld8s_i64, 1, 1, 1, IMPL64)
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index a9282cdcc6..bb522a865c 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -96,7 +96,6 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_extract_i64 0
#define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0
-#define TCG_TARGET_HAS_movcond_i64 0
#define TCG_TARGET_HAS_negsetcond_i64 0
#define TCG_TARGET_HAS_add2_i64 0
#define TCG_TARGET_HAS_sub2_i64 0
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index 98727ea53b..352e19aba8 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -85,7 +85,6 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i32 1
#define TCG_TARGET_HAS_sextract_i32 1
#define TCG_TARGET_HAS_extract2_i32 1
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
@@ -122,7 +121,6 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i64 1
#define TCG_TARGET_HAS_sextract_i64 1
#define TCG_TARGET_HAS_extract2_i64 1
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 311a985209..439898efb3 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -115,7 +115,6 @@ extern bool use_neon_instructions;
#define TCG_TARGET_HAS_extract_i32 use_armv7_instructions
#define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions
#define TCG_TARGET_HAS_extract2_i32 1
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 1
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 8417ea4899..7522ce7575 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -149,7 +149,6 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i32 1
#define TCG_TARGET_HAS_sextract_i32 1
#define TCG_TARGET_HAS_extract2_i32 1
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
@@ -186,7 +185,6 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i64 1
#define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 1
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 03017672f6..bebb2c6a05 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -97,7 +97,6 @@ extern bool use_lsx_instructions;
#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
/* optional instructions */
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 0
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 1
@@ -134,7 +133,6 @@ extern bool use_lsx_instructions;
#define TCG_TARGET_HAS_qemu_st8_i32 0
/* 64-bit operations */
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 0a4083f0d9..5b3fdcc726 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -154,7 +154,6 @@ extern bool use_mips32r2_instructions;
#endif
/* optional instructions detected at runtime */
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions
#define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions
#define TCG_TARGET_HAS_extract_i32 use_mips32r2_instructions
@@ -169,7 +168,6 @@ extern bool use_mips32r2_instructions;
#define TCG_TARGET_HAS_qemu_st8_i32 0
#if TCG_TARGET_REG_BITS == 64
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_bswap16_i64 use_mips32r2_instructions
#define TCG_TARGET_HAS_bswap32_i64 use_mips32r2_instructions
#define TCG_TARGET_HAS_bswap64_i64 use_mips32r2_instructions
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 8bfb14998e..a2856afd4d 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -96,7 +96,6 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i32 1
#define TCG_TARGET_HAS_sextract_i32 0
#define TCG_TARGET_HAS_extract2_i32 0
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_mulu2_i32 0
#define TCG_TARGET_HAS_muls2_i32 0
@@ -134,7 +133,6 @@ typedef enum {
#define TCG_TARGET_HAS_extract_i64 1
#define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index c1132d178f..f3644a8bc1 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -87,7 +87,6 @@ extern bool have_zbb;
#endif
/* optional instructions */
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 1
@@ -123,7 +122,6 @@ extern bool have_zbb;
#define TCG_TARGET_HAS_setcond2 1
#define TCG_TARGET_HAS_qemu_st8_i32 0
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1
diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h
index 50e12ef9d6..2c936c1bcb 100644
--- a/tcg/s390x/tcg-target.h
+++ b/tcg/s390x/tcg-target.h
@@ -95,7 +95,6 @@ extern uint64_t s390_facilities[3];
#define TCG_TARGET_HAS_extract_i32 1
#define TCG_TARGET_HAS_sextract_i32 0
#define TCG_TARGET_HAS_extract2_i32 0
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
@@ -131,7 +130,6 @@ extern uint64_t s390_facilities[3];
#define TCG_TARGET_HAS_extract_i64 1
#define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1
diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h
index 5cfc4b4679..4c286c6006 100644
--- a/tcg/sparc64/tcg-target.h
+++ b/tcg/sparc64/tcg-target.h
@@ -105,7 +105,6 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_extract_i32 0
#define TCG_TARGET_HAS_sextract_i32 0
#define TCG_TARGET_HAS_extract2_i32 0
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 1
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
@@ -142,7 +141,6 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_extract_i64 0
#define TCG_TARGET_HAS_sextract_i64 0
#define TCG_TARGET_HAS_extract2_i64 0
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 1
#define TCG_TARGET_HAS_add2_i64 1
#define TCG_TARGET_HAS_sub2_i64 1
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 91ca33b616..3503fc4a4c 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -69,7 +69,6 @@
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_orc_i32 1
#define TCG_TARGET_HAS_rot_i32 1
-#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_negsetcond_i32 0
#define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 0
@@ -104,7 +103,6 @@
#define TCG_TARGET_HAS_not_i64 1
#define TCG_TARGET_HAS_orc_i64 1
#define TCG_TARGET_HAS_rot_i64 1
-#define TCG_TARGET_HAS_movcond_i64 1
#define TCG_TARGET_HAS_negsetcond_i64 0
#define TCG_TARGET_HAS_muls2_i64 1
#define TCG_TARGET_HAS_add2_i32 1
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index 828eb9ee46..51de796769 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -864,17 +864,8 @@ void tcg_gen_movcond_i32(TCGCond cond, TCGv_i32 ret, TCGv_i32 c1,
tcg_gen_mov_i32(ret, v1);
} else if (cond == TCG_COND_NEVER) {
tcg_gen_mov_i32(ret, v2);
- } else if (TCG_TARGET_HAS_movcond_i32) {
- tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
} else {
- TCGv_i32 t0 = tcg_temp_ebb_new_i32();
- TCGv_i32 t1 = tcg_temp_ebb_new_i32();
- tcg_gen_negsetcond_i32(cond, t0, c1, c2);
- tcg_gen_and_i32(t1, v1, t0);
- tcg_gen_andc_i32(ret, v2, t0);
- tcg_gen_or_i32(ret, ret, t1);
- tcg_temp_free_i32(t0);
- tcg_temp_free_i32(t1);
+ tcg_gen_op6i_i32(INDEX_op_movcond_i32, ret, c1, c2, v1, v2, cond);
}
}
@@ -2600,43 +2591,22 @@ void tcg_gen_movcond_i64(TCGCond cond, TCGv_i64 ret, TCGv_i64 c1,
tcg_gen_mov_i64(ret, v1);
} else if (cond == TCG_COND_NEVER) {
tcg_gen_mov_i64(ret, v2);
- } else if (TCG_TARGET_REG_BITS == 32) {
+ } else if (TCG_TARGET_REG_BITS == 64) {
+ tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
+ } else {
TCGv_i32 t0 = tcg_temp_ebb_new_i32();
- TCGv_i32 t1 = tcg_temp_ebb_new_i32();
+ TCGv_i32 zero = tcg_constant_i32(0);
+
tcg_gen_op6i_i32(INDEX_op_setcond2_i32, t0,
TCGV_LOW(c1), TCGV_HIGH(c1),
TCGV_LOW(c2), TCGV_HIGH(c2), cond);
- if (TCG_TARGET_HAS_movcond_i32) {
- tcg_gen_movi_i32(t1, 0);
- tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, t1,
- TCGV_LOW(v1), TCGV_LOW(v2));
- tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, t1,
- TCGV_HIGH(v1), TCGV_HIGH(v2));
- } else {
- tcg_gen_neg_i32(t0, t0);
+ tcg_gen_movcond_i32(TCG_COND_NE, TCGV_LOW(ret), t0, zero,
+ TCGV_LOW(v1), TCGV_LOW(v2));
+ tcg_gen_movcond_i32(TCG_COND_NE, TCGV_HIGH(ret), t0, zero,
+ TCGV_HIGH(v1), TCGV_HIGH(v2));
- tcg_gen_and_i32(t1, TCGV_LOW(v1), t0);
- tcg_gen_andc_i32(TCGV_LOW(ret), TCGV_LOW(v2), t0);
- tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t1);
-
- tcg_gen_and_i32(t1, TCGV_HIGH(v1), t0);
- tcg_gen_andc_i32(TCGV_HIGH(ret), TCGV_HIGH(v2), t0);
- tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t1);
- }
tcg_temp_free_i32(t0);
- tcg_temp_free_i32(t1);
- } else if (TCG_TARGET_HAS_movcond_i64) {
- tcg_gen_op6i_i64(INDEX_op_movcond_i64, ret, c1, c2, v1, v2, cond);
- } else {
- TCGv_i64 t0 = tcg_temp_ebb_new_i64();
- TCGv_i64 t1 = tcg_temp_ebb_new_i64();
- tcg_gen_negsetcond_i64(cond, t0, c1, c2);
- tcg_gen_and_i64(t1, v1, t0);
- tcg_gen_andc_i64(ret, v2, t0);
- tcg_gen_or_i64(ret, ret, t1);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
}
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 57d0583fe7..5da03ba11d 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1874,6 +1874,7 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_mov_i32:
case INDEX_op_setcond_i32:
case INDEX_op_brcond_i32:
+ case INDEX_op_movcond_i32:
case INDEX_op_ld8u_i32:
case INDEX_op_ld8s_i32:
case INDEX_op_ld16u_i32:
@@ -1895,8 +1896,6 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_negsetcond_i32:
return TCG_TARGET_HAS_negsetcond_i32;
- case INDEX_op_movcond_i32:
- return TCG_TARGET_HAS_movcond_i32;
case INDEX_op_div_i32:
case INDEX_op_divu_i32:
return TCG_TARGET_HAS_div_i32;
@@ -1969,6 +1968,7 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_mov_i64:
case INDEX_op_setcond_i64:
case INDEX_op_brcond_i64:
+ case INDEX_op_movcond_i64:
case INDEX_op_ld8u_i64:
case INDEX_op_ld8s_i64:
case INDEX_op_ld16u_i64:
@@ -1995,8 +1995,6 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_negsetcond_i64:
return TCG_TARGET_HAS_negsetcond_i64;
- case INDEX_op_movcond_i64:
- return TCG_TARGET_HAS_movcond_i64;
case INDEX_op_div_i64:
case INDEX_op_divu_i64:
return TCG_TARGET_HAS_div_i64;
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/6] tcg/mips: Implement neg opcodes
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
` (2 preceding siblings ...)
2023-10-26 4:14 ` [PATCH 3/6] tcg: Remove TCG_TARGET_HAS_movcond_{i32,i64} Richard Henderson
@ 2023-10-26 4:14 ` Richard Henderson
2023-10-26 4:14 ` [PATCH 5/6] tcg/loongarch64: " Richard Henderson
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:14 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/mips/tcg-target.h | 4 ++--
tcg/mips/tcg-target.c.inc | 8 ++++++++
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 5b3fdcc726..20c14224fb 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -184,12 +184,12 @@ extern bool use_mips32r2_instructions;
#endif
/* optional instructions automatically implemented */
-#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
+#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */
#define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */
#if TCG_TARGET_REG_BITS == 64
-#define TCG_TARGET_HAS_neg_i64 0 /* sub rd, zero, rt */
+#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_ext8u_i64 0 /* andi rt, rs, 0xff */
#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */
#endif
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
index f9b790ed8a..c38f5c9450 100644
--- a/tcg/mips/tcg-target.c.inc
+++ b/tcg/mips/tcg-target.c.inc
@@ -1935,6 +1935,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
break;
+ case INDEX_op_neg_i32:
+ i1 = OPC_SUBU;
+ goto do_unary;
+ case INDEX_op_neg_i64:
+ i1 = OPC_DSUBU;
+ goto do_unary;
case INDEX_op_not_i32:
case INDEX_op_not_i64:
i1 = OPC_NOR;
@@ -2159,6 +2165,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_ld16u_i32:
case INDEX_op_ld16s_i32:
case INDEX_op_ld_i32:
+ case INDEX_op_neg_i32:
case INDEX_op_not_i32:
case INDEX_op_bswap16_i32:
case INDEX_op_bswap32_i32:
@@ -2172,6 +2179,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_ld32s_i64:
case INDEX_op_ld32u_i64:
case INDEX_op_ld_i64:
+ case INDEX_op_neg_i64:
case INDEX_op_not_i64:
case INDEX_op_bswap16_i64:
case INDEX_op_bswap32_i64:
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/6] tcg/loongarch64: Implement neg opcodes
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
` (3 preceding siblings ...)
2023-10-26 4:14 ` [PATCH 4/6] tcg/mips: Implement neg opcodes Richard Henderson
@ 2023-10-26 4:14 ` Richard Henderson
2023-10-26 4:14 ` [PATCH 6/6] tcg: Remove TCG_TARGET_HAS_neg_{i32,i64} Richard Henderson
2023-10-26 4:20 ` [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:14 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/loongarch64/tcg-target.h | 4 ++--
tcg/loongarch64/tcg-target.c.inc | 9 +++++++++
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index bebb2c6a05..d1c8e6d341 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -119,7 +119,7 @@ extern bool use_lsx_instructions;
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 0
+#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_orc_i32 1
#define TCG_TARGET_HAS_eqv_i32 0
@@ -153,7 +153,7 @@ extern bool use_lsx_instructions;
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_not_i64 1
-#define TCG_TARGET_HAS_neg_i64 0
+#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_orc_i64 1
#define TCG_TARGET_HAS_eqv_i64 0
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 4e850a29e5..f21fba9f66 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1458,6 +1458,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
break;
+ case INDEX_op_neg_i32:
+ tcg_out_opc_sub_w(s, a0, TCG_REG_ZERO, a1);
+ break;
+ case INDEX_op_neg_i64:
+ tcg_out_opc_sub_d(s, a0, TCG_REG_ZERO, a1);
+ break;
+
case INDEX_op_mul_i32:
tcg_out_opc_mul_w(s, a0, a1, a2);
break;
@@ -2093,6 +2100,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_extrl_i64_i32:
case INDEX_op_extrh_i64_i32:
case INDEX_op_ext_i32_i64:
+ case INDEX_op_neg_i32:
+ case INDEX_op_neg_i64:
case INDEX_op_not_i32:
case INDEX_op_not_i64:
case INDEX_op_extract_i32:
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/6] tcg: Remove TCG_TARGET_HAS_neg_{i32,i64}
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
` (4 preceding siblings ...)
2023-10-26 4:14 ` [PATCH 5/6] tcg/loongarch64: " Richard Henderson
@ 2023-10-26 4:14 ` Richard Henderson
2023-10-26 4:20 ` [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:14 UTC (permalink / raw)
To: qemu-devel
The movcond opcode is now mandatory for backends to implement.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/tcg/tcg-op-common.h | 12 ++----------
include/tcg/tcg-opc.h | 4 ++--
include/tcg/tcg.h | 1 -
tcg/aarch64/tcg-target.h | 2 --
tcg/arm/tcg-target.h | 1 -
tcg/i386/tcg-target.h | 2 --
tcg/loongarch64/tcg-target.h | 2 --
tcg/mips/tcg-target.h | 2 --
tcg/ppc/tcg-target.h | 2 --
tcg/riscv/tcg-target.h | 2 --
tcg/s390x/tcg-target.h | 2 --
tcg/sparc64/tcg-target.h | 2 --
tcg/tci/tcg-target.h | 2 --
tcg/optimize.c | 15 +++++----------
tcg/tcg-op.c | 10 ++++------
tcg/tcg.c | 6 ++----
tcg/tci.c | 2 --
17 files changed, 15 insertions(+), 54 deletions(-)
diff --git a/include/tcg/tcg-op-common.h b/include/tcg/tcg-op-common.h
index 677aea6dd1..7dc1184ba6 100644
--- a/include/tcg/tcg-op-common.h
+++ b/include/tcg/tcg-op-common.h
@@ -481,11 +481,7 @@ static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
static inline void tcg_gen_neg_i32(TCGv_i32 ret, TCGv_i32 arg)
{
- if (TCG_TARGET_HAS_neg_i32) {
- tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg);
- } else {
- tcg_gen_subfi_i32(ret, 0, arg);
- }
+ tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg);
}
static inline void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 arg)
@@ -732,11 +728,7 @@ void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2);
static inline void tcg_gen_neg_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- if (TCG_TARGET_HAS_neg_i64) {
- tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg);
- } else {
- tcg_gen_subfi_i64(ret, 0, arg);
- }
+ tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg);
}
/* Size changing operations. */
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index ecd08db0de..b80227fa1c 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -100,7 +100,7 @@ DEF(ext16u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16u_i32))
DEF(bswap16_i32, 1, 1, 1, IMPL(TCG_TARGET_HAS_bswap16_i32))
DEF(bswap32_i32, 1, 1, 1, IMPL(TCG_TARGET_HAS_bswap32_i32))
DEF(not_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_not_i32))
-DEF(neg_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_neg_i32))
+DEF(neg_i32, 1, 1, 0, 0)
DEF(andc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_andc_i32))
DEF(orc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_orc_i32))
DEF(eqv_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_eqv_i32))
@@ -171,7 +171,7 @@ DEF(bswap16_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap16_i64))
DEF(bswap32_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap32_i64))
DEF(bswap64_i64, 1, 1, 1, IMPL64 | IMPL(TCG_TARGET_HAS_bswap64_i64))
DEF(not_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_not_i64))
-DEF(neg_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_neg_i64))
+DEF(neg_i64, 1, 1, 0, IMPL64)
DEF(andc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_andc_i64))
DEF(orc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_orc_i64))
DEF(eqv_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_eqv_i64))
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index bb522a865c..2a0893e0f7 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -82,7 +82,6 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_bswap16_i64 0
#define TCG_TARGET_HAS_bswap32_i64 0
#define TCG_TARGET_HAS_bswap64_i64 0
-#define TCG_TARGET_HAS_neg_i64 0
#define TCG_TARGET_HAS_not_i64 0
#define TCG_TARGET_HAS_andc_i64 0
#define TCG_TARGET_HAS_orc_i64 0
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
index 352e19aba8..33f15a564a 100644
--- a/tcg/aarch64/tcg-target.h
+++ b/tcg/aarch64/tcg-target.h
@@ -71,7 +71,6 @@ typedef enum {
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_orc_i32 1
@@ -107,7 +106,6 @@ typedef enum {
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_not_i64 1
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_orc_i64 1
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 439898efb3..a712cc80ad 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -101,7 +101,6 @@ extern bool use_neon_instructions;
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_orc_i32 0
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 7522ce7575..fa34deec47 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -135,7 +135,6 @@ typedef enum {
#define TCG_TARGET_HAS_ext16u_i32 1
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_andc_i32 have_bmi1
#define TCG_TARGET_HAS_orc_i32 0
@@ -171,7 +170,6 @@ typedef enum {
#define TCG_TARGET_HAS_bswap16_i64 1
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_not_i64 1
#define TCG_TARGET_HAS_andc_i64 have_bmi1
#define TCG_TARGET_HAS_orc_i64 0
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index d1c8e6d341..428098cbc0 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -119,7 +119,6 @@ extern bool use_lsx_instructions;
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_orc_i32 1
#define TCG_TARGET_HAS_eqv_i32 0
@@ -153,7 +152,6 @@ extern bool use_lsx_instructions;
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_not_i64 1
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_orc_i64 1
#define TCG_TARGET_HAS_eqv_i64 0
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 20c14224fb..b98ffae1d0 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -184,12 +184,10 @@ extern bool use_mips32r2_instructions;
#endif
/* optional instructions automatically implemented */
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */
#define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */
#if TCG_TARGET_REG_BITS == 64
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_ext8u_i64 0 /* andi rt, rs, 0xff */
#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */
#endif
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index a2856afd4d..5295e4f9ab 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -83,7 +83,6 @@ typedef enum {
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_orc_i32 1
#define TCG_TARGET_HAS_eqv_i32 1
@@ -120,7 +119,6 @@ typedef enum {
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_not_i64 1
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_orc_i64 1
#define TCG_TARGET_HAS_eqv_i64 1
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index f3644a8bc1..a4edc3dc74 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -109,7 +109,6 @@ extern bool have_zbb;
#define TCG_TARGET_HAS_bswap16_i32 have_zbb
#define TCG_TARGET_HAS_bswap32_i32 have_zbb
#define TCG_TARGET_HAS_not_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_andc_i32 have_zbb
#define TCG_TARGET_HAS_orc_i32 have_zbb
#define TCG_TARGET_HAS_eqv_i32 have_zbb
@@ -142,7 +141,6 @@ extern bool have_zbb;
#define TCG_TARGET_HAS_bswap32_i64 have_zbb
#define TCG_TARGET_HAS_bswap64_i64 have_zbb
#define TCG_TARGET_HAS_not_i64 1
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_andc_i64 have_zbb
#define TCG_TARGET_HAS_orc_i64 have_zbb
#define TCG_TARGET_HAS_eqv_i64 have_zbb
diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h
index 2c936c1bcb..e69b0d2ddd 100644
--- a/tcg/s390x/tcg-target.h
+++ b/tcg/s390x/tcg-target.h
@@ -82,7 +82,6 @@ extern uint64_t s390_facilities[3];
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
#define TCG_TARGET_HAS_not_i32 HAVE_FACILITY(MISC_INSN_EXT3)
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_andc_i32 HAVE_FACILITY(MISC_INSN_EXT3)
#define TCG_TARGET_HAS_orc_i32 HAVE_FACILITY(MISC_INSN_EXT3)
#define TCG_TARGET_HAS_eqv_i32 HAVE_FACILITY(MISC_INSN_EXT3)
@@ -117,7 +116,6 @@ extern uint64_t s390_facilities[3];
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_not_i64 HAVE_FACILITY(MISC_INSN_EXT3)
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_andc_i64 HAVE_FACILITY(MISC_INSN_EXT3)
#define TCG_TARGET_HAS_orc_i64 HAVE_FACILITY(MISC_INSN_EXT3)
#define TCG_TARGET_HAS_eqv_i64 HAVE_FACILITY(MISC_INSN_EXT3)
diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h
index 4c286c6006..f8cf145266 100644
--- a/tcg/sparc64/tcg-target.h
+++ b/tcg/sparc64/tcg-target.h
@@ -91,7 +91,6 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_ext16u_i32 0
#define TCG_TARGET_HAS_bswap16_i32 0
#define TCG_TARGET_HAS_bswap32_i32 0
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_orc_i32 1
@@ -127,7 +126,6 @@ extern bool use_vis3_instructions;
#define TCG_TARGET_HAS_bswap16_i64 0
#define TCG_TARGET_HAS_bswap32_i64 0
#define TCG_TARGET_HAS_bswap64_i64 0
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_not_i64 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_orc_i64 1
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 3503fc4a4c..2a13816c8e 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -65,7 +65,6 @@
#define TCG_TARGET_HAS_clz_i32 1
#define TCG_TARGET_HAS_ctz_i32 1
#define TCG_TARGET_HAS_ctpop_i32 1
-#define TCG_TARGET_HAS_neg_i32 1
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_orc_i32 1
#define TCG_TARGET_HAS_rot_i32 1
@@ -99,7 +98,6 @@
#define TCG_TARGET_HAS_clz_i64 1
#define TCG_TARGET_HAS_ctz_i64 1
#define TCG_TARGET_HAS_ctpop_i64 1
-#define TCG_TARGET_HAS_neg_i64 1
#define TCG_TARGET_HAS_not_i64 1
#define TCG_TARGET_HAS_orc_i64 1
#define TCG_TARGET_HAS_rot_i64 1
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 27b1eaaa8d..5e16800cfa 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1930,7 +1930,7 @@ static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg)
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;
+ neg_opc = INDEX_op_neg_i32;
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;
@@ -1939,7 +1939,7 @@ static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg)
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;
+ neg_opc = INDEX_op_neg_i64;
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;
@@ -1986,15 +1986,10 @@ static void fold_setcond_tst_pow2(OptContext *ctx, TCGOp *op, bool neg)
op2->args[0] = ret;
op2->args[1] = ret;
op2->args[2] = arg_new_constant(ctx, 1);
- } else if (neg && neg_opc) {
+ } else if (neg) {
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;
}
}
@@ -2205,11 +2200,11 @@ static bool fold_sub_to_neg(OptContext *ctx, TCGOp *op)
switch (ctx->type) {
case TCG_TYPE_I32:
neg_op = INDEX_op_neg_i32;
- have_neg = TCG_TARGET_HAS_neg_i32;
+ have_neg = true;
break;
case TCG_TYPE_I64:
neg_op = INDEX_op_neg_i64;
- have_neg = TCG_TARGET_HAS_neg_i64;
+ have_neg = true;
break;
case TCG_TYPE_V64:
case TCG_TYPE_V128:
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index 51de796769..59deb3cbbb 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -138,9 +138,8 @@ void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
{
- if (arg1 == 0 && TCG_TARGET_HAS_neg_i32) {
- /* Don't recurse with tcg_gen_neg_i32. */
- tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
+ if (arg1 == 0) {
+ tcg_gen_neg_i32(ret, arg2);
} else {
tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
}
@@ -1342,9 +1341,8 @@ void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
{
- if (arg1 == 0 && TCG_TARGET_HAS_neg_i64) {
- /* Don't recurse with tcg_gen_neg_i64. */
- tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg2);
+ if (arg1 == 0) {
+ tcg_gen_neg_i64(ret, arg2);
} else if (TCG_TARGET_REG_BITS == 64) {
tcg_gen_sub_i64(ret, tcg_constant_i64(arg1), arg2);
} else {
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 5da03ba11d..a507c111cf 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1885,6 +1885,7 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_st_i32:
case INDEX_op_add_i32:
case INDEX_op_sub_i32:
+ case INDEX_op_neg_i32:
case INDEX_op_mul_i32:
case INDEX_op_and_i32:
case INDEX_op_or_i32:
@@ -1942,8 +1943,6 @@ bool tcg_op_supported(TCGOpcode op)
return TCG_TARGET_HAS_bswap32_i32;
case INDEX_op_not_i32:
return TCG_TARGET_HAS_not_i32;
- case INDEX_op_neg_i32:
- return TCG_TARGET_HAS_neg_i32;
case INDEX_op_andc_i32:
return TCG_TARGET_HAS_andc_i32;
case INDEX_op_orc_i32:
@@ -1982,6 +1981,7 @@ bool tcg_op_supported(TCGOpcode op)
case INDEX_op_st_i64:
case INDEX_op_add_i64:
case INDEX_op_sub_i64:
+ case INDEX_op_neg_i64:
case INDEX_op_mul_i64:
case INDEX_op_and_i64:
case INDEX_op_or_i64:
@@ -2038,8 +2038,6 @@ bool tcg_op_supported(TCGOpcode op)
return TCG_TARGET_HAS_bswap64_i64;
case INDEX_op_not_i64:
return TCG_TARGET_HAS_not_i64;
- case INDEX_op_neg_i64:
- return TCG_TARGET_HAS_neg_i64;
case INDEX_op_andc_i64:
return TCG_TARGET_HAS_andc_i64;
case INDEX_op_orc_i64:
diff --git a/tcg/tci.c b/tcg/tci.c
index 5e1c4a491d..39adcb7d82 100644
--- a/tcg/tci.c
+++ b/tcg/tci.c
@@ -745,12 +745,10 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
regs[r0] = ~regs[r1];
break;
#endif
-#if TCG_TARGET_HAS_neg_i32 || TCG_TARGET_HAS_neg_i64
CASE_32_64(neg)
tci_args_rr(insn, &r0, &r1);
regs[r0] = -regs[r1];
break;
-#endif
#if TCG_TARGET_REG_BITS == 64
/* Load/store operations (64 bit). */
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/6] tcg: Always implement neg and movcond
2023-10-26 4:13 [PATCH 0/6] tcg: Always implement neg and movcond Richard Henderson
` (5 preceding siblings ...)
2023-10-26 4:14 ` [PATCH 6/6] tcg: Remove TCG_TARGET_HAS_neg_{i32,i64} Richard Henderson
@ 2023-10-26 4:20 ` Richard Henderson
6 siblings, 0 replies; 8+ messages in thread
From: Richard Henderson @ 2023-10-26 4:20 UTC (permalink / raw)
To: qemu-devel
On 10/25/23 21:13, Richard Henderson wrote:
> Having opcodes always present means that we can remove some tests.
> NOT and MOVCOND were *almost* always present anyway.
>
> A close candidate is NOT. The hiccup is s390x: except for the most
> recent hardware revision, there is no single insn which can implement
> the operation.
>
> I experimented with replacements:
>
> i32: xilf r,-1 (6 bytes, requires R=X)
> lcr r,x; ahi r,-1 (6 bytes)
> i64: lcgr r,x; aghi r,-1 (8 bytes)
>
> But both don't compare well with the current
>
> lghi tmp,-1 (4 bytes, shared)
> xgrk r,x,tmp (4 bytes)
>
> With the constant -1 managed by register allocation, it gets loaded
> once and then reused between operations.
>
> An alternative might be to assume the presence of all opcodes during
> initial expansion and lower them later, after optimization. I'm close
> to doing just that for the more complex opcodes like deposit anyway,
> because the expansion is too complex for the optimizer to do anything
> sensible after constant propagation.
Oh, for the record,
Based-on: 20231025072707.833943-1-richard.henderson@linaro.org
("tcg: Introduce TCG_COND_TST{EQ,NE}")
r~
^ permalink raw reply [flat|nested] 8+ messages in thread