1 /* Generate from machine description: 2 - some #define configuration flags. 3 Copyright (C) 1987-2019 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 22 #include "bconfig.h" 23 #include "system.h" 24 #include "coretypes.h" 25 #include "tm.h" 26 #include "rtl.h" 27 #include "errors.h" 28 #include "gensupport.h" 29 30 31 /* flags to determine output of machine description dependent #define's. */ 32 static int max_recog_operands; /* Largest operand number seen. */ 33 static int max_dup_operands; /* Largest number of match_dup in any insn. */ 34 static int max_clobbers_per_insn; 35 static int have_cc0_flag; 36 static int have_cmove_flag; 37 static int have_cond_exec_flag; 38 static int have_lo_sum_flag; 39 static int have_rotate_flag; 40 static int have_rotatert_flag; 41 static int have_peephole_flag; 42 static int have_peephole2_flag; 43 44 /* Maximum number of insns seen in a split. */ 45 static int max_insns_per_split = 1; 46 47 /* Maximum number of input insns for peephole2. */ 48 static int max_insns_per_peep2; 49 50 static int clobbers_seen_this_insn; 51 static int dup_operands_seen_this_insn; 52 53 static void walk_insn_part (rtx, int, int); 54 55 /* RECOG_P will be nonzero if this pattern was seen in a context where it will 56 be used to recognize, rather than just generate an insn. 57 58 NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC 59 of a SET whose destination is not (pc). */ 60 61 static void 62 walk_insn_part (rtx part, int recog_p, int non_pc_set_src) 63 { 64 int i, j; 65 RTX_CODE code; 66 const char *format_ptr; 67 68 if (part == 0) 69 return; 70 71 code = GET_CODE (part); 72 switch (code) 73 { 74 case CLOBBER: 75 case CLOBBER_HIGH: 76 clobbers_seen_this_insn++; 77 break; 78 79 case MATCH_OPERAND: 80 if (XINT (part, 0) > max_recog_operands) 81 max_recog_operands = XINT (part, 0); 82 return; 83 84 case MATCH_OP_DUP: 85 case MATCH_PAR_DUP: 86 ++dup_operands_seen_this_insn; 87 /* FALLTHRU */ 88 case MATCH_SCRATCH: 89 case MATCH_PARALLEL: 90 case MATCH_OPERATOR: 91 if (XINT (part, 0) > max_recog_operands) 92 max_recog_operands = XINT (part, 0); 93 /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or 94 MATCH_PARALLEL. */ 95 break; 96 97 case LABEL_REF: 98 if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND 99 || GET_CODE (XEXP (part, 0)) == MATCH_DUP) 100 break; 101 return; 102 103 case MATCH_DUP: 104 ++dup_operands_seen_this_insn; 105 if (XINT (part, 0) > max_recog_operands) 106 max_recog_operands = XINT (part, 0); 107 return; 108 109 case CC0: 110 if (recog_p) 111 have_cc0_flag = 1; 112 return; 113 114 case LO_SUM: 115 if (recog_p) 116 have_lo_sum_flag = 1; 117 return; 118 119 case ROTATE: 120 if (recog_p) 121 have_rotate_flag = 1; 122 return; 123 124 case ROTATERT: 125 if (recog_p) 126 have_rotatert_flag = 1; 127 return; 128 129 case SET: 130 walk_insn_part (SET_DEST (part), 0, recog_p); 131 walk_insn_part (SET_SRC (part), recog_p, 132 GET_CODE (SET_DEST (part)) != PC); 133 return; 134 135 case IF_THEN_ELSE: 136 /* Only consider this machine as having a conditional move if the 137 two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, 138 we have some specific IF_THEN_ELSE construct (like the doz 139 instruction on the RS/6000) that can't be used in the general 140 context we want it for. */ 141 142 if (recog_p && non_pc_set_src 143 && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND 144 && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) 145 have_cmove_flag = 1; 146 break; 147 148 case COND_EXEC: 149 if (recog_p) 150 have_cond_exec_flag = 1; 151 break; 152 153 case REG: case CONST_INT: case SYMBOL_REF: 154 case PC: 155 return; 156 157 default: 158 break; 159 } 160 161 format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 162 163 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 164 switch (*format_ptr++) 165 { 166 case 'e': 167 case 'u': 168 walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); 169 break; 170 case 'E': 171 if (XVEC (part, i) != NULL) 172 for (j = 0; j < XVECLEN (part, i); j++) 173 walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); 174 break; 175 } 176 } 177 178 static void 179 gen_insn (md_rtx_info *info) 180 { 181 int i; 182 183 /* Walk the insn pattern to gather the #define's status. */ 184 rtx insn = info->def; 185 clobbers_seen_this_insn = 0; 186 dup_operands_seen_this_insn = 0; 187 if (XVEC (insn, 1) != 0) 188 for (i = 0; i < XVECLEN (insn, 1); i++) 189 walk_insn_part (XVECEXP (insn, 1, i), 1, 0); 190 191 if (clobbers_seen_this_insn > max_clobbers_per_insn) 192 max_clobbers_per_insn = clobbers_seen_this_insn; 193 if (dup_operands_seen_this_insn > max_dup_operands) 194 max_dup_operands = dup_operands_seen_this_insn; 195 } 196 197 /* Similar but scan a define_expand. */ 198 199 static void 200 gen_expand (md_rtx_info *info) 201 { 202 int i; 203 204 /* Walk the insn pattern to gather the #define's status. */ 205 206 /* Note that we don't bother recording the number of MATCH_DUPs 207 that occur in a gen_expand, because only reload cares about that. */ 208 rtx insn = info->def; 209 if (XVEC (insn, 1) != 0) 210 for (i = 0; i < XVECLEN (insn, 1); i++) 211 { 212 /* Compute the maximum SETs and CLOBBERS 213 in any one of the sub-insns; 214 don't sum across all of them. */ 215 clobbers_seen_this_insn = 0; 216 217 walk_insn_part (XVECEXP (insn, 1, i), 0, 0); 218 219 if (clobbers_seen_this_insn > max_clobbers_per_insn) 220 max_clobbers_per_insn = clobbers_seen_this_insn; 221 } 222 } 223 224 /* Similar but scan a define_split. */ 225 226 static void 227 gen_split (md_rtx_info *info) 228 { 229 int i; 230 231 /* Look through the patterns that are matched 232 to compute the maximum operand number. */ 233 rtx split = info->def; 234 for (i = 0; i < XVECLEN (split, 0); i++) 235 walk_insn_part (XVECEXP (split, 0, i), 1, 0); 236 /* Look at the number of insns this insn could split into. */ 237 if (XVECLEN (split, 2) > max_insns_per_split) 238 max_insns_per_split = XVECLEN (split, 2); 239 } 240 241 static void 242 gen_peephole (md_rtx_info *info) 243 { 244 int i; 245 246 /* Look through the patterns that are matched 247 to compute the maximum operand number. */ 248 rtx peep = info->def; 249 for (i = 0; i < XVECLEN (peep, 0); i++) 250 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 251 } 252 253 static void 254 gen_peephole2 (md_rtx_info *info) 255 { 256 int i, n; 257 258 /* Look through the patterns that are matched 259 to compute the maximum operand number. */ 260 rtx peep = info->def; 261 for (i = XVECLEN (peep, 0) - 1; i >= 0; --i) 262 walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 263 264 /* Look at the number of insns this insn can be matched from. */ 265 for (i = XVECLEN (peep, 0) - 1, n = 0; i >= 0; --i) 266 if (GET_CODE (XVECEXP (peep, 0, i)) != MATCH_DUP 267 && GET_CODE (XVECEXP (peep, 0, i)) != MATCH_SCRATCH) 268 n++; 269 if (n > max_insns_per_peep2) 270 max_insns_per_peep2 = n; 271 } 272 273 int 274 main (int argc, const char **argv) 275 { 276 progname = "genconfig"; 277 278 if (!init_rtx_reader_args (argc, argv)) 279 return (FATAL_EXIT_CODE); 280 281 puts ("/* Generated automatically by the program `genconfig'"); 282 puts (" from the machine description file `md'. */\n"); 283 puts ("#ifndef GCC_INSN_CONFIG_H"); 284 puts ("#define GCC_INSN_CONFIG_H\n"); 285 286 /* Allow at least 30 operands for the sake of asm constructs. */ 287 /* ??? We *really* ought to reorganize things such that there 288 is no fixed upper bound. */ 289 max_recog_operands = 29; /* We will add 1 later. */ 290 max_dup_operands = 1; 291 292 /* Read the machine description. */ 293 294 md_rtx_info info; 295 while (read_md_rtx (&info)) 296 switch (GET_CODE (info.def)) 297 { 298 case DEFINE_INSN: 299 gen_insn (&info); 300 break; 301 302 case DEFINE_EXPAND: 303 gen_expand (&info); 304 break; 305 306 case DEFINE_SPLIT: 307 gen_split (&info); 308 break; 309 310 case DEFINE_PEEPHOLE2: 311 have_peephole2_flag = 1; 312 gen_peephole2 (&info); 313 break; 314 315 case DEFINE_PEEPHOLE: 316 have_peephole_flag = 1; 317 gen_peephole (&info); 318 break; 319 320 default: 321 break; 322 } 323 324 printf ("#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); 325 printf ("#define MAX_DUP_OPERANDS %d\n", max_dup_operands); 326 327 /* This is conditionally defined, in case the user writes code which emits 328 more splits than we can readily see (and knows s/he does it). */ 329 printf ("#ifndef MAX_INSNS_PER_SPLIT\n"); 330 printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split); 331 printf ("#endif\n"); 332 333 if (have_cc0_flag) 334 { 335 printf ("#define HAVE_cc0 1\n"); 336 printf ("#define CC0_P(X) ((X) == cc0_rtx)\n"); 337 } 338 else 339 { 340 /* We output CC0_P this way to make sure that X is declared 341 somewhere. */ 342 printf ("#define HAVE_cc0 0\n"); 343 printf ("#define CC0_P(X) ((X) ? 0 : 0)\n"); 344 } 345 346 if (have_cmove_flag) 347 printf ("#define HAVE_conditional_move 1\n"); 348 else 349 printf ("#define HAVE_conditional_move 0\n"); 350 351 if (have_cond_exec_flag) 352 printf ("#define HAVE_conditional_execution 1\n"); 353 else 354 printf ("#define HAVE_conditional_execution 0\n"); 355 356 if (have_lo_sum_flag) 357 printf ("#define HAVE_lo_sum 1\n"); 358 else 359 printf ("#define HAVE_lo_sum 0\n"); 360 361 if (have_rotate_flag) 362 printf ("#define HAVE_rotate 1\n"); 363 364 if (have_rotatert_flag) 365 printf ("#define HAVE_rotatert 1\n"); 366 367 if (have_peephole_flag) 368 printf ("#define HAVE_peephole 1\n"); 369 else 370 printf ("#define HAVE_peephole 0\n"); 371 372 if (have_peephole2_flag) 373 { 374 printf ("#define HAVE_peephole2 1\n"); 375 printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); 376 } 377 else 378 { 379 printf ("#define HAVE_peephole2 0\n"); 380 printf ("#define MAX_INSNS_PER_PEEP2 0\n"); 381 } 382 383 puts ("\n#endif /* GCC_INSN_CONFIG_H */"); 384 385 if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 386 return FATAL_EXIT_CODE; 387 388 return SUCCESS_EXIT_CODE; 389 } 390