]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/mode-switching.c
[C++] Protect call to copy_attributes_to_builtin (PR91505)
[thirdparty/gcc.git] / gcc / mode-switching.c
index cbcd7365b5952a8992c2e56314708b8bd72d6f59..2ff21a400813f4be4cc2ae2dde651a4f02f40ec4 100644 (file)
@@ -1,5 +1,5 @@
 /* CPU mode switching
-   Copyright (C) 1998-2015 Free Software Foundation, Inc.
+   Copyright (C) 1998-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,20 +21,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "backend.h"
+#include "target.h"
 #include "rtl.h"
+#include "cfghooks.h"
 #include "df.h"
-#include "target.h"
+#include "memmodel.h"
+#include "tm_p.h"
 #include "regs.h"
-#include "flags.h"
-#include "insn-config.h"
-#include "recog.h"
+#include "emit-rtl.h"
 #include "cfgrtl.h"
 #include "cfganal.h"
 #include "lcm.h"
 #include "cfgcleanup.h"
-#include "tm_p.h"
 #include "tree-pass.h"
-#include "emit-rtl.h"
 
 /* We want target macros for the mode switching code to be able to refer
    to instruction attribute values.  */
@@ -249,8 +248,22 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
        gcc_assert (!pre_exit);
        /* If this function returns a value at the end, we have to
           insert the final mode switch before the return value copy
-          to its hard register.  */
-       if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1
+          to its hard register.
+
+          x86 targets use mode-switching infrastructure to
+          conditionally insert vzeroupper instruction at the exit
+          from the function where there is no need to switch the
+          mode before the return value copy.  The vzeroupper insertion
+          pass runs after reload, so use !reload_completed as a stand-in
+          for x86 to skip the search for the return value copy insn.
+
+          N.b.: the code below assumes that the return copy insn
+          immediately precedes its corresponding use insn.  This
+          assumption does not hold after reload, since sched1 pass
+          can schedule the return copy insn away from its
+          corresponding use insn.  */
+       if (!reload_completed
+           && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == 1
            && NONJUMP_INSN_P ((last_insn = BB_END (src_bb)))
            && GET_CODE (PATTERN (last_insn)) == USE
            && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
@@ -362,8 +375,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
                    if (!targetm.calls.function_value_regno_p (copy_start))
                      copy_num = 0;
                    else
-                     copy_num
-                       = hard_regno_nregs[copy_start][GET_MODE (copy_reg)];
+                     copy_num = hard_regno_nregs (copy_start,
+                                                  GET_MODE (copy_reg));
 
                    /* If the return register is not likely spilled, - as is
                       the case for floating point on SH4 - then it might
@@ -441,8 +454,7 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
                        || short_block
                        || !(targetm.class_likely_spilled_p
                             (REGNO_REG_CLASS (ret_start)))
-                       || (nregs
-                           != hard_regno_nregs[ret_start][GET_MODE (ret_reg)])
+                       || nregs != REG_NREGS (ret_reg)
                        /* For multi-hard-register floating point
                           values, sometimes the likely-spilled part
                           is ordinarily copied first, then the other
@@ -844,7 +856,10 @@ optimize_mode_switching (void)
     commit_edge_insertions ();
 
   if (targetm.mode_switching.entry && targetm.mode_switching.exit)
-    cleanup_cfg (CLEANUP_NO_INSN_DEL);
+    {
+      free_dominance_info (CDI_DOMINATORS);
+      cleanup_cfg (CLEANUP_NO_INSN_DEL);
+    }
   else if (!need_commit && !emitted)
     return 0;