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

--- Comment #10 from Andreas Krebbel <krebbel at gcc dot gnu.org> ---
We generate the movstrict target operand with gen_lowpart. If the operand for
gen_lowpart is already a paradoxical subreg the two subregs cancel each other
out and we end up with a plain reg. I'm testing the following patch right now.
It falls back to a normal move in that case and fixes the testcase:

diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 5aaf76a9490..d90ec1a6de1 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -6523,6 +6523,14 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
          rtx low_dest = gen_lowpart (smode, dest);
          rtx low_src = gen_lowpart (smode, src);

+         /* In case two subregs cancelled each other out, do a normal
+            move.  */
+         if (!SUBREG_P (low_dest))
+           {
+             emit_move_insn (low_dest, low_src);
+             return true;
+           }
+
          switch (smode)
            {
            case E_QImode: emit_insn (gen_movstrictqi (low_dest, low_src));
return true;

Reply via email to