qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Hexagon (target/hexagon) Fix predicated assignment to .tmp


From: Taylor Simpson
Subject: [PATCH] Hexagon (target/hexagon) Fix predicated assignment to .tmp
Date: Wed, 28 Sep 2022 19:31:31 -0700

Here is an example of an instruction with a predicated assignment
to a .tmp HVX register
    if (p1) v12.tmp = vmem(%1 + #0)
Note that the .tmp indicates that references to v12 in the same packet
take the result of the load.  However, when the predicate is false,
the value at the start of the packet should be used.

To fix this bug, we preload the temporary with the value from the
HVX register.

Test case added to tests/tcg/hexagon/hvx_misc.c

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
 target/hexagon/translate.h      |  5 +++++
 tests/tcg/hexagon/hvx_misc.c    | 39 +++++++++++++++++++++++++++++++++
 target/hexagon/gen_tcg_funcs.py | 12 ++++++++++
 3 files changed, 56 insertions(+)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index a245172827..1256899dfa 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -83,6 +83,11 @@ static inline bool is_preloaded(DisasContext *ctx, int num)
     return test_bit(num, ctx->regs_written);
 }
 
+static inline bool is_tmp_vreg_preloaded(DisasContext *ctx, int num)
+{
+    return test_bit(num, ctx->vregs_updated_tmp);
+}
+
 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
                              int num, bool alloc_ok);
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index 6e2c9ab3cd..3eb4705fb3 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -541,6 +541,43 @@ static void test_vshuff(void)
     check_output_b(__LINE__, 1);
 }
 
+static void test_load_tmp_predicated(void)
+{
+    void *p0 = buffer0;
+    void *p1 = buffer1;
+    void *pout = output;
+
+    for (int i = 0; i < BUFSIZE; i++) {
+        /*
+         * Load into v12 as .tmp with a false predicate, then
+         * use it in the next packet
+         * Should get old new value within the same packet and
+         * the old value in the next packet
+         */
+        asm("v3 = vmem(%0 + #0)\n\t"
+            "r1 = #1\n\t"
+            "v12 = vsplat(r1)\n\t"
+            "p1 = cmp.gt(r0, r0)\n\t"
+            "{\n\t"
+            "    if (p1) v12.tmp = vmem(%1 + #0)\n\t"
+            "    v4.w = vadd(v12.w, v3.w)\n\t"
+            "}\n\t"
+            "v4.w = vadd(v4.w, v12.w)\n\t"
+            "vmem(%2 + #0) = v4\n\t"
+            : : "r"(p0), "r"(p1), "r"(pout)
+            : "r1", "p1", "v12", "v3", "v4", "v6", "memory");
+        p0 += sizeof(MMVector);
+        p1 += sizeof(MMVector);
+        pout += sizeof(MMVector);
+
+        for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
+            expect[i].w[j] = buffer0[i].w[j] + 2;
+        }
+    }
+
+    check_output_w(__LINE__, BUFSIZE);
+}
+
 int main()
 {
     init_buffers();
@@ -578,6 +615,8 @@ int main()
 
     test_vshuff();
 
+    test_load_tmp_predicated();
+
     puts(err ? "FAIL" : "PASS");
     return err ? 1 : 0;
 }
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index d72c689ad7..0e13fcbe1f 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -169,6 +169,18 @@ def genptr_decl(f, tag, regtype, regid, regno):
             elif (hex_common.is_tmp_result(tag)):
                 f.write("        ctx_tmp_vreg_off(ctx, %s%sN, 1, true);\n" % \
                     (regtype, regid))
+                if ('A_CONDEXEC' in hex_common.attribdict[tag]):
+                    f.write("    if (!is_tmp_vreg_preloaded(ctx, %s)) {\n" % \
+                                     regN)
+                    f.write("        intptr_t src_off =")
+                    f.write(" offsetof(CPUHexagonState, VRegs[%s%sN]);\n"% \
+                                         (regtype, regid))
+                    f.write("        tcg_gen_gvec_mov(MO_64, %s%sV_off,\n" % \
+                                         (regtype, regid))
+                    f.write("                         src_off,\n")
+                    f.write("                         sizeof(MMVector),\n")
+                    f.write("                         sizeof(MMVector));\n")
+                    f.write("    }\n")
             else:
                 f.write("        ctx_future_vreg_off(ctx, %s%sN," % \
                     (regtype, regid))
-- 
2.17.1


reply via email to

[Prev in Thread] Current Thread [Next in Thread]