1 /* Scheduler hooks for IA-32 which implement bdver1-4 specific logic. 2 Copyright (C) 1988-2018 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 GCC is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #define IN_TARGET_CODE 1 21 22 #include "config.h" 23 #include "system.h" 24 #include "coretypes.h" 25 #include "backend.h" 26 #include "rtl.h" 27 #include "tree.h" 28 #include "cfghooks.h" 29 #include "tm_p.h" 30 #include "insn-config.h" 31 #include "insn-attr.h" 32 #include "recog.h" 33 #include "target.h" 34 #include "rtl-iter.h" 35 #include "regset.h" 36 #include "sched-int.h" 37 38 39 /* Model decoder of Core 2/i7. 40 Below hooks for multipass scheduling (see haifa-sched.c:max_issue) 41 track the instruction fetch block boundaries and make sure that long 42 (9+ bytes) instructions are assigned to D0. */ 43 44 /* Maximum length of an insn that can be handled by 45 a secondary decoder unit. '8' for Core 2/i7. */ 46 static int core2i7_secondary_decoder_max_insn_size; 47 48 /* Ifetch block size, i.e., number of bytes decoder reads per cycle. 49 '16' for Core 2/i7. */ 50 static int core2i7_ifetch_block_size; 51 52 /* Maximum number of instructions decoder can handle per cycle. 53 '6' for Core 2/i7. */ 54 static int core2i7_ifetch_block_max_insns; 55 56 typedef struct ix86_first_cycle_multipass_data_ * 57 ix86_first_cycle_multipass_data_t; 58 typedef const struct ix86_first_cycle_multipass_data_ * 59 const_ix86_first_cycle_multipass_data_t; 60 61 /* A variable to store target state across calls to max_issue within 62 one cycle. */ 63 static struct ix86_first_cycle_multipass_data_ _ix86_first_cycle_multipass_data, 64 *ix86_first_cycle_multipass_data = &_ix86_first_cycle_multipass_data; 65 66 /* Initialize DATA. */ 67 static void 68 core2i7_first_cycle_multipass_init (void *_data) 69 { 70 ix86_first_cycle_multipass_data_t data 71 = (ix86_first_cycle_multipass_data_t) _data; 72 73 data->ifetch_block_len = 0; 74 data->ifetch_block_n_insns = 0; 75 data->ready_try_change = NULL; 76 data->ready_try_change_size = 0; 77 } 78 79 /* Advancing the cycle; reset ifetch block counts. */ 80 static void 81 core2i7_dfa_post_advance_cycle (void) 82 { 83 ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data; 84 85 gcc_assert (data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns); 86 87 data->ifetch_block_len = 0; 88 data->ifetch_block_n_insns = 0; 89 } 90 91 /* Filter out insns from ready_try that the core will not be able to issue 92 on current cycle due to decoder. */ 93 static void 94 core2i7_first_cycle_multipass_filter_ready_try 95 (const_ix86_first_cycle_multipass_data_t data, 96 signed char *ready_try, int n_ready, bool first_cycle_insn_p) 97 { 98 while (n_ready--) 99 { 100 rtx_insn *insn; 101 int insn_size; 102 103 if (ready_try[n_ready]) 104 continue; 105 106 insn = get_ready_element (n_ready); 107 insn_size = ix86_min_insn_size (insn); 108 109 if (/* If this is a too long an insn for a secondary decoder ... */ 110 (!first_cycle_insn_p 111 && insn_size > core2i7_secondary_decoder_max_insn_size) 112 /* ... or it would not fit into the ifetch block ... */ 113 || data->ifetch_block_len + insn_size > core2i7_ifetch_block_size 114 /* ... or the decoder is full already ... */ 115 || data->ifetch_block_n_insns + 1 > core2i7_ifetch_block_max_insns) 116 /* ... mask the insn out. */ 117 { 118 ready_try[n_ready] = 1; 119 120 if (data->ready_try_change) 121 bitmap_set_bit (data->ready_try_change, n_ready); 122 } 123 } 124 } 125 126 /* Prepare for a new round of multipass lookahead scheduling. */ 127 static void 128 core2i7_first_cycle_multipass_begin (void *_data, 129 signed char *ready_try, int n_ready, 130 bool first_cycle_insn_p) 131 { 132 ix86_first_cycle_multipass_data_t data 133 = (ix86_first_cycle_multipass_data_t) _data; 134 const_ix86_first_cycle_multipass_data_t prev_data 135 = ix86_first_cycle_multipass_data; 136 137 /* Restore the state from the end of the previous round. */ 138 data->ifetch_block_len = prev_data->ifetch_block_len; 139 data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns; 140 141 /* Filter instructions that cannot be issued on current cycle due to 142 decoder restrictions. */ 143 core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready, 144 first_cycle_insn_p); 145 } 146 147 /* INSN is being issued in current solution. Account for its impact on 148 the decoder model. */ 149 static void 150 core2i7_first_cycle_multipass_issue (void *_data, 151 signed char *ready_try, int n_ready, 152 rtx_insn *insn, const void *_prev_data) 153 { 154 ix86_first_cycle_multipass_data_t data 155 = (ix86_first_cycle_multipass_data_t) _data; 156 const_ix86_first_cycle_multipass_data_t prev_data 157 = (const_ix86_first_cycle_multipass_data_t) _prev_data; 158 159 int insn_size = ix86_min_insn_size (insn); 160 161 data->ifetch_block_len = prev_data->ifetch_block_len + insn_size; 162 data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns + 1; 163 gcc_assert (data->ifetch_block_len <= core2i7_ifetch_block_size 164 && data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns); 165 166 /* Allocate or resize the bitmap for storing INSN's effect on ready_try. */ 167 if (!data->ready_try_change) 168 { 169 data->ready_try_change = sbitmap_alloc (n_ready); 170 data->ready_try_change_size = n_ready; 171 } 172 else if (data->ready_try_change_size < n_ready) 173 { 174 data->ready_try_change = sbitmap_resize (data->ready_try_change, 175 n_ready, 0); 176 data->ready_try_change_size = n_ready; 177 } 178 bitmap_clear (data->ready_try_change); 179 180 /* Filter out insns from ready_try that the core will not be able to issue 181 on current cycle due to decoder. */ 182 core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready, 183 false); 184 } 185 186 /* Revert the effect on ready_try. */ 187 static void 188 core2i7_first_cycle_multipass_backtrack (const void *_data, 189 signed char *ready_try, 190 int n_ready ATTRIBUTE_UNUSED) 191 { 192 const_ix86_first_cycle_multipass_data_t data 193 = (const_ix86_first_cycle_multipass_data_t) _data; 194 unsigned int i = 0; 195 sbitmap_iterator sbi; 196 197 gcc_assert (bitmap_last_set_bit (data->ready_try_change) < n_ready); 198 EXECUTE_IF_SET_IN_BITMAP (data->ready_try_change, 0, i, sbi) 199 { 200 ready_try[i] = 0; 201 } 202 } 203 204 /* Save the result of multipass lookahead scheduling for the next round. */ 205 static void 206 core2i7_first_cycle_multipass_end (const void *_data) 207 { 208 const_ix86_first_cycle_multipass_data_t data 209 = (const_ix86_first_cycle_multipass_data_t) _data; 210 ix86_first_cycle_multipass_data_t next_data 211 = ix86_first_cycle_multipass_data; 212 213 if (data != NULL) 214 { 215 next_data->ifetch_block_len = data->ifetch_block_len; 216 next_data->ifetch_block_n_insns = data->ifetch_block_n_insns; 217 } 218 } 219 220 /* Deallocate target data. */ 221 static void 222 core2i7_first_cycle_multipass_fini (void *_data) 223 { 224 ix86_first_cycle_multipass_data_t data 225 = (ix86_first_cycle_multipass_data_t) _data; 226 227 if (data->ready_try_change) 228 { 229 sbitmap_free (data->ready_try_change); 230 data->ready_try_change = NULL; 231 data->ready_try_change_size = 0; 232 } 233 } 234 235 void 236 ix86_core2i7_init_hooks (void) 237 { 238 targetm.sched.dfa_post_advance_cycle 239 = core2i7_dfa_post_advance_cycle; 240 targetm.sched.first_cycle_multipass_init 241 = core2i7_first_cycle_multipass_init; 242 targetm.sched.first_cycle_multipass_begin 243 = core2i7_first_cycle_multipass_begin; 244 targetm.sched.first_cycle_multipass_issue 245 = core2i7_first_cycle_multipass_issue; 246 targetm.sched.first_cycle_multipass_backtrack 247 = core2i7_first_cycle_multipass_backtrack; 248 targetm.sched.first_cycle_multipass_end 249 = core2i7_first_cycle_multipass_end; 250 targetm.sched.first_cycle_multipass_fini 251 = core2i7_first_cycle_multipass_fini; 252 253 /* Set decoder parameters. */ 254 core2i7_secondary_decoder_max_insn_size = 8; 255 core2i7_ifetch_block_size = 16; 256 core2i7_ifetch_block_max_insns = 6; 257 } 258