aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-12-08 18:06:03 +0000
committerRichard Henderson <richard.henderson@linaro.org>2023-01-06 23:07:07 +0000
commit4134083f805389f56fa9ca219c2fdadcd170e0f9 (patch)
treea33b30c26f2bb8cff85deaf880d865830d82c903 /tcg
parentb2509acc60f9380ee2473074c6999dcefd9284fc (diff)
tcg/s390x: Tighten constraints for and_i64
Let the register allocator handle such immediates by matching only what one insn can achieve. Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tcg')
-rw-r--r--tcg/s390x/tcg-target-con-set.h1
-rw-r--r--tcg/s390x/tcg-target-con-str.h2
-rw-r--r--tcg/s390x/tcg-target.c.inc114
3 files changed, 61 insertions, 56 deletions
diff --git a/tcg/s390x/tcg-target-con-set.h b/tcg/s390x/tcg-target-con-set.h
index 34ae4c7743..0c4d0da8f5 100644
--- a/tcg/s390x/tcg-target-con-set.h
+++ b/tcg/s390x/tcg-target-con-set.h
@@ -25,6 +25,7 @@ C_O1_I2(r, 0, rJ)
C_O1_I2(r, r, ri)
C_O1_I2(r, r, rJ)
C_O1_I2(r, r, rK)
+C_O1_I2(r, r, rNKR)
C_O1_I2(r, rZ, r)
C_O1_I2(v, v, r)
C_O1_I2(v, v, v)
diff --git a/tcg/s390x/tcg-target-con-str.h b/tcg/s390x/tcg-target-con-str.h
index 7b910d6d11..6fa64a1ed6 100644
--- a/tcg/s390x/tcg-target-con-str.h
+++ b/tcg/s390x/tcg-target-con-str.h
@@ -21,4 +21,6 @@ CONST('A', TCG_CT_CONST_S33)
CONST('I', TCG_CT_CONST_S16)
CONST('J', TCG_CT_CONST_S32)
CONST('K', TCG_CT_CONST_P32)
+CONST('N', TCG_CT_CONST_INV)
+CONST('R', TCG_CT_CONST_INVRISBG)
CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index 2a7410ba58..21007f94ad 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -33,11 +33,13 @@
#include "../tcg-pool.c.inc"
#include "elf.h"
-#define TCG_CT_CONST_S16 0x100
-#define TCG_CT_CONST_S32 0x200
-#define TCG_CT_CONST_S33 0x400
-#define TCG_CT_CONST_ZERO 0x800
-#define TCG_CT_CONST_P32 0x1000
+#define TCG_CT_CONST_S16 (1 << 8)
+#define TCG_CT_CONST_S32 (1 << 9)
+#define TCG_CT_CONST_S33 (1 << 10)
+#define TCG_CT_CONST_ZERO (1 << 11)
+#define TCG_CT_CONST_P32 (1 << 12)
+#define TCG_CT_CONST_INV (1 << 13)
+#define TCG_CT_CONST_INVRISBG (1 << 14)
#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 16)
#define ALL_VECTOR_REGS MAKE_64BIT_MASK(32, 32)
@@ -530,6 +532,38 @@ static int is_const_p32(uint64_t val)
return -1;
}
+/*
+ * Accept bit patterns like these:
+ * 0....01....1
+ * 1....10....0
+ * 1..10..01..1
+ * 0..01..10..0
+ * Copied from gcc sources.
+ */
+static bool risbg_mask(uint64_t c)
+{
+ uint64_t lsb;
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LSB zero. */
+ if (c & 1) {
+ c = ~c;
+ }
+ /* Reject all zeros or all ones. */
+ if (c == 0) {
+ return false;
+ }
+ /* Find the first transition. */
+ lsb = c & -c;
+ /* Invert to look for a second transition. */
+ c = ~c;
+ /* Erase the first transition. */
+ c &= -lsb;
+ /* Find the second transition, if any. */
+ lsb = c & -c;
+ /* Match if all the bits are 1's, or if c is zero. */
+ return c == -lsb;
+}
+
/* Test if a constant matches the constraint. */
static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
{
@@ -552,6 +586,9 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
return val == 0;
}
+ if (ct & TCG_CT_CONST_INV) {
+ val = ~val;
+ }
/*
* Note that is_const_p16 is a subset of is_const_p32,
* so we don't need both constraints.
@@ -559,6 +596,9 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
if ((ct & TCG_CT_CONST_P32) && is_const_p32(val) >= 0) {
return true;
}
+ if ((ct & TCG_CT_CONST_INVRISBG) && risbg_mask(~val)) {
+ return true;
+ }
return 0;
}
@@ -1057,36 +1097,6 @@ static inline void tgen_ext32u(TCGContext *s, TCGReg dest, TCGReg src)
tcg_out_insn(s, RRE, LLGFR, dest, src);
}
-/* Accept bit patterns like these:
- 0....01....1
- 1....10....0
- 1..10..01..1
- 0..01..10..0
- Copied from gcc sources. */
-static inline bool risbg_mask(uint64_t c)
-{
- uint64_t lsb;
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LSB zero. */
- if (c & 1) {
- c = ~c;
- }
- /* Reject all zeros or all ones. */
- if (c == 0) {
- return false;
- }
- /* Find the first transition. */
- lsb = c & -c;
- /* Invert to look for a second transition. */
- c = ~c;
- /* Erase the first transition. */
- c &= -lsb;
- /* Find the second transition, if any. */
- lsb = c & -c;
- /* Match if all the bits are 1's, or if c is zero. */
- return c == -lsb;
-}
-
static void tgen_andi_risbg(TCGContext *s, TCGReg out, TCGReg in, uint64_t val)
{
int msb, lsb;
@@ -1126,34 +1136,25 @@ static void tgen_andi(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
return;
}
- /* Try all 32-bit insns that can perform it in one go. */
- for (i = 0; i < 4; i++) {
- tcg_target_ulong mask = ~(0xffffull << i * 16);
- if (((val | ~valid) & mask) == mask) {
- tcg_out_insn_RI(s, ni_insns[i], dest, val >> i * 16);
- return;
- }
+ i = is_const_p16(~val & valid);
+ if (i >= 0) {
+ tcg_out_insn_RI(s, ni_insns[i], dest, val >> (i * 16));
+ return;
}
- /* Try all 48-bit insns that can perform it in one go. */
- for (i = 0; i < 2; i++) {
- tcg_target_ulong mask = ~(0xffffffffull << i * 32);
- if (((val | ~valid) & mask) == mask) {
- tcg_out_insn_RIL(s, nif_insns[i], dest, val >> i * 32);
- return;
- }
+ i = is_const_p32(~val & valid);
+ tcg_debug_assert(i == 0 || type != TCG_TYPE_I32);
+ if (i >= 0) {
+ tcg_out_insn_RIL(s, nif_insns[i], dest, val >> (i * 32));
+ return;
}
+
if (risbg_mask(val)) {
tgen_andi_risbg(s, dest, dest, val);
return;
}
- tcg_out_movi(s, type, TCG_TMP0, val);
- if (type == TCG_TYPE_I32) {
- tcg_out_insn(s, RR, NR, dest, TCG_TMP0);
- } else {
- tcg_out_insn(s, RRE, NGR, dest, TCG_TMP0);
- }
+ g_assert_not_reached();
}
static void tgen_ori(TCGContext *s, TCGReg dest, uint64_t val)
@@ -2935,10 +2936,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
case INDEX_op_sub_i32:
case INDEX_op_sub_i64:
case INDEX_op_and_i32:
- case INDEX_op_and_i64:
case INDEX_op_or_i32:
case INDEX_op_xor_i32:
return C_O1_I2(r, r, ri);
+ case INDEX_op_and_i64:
+ return C_O1_I2(r, r, rNKR);
case INDEX_op_or_i64:
case INDEX_op_xor_i64:
return C_O1_I2(r, r, rK);