1/* Generate code from machine description to perform peephole optimizations. 2 Copyright (C) 1987-2015 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 3, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16You should have received a copy of the GNU General Public License 17along with GCC; see the file COPYING3. If not see 18<http://www.gnu.org/licenses/>. */ 19 20 21#include "bconfig.h" 22#include "system.h" 23#include "coretypes.h" 24#include "tm.h" 25#include "rtl.h" 26#include "errors.h" 27#include "gensupport.h" 28 29 30/* While tree-walking an instruction pattern, we keep a chain 31 of these `struct link's to record how to get down to the 32 current position. In each one, POS is the operand number, 33 and if the operand is a vector VEC is the element number. 34 VEC is -1 if the operand is not a vector. */ 35 36struct link 37{ 38 struct link *next; 39 int pos; 40 int vecelt; 41}; 42 43static int max_opno; 44 45/* Number of operands used in current peephole definition. */ 46 47static int n_operands; 48 49static void gen_peephole (rtx, int); 50static void match_rtx (rtx, struct link *, int); 51static void print_path (struct link *); 52static void print_code (RTX_CODE); 53 54static void 55gen_peephole (rtx peep, int insn_code_number) 56{ 57 int ninsns = XVECLEN (peep, 0); 58 int i; 59 60 n_operands = 0; 61 62 printf (" insn = ins1;\n"); 63 64 for (i = 0; i < ninsns; i++) 65 { 66 if (i > 0) 67 { 68 printf (" do { insn = NEXT_INSN (insn);\n"); 69 printf (" if (insn == 0) goto L%d; }\n", 70 insn_code_number); 71 printf (" while (NOTE_P (insn)\n"); 72 printf ("\t || (NONJUMP_INSN_P (insn)\n"); 73 printf ("\t && (GET_CODE (PATTERN (insn)) == USE\n"); 74 printf ("\t\t || GET_CODE (PATTERN (insn)) == CLOBBER)));\n"); 75 76 printf (" if (LABEL_P (insn)\n\ 77 || BARRIER_P (insn))\n goto L%d;\n", 78 insn_code_number); 79 } 80 81 printf (" pat = PATTERN (insn);\n"); 82 83 /* Walk the insn's pattern, remembering at all times the path 84 down to the walking point. */ 85 86 match_rtx (XVECEXP (peep, 0, i), NULL, insn_code_number); 87 } 88 89 /* We get this far if the pattern matches. 90 Now test the extra condition. */ 91 92 if (XSTR (peep, 1) && XSTR (peep, 1)[0]) 93 printf (" if (! (%s)) goto L%d;\n", 94 XSTR (peep, 1), insn_code_number); 95 96 /* If that matches, construct new pattern and put it in the first insn. 97 This new pattern will never be matched. 98 It exists only so that insn-extract can get the operands back. 99 So use a simple regular form: a PARALLEL containing a vector 100 of all the operands. */ 101 102 printf (" PATTERN (ins1) = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (%d, operands));\n", n_operands); 103 104 /* Record this define_peephole's insn code in the insn, 105 as if it had been recognized to match this. */ 106 printf (" INSN_CODE (ins1) = %d;\n", 107 insn_code_number); 108 109 /* Delete the remaining insns. */ 110 if (ninsns > 1) 111 printf (" delete_for_peephole (NEXT_INSN (ins1), insn);\n"); 112 113 /* See reload1.c for insertion of NOTE which guarantees that this 114 cannot be zero. */ 115 printf (" return NEXT_INSN (insn);\n"); 116 117 printf (" L%d:\n\n", insn_code_number); 118} 119 120static void 121match_rtx (rtx x, struct link *path, int fail_label) 122{ 123 RTX_CODE code; 124 int i; 125 int len; 126 const char *fmt; 127 struct link link; 128 129 if (x == 0) 130 return; 131 132 133 code = GET_CODE (x); 134 135 switch (code) 136 { 137 case MATCH_OPERAND: 138 if (XINT (x, 0) > max_opno) 139 max_opno = XINT (x, 0); 140 if (XINT (x, 0) >= n_operands) 141 n_operands = 1 + XINT (x, 0); 142 143 printf (" x = "); 144 print_path (path); 145 printf (";\n"); 146 147 printf (" operands[%d] = x;\n", XINT (x, 0)); 148 if (XSTR (x, 1) && XSTR (x, 1)[0]) 149 printf (" if (! %s (x, %smode)) goto L%d;\n", 150 XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); 151 return; 152 153 case MATCH_DUP: 154 case MATCH_PAR_DUP: 155 printf (" x = "); 156 print_path (path); 157 printf (";\n"); 158 159 printf (" if (!rtx_equal_p (operands[%d], x)) goto L%d;\n", 160 XINT (x, 0), fail_label); 161 return; 162 163 case MATCH_OP_DUP: 164 printf (" x = "); 165 print_path (path); 166 printf (";\n"); 167 168 printf (" if (GET_CODE (operands[%d]) != GET_CODE (x)\n", XINT (x, 0)); 169 printf (" || GET_MODE (operands[%d]) != GET_MODE (x)) goto L%d;\n", 170 XINT (x, 0), fail_label); 171 printf (" operands[%d] = x;\n", XINT (x, 0)); 172 link.next = path; 173 link.vecelt = -1; 174 for (i = 0; i < XVECLEN (x, 1); i++) 175 { 176 link.pos = i; 177 match_rtx (XVECEXP (x, 1, i), &link, fail_label); 178 } 179 return; 180 181 case MATCH_OPERATOR: 182 if (XINT (x, 0) > max_opno) 183 max_opno = XINT (x, 0); 184 if (XINT (x, 0) >= n_operands) 185 n_operands = 1 + XINT (x, 0); 186 187 printf (" x = "); 188 print_path (path); 189 printf (";\n"); 190 191 printf (" operands[%d] = x;\n", XINT (x, 0)); 192 if (XSTR (x, 1) && XSTR (x, 1)[0]) 193 printf (" if (! %s (x, %smode)) goto L%d;\n", 194 XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); 195 link.next = path; 196 link.vecelt = -1; 197 for (i = 0; i < XVECLEN (x, 2); i++) 198 { 199 link.pos = i; 200 match_rtx (XVECEXP (x, 2, i), &link, fail_label); 201 } 202 return; 203 204 case MATCH_PARALLEL: 205 if (XINT (x, 0) > max_opno) 206 max_opno = XINT (x, 0); 207 if (XINT (x, 0) >= n_operands) 208 n_operands = 1 + XINT (x, 0); 209 210 printf (" x = "); 211 print_path (path); 212 printf (";\n"); 213 214 printf (" if (GET_CODE (x) != PARALLEL) goto L%d;\n", fail_label); 215 printf (" operands[%d] = x;\n", XINT (x, 0)); 216 if (XSTR (x, 1) && XSTR (x, 1)[0]) 217 printf (" if (! %s (x, %smode)) goto L%d;\n", 218 XSTR (x, 1), GET_MODE_NAME (GET_MODE (x)), fail_label); 219 link.next = path; 220 link.pos = 0; 221 for (i = 0; i < XVECLEN (x, 2); i++) 222 { 223 link.vecelt = i; 224 match_rtx (XVECEXP (x, 2, i), &link, fail_label); 225 } 226 return; 227 228 default: 229 break; 230 } 231 232 printf (" x = "); 233 print_path (path); 234 printf (";\n"); 235 236 printf (" if (GET_CODE (x) != "); 237 print_code (code); 238 printf (") goto L%d;\n", fail_label); 239 240 if (GET_MODE (x) != VOIDmode) 241 { 242 printf (" if (GET_MODE (x) != %smode) goto L%d;\n", 243 GET_MODE_NAME (GET_MODE (x)), fail_label); 244 } 245 246 link.next = path; 247 link.vecelt = -1; 248 fmt = GET_RTX_FORMAT (code); 249 len = GET_RTX_LENGTH (code); 250 for (i = 0; i < len; i++) 251 { 252 link.pos = i; 253 if (fmt[i] == 'e' || fmt[i] == 'u') 254 match_rtx (XEXP (x, i), &link, fail_label); 255 else if (fmt[i] == 'E') 256 { 257 int j; 258 printf (" if (XVECLEN (x, %d) != %d) goto L%d;\n", 259 i, XVECLEN (x, i), fail_label); 260 for (j = 0; j < XVECLEN (x, i); j++) 261 { 262 link.vecelt = j; 263 match_rtx (XVECEXP (x, i, j), &link, fail_label); 264 } 265 } 266 else if (fmt[i] == 'i') 267 { 268 /* Make sure that at run time `x' is the RTX we want to test. */ 269 if (i != 0) 270 { 271 printf (" x = "); 272 print_path (path); 273 printf (";\n"); 274 } 275 276 printf (" if (XINT (x, %d) != %d) goto L%d;\n", 277 i, XINT (x, i), fail_label); 278 } 279 else if (fmt[i] == 'w') 280 { 281 /* Make sure that at run time `x' is the RTX we want to test. */ 282 if (i != 0) 283 { 284 printf (" x = "); 285 print_path (path); 286 printf (";\n"); 287 } 288 289 printf (" if (XWINT (x, %d) != ", i); 290 printf (HOST_WIDE_INT_PRINT_DEC, XWINT (x, i)); 291 printf (") goto L%d;\n", fail_label); 292 } 293 else if (fmt[i] == 's') 294 { 295 /* Make sure that at run time `x' is the RTX we want to test. */ 296 if (i != 0) 297 { 298 printf (" x = "); 299 print_path (path); 300 printf (";\n"); 301 } 302 303 printf (" if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n", 304 i, XSTR (x, i), fail_label); 305 } 306 } 307} 308 309/* Given a PATH, representing a path down the instruction's 310 pattern from the root to a certain point, output code to 311 evaluate to the rtx at that point. */ 312 313static void 314print_path (struct link *path) 315{ 316 if (path == 0) 317 printf ("pat"); 318 else if (path->vecelt >= 0) 319 { 320 printf ("XVECEXP ("); 321 print_path (path->next); 322 printf (", %d, %d)", path->pos, path->vecelt); 323 } 324 else 325 { 326 printf ("XEXP ("); 327 print_path (path->next); 328 printf (", %d)", path->pos); 329 } 330} 331 332static void 333print_code (RTX_CODE code) 334{ 335 const char *p1; 336 for (p1 = GET_RTX_NAME (code); *p1; p1++) 337 putchar (TOUPPER (*p1)); 338} 339 340extern int main (int, char **); 341 342int 343main (int argc, char **argv) 344{ 345 rtx desc; 346 347 max_opno = -1; 348 349 progname = "genpeep"; 350 351 if (!init_rtx_reader_args (argc, argv)) 352 return (FATAL_EXIT_CODE); 353 354 printf ("/* Generated automatically by the program `genpeep'\n\ 355from the machine description file `md'. */\n\n"); 356 357 printf ("#include \"config.h\"\n"); 358 printf ("#include \"system.h\"\n"); 359 printf ("#include \"coretypes.h\"\n"); 360 printf ("#include \"tm.h\"\n"); 361 printf ("#include \"insn-config.h\"\n"); 362 printf ("#include \"hash-set.h\"\n"); 363 printf ("#include \"machmode.h\"\n"); 364 printf ("#include \"vec.h\"\n"); 365 printf ("#include \"double-int.h\"\n"); 366 printf ("#include \"input.h\"\n"); 367 printf ("#include \"alias.h\"\n"); 368 printf ("#include \"symtab.h\"\n"); 369 printf ("#include \"wide-int.h\"\n"); 370 printf ("#include \"inchash.h\"\n"); 371 printf ("#include \"tree.h\"\n"); 372 printf ("#include \"varasm.h\"\n"); 373 printf ("#include \"stor-layout.h\"\n"); 374 printf ("#include \"calls.h\"\n"); 375 printf ("#include \"rtl.h\"\n"); 376 printf ("#include \"tm_p.h\"\n"); 377 printf ("#include \"regs.h\"\n"); 378 printf ("#include \"output.h\"\n"); 379 printf ("#include \"recog.h\"\n"); 380 printf ("#include \"except.h\"\n"); 381 printf ("#include \"function.h\"\n"); 382 printf ("#include \"diagnostic-core.h\"\n"); 383 printf ("#include \"flags.h\"\n"); 384 printf ("#include \"tm-constrs.h\"\n\n"); 385 386 printf ("#ifdef HAVE_peephole\n"); 387 printf ("extern rtx peep_operand[];\n\n"); 388 printf ("#define operands peep_operand\n\n"); 389 390 printf ("rtx_insn *\npeephole (rtx_insn *ins1)\n{\n"); 391 printf (" rtx_insn *insn ATTRIBUTE_UNUSED;\n"); 392 printf (" rtx x ATTRIBUTE_UNUSED, pat ATTRIBUTE_UNUSED;\n\n"); 393 394 /* Early out: no peepholes for insns followed by barriers. */ 395 printf (" if (NEXT_INSN (ins1)\n"); 396 printf (" && BARRIER_P (NEXT_INSN (ins1)))\n"); 397 printf (" return 0;\n\n"); 398 399 /* Read the machine description. */ 400 401 while (1) 402 { 403 int line_no; 404 int insn_code_number; 405 406 desc = read_md_rtx (&line_no, &insn_code_number); 407 if (desc == NULL) 408 break; 409 410 if (GET_CODE (desc) == DEFINE_PEEPHOLE) 411 gen_peephole (desc, insn_code_number); 412 } 413 414 printf (" return 0;\n}\n\n"); 415 416 if (max_opno == -1) 417 max_opno = 1; 418 419 printf ("rtx peep_operand[%d];\n", max_opno + 1); 420 printf ("#endif\n"); 421 422 fflush (stdout); 423 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 424} 425