1 /* Scheduler hooks for IA-32 which implement atom+ 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 /* Try to reorder ready list to take advantage of Atom pipelined IMUL 39 execution. It is applied if 40 (1) IMUL instruction is on the top of list; 41 (2) There exists the only producer of independent IMUL instruction in 42 ready list. 43 Return index of IMUL producer if it was found and -1 otherwise. */ 44 static int 45 do_reorder_for_imul (rtx_insn **ready, int n_ready) 46 { 47 rtx_insn *insn; 48 rtx set, insn1, insn2; 49 sd_iterator_def sd_it; 50 dep_t dep; 51 int index = -1; 52 int i; 53 54 if (!TARGET_BONNELL) 55 return index; 56 57 /* Check that IMUL instruction is on the top of ready list. */ 58 insn = ready[n_ready - 1]; 59 set = single_set (insn); 60 if (!set) 61 return index; 62 if (!(GET_CODE (SET_SRC (set)) == MULT 63 && GET_MODE (SET_SRC (set)) == SImode)) 64 return index; 65 66 /* Search for producer of independent IMUL instruction. */ 67 for (i = n_ready - 2; i >= 0; i--) 68 { 69 insn = ready[i]; 70 if (!NONDEBUG_INSN_P (insn)) 71 continue; 72 /* Skip IMUL instruction. */ 73 insn2 = PATTERN (insn); 74 if (GET_CODE (insn2) == PARALLEL) 75 insn2 = XVECEXP (insn2, 0, 0); 76 if (GET_CODE (insn2) == SET 77 && GET_CODE (SET_SRC (insn2)) == MULT 78 && GET_MODE (SET_SRC (insn2)) == SImode) 79 continue; 80 81 FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep) 82 { 83 rtx con; 84 con = DEP_CON (dep); 85 if (!NONDEBUG_INSN_P (con)) 86 continue; 87 insn1 = PATTERN (con); 88 if (GET_CODE (insn1) == PARALLEL) 89 insn1 = XVECEXP (insn1, 0, 0); 90 91 if (GET_CODE (insn1) == SET 92 && GET_CODE (SET_SRC (insn1)) == MULT 93 && GET_MODE (SET_SRC (insn1)) == SImode) 94 { 95 sd_iterator_def sd_it1; 96 dep_t dep1; 97 /* Check if there is no other dependee for IMUL. */ 98 index = i; 99 FOR_EACH_DEP (con, SD_LIST_BACK, sd_it1, dep1) 100 { 101 rtx pro; 102 pro = DEP_PRO (dep1); 103 if (!NONDEBUG_INSN_P (pro)) 104 continue; 105 if (pro != insn) 106 index = -1; 107 } 108 if (index >= 0) 109 break; 110 } 111 } 112 if (index >= 0) 113 break; 114 } 115 return index; 116 } 117 118 /* Try to find the best candidate on the top of ready list if two insns 119 have the same priority - candidate is best if its dependees were 120 scheduled earlier. Applied for Silvermont only. 121 Return true if top 2 insns must be interchanged. */ 122 static bool 123 swap_top_of_ready_list (rtx_insn **ready, int n_ready) 124 { 125 rtx_insn *top = ready[n_ready - 1]; 126 rtx_insn *next = ready[n_ready - 2]; 127 rtx set; 128 sd_iterator_def sd_it; 129 dep_t dep; 130 int clock1 = -1; 131 int clock2 = -1; 132 #define INSN_TICK(INSN) (HID (INSN)->tick) 133 134 if (!TARGET_SILVERMONT && !TARGET_INTEL) 135 return false; 136 137 if (!NONDEBUG_INSN_P (top)) 138 return false; 139 if (!NONJUMP_INSN_P (top)) 140 return false; 141 if (!NONDEBUG_INSN_P (next)) 142 return false; 143 if (!NONJUMP_INSN_P (next)) 144 return false; 145 set = single_set (top); 146 if (!set) 147 return false; 148 set = single_set (next); 149 if (!set) 150 return false; 151 152 if (INSN_PRIORITY_KNOWN (top) && INSN_PRIORITY_KNOWN (next)) 153 { 154 if (INSN_PRIORITY (top) != INSN_PRIORITY (next)) 155 return false; 156 /* Determine winner more precise. */ 157 FOR_EACH_DEP (top, SD_LIST_RES_BACK, sd_it, dep) 158 { 159 rtx pro; 160 pro = DEP_PRO (dep); 161 if (!NONDEBUG_INSN_P (pro)) 162 continue; 163 if (INSN_TICK (pro) > clock1) 164 clock1 = INSN_TICK (pro); 165 } 166 FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep) 167 { 168 rtx pro; 169 pro = DEP_PRO (dep); 170 if (!NONDEBUG_INSN_P (pro)) 171 continue; 172 if (INSN_TICK (pro) > clock2) 173 clock2 = INSN_TICK (pro); 174 } 175 176 if (clock1 == clock2) 177 { 178 /* Determine winner - load must win. */ 179 enum attr_memory memory1, memory2; 180 memory1 = get_attr_memory (top); 181 memory2 = get_attr_memory (next); 182 if (memory2 == MEMORY_LOAD && memory1 != MEMORY_LOAD) 183 return true; 184 } 185 return (bool) (clock2 < clock1); 186 } 187 return false; 188 #undef INSN_TICK 189 } 190 191 /* Perform possible reodering of ready list for Atom/Silvermont only. 192 Return issue rate. */ 193 int 194 ix86_atom_sched_reorder (FILE *dump, int sched_verbose, rtx_insn **ready, 195 int *pn_ready, int clock_var) 196 { 197 int issue_rate = -1; 198 int n_ready = *pn_ready; 199 int i; 200 rtx_insn *insn; 201 int index = -1; 202 203 /* Set up issue rate. */ 204 issue_rate = ix86_issue_rate (); 205 206 /* Do reodering for BONNELL/SILVERMONT only. */ 207 if (!TARGET_BONNELL && !TARGET_SILVERMONT && !TARGET_INTEL) 208 return issue_rate; 209 210 /* Nothing to do if ready list contains only 1 instruction. */ 211 if (n_ready <= 1) 212 return issue_rate; 213 214 /* Do reodering for post-reload scheduler only. */ 215 if (!reload_completed) 216 return issue_rate; 217 218 if ((index = do_reorder_for_imul (ready, n_ready)) >= 0) 219 { 220 if (sched_verbose > 1) 221 fprintf (dump, ";;\tatom sched_reorder: put %d insn on top\n", 222 INSN_UID (ready[index])); 223 224 /* Put IMUL producer (ready[index]) at the top of ready list. */ 225 insn = ready[index]; 226 for (i = index; i < n_ready - 1; i++) 227 ready[i] = ready[i + 1]; 228 ready[n_ready - 1] = insn; 229 return issue_rate; 230 } 231 232 /* Skip selective scheduling since HID is not populated in it. */ 233 if (clock_var != 0 234 && !sel_sched_p () 235 && swap_top_of_ready_list (ready, n_ready)) 236 { 237 if (sched_verbose > 1) 238 fprintf (dump, ";;\tslm sched_reorder: swap %d and %d insns\n", 239 INSN_UID (ready[n_ready - 1]), INSN_UID (ready[n_ready - 2])); 240 /* Swap 2 top elements of ready list. */ 241 insn = ready[n_ready - 1]; 242 ready[n_ready - 1] = ready[n_ready - 2]; 243 ready[n_ready - 2] = insn; 244 } 245 return issue_rate; 246 } 247