From nobody Wed Apr 9 12:41:24 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1599610885; cv=none; d=zohomail.com; s=zohoarc; b=El0eGFHEmeVTm6+Dc2R+Nzau50bgaQRBc3p2tAUzJQfO0Heze/RqKbvhZmazP8KYPBtLWswJ3D+lJvaOZZ2CN3CxNzficafM7zy/6illgv0cvQrKTmYXUF8qy8K6qJDGE3L8+dBc9JJz7kO096TZb+QDbkBwkaCD5bj7ujmAYBs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1599610885; h=Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=KhE58qswq9YQaCuua4OczfbEB+B23TFmcdxq1bqWWp8=; b=IdGdGozIU3WsPBXTqt3RTS1a2d53sBVJc4BtlYBAeth4T63QVv0S6duW2jDAGRS1IofvpgSLHyY9sMpe39FE5z+wlkRuSo739Oh52GgfS44L3UKZ7ojtk6EUpy7WxwZz2mnJCokZjSJnSqRhoh635YxQ/+V1r8JoZRQ32fEUqAo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1599610885382286.7471656430712; Tue, 8 Sep 2020 17:21:25 -0700 (PDT) Received: from localhost ([::1]:47736 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kFnrX-00006J-Tw for importer@patchew.org; Tue, 08 Sep 2020 20:21:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37502) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kFnnY-0008Na-3i for qemu-devel@nongnu.org; Tue, 08 Sep 2020 20:17:16 -0400 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]:36730) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kFnnV-0002FG-Na for qemu-devel@nongnu.org; Tue, 08 Sep 2020 20:17:15 -0400 Received: by mail-pj1-x1043.google.com with SMTP id b17so435192pji.1 for ; Tue, 08 Sep 2020 17:17:13 -0700 (PDT) Received: from localhost.localdomain ([71.212.141.89]) by smtp.gmail.com with ESMTPSA id 137sm505437pfu.149.2020.09.08.17.17.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 17:17:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=KhE58qswq9YQaCuua4OczfbEB+B23TFmcdxq1bqWWp8=; b=dxnUxTlkhhj8f7eDl3RsFRUa2lksKybesVw7ZDebC+5q2jrBGPFFfJmbu+GjNexWIy 24glk4TZk1Odi15HPznhCyxZn55n0fX1pSXWxPHxJ1Eu2NNBSUXVSehMEEEcfa5/MHBj kKgUXm5doxSlZHXg+rC8Q0SB2nKSFhqXatR9KDcjlm6MRyuTmrSI8njcZCayRqK0nX/b GAf9672oq6WPXvcOoL2n9x3LCd8NHgJTAlvVsfUGd1vrrRvKKfFIYDWc+GMwApJmpNIC Rq0Ig83zwkNx7ZETgvEnO6IZ5A/B8r9iClfzDiotjwj6Ts/kZj4l2prw+ekMRx8RhAhA 7yxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KhE58qswq9YQaCuua4OczfbEB+B23TFmcdxq1bqWWp8=; b=U45wT99zHQD/sjaB9Fh0dphaDXRomF3vyVIRPphajczQKBO94fNh97XHse3YvFXdEl LPLSeWoixa4jS8PvItucibJ8lcb/DCQucnAvhmmBs/164PEN4Gj7ZTelz/0DG97tYayz VxIAFwNjX1UU85V2Vv61WIp3p9gA4QQ4uA6yi8vhAPo+SfKdC5LjCP/ZFjSyqx1sAdS3 0A3wUGyA7MOzEQpMCo3l3OVS3nD15F7Rh5EjCEZBLNGQnZ0lwIFYvFXnZwpOHHt9JOpm 6AyjxRKuK2mc+nVUhLGI9aqWUeZ7Tgn+EbheGUbBepqjDUbueEgKyU4Q8nAcVw3J1Lz2 ui9g== X-Gm-Message-State: AOAM531OjjXdj0YDzwbfvWjBKc8IUkBnKk2oZx8445Ds5WYQip2QDdsS maBsgHfhfesqtTd1q+vC19GrIwZJAAiTxA== X-Google-Smtp-Source: ABdhPJzqJYriTDR2fvXbFDPnFrfRpDWTx1Vt9xZ7A1SqAxapFxR3EV1YeloTTZGioXD+YXtVCu4NUA== X-Received: by 2002:a17:90a:9103:: with SMTP id k3mr1220342pjo.4.1599610631745; Tue, 08 Sep 2020 17:17:11 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Subject: [PATCH 18/43] tcg: Introduce TYPE_CONST temporaries Date: Tue, 8 Sep 2020 17:16:22 -0700 Message-Id: <20200909001647.532249-19-richard.henderson@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200909001647.532249-1-richard.henderson@linaro.org> References: <20200909001647.532249-1-richard.henderson@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1043; envelope-from=richard.henderson@linaro.org; helo=mail-pj1-x1043.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @linaro.org) Content-Type: text/plain; charset="utf-8" These will hold a single constant for the duration of the TB. They are hashed, so that each value has one temp across the TB. Not used yet, this is all infrastructure. Signed-off-by: Richard Henderson --- include/tcg/tcg.h | 24 +++++- tcg/optimize.c | 13 +++- tcg/tcg.c | 195 ++++++++++++++++++++++++++++++++++++---------- 3 files changed, 188 insertions(+), 44 deletions(-) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index f3eca6feb0..aa7b0ba163 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -492,6 +492,8 @@ typedef enum TCGTempKind { TEMP_GLOBAL, /* Temp is in a fixed register. */ TEMP_FIXED, + /* Temp is a fixed constant. */ + TEMP_CONST, } TCGTempKind; =20 typedef struct TCGTemp { @@ -667,6 +669,7 @@ struct TCGContext { QSIMPLEQ_HEAD(, TCGOp) plugin_ops; #endif =20 + GHashTable *const_table[TCG_TYPE_COUNT]; TCGTempSet free_temps[TCG_TYPE_COUNT * 2]; TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */ =20 @@ -683,7 +686,7 @@ struct TCGContext { =20 static inline bool temp_readonly(TCGTemp *ts) { - return ts->kind =3D=3D TEMP_FIXED; + return ts->kind >=3D TEMP_FIXED; } =20 extern TCGContext tcg_init_ctx; @@ -1051,6 +1054,7 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, = TCGOpcode opc); =20 void tcg_optimize(TCGContext *s); =20 +/* Allocate a new temporary and initialize it with a constant. */ TCGv_i32 tcg_const_i32(int32_t val); TCGv_i64 tcg_const_i64(int64_t val); TCGv_i32 tcg_const_local_i32(int32_t val); @@ -1060,6 +1064,24 @@ TCGv_vec tcg_const_ones_vec(TCGType); TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec); TCGv_vec tcg_const_ones_vec_matching(TCGv_vec); =20 +/* + * Locate or create a read-only temporary that is a constant. + * This kind of temporary need not and should not be freed. + */ +TCGTemp *tcg_constant_internal(TCGType type, int64_t val); + +static inline TCGv_i32 tcg_constant_i32(int32_t val) +{ + return temp_tcgv_i32(tcg_constant_internal(TCG_TYPE_I32, val)); +} + +static inline TCGv_i64 tcg_constant_i64(int64_t val) +{ + return temp_tcgv_i64(tcg_constant_internal(TCG_TYPE_I64, val)); +} + +TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val); + #if UINTPTR_MAX =3D=3D UINT32_MAX # define tcg_const_ptr(x) ((TCGv_ptr)tcg_const_i32((intptr_t)(x))) # define tcg_const_local_ptr(x) ((TCGv_ptr)tcg_const_local_i32((intptr_t)= (x))) diff --git a/tcg/optimize.c b/tcg/optimize.c index 33d1fc8f87..c0fd65d2e4 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -99,8 +99,17 @@ static void init_ts_info(TempOptInfo *infos, ts->state_ptr =3D ti; ti->next_copy =3D ts; ti->prev_copy =3D ts; - ti->is_const =3D false; - ti->mask =3D -1; + if (ts->kind =3D=3D TEMP_CONST) { + ti->is_const =3D true; + ti->val =3D ti->mask =3D ts->val; + if (TCG_TARGET_REG_BITS > 32 && ts->type =3D=3D TCG_TYPE_I32) { + /* High bits of a 32-bit quantity are garbage. */ + ti->mask |=3D ~0xffffffffull; + } + } else { + ti->is_const =3D false; + ti->mask =3D -1; + } set_bit(idx, temps_used->l); } } diff --git a/tcg/tcg.c b/tcg/tcg.c index 1650c5a9db..e413bf70d4 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1204,13 +1204,19 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, = TCGv_ptr base, bigendian =3D 1; #endif =20 - if (base_ts->kind !=3D TEMP_FIXED) { + switch (base_ts->kind) { + case TEMP_FIXED: + break; + case TEMP_GLOBAL: /* We do not support double-indirect registers. */ tcg_debug_assert(!base_ts->indirect_reg); base_ts->indirect_base =3D 1; s->nb_indirects +=3D (TCG_TARGET_REG_BITS =3D=3D 32 && type =3D=3D= TCG_TYPE_I64 ? 2 : 1); indirect_reg =3D 1; + break; + default: + g_assert_not_reached(); } =20 if (TCG_TARGET_REG_BITS =3D=3D 32 && type =3D=3D TCG_TYPE_I64) { @@ -1335,6 +1341,11 @@ void tcg_temp_free_internal(TCGTemp *ts) TCGContext *s =3D tcg_ctx; int k, idx; =20 + /* In order to simplify users of tcg_constant_*, silently ignore free.= */ + if (ts->kind =3D=3D TEMP_CONST) { + return; + } + #if defined(CONFIG_DEBUG_TCG) s->temps_in_use--; if (s->temps_in_use < 0) { @@ -1351,6 +1362,60 @@ void tcg_temp_free_internal(TCGTemp *ts) set_bit(idx, s->free_temps[k].l); } =20 +TCGTemp *tcg_constant_internal(TCGType type, int64_t val) +{ + TCGContext *s =3D tcg_ctx; + GHashTable *h =3D s->const_table[type]; + TCGTemp *ts; + + if (h =3D=3D NULL) { + h =3D g_hash_table_new(g_int64_hash, g_int64_equal); + s->const_table[type] =3D h; + } + + ts =3D g_hash_table_lookup(h, &val); + if (ts =3D=3D NULL) { + ts =3D tcg_temp_alloc(s); + + if (TCG_TARGET_REG_BITS =3D=3D 32 && type =3D=3D TCG_TYPE_I64) { + TCGTemp *ts2 =3D tcg_temp_alloc(s); + + ts->base_type =3D TCG_TYPE_I64; + ts->type =3D TCG_TYPE_I32; + ts->kind =3D TEMP_CONST; + ts->temp_allocated =3D 1; + /* + * Retain the full value of the 64-bit constant in the low + * part, so that the hash table works. Actual uses will + * truncate the value to the low part. + */ + ts->val =3D val; + + tcg_debug_assert(ts2 =3D=3D ts + 1); + ts2->base_type =3D TCG_TYPE_I64; + ts2->type =3D TCG_TYPE_I32; + ts2->kind =3D TEMP_CONST; + ts2->temp_allocated =3D 1; + ts2->val =3D val >> 32; + } else { + ts->base_type =3D type; + ts->type =3D type; + ts->kind =3D TEMP_CONST; + ts->temp_allocated =3D 1; + ts->val =3D val; + } + g_hash_table_insert(h, &ts->val, ts); + } + + return ts; +} + +TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val) +{ + val =3D dup_const(vece, val); + return temp_tcgv_vec(tcg_constant_internal(type, val)); +} + TCGv_i32 tcg_const_i32(int32_t val) { TCGv_i32 t0; @@ -1883,6 +1948,9 @@ static void tcg_reg_alloc_start(TCGContext *s) TCGTempVal val =3D TEMP_VAL_MEM; =20 switch (ts->kind) { + case TEMP_CONST: + val =3D TEMP_VAL_CONST; + break; case TEMP_FIXED: val =3D TEMP_VAL_REG; break; @@ -1919,6 +1987,26 @@ static char *tcg_get_arg_str_ptr(TCGContext *s, char= *buf, int buf_size, case TEMP_NORMAL: snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); break; + case TEMP_CONST: + switch (ts->type) { + case TCG_TYPE_I32: + snprintf(buf, buf_size, "$0x%x", (int32_t)ts->val); + break; +#if TCG_TARGET_REG_BITS > 32 + case TCG_TYPE_I64: + snprintf(buf, buf_size, "$0x%" PRIx64, ts->val); + break; +#endif + case TCG_TYPE_V64: + case TCG_TYPE_V128: + case TCG_TYPE_V256: + snprintf(buf, buf_size, "v%d$0x%" PRIx64, + 64 << (ts->type - TCG_TYPE_V64), ts->val); + break; + default: + g_assert_not_reached(); + } + break; } return buf; } @@ -2519,6 +2607,7 @@ static void la_bb_end(TCGContext *s, int ng, int nt) state =3D TS_DEAD | TS_MEM; break; case TEMP_NORMAL: + case TEMP_CONST: state =3D TS_DEAD; break; default: @@ -3172,15 +3261,28 @@ static void temp_load(TCGContext *, TCGTemp *, TCGR= egSet, TCGRegSet, TCGRegSet); mark it free; otherwise mark it dead. */ static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead) { - if (temp_readonly(ts)) { + TCGTempVal new_type; + + switch (ts->kind) { + case TEMP_FIXED: return; + case TEMP_GLOBAL: + case TEMP_LOCAL: + new_type =3D TEMP_VAL_MEM; + break; + case TEMP_NORMAL: + new_type =3D free_or_dead < 0 ? TEMP_VAL_MEM : TEMP_VAL_DEAD; + break; + case TEMP_CONST: + new_type =3D TEMP_VAL_CONST; + break; + default: + g_assert_not_reached(); } if (ts->val_type =3D=3D TEMP_VAL_REG) { s->reg_to_temp[ts->reg] =3D NULL; } - ts->val_type =3D (free_or_dead < 0 - || ts->kind !=3D TEMP_NORMAL - ? TEMP_VAL_MEM : TEMP_VAL_DEAD); + ts->val_type =3D new_type; } =20 /* Mark a temporary as dead. */ @@ -3196,10 +3298,7 @@ static inline void temp_dead(TCGContext *s, TCGTemp = *ts) static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs, TCGRegSet preferred_regs, int free_or_dead) { - if (temp_readonly(ts)) { - return; - } - if (!ts->mem_coherent) { + if (!temp_readonly(ts) && !ts->mem_coherent) { if (!ts->mem_allocated) { temp_allocate_frame(s, ts); } @@ -3417,12 +3516,22 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCG= RegSet allocated_regs) =20 for (i =3D s->nb_globals; i < s->nb_temps; i++) { TCGTemp *ts =3D &s->temps[i]; - if (ts->kind =3D=3D TEMP_LOCAL) { + + switch (ts->kind) { + case TEMP_LOCAL: temp_save(s, ts, allocated_regs); - } else { + break; + case TEMP_NORMAL: /* The liveness analysis already ensures that temps are dead. Keep an tcg_debug_assert for safety. */ tcg_debug_assert(ts->val_type =3D=3D TEMP_VAL_DEAD); + break; + case TEMP_CONST: + /* Similarly, we should have freed any allocated register. */ + tcg_debug_assert(ts->val_type =3D=3D TEMP_VAL_CONST); + break; + default: + g_assert_not_reached(); } } =20 @@ -3715,45 +3824,42 @@ static void tcg_reg_alloc_op(TCGContext *s, const T= CGOp *op) i_preferred_regs =3D o_preferred_regs =3D 0; if (arg_ct->ialias) { o_preferred_regs =3D op->output_pref[arg_ct->alias_index]; - if (ts->kind =3D=3D TEMP_FIXED) { - /* if fixed register, we must allocate a new register - if the alias is not the same register */ - if (arg !=3D op->args[arg_ct->alias_index]) { - goto allocate_in_reg; - } - } else { - /* if the input is aliased to an output and if it is - not dead after the instruction, we must allocate - a new register and move it */ - if (!IS_DEAD_ARG(i)) { - goto allocate_in_reg; - } =20 - /* check if the current register has already been allocated - for another input aliased to an output */ - if (ts->val_type =3D=3D TEMP_VAL_REG) { - int k2, i2; - reg =3D ts->reg; - for (k2 =3D 0 ; k2 < k ; k2++) { - i2 =3D def->args_ct[nb_oargs + k2].sort_index; - if (def->args_ct[i2].ialias && reg =3D=3D new_args= [i2]) { - goto allocate_in_reg; - } + /* + * If the input is readonly, then it cannot also be an + * output and aliased to itself. If the input is not + * dead after the instruction, we must allocate a new + * register and move it. + */ + if (temp_readonly(ts) || !IS_DEAD_ARG(i)) { + goto allocate_in_reg; + } + + /* + * Check if the current register has already been allocated + * for another input aliased to an output. + */ + if (ts->val_type =3D=3D TEMP_VAL_REG) { + reg =3D ts->reg; + for (int k2 =3D 0; k2 < k; k2++) { + int i2 =3D def->args_ct[nb_oargs + k2].sort_index; + if (def->args_ct[i2].ialias && reg =3D=3D new_args[i2]= ) { + goto allocate_in_reg; } } - i_preferred_regs =3D o_preferred_regs; } + i_preferred_regs =3D o_preferred_regs; } =20 temp_load(s, ts, arg_ct->regs, i_allocated_regs, i_preferred_regs); reg =3D ts->reg; =20 - if (tcg_regset_test_reg(arg_ct->regs, reg)) { - /* nothing to do : the constraint is satisfied */ - } else { - allocate_in_reg: - /* allocate a new register matching the constraint=20 - and move the temporary register into it */ + if (!tcg_regset_test_reg(arg_ct->regs, reg)) { + allocate_in_reg: + /* + * Allocate a new register matching the constraint + * and move the temporary register into it. + */ temp_load(s, ts, tcg_target_available_regs[ts->type], i_allocated_regs, 0); reg =3D tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs, @@ -4211,6 +4317,13 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) } #endif =20 + for (i =3D 0; i < TCG_TYPE_COUNT; ++i) { + if (s->const_table[i]) { + g_hash_table_destroy(s->const_table[i]); + s->const_table[i] =3D NULL; + } + } + tcg_reg_alloc_start(s); =20 s->code_buf =3D tb->tc.ptr; --=20 2.25.1