]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/lra-remat.c
Fix missed IPA-CP on by-ref argument directly passed through (PR 93429)
[thirdparty/gcc.git] / gcc / lra-remat.c
index f28993e818d1eff2f5742731628b10f0184f7639..72309e52694348a5078a0f5341e3b65342bb8ba8 100644 (file)
@@ -1,5 +1,5 @@
 /* Rematerialize pseudos values.
-   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   Copyright (C) 2014-2020 Free Software Foundation, Inc.
    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
 
 This file is part of GCC.
@@ -65,16 +65,11 @@ along with GCC; see the file COPYING3.      If not see
 #include "recog.h"
 #include "lra.h"
 #include "lra-int.h"
+#include "function-abi.h"
 
 /* Number of candidates for rematerialization.  */
 static unsigned int cands_num;
 
-/* The following is used for representation of call_used_reg_set in
-   form array whose elements are hard register numbers with nonzero bit
-   in CALL_USED_REG_SET. */
-static int call_used_regs_arr_len;
-static int call_used_regs_arr[FIRST_PSEUDO_REGISTER];
-
 /* Bitmap used for different calculations.  */
 static bitmap_head temp_bitmap;
 
@@ -110,8 +105,8 @@ struct cand
 
 /* Vector containing all candidates.  */
 static vec<cand_t> all_cands;
-/* Map: insn -> candidate representing it.  It is null if the insn can
-   not be used for rematerialization.  */
+/* Map: insn -> candidate representing it.  It is null if the insn cannot
+   be used for rematerialization.  */
 static cand_t *insn_to_cand;
 /* A secondary map, for candidates that involve two insns, where the
    second one makes the equivalence.  The candidate must not be used
@@ -124,8 +119,9 @@ static cand_t *regno_cands;
 
 /* Data about basic blocks used for the rematerialization
    sub-pass.  */
-struct remat_bb_data
+class remat_bb_data
 {
+public:
   /* Basic block about which the below data are.  */
   basic_block bb;
   /* Registers changed in the basic block: */
@@ -144,7 +140,7 @@ struct remat_bb_data
 };
 
 /* Array for all BB data.  Indexed by the corresponding BB index.  */
-typedef struct remat_bb_data *remat_bb_data_t;
+typedef class remat_bb_data *remat_bb_data_t;
 
 /* Basic blocks for data flow problems -- all bocks except the special
    ones.  */
@@ -253,7 +249,7 @@ finish_cand_table (void)
 
 \f
 
-/* Return true if X contains memory or some UNSPEC.  We can not just
+/* Return true if X contains memory or some UNSPEC.  We cannot just
    check insn operands as memory or unspec might be not an operand
    itself but contain an operand.  Insn with memory access is not
    profitable for rematerialization.  Rematerialization of UNSPEC
@@ -287,7 +283,7 @@ bad_for_rematerialization_p (rtx x)
   return false;
 }
 
-/* If INSN can not be used for rematerialization, return negative
+/* If INSN cannot be used for rematerialization, return negative
    value.  If INSN can be considered as a candidate for
    rematerialization, return value which is the operand number of the
    pseudo for which the insn can be used for rematerialization.  Here
@@ -306,10 +302,10 @@ operand_to_remat (rtx_insn *insn)
   /* First find a pseudo which can be rematerialized.  */
   for (reg = id->regs; reg != NULL; reg = reg->next)
     {
-      /* True FRAME_POINTER_NEEDED might be because we can not follow
+      /* True FRAME_POINTER_NEEDED might be because we cannot follow
         changing sp offsets, e.g. alloca is used.  If the insn contains
-        stack pointer in such case, we can not rematerialize it as we
-        can not know sp offset at a rematerialization place.  */
+        stack pointer in such case, we cannot rematerialize it as we
+        cannot know sp offset at a rematerialization place.  */
       if (reg->regno == STACK_POINTER_REGNUM && frame_pointer_needed)
        return -1;
       else if (reg->type == OP_OUT && ! reg->subreg_p
@@ -367,8 +363,7 @@ operand_to_remat (rtx_insn *insn)
            if (reg2->type == OP_OUT
                && reg->regno <= reg2->regno
                && (reg2->regno
-                   < (reg->regno
-                      + hard_regno_nregs[reg->regno][reg->biggest_mode])))
+                   < (int) end_hard_regno (reg->biggest_mode, reg->regno)))
              return -1;
       }
   /* Check hard coded insn registers.  */
@@ -510,7 +505,7 @@ create_remat_bb_data (void)
   basic_block bb;
   remat_bb_data_t bb_info;
 
-  remat_bb_data = XNEWVEC (struct remat_bb_data,
+  remat_bb_data = XNEWVEC (class remat_bb_data,
                           last_basic_block_for_fn (cfun));
   FOR_ALL_BB_FN (bb, cfun)
     {
@@ -633,9 +628,12 @@ set_bb_regs (basic_block bb, rtx_insn *insn)
        bitmap_set_bit (&subreg_regs, regno);
     }
   if (CALL_P (insn))
-    for (int i = 0; i < call_used_regs_arr_len; i++)
-      bitmap_set_bit (&get_remat_bb_data (bb)->dead_regs,
-                     call_used_regs_arr[i]);
+    {
+      /* Partially-clobbered registers might still be live.  */
+      HARD_REG_SET clobbers = insn_callee_abi (insn).full_reg_clobbers ();
+      bitmap_ior_into (&get_remat_bb_data (bb)->dead_regs,
+                      bitmap_view<HARD_REG_SET> (clobbers));
+    }
 }
 
 /* Calculate changed_regs and dead_regs for each BB.  */
@@ -668,7 +666,7 @@ reg_overlap_for_remat_p (lra_insn_reg *reg, rtx_insn *insn)
   if (regno >= FIRST_PSEUDO_REGISTER)
     nregs = 1;
   else
-    nregs = hard_regno_nregs[regno][reg->biggest_mode];
+    nregs = hard_regno_nregs (regno, reg->biggest_mode);
 
   struct lra_insn_reg *reg2;
 
@@ -684,10 +682,10 @@ reg_overlap_for_remat_p (lra_insn_reg *reg, rtx_insn *insn)
 
        if (regno2 >= FIRST_PSEUDO_REGISTER && reg_renumber[regno2] >= 0)
          regno2 = reg_renumber[regno2];
-       if (regno >= FIRST_PSEUDO_REGISTER)
+       if (regno2 >= FIRST_PSEUDO_REGISTER)
          nregs2 = 1;
        else
-         nregs2 = hard_regno_nregs[regno2][reg->biggest_mode];
+         nregs2 = hard_regno_nregs (regno2, reg->biggest_mode);
 
        if ((regno2 + nregs2 - 1 >= regno && regno2 < regno + nregs)
            || (regno + nregs - 1 >= regno2 && regno < regno2 + nregs2))
@@ -698,7 +696,7 @@ reg_overlap_for_remat_p (lra_insn_reg *reg, rtx_insn *insn)
 
 /* Return true if a call used register is an input operand of INSN.  */
 static bool
-call_used_input_regno_present_p (rtx_insn *insn)
+call_used_input_regno_present_p (const function_abi &abi, rtx_insn *insn)
 {
   int iter;
   lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
@@ -709,8 +707,9 @@ call_used_input_regno_present_p (rtx_insn *insn)
     for (reg = (iter == 0 ? id->regs : static_id->hard_regs);
         reg != NULL;
         reg = reg->next)
-      if (reg->type == OP_IN && reg->regno <= FIRST_PSEUDO_REGISTER
-         && TEST_HARD_REG_BIT (call_used_reg_set, reg->regno))
+      if (reg->type == OP_IN
+         && reg->regno < FIRST_PSEUDO_REGISTER
+         && abi.clobbers_reg_p (reg->biggest_mode, reg->regno))
        return true;
   return false;
 }
@@ -799,18 +798,21 @@ calculate_gen_cands (void)
                    }
            
            if (CALL_P (insn))
-             EXECUTE_IF_SET_IN_BITMAP (gen_insns, 0, uid, bi)
-               {
-                 rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
+             {
+               function_abi callee_abi = insn_callee_abi (insn);
+               EXECUTE_IF_SET_IN_BITMAP (gen_insns, 0, uid, bi)
+                 {
+                   rtx_insn *insn2 = lra_insn_recog_data[uid]->insn;
                  
-                 cand = insn_to_cand[INSN_UID (insn2)];
-                 gcc_assert (cand != NULL);
-                 if (call_used_input_regno_present_p (insn2))
-                   {
-                     bitmap_clear_bit (gen_cands, cand->index);
-                     bitmap_set_bit (&temp_bitmap, uid);
-                   }
-               }
+                   cand = insn_to_cand[INSN_UID (insn2)];
+                   gcc_assert (cand != NULL);
+                   if (call_used_input_regno_present_p (callee_abi, insn2))
+                     {
+                       bitmap_clear_bit (gen_cands, cand->index);
+                       bitmap_set_bit (&temp_bitmap, uid);
+                     }
+                 }
+             }
            bitmap_and_compl_into (gen_insns, &temp_bitmap);
 
            cand = insn_to_cand[INSN_UID (insn)];
@@ -995,7 +997,7 @@ calculate_global_remat_bb_data (void)
 
 /* Setup sp offset attribute to SP_OFFSET for all INSNS.  */
 static void
-change_sp_offset (rtx_insn *insns, HOST_WIDE_INT sp_offset)
+change_sp_offset (rtx_insn *insns, poly_int64 sp_offset)
 {
   for (rtx_insn *insn = insns; insn != NULL; insn = NEXT_INSN (insn))
     eliminate_regs_in_insn (insn, false, false, sp_offset);
@@ -1012,7 +1014,7 @@ get_hard_regs (struct lra_insn_reg *reg, int &nregs)
   int hard_regno = regno < FIRST_PSEUDO_REGISTER ? regno : reg_renumber[regno];
 
   if (hard_regno >= 0)
-    nregs = hard_regno_nregs[hard_regno][reg->biggest_mode];
+    nregs = hard_regno_nregs (hard_regno, reg->biggest_mode);
   return hard_regno;
 }
 
@@ -1021,7 +1023,6 @@ get_hard_regs (struct lra_insn_reg *reg, int &nregs)
 static void
 update_scratch_ops (rtx_insn *remat_insn)
 {
-  int hard_regno;
   lra_insn_recog_data_t id = lra_get_insn_recog_data (remat_insn);
   struct lra_static_insn_data *static_id = id->insn_static_data;
   for (int i = 0; i < static_id->n_operands; i++)
@@ -1032,18 +1033,10 @@ update_scratch_ops (rtx_insn *remat_insn)
       int regno = REGNO (*loc);
       if (! lra_former_scratch_p (regno))
        continue;
-      hard_regno = reg_renumber[regno];
       *loc = lra_create_new_reg (GET_MODE (*loc), *loc,
                                 lra_get_allocno_class (regno),
                                 "scratch pseudo copy");
-      if (hard_regno >= 0)
-       {
-         reg_renumber[REGNO (*loc)] = hard_regno;
-         if (lra_dump_file)
-           fprintf (lra_dump_file, "    Assigning the same %d to r%d\n",
-                    REGNO (*loc), hard_regno);
-       }
-      lra_register_new_scratch_op (remat_insn, i);
+      lra_register_new_scratch_op (remat_insn, i, id->icode);
     }
   
 }
@@ -1119,7 +1112,7 @@ do_remat (void)
          int i, hard_regno, nregs;
          int dst_hard_regno, dst_nregs;
          rtx_insn *remat_insn = NULL;
-         HOST_WIDE_INT cand_sp_offset = 0;
+         poly_int64 cand_sp_offset = 0;
          if (cand != NULL)
            {
              lra_insn_recog_data_t cand_id
@@ -1136,7 +1129,7 @@ do_remat (void)
                ? dst_regno : reg_renumber[dst_regno];
              gcc_assert (dst_hard_regno >= 0);
              machine_mode mode = GET_MODE (SET_DEST (set));
-             dst_nregs = hard_regno_nregs[dst_hard_regno][mode];
+             dst_nregs = hard_regno_nregs (dst_hard_regno, mode);
 
              for (reg = cand_id->regs; reg != NULL; reg = reg->next)
                if (reg->type != OP_IN && reg->regno != ignore_regno)
@@ -1214,13 +1207,16 @@ do_remat (void)
                  }
 
          if (CALL_P (insn))
-           EXECUTE_IF_SET_IN_BITMAP (avail_cands, 0, cid, bi)
-             {
-               cand = all_cands[cid];
+           {
+             function_abi callee_abi = insn_callee_abi (insn);
+             EXECUTE_IF_SET_IN_BITMAP (avail_cands, 0, cid, bi)
+               {
+                 cand = all_cands[cid];
                
-               if (call_used_input_regno_present_p (cand->insn))
-                 bitmap_set_bit (&temp_bitmap, cand->index);
-             }
+                 if (call_used_input_regno_present_p (callee_abi, cand->insn))
+                   bitmap_set_bit (&temp_bitmap, cand->index);
+               }
+           }
 
          bitmap_and_compl_into (avail_cands, &temp_bitmap);
 
@@ -1242,8 +1238,8 @@ do_remat (void)
 
          if (remat_insn != NULL)
            {
-             HOST_WIDE_INT sp_offset_change = cand_sp_offset - id->sp_offset;
-             if (sp_offset_change != 0)
+             poly_int64 sp_offset_change = cand_sp_offset - id->sp_offset;
+             if (maybe_ne (sp_offset_change, 0))
                change_sp_offset (remat_insn, sp_offset_change);
              update_scratch_ops (remat_insn);
              lra_process_new_insns (insn, remat_insn, NULL,
@@ -1316,10 +1312,6 @@ lra_remat (void)
   insn_to_cand_activation = XCNEWVEC (cand_t, get_max_uid ());
   regno_cands = XCNEWVEC (cand_t, max_regno);
   all_cands.create (8000);
-  call_used_regs_arr_len = 0;
-  for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (call_used_regs[i])
-      call_used_regs_arr[call_used_regs_arr_len++] = i;
   initiate_cand_table ();
   create_remat_bb_data ();
   bitmap_initialize (&temp_bitmap, &reg_obstack);