Hexagon (target/hexagon) Analyze reads before writes

We divide gen_analyze_funcs.py into 3 phases
    Declare the operands
    Analyze the register reads
    Analyze the register writes

We also create special versions of ctx_log_*_read for new operands
    Check that the operand is written before the read

This is a precursor to improving the analysis for short-circuiting
the packet semantics in a subsequent commit

Signed-off-by: Taylor Simpson <ltaylorsimpson@gmail.com>
Reviewed-by: Brian Cain <bcain@quicinc.com>
Message-Id: <20240201103340.119081-2-ltaylorsimpson@gmail.com>
Signed-off-by: Brian Cain <bcain@quicinc.com>
This commit is contained in:
Taylor Simpson 2024-02-01 03:33:38 -07:00 committed by Brian Cain
parent 248f6f62df
commit 76eaa97157
4 changed files with 83 additions and 49 deletions

View file

@ -183,10 +183,11 @@ when the override is present.
}
We also generate an analyze_<tag> function for each instruction. Currently,
these functions record the writes to registers by calling ctx_log_*. During
gen_start_packet, we invoke the analyze_<tag> function for each instruction in
the packet, and we mark the implicit writes. After the analysis is performed,
we initialize the result register for each of the predicated assignments.
these functions record the reads and writes to registers by calling ctx_log_*.
During gen_start_packet, we invoke the analyze_<tag> function for each instruction in
the packet, and we mark the implicit writes. The analysis determines if the packet
semantics can be short-circuited. If not, we initialize the result register for each
of the predicated assignments.
In addition to instruction semantics, we use a generator to create the decode
tree. This generation is a four step process.

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
##
## Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
## Copyright(c) 2022-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@ -44,15 +44,25 @@ def gen_analyze_func(f, tag, regs, imms):
f.write(" Insn *insn G_GNUC_UNUSED = ctx->insn;\n")
i = 0
## Analyze all the registers
for regtype, regid in regs:
reg = hex_common.get_register(tag, regtype, regid)
## Declare all the registers
for regno, register in enumerate(regs):
reg_type, reg_id = register
reg = hex_common.get_register(tag, reg_type, reg_id)
reg.decl_reg_num(f, regno)
## Analyze the register reads
for regno, register in enumerate(regs):
reg_type, reg_id = register
reg = hex_common.get_register(tag, reg_type, reg_id)
if reg.is_read():
reg.analyze_read(f, regno)
## Analyze the register writes
for regno, register in enumerate(regs):
reg_type, reg_id = register
reg = hex_common.get_register(tag, reg_type, reg_id)
if reg.is_written():
reg.analyze_write(f, tag, i)
else:
reg.analyze_read(f, i)
i += 1
reg.analyze_write(f, tag, regno)
has_generated_helper = not hex_common.skip_qemu_helper(
tag
@ -89,13 +99,13 @@ def main():
tagimms = hex_common.get_tagimms()
with open(sys.argv[-1], "w") as f:
f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
f.write("#ifndef HEXAGON_ANALYZE_FUNCS_C_INC\n")
f.write("#define HEXAGON_ANALYZE_FUNCS_C_INC\n\n")
for tag in hex_common.tags:
gen_analyze_func(f, tag, tagregs[tag], tagimms[tag])
f.write("#endif /* HEXAGON_TCG_FUNCS_H */\n")
f.write("#endif /* HEXAGON_ANALYZE_FUNCS_C_INC */\n")
if __name__ == "__main__":

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
##
## Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
## Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@ -425,7 +425,6 @@ def log_write(self, f, tag):
gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
@ -438,7 +437,6 @@ def decl_tcg(self, f, tag, regno):
TCGv {self.reg_tcg()} = hex_gpr[{self.reg_num}];
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_reg_read(ctx, {self.reg_num});
"""))
@ -449,9 +447,8 @@ def decl_tcg(self, f, tag, regno):
TCGv {self.reg_tcg()} = get_result_gpr(ctx, insn->regno[{regno}]);
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_reg_read(ctx, {self.reg_num});
ctx_log_reg_read_new(ctx, {self.reg_num});
"""))
class GprReadWrite(Register, Single, ReadWrite):
@ -471,8 +468,11 @@ def log_write(self, f, tag):
f.write(code_fmt(f"""\
gen_log_reg_write(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_reg_read(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
@ -493,7 +493,6 @@ def log_write(self, f, tag):
gen_write_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
ctx_log_reg_write(ctx, {self.reg_num}, {predicated});
@ -511,7 +510,6 @@ def decl_tcg(self, f, tag, regno):
gen_read_ctrl_reg(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_reg_read(ctx, {self.reg_num});
"""))
@ -532,7 +530,6 @@ def idef_arg(self, declared):
declared.append(self.reg_tcg())
declared.append("CS")
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_reg_read(ctx, {self.reg_num});
"""))
@ -548,7 +545,6 @@ def log_write(self, f, tag):
gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_pred_write(ctx, {self.reg_num});
"""))
@ -560,7 +556,6 @@ def decl_tcg(self, f, tag, regno):
TCGv {self.reg_tcg()} = hex_pred[{self.reg_num}];
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_pred_read(ctx, {self.reg_num});
"""))
@ -571,9 +566,8 @@ def decl_tcg(self, f, tag, regno):
TCGv {self.reg_tcg()} = get_result_pred(ctx, insn->regno[{regno}]);
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_pred_read(ctx, {self.reg_num});
ctx_log_pred_read_new(ctx, {self.reg_num});
"""))
class PredReadWrite(Register, Single, ReadWrite):
@ -587,8 +581,11 @@ def log_write(self, f, tag):
f.write(code_fmt(f"""\
gen_log_pred_write(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_pred_read(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_pred_write(ctx, {self.reg_num});
"""))
@ -605,7 +602,6 @@ def log_write(self, f, tag):
gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
@ -621,7 +617,6 @@ def decl_tcg(self, f, tag, regno):
hex_gpr[{self.reg_num} + 1]);
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_reg_read_pair(ctx, {self.reg_num});
"""))
@ -640,8 +635,11 @@ def log_write(self, f, tag):
f.write(code_fmt(f"""\
gen_log_reg_write_pair(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_reg_read_pair(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
@ -663,7 +661,6 @@ def log_write(self, f, tag):
gen_write_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
ctx_log_reg_write_pair(ctx, {self.reg_num}, {predicated});
@ -681,7 +678,6 @@ def decl_tcg(self, f, tag, regno):
gen_read_ctrl_reg_pair(ctx, {self.reg_num}, {self.reg_tcg()});
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_reg_read_pair(ctx, {self.reg_num});
"""))
@ -705,7 +701,6 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
newv = hvx_newv(tag)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
@ -728,7 +723,6 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_vreg_read(ctx, {self.reg_num});
"""))
@ -746,9 +740,8 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_vreg_read(ctx, {self.reg_num});
ctx_log_vreg_read_new(ctx, {self.reg_num});
"""))
class VRegReadWrite(Register, Hvx, ReadWrite):
@ -772,8 +765,11 @@ def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_vreg_read(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
newv = hvx_newv(tag)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
@ -803,8 +799,11 @@ def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMVector *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_vreg_read(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
newv = hvx_newv(tag)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
@ -830,7 +829,6 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
newv = hvx_newv(tag)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
@ -860,7 +858,6 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_vreg_read_pair(ctx, {self.reg_num});
"""))
@ -892,8 +889,11 @@ def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMVectorPair *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_vreg_read_pair(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
newv = hvx_newv(tag)
predicated = "true" if is_predicated(tag) else "false"
f.write(code_fmt(f"""\
@ -919,7 +919,6 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_qreg_write(ctx, {self.reg_num});
"""))
@ -941,7 +940,6 @@ def helper_hvx_desc(self, f):
/* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_qreg_read(ctx, {self.reg_num});
"""))
@ -967,8 +965,11 @@ def helper_hvx_desc(self, f):
f.write(code_fmt(f"""\
/* {self.reg_tcg()} is *(MMQReg *)({self.helper_arg_name()}) */
"""))
def analyze_read(self, f, regno):
f.write(code_fmt(f"""\
ctx_log_qreg_read(ctx, {self.reg_num});
"""))
def analyze_write(self, f, tag, regno):
self.decl_reg_num(f, regno)
f.write(code_fmt(f"""\
ctx_log_qreg_write(ctx, {self.reg_num});
"""))

View file

@ -1,5 +1,5 @@
/*
* Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
* Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -75,6 +75,8 @@ typedef struct DisasContext {
TCGv dczero_addr;
} DisasContext;
bool is_gather_store_insn(DisasContext *ctx);
static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
{
if (!test_bit(pnum, ctx->pregs_written)) {
@ -89,6 +91,12 @@ static inline void ctx_log_pred_read(DisasContext *ctx, int pnum)
set_bit(pnum, ctx->pregs_read);
}
static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum)
{
g_assert(test_bit(pnum, ctx->pregs_written));
set_bit(pnum, ctx->pregs_read);
}
static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
bool is_predicated)
{
@ -120,6 +128,12 @@ static inline void ctx_log_reg_read(DisasContext *ctx, int rnum)
set_bit(rnum, ctx->regs_read);
}
static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum)
{
g_assert(test_bit(rnum, ctx->regs_written));
set_bit(rnum, ctx->regs_read);
}
static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
{
ctx_log_reg_read(ctx, rnum);
@ -171,6 +185,15 @@ static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum)
set_bit(rnum, ctx->vregs_read);
}
static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum)
{
g_assert(is_gather_store_insn(ctx) ||
test_bit(rnum, ctx->vregs_updated) ||
test_bit(rnum, ctx->vregs_select) ||
test_bit(rnum, ctx->vregs_updated_tmp));
set_bit(rnum, ctx->vregs_read);
}
static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum)
{
ctx_log_vreg_read(ctx, rnum ^ 0);
@ -205,7 +228,6 @@ extern TCGv hex_vstore_addr[VSTORES_MAX];
extern TCGv hex_vstore_size[VSTORES_MAX];
extern TCGv hex_vstore_pending[VSTORES_MAX];
bool is_gather_store_insn(DisasContext *ctx);
void process_store(DisasContext *ctx, int slot_num);
FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX, 0, 2)