This fixes fallout from the PR64164 expander revamp.  On alpha, PARALLEL
hard return values may be modeless, and this confuses the code that
wants to copy the pseudo/s in the returned value to the return hard
regs.

It used to work because PARALLELs and CONCATs used to lead to DECL_RTL
with the same mode, but now we try harder to create a pseudo or MEM with
a reasonable mode.

The solution was as simple as moving down the code that handled mode
differences, so that PARALLELs and CONCATs are handled as they should.
Since AFAICT they don't ever have to deal with mode promotion anyway, we
should be fine with this simple change, that Uroš kindly tested with an
alpha-linux-gnu regstrap.  I tested it myself on x86_64-linux-gnu and
i686-linux-gnu.

Ok to install?


[PR67766] reorder handling of parallels, concats and promoted values in return

From: Alexandre Oliva <aol...@redhat.com>

for  gcc/ChangeLog

        PR middle-end/67766
        * function.c (expand_function_end): Move return value
        promotion past the handling of PARALLELs and CONCATs.
---
 gcc/function.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/gcc/function.c b/gcc/function.c
index e76ba2b..d16d6d8 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5446,18 +5446,6 @@ expand_function_end (void)
                              decl_rtl);
              shift_return_value (GET_MODE (decl_rtl), true, real_decl_rtl);
            }
-         /* If a named return value dumped decl_return to memory, then
-            we may need to re-do the PROMOTE_MODE signed/unsigned
-            extension.  */
-         else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
-           {
-             int unsignedp = TYPE_UNSIGNED (TREE_TYPE (decl_result));
-             promote_function_mode (TREE_TYPE (decl_result),
-                                    GET_MODE (decl_rtl), &unsignedp,
-                                    TREE_TYPE (current_function_decl), 1);
-
-             convert_move (real_decl_rtl, decl_rtl, unsignedp);
-           }
          else if (GET_CODE (real_decl_rtl) == PARALLEL)
            {
              /* If expand_function_start has created a PARALLEL for decl_rtl,
@@ -5488,6 +5476,18 @@ expand_function_end (void)
              emit_move_insn (tmp, decl_rtl);
              emit_move_insn (real_decl_rtl, tmp);
            }
+         /* If a named return value dumped decl_return to memory, then
+            we may need to re-do the PROMOTE_MODE signed/unsigned
+            extension.  */
+         else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
+           {
+             int unsignedp = TYPE_UNSIGNED (TREE_TYPE (decl_result));
+             promote_function_mode (TREE_TYPE (decl_result),
+                                    GET_MODE (decl_rtl), &unsignedp,
+                                    TREE_TYPE (current_function_decl), 1);
+
+             convert_move (real_decl_rtl, decl_rtl, unsignedp);
+           }
          else
            emit_move_insn (real_decl_rtl, decl_rtl);
        }


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

Reply via email to