1 1.1 mrg /* Scheduler hooks for IA-32 which implement atom+ specific logic. 2 1.1 mrg Copyright (C) 1988-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify 7 1.1 mrg it under the terms of the GNU General Public License as published by 8 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg any later version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, 12 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 mrg GNU General Public License for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License 17 1.1 mrg along with GCC; see the file COPYING3. If not see 18 1.1 mrg <http://www.gnu.org/licenses/>. */ 19 1.1 mrg 20 1.1 mrg #define IN_TARGET_CODE 1 21 1.1 mrg 22 1.1 mrg #include "config.h" 23 1.1 mrg #include "system.h" 24 1.1 mrg #include "coretypes.h" 25 1.1 mrg #include "backend.h" 26 1.1 mrg #include "rtl.h" 27 1.1 mrg #include "tree.h" 28 1.1 mrg #include "cfghooks.h" 29 1.1 mrg #include "tm_p.h" 30 1.1 mrg #include "insn-config.h" 31 1.1 mrg #include "insn-attr.h" 32 1.1 mrg #include "recog.h" 33 1.1 mrg #include "target.h" 34 1.1 mrg #include "rtl-iter.h" 35 1.1 mrg #include "regset.h" 36 1.1 mrg #include "sched-int.h" 37 1.1 mrg 38 1.1 mrg /* Try to reorder ready list to take advantage of Atom pipelined IMUL 39 1.1 mrg execution. It is applied if 40 1.1 mrg (1) IMUL instruction is on the top of list; 41 1.1 mrg (2) There exists the only producer of independent IMUL instruction in 42 1.1 mrg ready list. 43 1.1 mrg Return index of IMUL producer if it was found and -1 otherwise. */ 44 1.1 mrg static int 45 1.1 mrg do_reorder_for_imul (rtx_insn **ready, int n_ready) 46 1.1 mrg { 47 1.1 mrg rtx_insn *insn; 48 1.1 mrg rtx set, insn1, insn2; 49 1.1 mrg sd_iterator_def sd_it; 50 1.1 mrg dep_t dep; 51 1.1 mrg int index = -1; 52 1.1 mrg int i; 53 1.1 mrg 54 1.1 mrg if (!TARGET_CPU_P (BONNELL)) 55 1.1 mrg return index; 56 1.1 mrg 57 1.1 mrg /* Check that IMUL instruction is on the top of ready list. */ 58 1.1 mrg insn = ready[n_ready - 1]; 59 1.1 mrg set = single_set (insn); 60 1.1 mrg if (!set) 61 1.1 mrg return index; 62 1.1 mrg if (!(GET_CODE (SET_SRC (set)) == MULT 63 1.1 mrg && GET_MODE (SET_SRC (set)) == SImode)) 64 1.1 mrg return index; 65 1.1 mrg 66 1.1 mrg /* Search for producer of independent IMUL instruction. */ 67 1.1 mrg for (i = n_ready - 2; i >= 0; i--) 68 1.1 mrg { 69 1.1 mrg insn = ready[i]; 70 1.1 mrg if (!NONDEBUG_INSN_P (insn)) 71 1.1 mrg continue; 72 1.1 mrg /* Skip IMUL instruction. */ 73 1.1 mrg insn2 = PATTERN (insn); 74 1.1 mrg if (GET_CODE (insn2) == PARALLEL) 75 1.1 mrg insn2 = XVECEXP (insn2, 0, 0); 76 1.1 mrg if (GET_CODE (insn2) == SET 77 1.1 mrg && GET_CODE (SET_SRC (insn2)) == MULT 78 1.1 mrg && GET_MODE (SET_SRC (insn2)) == SImode) 79 1.1 mrg continue; 80 1.1 mrg 81 1.1 mrg FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep) 82 1.1 mrg { 83 1.1 mrg rtx con; 84 1.1 mrg con = DEP_CON (dep); 85 1.1 mrg if (!NONDEBUG_INSN_P (con)) 86 1.1 mrg continue; 87 1.1 mrg insn1 = PATTERN (con); 88 1.1 mrg if (GET_CODE (insn1) == PARALLEL) 89 1.1 mrg insn1 = XVECEXP (insn1, 0, 0); 90 1.1 mrg 91 1.1 mrg if (GET_CODE (insn1) == SET 92 1.1 mrg && GET_CODE (SET_SRC (insn1)) == MULT 93 1.1 mrg && GET_MODE (SET_SRC (insn1)) == SImode) 94 1.1 mrg { 95 1.1 mrg sd_iterator_def sd_it1; 96 1.1 mrg dep_t dep1; 97 1.1 mrg /* Check if there is no other dependee for IMUL. */ 98 1.1 mrg index = i; 99 1.1 mrg FOR_EACH_DEP (con, SD_LIST_BACK, sd_it1, dep1) 100 1.1 mrg { 101 1.1 mrg rtx pro; 102 1.1 mrg pro = DEP_PRO (dep1); 103 1.1 mrg if (!NONDEBUG_INSN_P (pro)) 104 1.1 mrg continue; 105 1.1 mrg if (pro != insn) 106 1.1 mrg index = -1; 107 1.1 mrg } 108 1.1 mrg if (index >= 0) 109 1.1 mrg break; 110 1.1 mrg } 111 1.1 mrg } 112 1.1 mrg if (index >= 0) 113 1.1 mrg break; 114 1.1 mrg } 115 1.1 mrg return index; 116 1.1 mrg } 117 1.1 mrg 118 1.1 mrg /* Try to find the best candidate on the top of ready list if two insns 119 1.1 mrg have the same priority - candidate is best if its dependees were 120 1.1 mrg scheduled earlier. Applied for Silvermont only. 121 1.1 mrg Return true if top 2 insns must be interchanged. */ 122 1.1 mrg static bool 123 1.1 mrg swap_top_of_ready_list (rtx_insn **ready, int n_ready) 124 1.1 mrg { 125 1.1 mrg rtx_insn *top = ready[n_ready - 1]; 126 1.1 mrg rtx_insn *next = ready[n_ready - 2]; 127 1.1 mrg rtx set; 128 1.1 mrg sd_iterator_def sd_it; 129 1.1 mrg dep_t dep; 130 1.1 mrg int clock1 = -1; 131 1.1 mrg int clock2 = -1; 132 1.1 mrg #define INSN_TICK(INSN) (HID (INSN)->tick) 133 1.1 mrg 134 1.1 mrg if (!TARGET_CPU_P (SILVERMONT) && !TARGET_CPU_P (INTEL)) 135 1.1 mrg return false; 136 1.1 mrg 137 1.1 mrg if (!NONDEBUG_INSN_P (top)) 138 1.1 mrg return false; 139 1.1 mrg if (!NONJUMP_INSN_P (top)) 140 1.1 mrg return false; 141 1.1 mrg if (!NONDEBUG_INSN_P (next)) 142 1.1 mrg return false; 143 1.1 mrg if (!NONJUMP_INSN_P (next)) 144 1.1 mrg return false; 145 1.1 mrg set = single_set (top); 146 1.1 mrg if (!set) 147 1.1 mrg return false; 148 1.1 mrg set = single_set (next); 149 1.1 mrg if (!set) 150 1.1 mrg return false; 151 1.1 mrg 152 1.1 mrg if (INSN_PRIORITY_KNOWN (top) && INSN_PRIORITY_KNOWN (next)) 153 1.1 mrg { 154 1.1 mrg if (INSN_PRIORITY (top) != INSN_PRIORITY (next)) 155 1.1 mrg return false; 156 1.1 mrg /* Determine winner more precise. */ 157 1.1 mrg FOR_EACH_DEP (top, SD_LIST_RES_BACK, sd_it, dep) 158 1.1 mrg { 159 1.1 mrg rtx pro; 160 1.1 mrg pro = DEP_PRO (dep); 161 1.1 mrg if (!NONDEBUG_INSN_P (pro)) 162 1.1 mrg continue; 163 1.1 mrg if (INSN_TICK (pro) > clock1) 164 1.1 mrg clock1 = INSN_TICK (pro); 165 1.1 mrg } 166 1.1 mrg FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep) 167 1.1 mrg { 168 1.1 mrg rtx pro; 169 1.1 mrg pro = DEP_PRO (dep); 170 1.1 mrg if (!NONDEBUG_INSN_P (pro)) 171 1.1 mrg continue; 172 1.1 mrg if (INSN_TICK (pro) > clock2) 173 1.1 mrg clock2 = INSN_TICK (pro); 174 1.1 mrg } 175 1.1 mrg 176 1.1 mrg if (clock1 == clock2) 177 1.1 mrg { 178 1.1 mrg /* Determine winner - load must win. */ 179 1.1 mrg enum attr_memory memory1, memory2; 180 1.1 mrg memory1 = get_attr_memory (top); 181 1.1 mrg memory2 = get_attr_memory (next); 182 1.1 mrg if (memory2 == MEMORY_LOAD && memory1 != MEMORY_LOAD) 183 1.1 mrg return true; 184 1.1 mrg } 185 1.1 mrg return (bool) (clock2 < clock1); 186 1.1 mrg } 187 1.1 mrg return false; 188 1.1 mrg #undef INSN_TICK 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg /* Perform possible reodering of ready list for Atom/Silvermont only. 192 1.1 mrg Return issue rate. */ 193 1.1 mrg int 194 1.1 mrg ix86_atom_sched_reorder (FILE *dump, int sched_verbose, rtx_insn **ready, 195 1.1 mrg int *pn_ready, int clock_var) 196 1.1 mrg { 197 1.1 mrg int issue_rate = -1; 198 1.1 mrg int n_ready = *pn_ready; 199 1.1 mrg int i; 200 1.1 mrg rtx_insn *insn; 201 1.1 mrg int index = -1; 202 1.1 mrg 203 1.1 mrg /* Set up issue rate. */ 204 1.1 mrg issue_rate = ix86_issue_rate (); 205 1.1 mrg 206 1.1 mrg /* Do reodering for BONNELL/SILVERMONT only. */ 207 1.1 mrg if (!TARGET_CPU_P (BONNELL) && !TARGET_CPU_P (SILVERMONT) 208 1.1 mrg && !TARGET_CPU_P (INTEL)) 209 1.1 mrg return issue_rate; 210 1.1 mrg 211 1.1 mrg /* Nothing to do if ready list contains only 1 instruction. */ 212 1.1 mrg if (n_ready <= 1) 213 1.1 mrg return issue_rate; 214 1.1 mrg 215 1.1 mrg /* Do reodering for post-reload scheduler only. */ 216 1.1 mrg if (!reload_completed) 217 1.1 mrg return issue_rate; 218 1.1 mrg 219 1.1 mrg if ((index = do_reorder_for_imul (ready, n_ready)) >= 0) 220 1.1 mrg { 221 1.1 mrg if (sched_verbose > 1) 222 1.1 mrg fprintf (dump, ";;\tatom sched_reorder: put %d insn on top\n", 223 1.1 mrg INSN_UID (ready[index])); 224 1.1 mrg 225 1.1 mrg /* Put IMUL producer (ready[index]) at the top of ready list. */ 226 1.1 mrg insn = ready[index]; 227 1.1 mrg for (i = index; i < n_ready - 1; i++) 228 1.1 mrg ready[i] = ready[i + 1]; 229 1.1 mrg ready[n_ready - 1] = insn; 230 1.1 mrg return issue_rate; 231 1.1 mrg } 232 1.1 mrg 233 1.1 mrg /* Skip selective scheduling since HID is not populated in it. */ 234 1.1 mrg if (clock_var != 0 235 1.1 mrg && !sel_sched_p () 236 1.1 mrg && swap_top_of_ready_list (ready, n_ready)) 237 1.1 mrg { 238 1.1 mrg if (sched_verbose > 1) 239 1.1 mrg fprintf (dump, ";;\tslm sched_reorder: swap %d and %d insns\n", 240 1.1 mrg INSN_UID (ready[n_ready - 1]), INSN_UID (ready[n_ready - 2])); 241 1.1 mrg /* Swap 2 top elements of ready list. */ 242 1.1 mrg insn = ready[n_ready - 1]; 243 1.1 mrg ready[n_ready - 1] = ready[n_ready - 2]; 244 1.1 mrg ready[n_ready - 2] = insn; 245 1.1 mrg } 246 1.1 mrg return issue_rate; 247 1.1 mrg } 248