Hexagon (target/hexagon) Only use branch_taken when packet has multi cof
authorTaylor Simpson <tsimpson@quicinc.com>
Tue, 8 Nov 2022 16:28:59 +0000 (08:28 -0800)
committerTaylor Simpson <tsimpson@quicinc.com>
Fri, 16 Dec 2022 18:10:28 +0000 (10:10 -0800)
When a packet has more than one change-of-flow instruction, only the first
one to branch is considered.  We use the branch_taken variable to keep
track of this.

However, when there is a single cof instruction, we don't need the same
amount of bookkeeping.

We add the pkt_has_multi_cof member to the Packet structure, and pass this
information to the needed functions.

When there is a generated helper function with cof, the generator will
pass this pkt_has_multi_cof as a runtime value.

Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Message-Id: <20221108162906.3166-5-tsimpson@quicinc.com>

target/hexagon/decode.c
target/hexagon/gen_helper_funcs.py
target/hexagon/gen_helper_protos.py
target/hexagon/gen_tcg_funcs.py
target/hexagon/hex_common.py
target/hexagon/insn.h
target/hexagon/macros.h
target/hexagon/op_helper.c
target/hexagon/translate.c

index 6b73b5c60c3dfe239cb8f62bd3c45a4d0085f5f9..041c8de751b4e931d1f4ef169ca225306a06cd33 100644 (file)
@@ -388,6 +388,7 @@ static void decode_set_insn_attr_fields(Packet *pkt)
     uint16_t opcode;
 
     pkt->pkt_has_cof = false;
+    pkt->pkt_has_multi_cof = false;
     pkt->pkt_has_endloop = false;
     pkt->pkt_has_dczeroa = false;
 
@@ -412,13 +413,23 @@ static void decode_set_insn_attr_fields(Packet *pkt)
             }
         }
 
-        pkt->pkt_has_cof |= decode_opcode_can_jump(opcode);
+        if (decode_opcode_can_jump(opcode)) {
+            if (pkt->pkt_has_cof) {
+                pkt->pkt_has_multi_cof = true;
+            }
+            pkt->pkt_has_cof = true;
+        }
 
         pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
 
         pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
 
-        pkt->pkt_has_cof |= pkt->pkt_has_endloop;
+        if (pkt->pkt_has_endloop) {
+            if (pkt->pkt_has_cof) {
+                pkt->pkt_has_multi_cof = true;
+            }
+            pkt->pkt_has_cof = true;
+        }
     }
 }
 
index a446c4538452a6e89cc72f1843411ff9863b642a..c4fc609b31b4caeb295d4e0cc710e3f914d65e1f 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+##  Copyright(c) 2019-2022 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
@@ -238,6 +238,9 @@ def gen_helper_function(f, tag, tagregs, tagimms):
             gen_helper_arg_imm(f,immlett)
             i += 1
 
+        if (hex_common.need_pkt_has_multi_cof(tag)):
+            f.write(", uint32_t pkt_has_multi_cof")
+
         if hex_common.need_slot(tag):
             if i > 0: f.write(", ")
             f.write("uint32_t slot")
index 3b4e993fd17749162456c8d9e4e91e6b6c599612..8c6b36d8d85fcbedf47ab45676098d05c0b9b328 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+##  Copyright(c) 2019-2022 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
@@ -82,6 +82,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         ## Figure out how many arguments the helper will take
         if (numscalarresults == 0):
             def_helper_size = len(regs)+len(imms)+numscalarreadwrite+1
+            if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
@@ -89,6 +90,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
             f.write(', void' )
         else:
             def_helper_size = len(regs)+len(imms)+numscalarreadwrite
+            if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
             if hex_common.need_part1(tag): def_helper_size += 1
             if hex_common.need_slot(tag): def_helper_size += 1
             f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
@@ -126,7 +128,9 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
         for immlett,bits,immshift in imms:
             f.write(", s32")
 
-        ## Add the arguments for the instruction slot and part1 (if needed)
+        ## Add the arguments for the instruction pkt_has_multi_cof, slot and
+        ## part1 (if needed)
+        if hex_common.need_pkt_has_multi_cof(tag): f.write(', i32')
         if hex_common.need_slot(tag): f.write(', i32' )
         if hex_common.need_part1(tag): f.write(' , i32' )
         f.write(')\n')
index ca5fde91ccb6532c2112a4db716ed70165479a98..bd199dcbf1c59638fd5a11afcd515024d89cbfd9 100755 (executable)
@@ -622,6 +622,9 @@ def gen_tcg_func(f, tag, regs, imms):
         ## Generate the call to the helper
         for immlett,bits,immshift in imms:
             gen_helper_decl_imm(f,immlett)
+        if hex_common.need_pkt_has_multi_cof(tag):
+            f.write("    TCGv pkt_has_multi_cof = ")
+            f.write("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof);\n")
         if hex_common.need_part1(tag):
             f.write("    TCGv part1 = tcg_constant_tl(insn->part1);\n")
         if hex_common.need_slot(tag):
@@ -654,6 +657,8 @@ def gen_tcg_func(f, tag, regs, imms):
         for immlett,bits,immshift in imms:
             gen_helper_call_imm(f,immlett)
 
+        if hex_common.need_pkt_has_multi_cof(tag):
+            f.write(", pkt_has_multi_cof")
         if hex_common.need_slot(tag): f.write(", slot")
         if hex_common.need_part1(tag): f.write(", part1" )
         f.write(");\n")
index d9ba7df786cb8bad1d89d06ac9a99af810d3a3cc..f5b58501db7abddc6c8a22d00ef24e6c766880b7 100755 (executable)
@@ -207,6 +207,9 @@ def need_part1(tag):
 def need_ea(tag):
     return re.compile(r"\bEA\b").search(semdict[tag])
 
+def need_pkt_has_multi_cof(tag):
+    return 'A_COF' in attribdict[tag]
+
 def skip_qemu_helper(tag):
     return tag in overrides.keys()
 
index cb92586802070239adb356cb9a477ec2b8f7bfb7..775c4c183da1f811742cbb00dfaa9fbf13c5f33a 100644 (file)
@@ -57,6 +57,7 @@ struct Packet {
 
     /* Pre-decodes about COF */
     bool pkt_has_cof;          /* Has any change-of-flow */
+    bool pkt_has_multi_cof;    /* Has more than one change-of-flow */
     bool pkt_has_endloop;
 
     bool pkt_has_dczeroa;
index 93ee4739a1ac82f535131a66f7f4a1bf5087f825..8fd8123cec91761d36a77299478166e8d34de5d8 100644 (file)
@@ -407,7 +407,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
 
 #define fCHECK_PCALIGN(A)
 
-#define fWRITE_NPC(A) write_new_pc(env, A)
+#define fWRITE_NPC(A) write_new_pc(env, pkt_has_multi_cof != 0, A)
 
 #define fBRANCH(LOC, TYPE)          fWRITE_NPC(LOC)
 #define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
index 085afc32746310dc3de6478e41c8a872ddad347d..84391e25ebb3eabcf1e45028b4da5aa6c4535801 100644 (file)
@@ -104,20 +104,26 @@ static void log_store64(CPUHexagonState *env, target_ulong addr,
     env->mem_log_stores[slot].data64 = val;
 }
 
-static void write_new_pc(CPUHexagonState *env, target_ulong addr)
+static void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof,
+                         target_ulong addr)
 {
     HEX_DEBUG_LOG("write_new_pc(0x" TARGET_FMT_lx ")\n", addr);
 
-    /*
-     * If more than one branch is taken in a packet, only the first one
-     * is actually done.
-     */
-    if (env->branch_taken) {
-        HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
-                      "ignoring the second one\n");
+    if (pkt_has_multi_cof) {
+        /*
+         * If more than one branch is taken in a packet, only the first one
+         * is actually done.
+         */
+        if (env->branch_taken) {
+            HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
+                          "ignoring the second one\n");
+        } else {
+            fCHECK_PCALIGN(addr);
+            env->next_PC = addr;
+            env->branch_taken = 1;
+        }
     } else {
         fCHECK_PCALIGN(addr);
-        env->branch_taken = 1;
         env->next_PC = addr;
     }
 }
index 0940d0f2c17155912facd4634593175cc0de2993..1d872d72b64309c73553f39dbdf5480a0cbbadfc 100644 (file)
@@ -248,7 +248,9 @@ static void gen_start_packet(DisasContext *ctx)
         tcg_gen_movi_tl(hex_slot_cancelled, 0);
     }
     if (pkt->pkt_has_cof) {
-        tcg_gen_movi_tl(hex_branch_taken, 0);
+        if (pkt->pkt_has_multi_cof) {
+            tcg_gen_movi_tl(hex_branch_taken, 0);
+        }
         tcg_gen_movi_tl(hex_next_PC, next_PC);
     }
     if (need_pred_written(pkt)) {