diff mbox series

[v2,1/3] Hexagon (target/hexagon) Analyze reads before writes

Message ID 20240201103340.119081-2-ltaylorsimpson@gmail.com
State New
Headers show
Series Hexagon (target/hexagon) Enable more short-circuit packets | expand

Commit Message

Taylor Simpson Feb. 1, 2024, 10:33 a.m. UTC
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>
---
 target/hexagon/translate.h          | 26 +++++++++++-
 target/hexagon/README               |  9 +++--
 target/hexagon/gen_analyze_funcs.py | 34 ++++++++++------
 target/hexagon/hex_common.py        | 63 +++++++++++++++--------------
 4 files changed, 83 insertions(+), 49 deletions(-)

Comments

Brian Cain March 29, 2024, 2:05 a.m. UTC | #1
> -----Original Message-----
> From: Taylor Simpson <ltaylorsimpson@gmail.com>
> Sent: Thursday, February 1, 2024 4:34 AM
> To: qemu-devel@nongnu.org
> Cc: Brian Cain <bcain@quicinc.com>; Matheus Bernardino (QUIC)
> <quic_mathbern@quicinc.com>; Sid Manning <sidneym@quicinc.com>;
> Marco Liebel (QUIC) <quic_mliebel@quicinc.com>;
> richard.henderson@linaro.org; philmd@linaro.org; ale@rev.ng; anjo@rev.ng;
> ltaylorsimpson@gmail.com
> Subject: [PATCH v2 1/3] Hexagon (target/hexagon) Analyze reads before
> writes
> 
> WARNING: This email originated from outside of Qualcomm. Please be wary
> of any links or attachments, and do not enable macros.
> 
> 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>
> ---
>  target/hexagon/translate.h          | 26 +++++++++++-
>  target/hexagon/README               |  9 +++--
>  target/hexagon/gen_analyze_funcs.py | 34 ++++++++++------
>  target/hexagon/hex_common.py        | 63 +++++++++++++++--------------
>  4 files changed, 83 insertions(+), 49 deletions(-)
> 
> diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
> index 4dd59c6726..f06d71fc53 100644
> --- a/target/hexagon/translate.h
> +++ b/target/hexagon/translate.h
> @@ -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)
> diff --git a/target/hexagon/README b/target/hexagon/README
> index 746ebec378..c1d8c8d0ab 100644
> --- a/target/hexagon/README
> +++ b/target/hexagon/README
> @@ -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.
> diff --git a/target/hexagon/gen_analyze_funcs.py
> b/target/hexagon/gen_analyze_funcs.py
> index a9af666cef..890e6a3a95 100755
> --- a/target/hexagon/gen_analyze_funcs.py
> +++ b/target/hexagon/gen_analyze_funcs.py
> @@ -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__":
> diff --git a/target/hexagon/hex_common.py
> b/target/hexagon/hex_common.py
> index 195620c7ec..33801e4bd7 100755
> --- a/target/hexagon/hex_common.py
> +++ b/target/hexagon/hex_common.py
> @@ -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});
>          """))
> --
> 2.34.1

Reviewed-by: Brian Cain <bcain@quicinc.com>
diff mbox series

Patch

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 4dd59c6726..f06d71fc53 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -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)
diff --git a/target/hexagon/README b/target/hexagon/README
index 746ebec378..c1d8c8d0ab 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -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.
diff --git a/target/hexagon/gen_analyze_funcs.py b/target/hexagon/gen_analyze_funcs.py
index a9af666cef..890e6a3a95 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -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__":
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 195620c7ec..33801e4bd7 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -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});
         """))