lra-coalesce.c 11.6 KB
Newer Older
1
/* Coalesce spilled pseudos.
2
   Copyright (C) 2010-2019 Free Software Foundation, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
   Contributed by Vladimir Makarov <vmakarov@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.	If not see
<http://www.gnu.org/licenses/>.	 */


/* This file contains a pass making some simple RTL code
   transformations by coalescing pseudos to remove some move insns.

   Spilling pseudos in LRA can create memory-memory moves.  We should
   remove potential memory-memory moves before the next constraint
   pass because the constraint pass will generate additional insns for
   such moves and all these insns will be hard to remove afterwards.

   Here we coalesce only spilled pseudos.  Coalescing non-spilled
   pseudos (with different hard regs) might result in spilling
   additional pseudos because of possible conflicts with other
   non-spilled pseudos and, as a consequence, in more constraint
   passes and even LRA infinite cycling.  Trivial the same hard
   register moves will be removed by subsequent compiler passes.

   We don't coalesce special reload pseudos.  It complicates LRA code
   a lot without visible generated code improvement.

   The pseudo live-ranges are used to find conflicting pseudos during
   coalescing.

   Most frequently executed moves is tried to be coalesced first.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
48
#include "backend.h"
49
#include "rtl.h"
50
#include "predict.h"
51
#include "df.h"
52
#include "insn-config.h"
53
#include "regs.h"
54
#include "memmodel.h"
55
#include "ira.h"
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
#include "recog.h"
#include "lra-int.h"

/* Arrays whose elements represent the first and the next pseudo
   (regno) in the coalesced pseudos group to which given pseudo (its
   regno is the index) belongs.	 The next of the last pseudo in the
   group refers to the first pseudo in the group, in other words the
   group is represented by a cyclic list.  */
static int *first_coalesced_pseudo, *next_coalesced_pseudo;

/* The function is used to sort moves according to their execution
   frequencies.	 */
static int
move_freq_compare_func (const void *v1p, const void *v2p)
{
David Malcolm committed
71 72
  rtx_insn *mv1 = *(rtx_insn * const *) v1p;
  rtx_insn *mv2 = *(rtx_insn * const *) v2p;
73
  int pri1, pri2;
H.J. Lu committed
74

75 76
  pri1 = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv1));
  pri2 = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv2));
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
  if (pri2 - pri1)
    return pri2 - pri1;

  /* If frequencies are equal, sort by moves, so that the results of
     qsort leave nothing to chance.  */
  return (int) INSN_UID (mv1) - (int) INSN_UID (mv2);
}

/* Pseudos which go away after coalescing.  */
static bitmap_head coalesced_pseudos_bitmap;

/* Merge two sets of coalesced pseudos given correspondingly by
   pseudos REGNO1 and REGNO2 (more accurately merging REGNO2 group
   into REGNO1 group).	Set up COALESCED_PSEUDOS_BITMAP.  */
static void
merge_pseudos (int regno1, int regno2)
{
  int regno, first, first2, last, next;

  first = first_coalesced_pseudo[regno1];
  if ((first2 = first_coalesced_pseudo[regno2]) == first)
    return;
  for (last = regno2, regno = next_coalesced_pseudo[regno2];;
       regno = next_coalesced_pseudo[regno])
    {
      first_coalesced_pseudo[regno] = first;
      bitmap_set_bit (&coalesced_pseudos_bitmap, regno);
      if (regno == regno2)
	break;
      last = regno;
    }
  next = next_coalesced_pseudo[first];
  next_coalesced_pseudo[first] = regno2;
  next_coalesced_pseudo[last] = next;
  lra_reg_info[first].live_ranges
    = (lra_merge_live_ranges
       (lra_reg_info[first].live_ranges,
	lra_copy_live_range_list (lra_reg_info[first2].live_ranges)));
115 116
  if (partial_subreg_p (lra_reg_info[first].biggest_mode,
			lra_reg_info[first2].biggest_mode))
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
    lra_reg_info[first].biggest_mode = lra_reg_info[first2].biggest_mode;
}

/* Change pseudos in *LOC on their coalescing group
   representatives.  */
static bool
substitute (rtx *loc)
{
  int i, regno;
  const char *fmt;
  enum rtx_code code;
  bool res;

  if (*loc == NULL_RTX)
    return false;
  code = GET_CODE (*loc);
  if (code == REG)
    {
      regno = REGNO (*loc);
      if (regno < FIRST_PSEUDO_REGISTER
	  || first_coalesced_pseudo[regno] == regno)
	return false;
      *loc = regno_reg_rtx[first_coalesced_pseudo[regno]];
      return true;
    }

  res = false;
  fmt = GET_RTX_FORMAT (code);
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
      if (fmt[i] == 'e')
	{
	  if (substitute (&XEXP (*loc, i)))
	    res = true;
	}
      else if (fmt[i] == 'E')
	{
	  int j;

	  for (j = XVECLEN (*loc, i) - 1; j >= 0; j--)
	    if (substitute (&XVECEXP (*loc, i, j)))
	      res = true;
	}
    }
  return res;
}

David Malcolm committed
164 165 166 167 168 169 170 171 172 173
/* Specialize "substitute" for use on an insn.  This can't change
   the insn ptr, just the contents of the insn.  */

static bool
substitute_within_insn (rtx_insn *insn)
{
  rtx loc = insn;
  return substitute (&loc);
}

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
/* The current iteration (1, 2, ...) of the coalescing pass.  */
int lra_coalesce_iter;

/* Return true if the move involving REGNO1 and REGNO2 is a potential
   memory-memory move.	*/
static bool
mem_move_p (int regno1, int regno2)
{
  return reg_renumber[regno1] < 0 && reg_renumber[regno2] < 0;
}

/* Pseudos used instead of the coalesced pseudos.  */
static bitmap_head used_pseudos_bitmap;

/* Set up USED_PSEUDOS_BITMAP, and update LR_BITMAP (a BB live info
   bitmap).  */
static void
update_live_info (bitmap lr_bitmap)
{
  unsigned int j;
  bitmap_iterator bi;

  bitmap_clear (&used_pseudos_bitmap);
  EXECUTE_IF_AND_IN_BITMAP (&coalesced_pseudos_bitmap, lr_bitmap,
			    FIRST_PSEUDO_REGISTER, j, bi)
    bitmap_set_bit (&used_pseudos_bitmap, first_coalesced_pseudo[j]);
  if (! bitmap_empty_p (&used_pseudos_bitmap))
    {
      bitmap_and_compl_into (lr_bitmap, &coalesced_pseudos_bitmap);
      bitmap_ior_into (lr_bitmap, &used_pseudos_bitmap);
    }
}

Vladimir Makarov committed
207
/* Return true if pseudo REGNO can be potentially coalesced.  */
208
static bool
Vladimir Makarov committed
209
coalescable_pseudo_p (int regno)
210 211
{
  lra_assert (regno >= FIRST_PSEUDO_REGISTER);
Vladimir Makarov committed
212
  return (/* We don't want to coalesce regnos with equivalences, at
213
	     least without updating this info.  */
Vladimir Makarov committed
214
	  ira_reg_equiv[regno].constant == NULL_RTX
215 216 217 218 219 220 221 222 223 224
	  && ira_reg_equiv[regno].memory == NULL_RTX
	  && ira_reg_equiv[regno].invariant == NULL_RTX);
}

/* The major function for aggressive pseudo coalescing of moves only
   if the both pseudos were spilled and not special reload pseudos.  */
bool
lra_coalesce (void)
{
  basic_block bb;
David Malcolm committed
225 226
  rtx_insn *mv, *insn, *next, **sorted_moves;
  rtx set;
Vladimir Makarov committed
227
  int i, mv_num, sregno, dregno;
228 229
  int coalesced_moves;
  int max_regno = max_reg_num ();
Vladimir Makarov committed
230
  bitmap_head involved_insns_bitmap;
231
  
232 233 234 235 236 237 238 239 240 241
  timevar_push (TV_LRA_COALESCE);

  if (lra_dump_file != NULL)
    fprintf (lra_dump_file,
	     "\n********** Pseudos coalescing #%d: **********\n\n",
	     ++lra_coalesce_iter);
  first_coalesced_pseudo = XNEWVEC (int, max_regno);
  next_coalesced_pseudo = XNEWVEC (int, max_regno);
  for (i = 0; i < max_regno; i++)
    first_coalesced_pseudo[i] = next_coalesced_pseudo[i] = i;
David Malcolm committed
242
  sorted_moves = XNEWVEC (rtx_insn *, get_max_uid ());
243 244 245
  mv_num = 0;
  /* Collect moves.  */
  coalesced_moves = 0;
246
  FOR_EACH_BB_FN (bb, cfun)
247 248 249 250 251 252 253 254
    {
      FOR_BB_INSNS_SAFE (bb, insn, next)
	if (INSN_P (insn)
	    && (set = single_set (insn)) != NULL_RTX
	    && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set))
	    && (sregno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER
	    && (dregno = REGNO (SET_DEST (set))) >= FIRST_PSEUDO_REGISTER
	    && mem_move_p (sregno, dregno)
Vladimir Makarov committed
255
	    && coalescable_pseudo_p (sregno) && coalescable_pseudo_p (dregno)
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
	    && ! side_effects_p (set)
	    && !(lra_intersected_live_ranges_p
		 (lra_reg_info[sregno].live_ranges,
		  lra_reg_info[dregno].live_ranges)))
	  sorted_moves[mv_num++] = insn;
    }
  qsort (sorted_moves, mv_num, sizeof (rtx), move_freq_compare_func);
  /* Coalesced copies, most frequently executed first.	*/
  bitmap_initialize (&coalesced_pseudos_bitmap, &reg_obstack);
  bitmap_initialize (&involved_insns_bitmap, &reg_obstack);
  for (i = 0; i < mv_num; i++)
    {
      mv = sorted_moves[i];
      set = single_set (mv);
      lra_assert (set != NULL && REG_P (SET_SRC (set))
		  && REG_P (SET_DEST (set)));
      sregno = REGNO (SET_SRC (set));
      dregno = REGNO (SET_DEST (set));
      if (first_coalesced_pseudo[sregno] == first_coalesced_pseudo[dregno])
	{
	  coalesced_moves++;
	  if (lra_dump_file != NULL)
	    fprintf
	      (lra_dump_file, "      Coalescing move %i:r%d-r%d (freq=%d)\n",
	       INSN_UID (mv), sregno, dregno,
281
	       REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv)));
282 283 284 285 286 287 288 289 290 291 292 293 294
	  /* We updated involved_insns_bitmap when doing the merge.  */
	}
      else if (!(lra_intersected_live_ranges_p
		 (lra_reg_info[first_coalesced_pseudo[sregno]].live_ranges,
		  lra_reg_info[first_coalesced_pseudo[dregno]].live_ranges)))
	{
	  coalesced_moves++;
	  if (lra_dump_file != NULL)
	    fprintf
	      (lra_dump_file,
	       "  Coalescing move %i:r%d(%d)-r%d(%d) (freq=%d)\n",
	       INSN_UID (mv), sregno, ORIGINAL_REGNO (SET_SRC (set)),
	       dregno, ORIGINAL_REGNO (SET_DEST (set)),
295
	       REG_FREQ_FROM_BB (BLOCK_FOR_INSN (mv)));
296 297 298 299 300 301 302 303
	  bitmap_ior_into (&involved_insns_bitmap,
			   &lra_reg_info[sregno].insn_bitmap);
	  bitmap_ior_into (&involved_insns_bitmap,
			   &lra_reg_info[dregno].insn_bitmap);
	  merge_pseudos (sregno, dregno);
	}
    }
  bitmap_initialize (&used_pseudos_bitmap, &reg_obstack);
304
  FOR_EACH_BB_FN (bb, cfun)
305 306 307 308 309 310 311
    {
      update_live_info (df_get_live_in (bb));
      update_live_info (df_get_live_out (bb));
      FOR_BB_INSNS_SAFE (bb, insn, next)
	if (INSN_P (insn)
	    && bitmap_bit_p (&involved_insns_bitmap, INSN_UID (insn)))
	  {
David Malcolm committed
312
	    if (! substitute_within_insn (insn))
313 314 315 316 317 318 319
	      continue;
	    lra_update_insn_regno_info (insn);
	    if ((set = single_set (insn)) != NULL_RTX && set_noop_p (set))
	      {
		/* Coalesced move.  */
		if (lra_dump_file != NULL)
		  fprintf (lra_dump_file, "	 Removing move %i (freq=%d)\n",
320 321
			   INSN_UID (insn),
			   REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)));
322 323 324 325
		lra_set_insn_deleted (insn);
	      }
	  }
    }
326 327
  /* If we have situation after inheritance pass:

328
     r1 <- p1   insn originally setting p1
329 330 331 332 333 334 335 336 337 338 339
     i1 <- r1   setting inheritance i1 from reload r1
       ...
     ... <- ... p2 ... dead p2
     ..
     p1 <- i1
     r2 <- i1
     ...<- ... r2 ...

     And we are coalescing p1 and p2 using p1.  In this case i1 and p1
     should have different values, otherwise they can get the same
     hard reg and this is wrong for insn using p2 before coalescing.
340 341 342 343 344 345
     The situation even can be more complicated when new reload
     pseudos occur after the inheriatnce.  So invalidate the result
     pseudos.  */
  for (i = 0; i < max_regno; i++)
    if (first_coalesced_pseudo[i] == i
	&& first_coalesced_pseudo[i] != next_coalesced_pseudo[i])
346
      {
347
	lra_set_regno_unique_value (i);
348 349
	if (lra_dump_file != NULL)
	  fprintf (lra_dump_file,
350
		   "	 Make unique value for coalescing result r%d\n", i);
351
      }
352 353 354 355 356 357 358 359 360 361 362
  bitmap_clear (&used_pseudos_bitmap);
  bitmap_clear (&involved_insns_bitmap);
  bitmap_clear (&coalesced_pseudos_bitmap);
  if (lra_dump_file != NULL && coalesced_moves != 0)
    fprintf (lra_dump_file, "Coalesced Moves = %d\n", coalesced_moves);
  free (sorted_moves);
  free (next_coalesced_pseudo);
  free (first_coalesced_pseudo);
  timevar_pop (TV_LRA_COALESCE);
  return coalesced_moves != 0;
}