view gcc/config/i386/x86-tune-sched-core.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
line wrap: on
line source

/* Scheduler hooks for IA-32 which implement bdver1-4 specific logic.
   Copyright (C) 1988-2017 Free Software Foundation, Inc.

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/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "cfghooks.h"
#include "tm_p.h"
#include "insn-config.h"
#include "insn-attr.h"
#include "recog.h"
#include "target.h"
#include "rtl-iter.h"
#include "regset.h"
#include "sched-int.h"


/* Model decoder of Core 2/i7.
   Below hooks for multipass scheduling (see haifa-sched.c:max_issue)
   track the instruction fetch block boundaries and make sure that long
   (9+ bytes) instructions are assigned to D0.  */

/* Maximum length of an insn that can be handled by
   a secondary decoder unit.  '8' for Core 2/i7.  */
static int core2i7_secondary_decoder_max_insn_size;

/* Ifetch block size, i.e., number of bytes decoder reads per cycle.
   '16' for Core 2/i7.  */
static int core2i7_ifetch_block_size;

/* Maximum number of instructions decoder can handle per cycle.
   '6' for Core 2/i7.  */
static int core2i7_ifetch_block_max_insns;

typedef struct ix86_first_cycle_multipass_data_ *
  ix86_first_cycle_multipass_data_t;
typedef const struct ix86_first_cycle_multipass_data_ *
  const_ix86_first_cycle_multipass_data_t;

/* A variable to store target state across calls to max_issue within
   one cycle.  */
static struct ix86_first_cycle_multipass_data_ _ix86_first_cycle_multipass_data,
  *ix86_first_cycle_multipass_data = &_ix86_first_cycle_multipass_data;

/* Initialize DATA.  */
static void
core2i7_first_cycle_multipass_init (void *_data)
{
  ix86_first_cycle_multipass_data_t data
    = (ix86_first_cycle_multipass_data_t) _data;

  data->ifetch_block_len = 0;
  data->ifetch_block_n_insns = 0;
  data->ready_try_change = NULL;
  data->ready_try_change_size = 0;
}

/* Advancing the cycle; reset ifetch block counts.  */
static void
core2i7_dfa_post_advance_cycle (void)
{
  ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data;

  gcc_assert (data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);

  data->ifetch_block_len = 0;
  data->ifetch_block_n_insns = 0;
}

/* Filter out insns from ready_try that the core will not be able to issue
   on current cycle due to decoder.  */
static void
core2i7_first_cycle_multipass_filter_ready_try
(const_ix86_first_cycle_multipass_data_t data,
 signed char *ready_try, int n_ready, bool first_cycle_insn_p)
{
  while (n_ready--)
    {
      rtx_insn *insn;
      int insn_size;

      if (ready_try[n_ready])
	continue;

      insn = get_ready_element (n_ready);
      insn_size = ix86_min_insn_size (insn);

      if (/* If this is a too long an insn for a secondary decoder ...  */
	  (!first_cycle_insn_p
	   && insn_size > core2i7_secondary_decoder_max_insn_size)
	  /* ... or it would not fit into the ifetch block ...  */
	  || data->ifetch_block_len + insn_size > core2i7_ifetch_block_size
	  /* ... or the decoder is full already ...  */
	  || data->ifetch_block_n_insns + 1 > core2i7_ifetch_block_max_insns)
	/* ... mask the insn out.  */
	{
	  ready_try[n_ready] = 1;

	  if (data->ready_try_change)
	    bitmap_set_bit (data->ready_try_change, n_ready);
	}
    }
}

/* Prepare for a new round of multipass lookahead scheduling.  */
static void
core2i7_first_cycle_multipass_begin (void *_data,
				     signed char *ready_try, int n_ready,
				     bool first_cycle_insn_p)
{
  ix86_first_cycle_multipass_data_t data
    = (ix86_first_cycle_multipass_data_t) _data;
  const_ix86_first_cycle_multipass_data_t prev_data
    = ix86_first_cycle_multipass_data;

  /* Restore the state from the end of the previous round.  */
  data->ifetch_block_len = prev_data->ifetch_block_len;
  data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns;

  /* Filter instructions that cannot be issued on current cycle due to
     decoder restrictions.  */
  core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
						  first_cycle_insn_p);
}

/* INSN is being issued in current solution.  Account for its impact on
   the decoder model.  */
static void
core2i7_first_cycle_multipass_issue (void *_data,
				     signed char *ready_try, int n_ready,
				     rtx_insn *insn, const void *_prev_data)
{
  ix86_first_cycle_multipass_data_t data
    = (ix86_first_cycle_multipass_data_t) _data;
  const_ix86_first_cycle_multipass_data_t prev_data
    = (const_ix86_first_cycle_multipass_data_t) _prev_data;

  int insn_size = ix86_min_insn_size (insn);

  data->ifetch_block_len = prev_data->ifetch_block_len + insn_size;
  data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns + 1;
  gcc_assert (data->ifetch_block_len <= core2i7_ifetch_block_size
	      && data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);

  /* Allocate or resize the bitmap for storing INSN's effect on ready_try.  */
  if (!data->ready_try_change)
    {
      data->ready_try_change = sbitmap_alloc (n_ready);
      data->ready_try_change_size = n_ready;
    }
  else if (data->ready_try_change_size < n_ready)
    {
      data->ready_try_change = sbitmap_resize (data->ready_try_change,
					       n_ready, 0);
      data->ready_try_change_size = n_ready;
    }
  bitmap_clear (data->ready_try_change);

  /* Filter out insns from ready_try that the core will not be able to issue
     on current cycle due to decoder.  */
  core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
						  false);
}

/* Revert the effect on ready_try.  */
static void
core2i7_first_cycle_multipass_backtrack (const void *_data,
					 signed char *ready_try,
					 int n_ready ATTRIBUTE_UNUSED)
{
  const_ix86_first_cycle_multipass_data_t data
    = (const_ix86_first_cycle_multipass_data_t) _data;
  unsigned int i = 0;
  sbitmap_iterator sbi;

  gcc_assert (bitmap_last_set_bit (data->ready_try_change) < n_ready);
  EXECUTE_IF_SET_IN_BITMAP (data->ready_try_change, 0, i, sbi)
    {
      ready_try[i] = 0;
    }
}

/* Save the result of multipass lookahead scheduling for the next round.  */
static void
core2i7_first_cycle_multipass_end (const void *_data)
{
  const_ix86_first_cycle_multipass_data_t data
    = (const_ix86_first_cycle_multipass_data_t) _data;
  ix86_first_cycle_multipass_data_t next_data
    = ix86_first_cycle_multipass_data;

  if (data != NULL)
    {
      next_data->ifetch_block_len = data->ifetch_block_len;
      next_data->ifetch_block_n_insns = data->ifetch_block_n_insns;
    }
}

/* Deallocate target data.  */
static void
core2i7_first_cycle_multipass_fini (void *_data)
{
  ix86_first_cycle_multipass_data_t data
    = (ix86_first_cycle_multipass_data_t) _data;

  if (data->ready_try_change)
    {
      sbitmap_free (data->ready_try_change);
      data->ready_try_change = NULL;
      data->ready_try_change_size = 0;
    }
}

void
ix86_core2i7_init_hooks (void)
{
  targetm.sched.dfa_post_advance_cycle
    = core2i7_dfa_post_advance_cycle;
  targetm.sched.first_cycle_multipass_init
    = core2i7_first_cycle_multipass_init;
  targetm.sched.first_cycle_multipass_begin
    = core2i7_first_cycle_multipass_begin;
  targetm.sched.first_cycle_multipass_issue
    = core2i7_first_cycle_multipass_issue;
  targetm.sched.first_cycle_multipass_backtrack
    = core2i7_first_cycle_multipass_backtrack;
  targetm.sched.first_cycle_multipass_end
    = core2i7_first_cycle_multipass_end;
  targetm.sched.first_cycle_multipass_fini
    = core2i7_first_cycle_multipass_fini;

  /* Set decoder parameters.  */
  core2i7_secondary_decoder_max_insn_size = 8;
  core2i7_ifetch_block_size = 16;
  core2i7_ifetch_block_max_insns = 6;
}