https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64833

--- Comment #12 from Kazumoto Kojima <kkojima at gcc dot gnu.org> ---
I could reproduce the problem on trunk with '-DXS_VERSION=\"6.89\" -fwrapv
-fno-strict-aliasing -fopenmp -O2 -fstack-protector-strong -fexceptions -fPIC'
with the cross sh4-unknown-linux-gnu compiler.

It seems that get_attr_length returns 4 instead of 8 which is the correct
length for casesi_worker_2 in find_barrier function for the problematic
situation.  In that case, the casesi_worker_1 insn of which length is 4,
was transformed to casesi_worker_2 and get_attr_length returns the cached
old value which is the length for the original casesi_worker_1.
It looks to be latent in the older compilers, though the PR is a 4.9/5/6
regression formally.
Here is a possible fix:

diff --git a/config/sh/sh.c b/config/sh/sh.c
index 0139095..86cbea7 100644
--- a/config/sh/sh.c
+++ b/config/sh/sh.c
@@ -5261,6 +5261,11 @@ find_barrier (int num_mova, rtx_insn *mova, rtx_insn
*from)
               && GET_CODE (PATTERN (from)) == UNSPEC_VOLATILE
               && XINT (PATTERN (from), 1) == UNSPECV_CONST_END)
        return from;
+      /* get_attr_length might return the length of the original worker
+        for casesi_worker_2.  Get uncached length for it.  */
+      else if (NONJUMP_INSN_P (from)
+              && recog_memoized (from) == CODE_FOR_casesi_worker_2)
+       inc = insn_default_length (from);

       if (BARRIER_P (from))
        {

Reply via email to