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