Hexagon (target/hexagon) decide if pred has been written at TCG gen time
Multiple writes to the same preg are and'ed together. Rather than generating a runtime check, we can determine at TCG generation time if the predicate has previously been written in the packet. Test added to tests/tcg/hexagon/misc.c Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Taylor Simpson <tsimpson@quicinc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <1617930474-31979-7-git-send-email-tsimpson@quicinc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
743debbc37
commit
6c677c60ae
@ -316,7 +316,7 @@ def genptr_dst_write(f, tag, regtype, regid):
|
|||||||
print("Bad register parse: ", regtype, regid)
|
print("Bad register parse: ", regtype, regid)
|
||||||
elif (regtype == "P"):
|
elif (regtype == "P"):
|
||||||
if (regid in {"d", "e", "x"}):
|
if (regid in {"d", "e", "x"}):
|
||||||
f.write(" gen_log_pred_write(%s%sN, %s%sV);\n" % \
|
f.write(" gen_log_pred_write(ctx, %s%sN, %s%sV);\n" % \
|
||||||
(regtype, regid, regtype, regid))
|
(regtype, regid, regtype, regid))
|
||||||
f.write(" ctx_log_pred_write(ctx, %s%sN);\n" % \
|
f.write(" ctx_log_pred_write(ctx, %s%sN);\n" % \
|
||||||
(regtype, regid))
|
(regtype, regid))
|
||||||
|
@ -119,20 +119,28 @@ static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_log_pred_write(int pnum, TCGv val)
|
static inline void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
|
||||||
{
|
{
|
||||||
TCGv zero = tcg_const_tl(0);
|
TCGv zero = tcg_const_tl(0);
|
||||||
TCGv base_val = tcg_temp_new();
|
TCGv base_val = tcg_temp_new();
|
||||||
TCGv and_val = tcg_temp_new();
|
TCGv and_val = tcg_temp_new();
|
||||||
TCGv pred_written = tcg_temp_new();
|
TCGv pred_written = tcg_temp_new();
|
||||||
|
|
||||||
/* Multiple writes to the same preg are and'ed together */
|
|
||||||
tcg_gen_andi_tl(base_val, val, 0xff);
|
tcg_gen_andi_tl(base_val, val, 0xff);
|
||||||
tcg_gen_and_tl(and_val, base_val, hex_new_pred_value[pnum]);
|
|
||||||
tcg_gen_andi_tl(pred_written, hex_pred_written, 1 << pnum);
|
/*
|
||||||
tcg_gen_movcond_tl(TCG_COND_NE, hex_new_pred_value[pnum],
|
* Section 6.1.3 of the Hexagon V67 Programmer's Reference Manual
|
||||||
pred_written, zero,
|
*
|
||||||
and_val, base_val);
|
* Multiple writes to the same preg are and'ed together
|
||||||
|
* If this is the first predicate write in the packet, do a
|
||||||
|
* straight assignment. Otherwise, do an and.
|
||||||
|
*/
|
||||||
|
if (!test_bit(pnum, ctx->pregs_written)) {
|
||||||
|
tcg_gen_mov_tl(hex_new_pred_value[pnum], base_val);
|
||||||
|
} else {
|
||||||
|
tcg_gen_and_tl(hex_new_pred_value[pnum],
|
||||||
|
hex_new_pred_value[pnum], base_val);
|
||||||
|
}
|
||||||
tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
|
tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
|
||||||
|
|
||||||
tcg_temp_free(zero);
|
tcg_temp_free(zero);
|
||||||
|
@ -172,6 +172,7 @@ static void gen_start_packet(DisasContext *ctx, Packet *pkt)
|
|||||||
ctx->reg_log_idx = 0;
|
ctx->reg_log_idx = 0;
|
||||||
bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
|
bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
|
||||||
ctx->preg_log_idx = 0;
|
ctx->preg_log_idx = 0;
|
||||||
|
bitmap_zero(ctx->pregs_written, NUM_PREGS);
|
||||||
for (i = 0; i < STORES_MAX; i++) {
|
for (i = 0; i < STORES_MAX; i++) {
|
||||||
ctx->store_width[i] = 0;
|
ctx->store_width[i] = 0;
|
||||||
}
|
}
|
||||||
@ -226,7 +227,7 @@ static void mark_implicit_pred_write(DisasContext *ctx, Insn *insn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_implicit_writes(DisasContext *ctx, Insn *insn)
|
static void mark_implicit_reg_writes(DisasContext *ctx, Insn *insn)
|
||||||
{
|
{
|
||||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_FP, HEX_REG_FP);
|
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_FP, HEX_REG_FP);
|
||||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SP, HEX_REG_SP);
|
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SP, HEX_REG_SP);
|
||||||
@ -235,7 +236,10 @@ static void mark_implicit_writes(DisasContext *ctx, Insn *insn)
|
|||||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
|
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
|
||||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
|
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
|
||||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
|
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_implicit_pred_writes(DisasContext *ctx, Insn *insn)
|
||||||
|
{
|
||||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P0, 0);
|
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P0, 0);
|
||||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P1, 1);
|
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P1, 1);
|
||||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P2, 2);
|
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P2, 2);
|
||||||
@ -246,8 +250,9 @@ static void gen_insn(CPUHexagonState *env, DisasContext *ctx,
|
|||||||
Insn *insn, Packet *pkt)
|
Insn *insn, Packet *pkt)
|
||||||
{
|
{
|
||||||
if (insn->generate) {
|
if (insn->generate) {
|
||||||
mark_implicit_writes(ctx, insn);
|
mark_implicit_reg_writes(ctx, insn);
|
||||||
insn->generate(env, ctx, insn, pkt);
|
insn->generate(env, ctx, insn, pkt);
|
||||||
|
mark_implicit_pred_writes(ctx, insn);
|
||||||
} else {
|
} else {
|
||||||
gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE);
|
gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ typedef struct DisasContext {
|
|||||||
DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
|
DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
|
||||||
int preg_log[PRED_WRITES_MAX];
|
int preg_log[PRED_WRITES_MAX];
|
||||||
int preg_log_idx;
|
int preg_log_idx;
|
||||||
|
DECLARE_BITMAP(pregs_written, NUM_PREGS);
|
||||||
uint8_t store_width[STORES_MAX];
|
uint8_t store_width[STORES_MAX];
|
||||||
uint8_t s1_store_processed;
|
uint8_t s1_store_processed;
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
@ -60,6 +61,7 @@ static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
|
|||||||
{
|
{
|
||||||
ctx->preg_log[ctx->preg_log_idx] = pnum;
|
ctx->preg_log[ctx->preg_log_idx] = pnum;
|
||||||
ctx->preg_log_idx++;
|
ctx->preg_log_idx++;
|
||||||
|
set_bit(pnum, ctx->pregs_written);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_preloaded(DisasContext *ctx, int num)
|
static inline bool is_preloaded(DisasContext *ctx, int num)
|
||||||
|
@ -264,6 +264,22 @@ static long long creg_pair(int x, int y)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check that predicates are auto-and'ed in a packet */
|
||||||
|
static int auto_and(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
asm ("r5 = #1\n\t"
|
||||||
|
"{\n\t"
|
||||||
|
" p0 = cmp.eq(r1, #1)\n\t"
|
||||||
|
" p0 = cmp.eq(r1, #2)\n\t"
|
||||||
|
"}\n\t"
|
||||||
|
"%0 = p0\n\t"
|
||||||
|
: "=r"(retval)
|
||||||
|
:
|
||||||
|
: "r5", "p0");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -375,6 +391,9 @@ int main()
|
|||||||
res = test_clrtnew(2, 7);
|
res = test_clrtnew(2, 7);
|
||||||
check(res, 7);
|
check(res, 7);
|
||||||
|
|
||||||
|
res = auto_and();
|
||||||
|
check(res, 0);
|
||||||
|
|
||||||
puts(err ? "FAIL" : "PASS");
|
puts(err ? "FAIL" : "PASS");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user