From: Brian Cain <brian.cain@oss.qualcomm.com>
To: qemu-devel@nongnu.org, peter.maydell@linaro.org
Cc: brian.cain@oss.qualcomm.com, Taylor Simpson <ltaylorsimpson@gmail.com>
Subject: [PULL 2/3] target/hexagon: use TCG_COND_TSTEQ/TSTNE for predicate branches
Date: Fri, 20 Mar 2026 07:50:40 -0700 [thread overview]
Message-ID: <20260320145041.3027130-3-brian.cain@oss.qualcomm.com> (raw)
In-Reply-To: <20260320145041.3027130-1-brian.cain@oss.qualcomm.com>
Replace TCG_COND_EQ/NE comparisons against 0 with TCG_COND_TSTEQ/TSTNE
comparisons against 1 for all predicate-conditional branches. This tests
bit 0 of the predicate register directly, eliminating redundant andi
operations that previously extracted the LSB before the comparison.
For predicate-conditional jumps (jumpt, jumpf, jumptnew, etc.) and
jump-register variants (jumprt, jumprf, etc.), pass the raw predicate
value directly instead of going through fLSBOLD/fLSBNEW extraction.
For callers that produce a 0/1 result via setcond (compare-and-jump,
jumprz, etc.), the TSTEQ/TSTNE test on bit 0 is equivalent to the
previous EQ/NE test against 0.
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
target/hexagon/gen_tcg.h | 94 +++++++++++++++-----------------------
target/hexagon/genptr.c | 32 +++++--------
target/hexagon/translate.c | 2 +-
3 files changed, 50 insertions(+), 78 deletions(-)
diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 45ccd518883..1e0cc3b29a8 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -696,13 +696,13 @@
gen_callr(ctx, RsV)
#define fGEN_TCG_J2_callt(SHORTCODE) \
- gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
+ gen_cond_call(ctx, PuV, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J2_callf(SHORTCODE) \
- gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
+ gen_cond_call(ctx, PuV, TCG_COND_TSTNE, riV)
#define fGEN_TCG_J2_callrt(SHORTCODE) \
- gen_cond_callr(ctx, TCG_COND_EQ, PuV, RsV)
+ gen_cond_callr(ctx, TCG_COND_TSTEQ, PuV, RsV)
#define fGEN_TCG_J2_callrf(SHORTCODE) \
- gen_cond_callr(ctx, TCG_COND_NE, PuV, RsV)
+ gen_cond_callr(ctx, TCG_COND_TSTNE, PuV, RsV)
#define fGEN_TCG_J2_loop0r(SHORTCODE) \
gen_loop0r(ctx, RsV, riV)
@@ -893,21 +893,21 @@
gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_tstbit0_tp0_jump_nt(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J4_tstbit0_tp0_jump_t(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J4_tstbit0_fp0_jump_nt(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTNE, riV)
#define fGEN_TCG_J4_tstbit0_fp0_jump_t(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_TSTNE, riV)
#define fGEN_TCG_J4_tstbit0_tp1_jump_nt(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J4_tstbit0_tp1_jump_t(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J4_tstbit0_fp1_jump_nt(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTNE, riV)
#define fGEN_TCG_J4_tstbit0_fp1_jump_t(SHORTCODE) \
- gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
+ gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_TSTNE, riV)
/* p0 = cmp.eq(r0, #7) */
#define fGEN_TCG_SA1_cmpeqi(SHORTCODE) \
@@ -933,31 +933,24 @@
do { \
TCGv LSB = tcg_temp_new(); \
COND; \
- gen_cond_jump(ctx, TCG_COND_EQ, LSB, riV); \
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, LSB, riV); \
} while (0)
-#define fGEN_TCG_cond_jumpf(COND) \
- do { \
- TCGv LSB = tcg_temp_new(); \
- COND; \
- gen_cond_jump(ctx, TCG_COND_NE, LSB, riV); \
- } while (0)
-
#define fGEN_TCG_J2_jumpt(SHORTCODE) \
- fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, PuV, riV)
#define fGEN_TCG_J2_jumptpt(SHORTCODE) \
- fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, PuV, riV)
#define fGEN_TCG_J2_jumpf(SHORTCODE) \
- fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
+ gen_cond_jump(ctx, TCG_COND_TSTNE, PuV, riV)
#define fGEN_TCG_J2_jumpfpt(SHORTCODE) \
- fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
+ gen_cond_jump(ctx, TCG_COND_TSTNE, PuV, riV)
#define fGEN_TCG_J2_jumptnew(SHORTCODE) \
- fGEN_TCG_cond_jumpt(fLSBNEW(PuN))
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, PuN, riV)
#define fGEN_TCG_J2_jumptnewpt(SHORTCODE) \
- fGEN_TCG_cond_jumpt(fLSBNEW(PuN))
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, PuN, riV)
#define fGEN_TCG_J2_jumpfnewpt(SHORTCODE) \
- fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
+ gen_cond_jump(ctx, TCG_COND_TSTNE, PuN, riV)
#define fGEN_TCG_J2_jumpfnew(SHORTCODE) \
- fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
+ gen_cond_jump(ctx, TCG_COND_TSTNE, PuN, riV)
#define fGEN_TCG_J2_jumprz(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_NE, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprzpt(SHORTCODE) \
@@ -975,35 +968,22 @@
#define fGEN_TCG_J2_jumprltezpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_LE, LSB, RsV, 0))
-#define fGEN_TCG_cond_jumprt(COND) \
- do { \
- TCGv LSB = tcg_temp_new(); \
- COND; \
- gen_cond_jumpr(ctx, RsV, TCG_COND_EQ, LSB); \
- } while (0)
-#define fGEN_TCG_cond_jumprf(COND) \
- do { \
- TCGv LSB = tcg_temp_new(); \
- COND; \
- gen_cond_jumpr(ctx, RsV, TCG_COND_NE, LSB); \
- } while (0)
-
#define fGEN_TCG_J2_jumprt(SHORTCODE) \
- fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuV)
#define fGEN_TCG_J2_jumprtpt(SHORTCODE) \
- fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuV)
#define fGEN_TCG_J2_jumprf(SHORTCODE) \
- fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuV)
#define fGEN_TCG_J2_jumprfpt(SHORTCODE) \
- fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuV)
#define fGEN_TCG_J2_jumprtnew(SHORTCODE) \
- fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuN)
#define fGEN_TCG_J2_jumprtnewpt(SHORTCODE) \
- fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTEQ, PuN)
#define fGEN_TCG_J2_jumprfnew(SHORTCODE) \
- fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuN)
#define fGEN_TCG_J2_jumprfnewpt(SHORTCODE) \
- fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
+ gen_cond_jumpr(ctx, RsV, TCG_COND_TSTNE, PuN)
/*
* New value compare & jump instructions
@@ -1101,13 +1081,13 @@
gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, -1, riV)
#define fGEN_TCG_J4_tstbit0_t_jumpnv_t(SHORTCODE) \
- gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
+ gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J4_tstbit0_t_jumpnv_nt(SHORTCODE) \
- gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
+ gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTEQ, riV)
#define fGEN_TCG_J4_tstbit0_f_jumpnv_t(SHORTCODE) \
- gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
+ gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTNE, riV)
#define fGEN_TCG_J4_tstbit0_f_jumpnv_nt(SHORTCODE) \
- gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
+ gen_testbit0_jumpnv(ctx, NsN, TCG_COND_TSTNE, riV)
/* r0 = r1 ; jump address */
#define fGEN_TCG_J4_jumpsetr(SHORTCODE) \
@@ -1150,14 +1130,14 @@
gen_jumpr(ctx, hex_gpr[HEX_REG_LR])
#define fGEN_TCG_SL2_jumpr31_t(SHORTCODE) \
- gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_pred[0])
+ gen_cond_jumpr31(ctx, TCG_COND_TSTEQ, hex_pred[0])
#define fGEN_TCG_SL2_jumpr31_f(SHORTCODE) \
- gen_cond_jumpr31(ctx, TCG_COND_NE, hex_pred[0])
+ gen_cond_jumpr31(ctx, TCG_COND_TSTNE, hex_pred[0])
#define fGEN_TCG_SL2_jumpr31_tnew(SHORTCODE) \
- gen_cond_jumpr31(ctx, TCG_COND_EQ, ctx->new_pred_value[0])
+ gen_cond_jumpr31(ctx, TCG_COND_TSTEQ, ctx->new_pred_value[0])
#define fGEN_TCG_SL2_jumpr31_fnew(SHORTCODE) \
- gen_cond_jumpr31(ctx, TCG_COND_NE, ctx->new_pred_value[0])
+ gen_cond_jumpr31(ctx, TCG_COND_TSTNE, ctx->new_pred_value[0])
/* Count trailing zeros/ones */
#define fGEN_TCG_S2_ct0(SHORTCODE) \
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 9eb21da6f3e..c7b9436c8d4 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -455,7 +455,7 @@ static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
TCGLabel *pred_false = NULL;
if (cond != TCG_COND_ALWAYS) {
pred_false = gen_new_label();
- tcg_gen_brcondi_tl(cond, pred, 0, pred_false);
+ tcg_gen_brcondi_tl(cond, pred, 1, pred_false);
}
if (ctx->pkt->pkt_has_multi_cof) {
@@ -579,9 +579,7 @@ static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
static void gen_cond_jumpr31(DisasContext *ctx, TCGCond cond, TCGv pred)
{
- TCGv LSB = tcg_temp_new();
- tcg_gen_andi_tl(LSB, pred, 1);
- gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, LSB);
+ gen_cond_jumpr(ctx, hex_gpr[HEX_REG_LR], cond, pred);
}
static void gen_cond_jump(DisasContext *ctx, TCGCond cond, TCGv pred,
@@ -609,14 +607,14 @@ static void gen_cmpnd_cmp_jmp_t(DisasContext *ctx,
int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
int pc_off)
{
- gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_EQ, pc_off);
+ gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_TSTEQ, pc_off);
}
static void gen_cmpnd_cmp_jmp_f(DisasContext *ctx,
int pnum, TCGCond cond, TCGv arg1, TCGv arg2,
int pc_off)
{
- gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_NE, pc_off);
+ gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, arg2, TCG_COND_TSTNE, pc_off);
}
static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
@@ -624,7 +622,7 @@ static void gen_cmpnd_cmpi_jmp_t(DisasContext *ctx,
int pc_off)
{
TCGv tmp = tcg_constant_tl(arg2);
- gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_EQ, pc_off);
+ gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_TSTEQ, pc_off);
}
static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
@@ -632,7 +630,7 @@ static void gen_cmpnd_cmpi_jmp_f(DisasContext *ctx,
int pc_off)
{
TCGv tmp = tcg_constant_tl(arg2);
- gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_NE, pc_off);
+ gen_cmpnd_cmp_jmp(ctx, pnum, cond, arg1, tmp, TCG_COND_TSTNE, pc_off);
}
static void gen_cmpnd_cmp_n1_jmp_t(DisasContext *ctx, int pnum, TCGCond cond,
@@ -665,9 +663,7 @@ static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
static void gen_testbit0_jumpnv(DisasContext *ctx,
TCGv arg, TCGCond cond, int pc_off)
{
- TCGv pred = tcg_temp_new();
- tcg_gen_andi_tl(pred, arg, 1);
- gen_cond_jump(ctx, cond, pred, pc_off);
+ gen_cond_jump(ctx, cond, arg, pc_off);
}
static void gen_jump(DisasContext *ctx, int pc_off)
@@ -698,11 +694,9 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
TCGCond cond, int pc_off)
{
TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
- TCGv lsb = tcg_temp_new();
TCGLabel *skip = gen_new_label();
- tcg_gen_andi_tl(lsb, pred, 1);
- gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
- tcg_gen_brcondi_tl(cond, lsb, 0, skip);
+ gen_write_new_pc_pcrel(ctx, pc_off, cond, pred);
+ tcg_gen_brcondi_tl(cond, pred, 1, skip);
tcg_gen_movi_tl(lr, ctx->next_PC);
gen_set_label(skip);
}
@@ -710,10 +704,8 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
static void gen_cond_callr(DisasContext *ctx,
TCGCond cond, TCGv pred, TCGv new_pc)
{
- TCGv lsb = tcg_temp_new();
TCGLabel *skip = gen_new_label();
- tcg_gen_andi_tl(lsb, pred, 1);
- tcg_gen_brcondi_tl(cond, lsb, 0, skip);
+ tcg_gen_brcondi_tl(cond, pred, 1, skip);
gen_callr(ctx, new_pc);
gen_set_label(skip);
}
@@ -955,7 +947,7 @@ static void gen_cmp_jumpnv(DisasContext *ctx,
{
TCGv pred = tcg_temp_new();
tcg_gen_setcond_tl(cond, pred, val, src);
- gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, pred, pc_off);
}
static void gen_cmpi_jumpnv(DisasContext *ctx,
@@ -963,7 +955,7 @@ static void gen_cmpi_jumpnv(DisasContext *ctx,
{
TCGv pred = tcg_temp_new();
tcg_gen_setcondi_tl(cond, pred, val, src);
- gen_cond_jump(ctx, TCG_COND_EQ, pred, pc_off);
+ gen_cond_jump(ctx, TCG_COND_TSTEQ, pred, pc_off);
}
/* Shift left with saturation */
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 8a223f6e13e..633401451d8 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -163,7 +163,7 @@ static void gen_end_tb(DisasContext *ctx)
if (ctx->branch_cond != TCG_COND_NEVER) {
if (ctx->branch_cond != TCG_COND_ALWAYS) {
TCGLabel *skip = gen_new_label();
- tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 0, skip);
+ tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 1, skip);
gen_goto_tb(ctx, 0, ctx->branch_dest, true);
gen_set_label(skip);
gen_goto_tb(ctx, 1, ctx->next_PC, false);
--
2.34.1
next prev parent reply other threads:[~2026-03-20 14:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-20 14:50 [PULL 0/3] hex queue Brian Cain
2026-03-20 14:50 ` [PULL 1/3] target/hexagon: fix J2_jumptnew/pt predicate check to use LSB Brian Cain
2026-03-20 14:50 ` Brian Cain [this message]
2026-03-20 14:50 ` [PULL 3/3] tests/tcg/hexagon: add test for predicated .new branch LSB evaluation Brian Cain
2026-03-23 12:42 ` [PULL 0/3] hex queue Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260320145041.3027130-3-brian.cain@oss.qualcomm.com \
--to=brian.cain@oss.qualcomm.com \
--cc=ltaylorsimpson@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.