118334Speter/* Subroutines used by or related to instruction recognition. 290075Sobrien Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 3169699Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 418334Speter 590075SobrienThis file is part of GCC. 618334Speter 790075SobrienGCC is free software; you can redistribute it and/or modify it under 890075Sobrienthe terms of the GNU General Public License as published by the Free 990075SobrienSoftware Foundation; either version 2, or (at your option) any later 1090075Sobrienversion. 1118334Speter 1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590075Sobrienfor more details. 1618334Speter 1718334SpeterYou should have received a copy of the GNU General Public License 1890075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 19169699SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169699Skan02110-1301, USA. */ 2118334Speter 2218334Speter 2318334Speter#include "config.h" 2450397Sobrien#include "system.h" 25132727Skan#include "coretypes.h" 26132727Skan#include "tm.h" 2718334Speter#include "rtl.h" 2890075Sobrien#include "tm_p.h" 2918334Speter#include "insn-config.h" 3018334Speter#include "insn-attr.h" 3190075Sobrien#include "hard-reg-set.h" 3218334Speter#include "recog.h" 3318334Speter#include "regs.h" 34169699Skan#include "addresses.h" 3590075Sobrien#include "expr.h" 3690075Sobrien#include "function.h" 3718334Speter#include "flags.h" 3818334Speter#include "real.h" 3952284Sobrien#include "toplev.h" 4052284Sobrien#include "basic-block.h" 4190075Sobrien#include "output.h" 4290075Sobrien#include "reload.h" 43169699Skan#include "timevar.h" 44169699Skan#include "tree-pass.h" 4518334Speter 4618334Speter#ifndef STACK_PUSH_CODE 4718334Speter#ifdef STACK_GROWS_DOWNWARD 4818334Speter#define STACK_PUSH_CODE PRE_DEC 4918334Speter#else 5018334Speter#define STACK_PUSH_CODE PRE_INC 5118334Speter#endif 5218334Speter#endif 5318334Speter 5452284Sobrien#ifndef STACK_POP_CODE 5552284Sobrien#ifdef STACK_GROWS_DOWNWARD 5652284Sobrien#define STACK_POP_CODE POST_INC 5752284Sobrien#else 5852284Sobrien#define STACK_POP_CODE POST_DEC 5952284Sobrien#endif 6052284Sobrien#endif 6118334Speter 62132727Skanstatic void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx); 63132727Skanstatic rtx *find_single_use_1 (rtx, rtx *); 64132727Skanstatic void validate_replace_src_1 (rtx *, void *); 65132727Skanstatic rtx split_insn (rtx); 6618334Speter 6718334Speter/* Nonzero means allow operands to be volatile. 6818334Speter This should be 0 if you are generating rtl, such as if you are calling 6918334Speter the functions in optabs.c and expmed.c (most of the time). 7018334Speter This should be 1 if all valid insns need to be recognized, 7118334Speter such as in regclass.c and final.c and reload.c. 7218334Speter 7318334Speter init_recog and init_recog_no_volatile are responsible for setting this. */ 7418334Speter 7518334Speterint volatile_ok; 7618334Speter 7790075Sobrienstruct recog_data recog_data; 7852284Sobrien 7952284Sobrien/* Contains a vector of operand_alternative structures for every operand. 8052284Sobrien Set up by preprocess_constraints. */ 8152284Sobrienstruct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES]; 8252284Sobrien 8318334Speter/* On return from `constrain_operands', indicate which alternative 8418334Speter was satisfied. */ 8518334Speter 8618334Speterint which_alternative; 8718334Speter 8818334Speter/* Nonzero after end of reload pass. 8918334Speter Set to 1 or 0 by toplev.c. 9018334Speter Controls the significance of (SUBREG (MEM)). */ 9118334Speter 9218334Speterint reload_completed; 9318334Speter 94132727Skan/* Nonzero after thread_prologue_and_epilogue_insns has run. */ 95132727Skanint epilogue_completed; 96132727Skan 9718334Speter/* Initialize data used by the function `recog'. 9818334Speter This must be called once in the compilation of a function 9918334Speter before any insn recognition may be done in the function. */ 10018334Speter 10118334Spetervoid 102132727Skaninit_recog_no_volatile (void) 10318334Speter{ 10418334Speter volatile_ok = 0; 10518334Speter} 10618334Speter 10718334Spetervoid 108132727Skaninit_recog (void) 10918334Speter{ 11018334Speter volatile_ok = 1; 11118334Speter} 11218334Speter 11318334Speter 11418334Speter/* Check that X is an insn-body for an `asm' with operands 11518334Speter and that the operands mentioned in it are legitimate. */ 11618334Speter 11718334Speterint 118132727Skancheck_asm_operands (rtx x) 11918334Speter{ 12052284Sobrien int noperands; 12118334Speter rtx *operands; 12252284Sobrien const char **constraints; 12318334Speter int i; 12418334Speter 12552284Sobrien /* Post-reload, be more strict with things. */ 12652284Sobrien if (reload_completed) 12752284Sobrien { 12852284Sobrien /* ??? Doh! We've not got the wrapping insn. Cook one up. */ 12952284Sobrien extract_insn (make_insn_raw (x)); 13052284Sobrien constrain_operands (1); 13152284Sobrien return which_alternative >= 0; 13252284Sobrien } 13352284Sobrien 13452284Sobrien noperands = asm_noperands (x); 13518334Speter if (noperands < 0) 13618334Speter return 0; 13718334Speter if (noperands == 0) 13818334Speter return 1; 13918334Speter 140132727Skan operands = alloca (noperands * sizeof (rtx)); 141132727Skan constraints = alloca (noperands * sizeof (char *)); 14218334Speter 14390075Sobrien decode_asm_operands (x, operands, NULL, constraints, NULL); 14452284Sobrien 14518334Speter for (i = 0; i < noperands; i++) 14652284Sobrien { 14752284Sobrien const char *c = constraints[i]; 14852284Sobrien if (c[0] == '%') 14952284Sobrien c++; 15090075Sobrien if (ISDIGIT ((unsigned char) c[0]) && c[1] == '\0') 15152284Sobrien c = constraints[c[0] - '0']; 15218334Speter 15352284Sobrien if (! asm_operand_ok (operands[i], c)) 154117404Skan return 0; 15552284Sobrien } 15652284Sobrien 15718334Speter return 1; 15818334Speter} 15918334Speter 16052284Sobrien/* Static data for the next two routines. */ 16118334Speter 16252284Sobrientypedef struct change_t 16352284Sobrien{ 16452284Sobrien rtx object; 16552284Sobrien int old_code; 16652284Sobrien rtx *loc; 16752284Sobrien rtx old; 16852284Sobrien} change_t; 16918334Speter 17052284Sobrienstatic change_t *changes; 17152284Sobrienstatic int changes_allocated; 17218334Speter 17318334Speterstatic int num_changes = 0; 17418334Speter 17590075Sobrien/* Validate a proposed change to OBJECT. LOC is the location in the rtl 17618334Speter at which NEW will be placed. If OBJECT is zero, no validation is done, 17718334Speter the change is simply made. 17818334Speter 17918334Speter Two types of objects are supported: If OBJECT is a MEM, memory_address_p 18018334Speter will be called with the address and mode as parameters. If OBJECT is 18118334Speter an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with 18218334Speter the change in place. 18318334Speter 184117404Skan IN_GROUP is nonzero if this is part of a group of changes that must be 18518334Speter performed as a group. In that case, the changes will be stored. The 18618334Speter function `apply_change_group' will validate and apply the changes. 18718334Speter 18818334Speter If IN_GROUP is zero, this is a single change. Try to recognize the insn 18918334Speter or validate the memory reference with the change applied. If the result 19018334Speter is not valid for the machine, suppress the change and return zero. 19118334Speter Otherwise, perform the change and return 1. */ 19218334Speter 19318334Speterint 194132727Skanvalidate_change (rtx object, rtx *loc, rtx new, int in_group) 19518334Speter{ 19618334Speter rtx old = *loc; 19718334Speter 19818334Speter if (old == new || rtx_equal_p (old, new)) 19918334Speter return 1; 20018334Speter 201169699Skan gcc_assert (in_group != 0 || num_changes == 0); 20218334Speter 20318334Speter *loc = new; 20418334Speter 20518334Speter /* Save the information describing this change. */ 20652284Sobrien if (num_changes >= changes_allocated) 20752284Sobrien { 20852284Sobrien if (changes_allocated == 0) 20952284Sobrien /* This value allows for repeated substitutions inside complex 21052284Sobrien indexed addresses, or changes in up to 5 insns. */ 21152284Sobrien changes_allocated = MAX_RECOG_OPERANDS * 5; 21252284Sobrien else 21352284Sobrien changes_allocated *= 2; 21418334Speter 215132727Skan changes = xrealloc (changes, sizeof (change_t) * changes_allocated); 21652284Sobrien } 217117404Skan 21852284Sobrien changes[num_changes].object = object; 21952284Sobrien changes[num_changes].loc = loc; 22052284Sobrien changes[num_changes].old = old; 22152284Sobrien 222169699Skan if (object && !MEM_P (object)) 22318334Speter { 22418334Speter /* Set INSN_CODE to force rerecognition of insn. Save old code in 22518334Speter case invalid. */ 22652284Sobrien changes[num_changes].old_code = INSN_CODE (object); 22718334Speter INSN_CODE (object) = -1; 22818334Speter } 22918334Speter 23018334Speter num_changes++; 23118334Speter 23218334Speter /* If we are making a group of changes, return 1. Otherwise, validate the 23318334Speter change group we made. */ 23418334Speter 23518334Speter if (in_group) 23618334Speter return 1; 23718334Speter else 23818334Speter return apply_change_group (); 23918334Speter} 24018334Speter 241169699Skan 24252284Sobrien/* This subroutine of apply_change_group verifies whether the changes to INSN 24352284Sobrien were valid; i.e. whether INSN can still be recognized. */ 24452284Sobrien 24590075Sobrienint 246132727Skaninsn_invalid_p (rtx insn) 24752284Sobrien{ 24890075Sobrien rtx pat = PATTERN (insn); 24990075Sobrien int num_clobbers = 0; 25090075Sobrien /* If we are before reload and the pattern is a SET, see if we can add 25190075Sobrien clobbers. */ 25290075Sobrien int icode = recog (pat, insn, 25390075Sobrien (GET_CODE (pat) == SET 25490075Sobrien && ! reload_completed && ! reload_in_progress) 25590075Sobrien ? &num_clobbers : 0); 25652284Sobrien int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0; 25752284Sobrien 258117404Skan 25990075Sobrien /* If this is an asm and the operand aren't legal, then fail. Likewise if 26090075Sobrien this is not an asm and the insn wasn't recognized. */ 26190075Sobrien if ((is_asm && ! check_asm_operands (PATTERN (insn))) 26290075Sobrien || (!is_asm && icode < 0)) 26352284Sobrien return 1; 26452284Sobrien 26590075Sobrien /* If we have to add CLOBBERs, fail if we have to add ones that reference 26690075Sobrien hard registers since our callers can't know if they are live or not. 26790075Sobrien Otherwise, add them. */ 26890075Sobrien if (num_clobbers > 0) 26990075Sobrien { 27090075Sobrien rtx newpat; 27190075Sobrien 27290075Sobrien if (added_clobbers_hard_reg_p (icode)) 27390075Sobrien return 1; 27490075Sobrien 27590075Sobrien newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1)); 27690075Sobrien XVECEXP (newpat, 0, 0) = pat; 27790075Sobrien add_clobbers (newpat, icode); 27890075Sobrien PATTERN (insn) = pat = newpat; 27990075Sobrien } 28090075Sobrien 28152284Sobrien /* After reload, verify that all constraints are satisfied. */ 28252284Sobrien if (reload_completed) 28352284Sobrien { 28452284Sobrien extract_insn (insn); 28552284Sobrien 28652284Sobrien if (! constrain_operands (1)) 28752284Sobrien return 1; 28852284Sobrien } 28952284Sobrien 29090075Sobrien INSN_CODE (insn) = icode; 29152284Sobrien return 0; 29252284Sobrien} 29352284Sobrien 294117404Skan/* Return number of changes made and not validated yet. */ 295117404Skanint 296132727Skannum_changes_pending (void) 297117404Skan{ 298117404Skan return num_changes; 299117404Skan} 300117404Skan 301169699Skan/* Tentatively apply the changes numbered NUM and up. 30218334Speter Return 1 if all changes are valid, zero otherwise. */ 30318334Speter 30418334Speterint 305169699Skanverify_changes (int num) 30618334Speter{ 30718334Speter int i; 30890075Sobrien rtx last_validated = NULL_RTX; 30918334Speter 31018334Speter /* The changes have been applied and all INSN_CODEs have been reset to force 31118334Speter rerecognition. 31218334Speter 31318334Speter The changes are valid if we aren't given an object, or if we are 31418334Speter given a MEM and it still is a valid address, or if this is in insn 31518334Speter and it is recognized. In the latter case, if reload has completed, 31618334Speter we also require that the operands meet the constraints for 31752284Sobrien the insn. */ 31818334Speter 319169699Skan for (i = num; i < num_changes; i++) 32018334Speter { 32152284Sobrien rtx object = changes[i].object; 32218334Speter 323132727Skan /* If there is no object to test or if it is the same as the one we 32490075Sobrien already tested, ignore it. */ 32590075Sobrien if (object == 0 || object == last_validated) 32618334Speter continue; 32718334Speter 328169699Skan if (MEM_P (object)) 32918334Speter { 33018334Speter if (! memory_address_p (GET_MODE (object), XEXP (object, 0))) 33118334Speter break; 33218334Speter } 33352284Sobrien else if (insn_invalid_p (object)) 33418334Speter { 33518334Speter rtx pat = PATTERN (object); 33618334Speter 33718334Speter /* Perhaps we couldn't recognize the insn because there were 33818334Speter extra CLOBBERs at the end. If so, try to re-recognize 33918334Speter without the last CLOBBER (later iterations will cause each of 34018334Speter them to be eliminated, in turn). But don't do this if we 34118334Speter have an ASM_OPERAND. */ 34218334Speter if (GET_CODE (pat) == PARALLEL 34318334Speter && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER 34418334Speter && asm_noperands (PATTERN (object)) < 0) 34518334Speter { 34690075Sobrien rtx newpat; 34718334Speter 34890075Sobrien if (XVECLEN (pat, 0) == 2) 34990075Sobrien newpat = XVECEXP (pat, 0, 0); 35090075Sobrien else 35190075Sobrien { 35290075Sobrien int j; 35318334Speter 35490075Sobrien newpat 355117404Skan = gen_rtx_PARALLEL (VOIDmode, 35690075Sobrien rtvec_alloc (XVECLEN (pat, 0) - 1)); 35790075Sobrien for (j = 0; j < XVECLEN (newpat, 0); j++) 35890075Sobrien XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j); 35990075Sobrien } 36018334Speter 36190075Sobrien /* Add a new change to this group to replace the pattern 36290075Sobrien with this new pattern. Then consider this change 36390075Sobrien as having succeeded. The change we added will 36490075Sobrien cause the entire call to fail if things remain invalid. 36518334Speter 36690075Sobrien Note that this can lose if a later change than the one 36790075Sobrien we are processing specified &XVECEXP (PATTERN (object), 0, X) 36890075Sobrien but this shouldn't occur. */ 36918334Speter 37090075Sobrien validate_change (object, &PATTERN (object), newpat, 1); 37190075Sobrien continue; 37290075Sobrien } 37318334Speter else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) 37418334Speter /* If this insn is a CLOBBER or USE, it is always valid, but is 37518334Speter never recognized. */ 37618334Speter continue; 37718334Speter else 37818334Speter break; 37918334Speter } 38090075Sobrien last_validated = object; 38118334Speter } 38218334Speter 383169699Skan return (i == num_changes); 384169699Skan} 385117404Skan 386169699Skan/* A group of changes has previously been issued with validate_change and 387169699Skan verified with verify_changes. Update the BB_DIRTY flags of the affected 388169699Skan blocks, and clear num_changes. */ 389117404Skan 390169699Skanvoid 391169699Skanconfirm_change_group (void) 392169699Skan{ 393169699Skan int i; 394169699Skan basic_block bb; 395169699Skan 396169699Skan for (i = 0; i < num_changes; i++) 397169699Skan if (changes[i].object 398169699Skan && INSN_P (changes[i].object) 399169699Skan && (bb = BLOCK_FOR_INSN (changes[i].object))) 400169699Skan bb->flags |= BB_DIRTY; 401169699Skan 402169699Skan num_changes = 0; 403169699Skan} 404169699Skan 405169699Skan/* Apply a group of changes previously issued with `validate_change'. 406169699Skan If all changes are valid, call confirm_change_group and return 1, 407169699Skan otherwise, call cancel_changes and return 0. */ 408169699Skan 409169699Skanint 410169699Skanapply_change_group (void) 411169699Skan{ 412169699Skan if (verify_changes (0)) 413169699Skan { 414169699Skan confirm_change_group (); 41518334Speter return 1; 41618334Speter } 41718334Speter else 41818334Speter { 41918334Speter cancel_changes (0); 42018334Speter return 0; 42118334Speter } 42218334Speter} 42318334Speter 424169699Skan 42590075Sobrien/* Return the number of changes so far in the current group. */ 42618334Speter 42718334Speterint 428132727Skannum_validated_changes (void) 42918334Speter{ 43018334Speter return num_changes; 43118334Speter} 43218334Speter 43318334Speter/* Retract the changes numbered NUM and up. */ 43418334Speter 43518334Spetervoid 436132727Skancancel_changes (int num) 43718334Speter{ 43818334Speter int i; 43918334Speter 44018334Speter /* Back out all the changes. Do this in the opposite order in which 44118334Speter they were made. */ 44218334Speter for (i = num_changes - 1; i >= num; i--) 44318334Speter { 44452284Sobrien *changes[i].loc = changes[i].old; 445169699Skan if (changes[i].object && !MEM_P (changes[i].object)) 44652284Sobrien INSN_CODE (changes[i].object) = changes[i].old_code; 44718334Speter } 44818334Speter num_changes = num; 44918334Speter} 45018334Speter 45118334Speter/* Replace every occurrence of FROM in X with TO. Mark each change with 45218334Speter validate_change passing OBJECT. */ 45318334Speter 45418334Speterstatic void 455132727Skanvalidate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object) 45618334Speter{ 45790075Sobrien int i, j; 45890075Sobrien const char *fmt; 45990075Sobrien rtx x = *loc; 46090075Sobrien enum rtx_code code; 46190075Sobrien enum machine_mode op0_mode = VOIDmode; 46290075Sobrien int prev_changes = num_changes; 46390075Sobrien rtx new; 46418334Speter 46590075Sobrien if (!x) 46690075Sobrien return; 46790075Sobrien 46890075Sobrien code = GET_CODE (x); 46990075Sobrien fmt = GET_RTX_FORMAT (code); 47090075Sobrien if (fmt[0] == 'e') 47190075Sobrien op0_mode = GET_MODE (XEXP (x, 0)); 47290075Sobrien 47318334Speter /* X matches FROM if it is the same rtx or they are both referring to the 47418334Speter same register in the same mode. Avoid calling rtx_equal_p unless the 47518334Speter operands look similar. */ 47618334Speter 47718334Speter if (x == from 478169699Skan || (REG_P (x) && REG_P (from) 47918334Speter && GET_MODE (x) == GET_MODE (from) 48018334Speter && REGNO (x) == REGNO (from)) 48118334Speter || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from) 48218334Speter && rtx_equal_p (x, from))) 48318334Speter { 48418334Speter validate_change (object, loc, to, 1); 48518334Speter return; 48618334Speter } 48718334Speter 488132727Skan /* Call ourself recursively to perform the replacements. 489132727Skan We must not replace inside already replaced expression, otherwise we 490132727Skan get infinite recursion for replacements like (reg X)->(subreg (reg X)) 491132727Skan done by regmove, so we must special case shared ASM_OPERANDS. */ 49290075Sobrien 493132727Skan if (GET_CODE (x) == PARALLEL) 49418334Speter { 495132727Skan for (j = XVECLEN (x, 0) - 1; j >= 0; j--) 496132727Skan { 497132727Skan if (j && GET_CODE (XVECEXP (x, 0, j)) == SET 498132727Skan && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS) 499132727Skan { 500132727Skan /* Verify that operands are really shared. */ 501169699Skan gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0))) 502169699Skan == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP 503169699Skan (x, 0, j)))); 504132727Skan validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)), 505132727Skan from, to, object); 506132727Skan } 507132727Skan else 508132727Skan validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object); 509132727Skan } 51090075Sobrien } 511132727Skan else 512132727Skan for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 513132727Skan { 514132727Skan if (fmt[i] == 'e') 515132727Skan validate_replace_rtx_1 (&XEXP (x, i), from, to, object); 516132727Skan else if (fmt[i] == 'E') 517132727Skan for (j = XVECLEN (x, i) - 1; j >= 0; j--) 518132727Skan validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object); 519132727Skan } 52018334Speter 52190075Sobrien /* If we didn't substitute, there is nothing more to do. */ 52290075Sobrien if (num_changes == prev_changes) 52390075Sobrien return; 52490075Sobrien 52590075Sobrien /* Allow substituted expression to have different mode. This is used by 52690075Sobrien regmove to change mode of pseudo register. */ 52790075Sobrien if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode) 52890075Sobrien op0_mode = GET_MODE (XEXP (x, 0)); 52990075Sobrien 53090075Sobrien /* Do changes needed to keep rtx consistent. Don't do any other 53190075Sobrien simplifications, as it is not our job. */ 53290075Sobrien 533169699Skan if (SWAPPABLE_OPERANDS_P (x) 53490075Sobrien && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) 53590075Sobrien { 53690075Sobrien validate_change (object, loc, 537169699Skan gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code 53890075Sobrien : swap_condition (code), 53990075Sobrien GET_MODE (x), XEXP (x, 1), 54090075Sobrien XEXP (x, 0)), 1); 54190075Sobrien x = *loc; 54290075Sobrien code = GET_CODE (x); 54318334Speter } 54418334Speter 54518334Speter switch (code) 54618334Speter { 54718334Speter case PLUS: 54850397Sobrien /* If we have a PLUS whose second operand is now a CONST_INT, use 549110621Skan simplify_gen_binary to try to simplify it. 55090075Sobrien ??? We may want later to remove this, once simplification is 55190075Sobrien separated from this function. */ 552110621Skan if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to) 55390075Sobrien validate_change (object, loc, 55490075Sobrien simplify_gen_binary 55590075Sobrien (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1); 55690075Sobrien break; 55750397Sobrien case MINUS: 55890075Sobrien if (GET_CODE (XEXP (x, 1)) == CONST_INT 55990075Sobrien || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE) 56090075Sobrien validate_change (object, loc, 56190075Sobrien simplify_gen_binary 56290075Sobrien (PLUS, GET_MODE (x), XEXP (x, 0), 56390075Sobrien simplify_gen_unary (NEG, 56490075Sobrien GET_MODE (x), XEXP (x, 1), 56590075Sobrien GET_MODE (x))), 1); 56650397Sobrien break; 56718334Speter case ZERO_EXTEND: 56818334Speter case SIGN_EXTEND: 56990075Sobrien if (GET_MODE (XEXP (x, 0)) == VOIDmode) 57018334Speter { 57190075Sobrien new = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0), 57290075Sobrien op0_mode); 57390075Sobrien /* If any of the above failed, substitute in something that 57490075Sobrien we know won't be recognized. */ 57590075Sobrien if (!new) 57650397Sobrien new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); 57718334Speter validate_change (object, loc, new, 1); 57818334Speter } 57918334Speter break; 58018334Speter case SUBREG: 58190075Sobrien /* All subregs possible to simplify should be simplified. */ 58290075Sobrien new = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode, 58390075Sobrien SUBREG_BYTE (x)); 58418334Speter 58590075Sobrien /* Subregs of VOIDmode operands are incorrect. */ 58690075Sobrien if (!new && GET_MODE (SUBREG_REG (x)) == VOIDmode) 58790075Sobrien new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); 58890075Sobrien if (new) 58990075Sobrien validate_change (object, loc, new, 1); 59018334Speter break; 59118334Speter case ZERO_EXTRACT: 59218334Speter case SIGN_EXTRACT: 59318334Speter /* If we are replacing a register with memory, try to change the memory 59490075Sobrien to be the mode required for memory in extract operations (this isn't 59590075Sobrien likely to be an insertion operation; if it was, nothing bad will 59690075Sobrien happen, we might just fail in some cases). */ 59718334Speter 598169699Skan if (MEM_P (XEXP (x, 0)) 59918334Speter && GET_CODE (XEXP (x, 1)) == CONST_INT 60018334Speter && GET_CODE (XEXP (x, 2)) == CONST_INT 60190075Sobrien && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0)) 60290075Sobrien && !MEM_VOLATILE_P (XEXP (x, 0))) 60318334Speter { 60418334Speter enum machine_mode wanted_mode = VOIDmode; 60590075Sobrien enum machine_mode is_mode = GET_MODE (XEXP (x, 0)); 60618334Speter int pos = INTVAL (XEXP (x, 2)); 60718334Speter 60890075Sobrien if (GET_CODE (x) == ZERO_EXTRACT) 60952284Sobrien { 61090075Sobrien enum machine_mode new_mode 61190075Sobrien = mode_for_extraction (EP_extzv, 1); 61290075Sobrien if (new_mode != MAX_MACHINE_MODE) 61390075Sobrien wanted_mode = new_mode; 61452284Sobrien } 61590075Sobrien else if (GET_CODE (x) == SIGN_EXTRACT) 61652284Sobrien { 61790075Sobrien enum machine_mode new_mode 61890075Sobrien = mode_for_extraction (EP_extv, 1); 61990075Sobrien if (new_mode != MAX_MACHINE_MODE) 62090075Sobrien wanted_mode = new_mode; 62152284Sobrien } 62218334Speter 62318334Speter /* If we have a narrower mode, we can do something. */ 62418334Speter if (wanted_mode != VOIDmode 62518334Speter && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode)) 62618334Speter { 62718334Speter int offset = pos / BITS_PER_UNIT; 62818334Speter rtx newmem; 62918334Speter 63090075Sobrien /* If the bytes and bits are counted differently, we 63190075Sobrien must adjust the offset. */ 63218334Speter if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN) 63390075Sobrien offset = 63490075Sobrien (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode) - 63590075Sobrien offset); 63618334Speter 63718334Speter pos %= GET_MODE_BITSIZE (wanted_mode); 63818334Speter 63990075Sobrien newmem = adjust_address_nv (XEXP (x, 0), wanted_mode, offset); 64018334Speter 64118334Speter validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1); 64218334Speter validate_change (object, &XEXP (x, 0), newmem, 1); 64318334Speter } 64418334Speter } 64518334Speter 64618334Speter break; 64790075Sobrien 64850397Sobrien default: 64950397Sobrien break; 65018334Speter } 65118334Speter} 65218334Speter 65318334Speter/* Try replacing every occurrence of FROM in INSN with TO. After all 65418334Speter changes have been made, validate by seeing if INSN is still valid. */ 65518334Speter 65618334Speterint 657132727Skanvalidate_replace_rtx (rtx from, rtx to, rtx insn) 65818334Speter{ 65918334Speter validate_replace_rtx_1 (&PATTERN (insn), from, to, insn); 66018334Speter return apply_change_group (); 66118334Speter} 66250397Sobrien 66390075Sobrien/* Try replacing every occurrence of FROM in INSN with TO. */ 66452284Sobrien 66552284Sobrienvoid 666132727Skanvalidate_replace_rtx_group (rtx from, rtx to, rtx insn) 66752284Sobrien{ 66852284Sobrien validate_replace_rtx_1 (&PATTERN (insn), from, to, insn); 66952284Sobrien} 67052284Sobrien 67190075Sobrien/* Function called by note_uses to replace used subexpressions. */ 67290075Sobrienstruct validate_replace_src_data 67390075Sobrien{ 67490075Sobrien rtx from; /* Old RTX */ 67590075Sobrien rtx to; /* New RTX */ 67690075Sobrien rtx insn; /* Insn in which substitution is occurring. */ 67790075Sobrien}; 67890075Sobrien 67990075Sobrienstatic void 680132727Skanvalidate_replace_src_1 (rtx *x, void *data) 68190075Sobrien{ 68290075Sobrien struct validate_replace_src_data *d 68390075Sobrien = (struct validate_replace_src_data *) data; 68490075Sobrien 68590075Sobrien validate_replace_rtx_1 (x, d->from, d->to, d->insn); 68690075Sobrien} 68790075Sobrien 68850397Sobrien/* Try replacing every occurrence of FROM in INSN with TO, avoiding 689117404Skan SET_DESTs. */ 69050397Sobrien 691117404Skanvoid 692132727Skanvalidate_replace_src_group (rtx from, rtx to, rtx insn) 69350397Sobrien{ 69490075Sobrien struct validate_replace_src_data d; 69550397Sobrien 69690075Sobrien d.from = from; 69790075Sobrien d.to = to; 69890075Sobrien d.insn = insn; 69990075Sobrien note_uses (&PATTERN (insn), validate_replace_src_1, &d); 700117404Skan} 701117404Skan 702169699Skan/* Try simplify INSN. 703169699Skan Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's 704169699Skan pattern and return true if something was simplified. */ 705169699Skan 706169699Skanbool 707169699Skanvalidate_simplify_insn (rtx insn) 708117404Skan{ 709169699Skan int i; 710169699Skan rtx pat = NULL; 711169699Skan rtx newpat = NULL; 712169699Skan 713169699Skan pat = PATTERN (insn); 714169699Skan 715169699Skan if (GET_CODE (pat) == SET) 716169699Skan { 717169699Skan newpat = simplify_rtx (SET_SRC (pat)); 718169699Skan if (newpat && !rtx_equal_p (SET_SRC (pat), newpat)) 719169699Skan validate_change (insn, &SET_SRC (pat), newpat, 1); 720169699Skan newpat = simplify_rtx (SET_DEST (pat)); 721169699Skan if (newpat && !rtx_equal_p (SET_DEST (pat), newpat)) 722169699Skan validate_change (insn, &SET_DEST (pat), newpat, 1); 723169699Skan } 724169699Skan else if (GET_CODE (pat) == PARALLEL) 725169699Skan for (i = 0; i < XVECLEN (pat, 0); i++) 726169699Skan { 727169699Skan rtx s = XVECEXP (pat, 0, i); 728169699Skan 729169699Skan if (GET_CODE (XVECEXP (pat, 0, i)) == SET) 730169699Skan { 731169699Skan newpat = simplify_rtx (SET_SRC (s)); 732169699Skan if (newpat && !rtx_equal_p (SET_SRC (s), newpat)) 733169699Skan validate_change (insn, &SET_SRC (s), newpat, 1); 734169699Skan newpat = simplify_rtx (SET_DEST (s)); 735169699Skan if (newpat && !rtx_equal_p (SET_DEST (s), newpat)) 736169699Skan validate_change (insn, &SET_DEST (s), newpat, 1); 737169699Skan } 738169699Skan } 739169699Skan return ((num_changes_pending () > 0) && (apply_change_group () > 0)); 74050397Sobrien} 74118334Speter 74218334Speter#ifdef HAVE_cc0 74318334Speter/* Return 1 if the insn using CC0 set by INSN does not contain 74418334Speter any ordered tests applied to the condition codes. 74518334Speter EQ and NE tests do not count. */ 74618334Speter 74718334Speterint 748132727Skannext_insn_tests_no_inequality (rtx insn) 74918334Speter{ 75090075Sobrien rtx next = next_cc0_user (insn); 75118334Speter 75218334Speter /* If there is no next insn, we have to take the conservative choice. */ 75318334Speter if (next == 0) 75418334Speter return 0; 75518334Speter 756169699Skan return (INSN_P (next) 75718334Speter && ! inequality_comparisons_p (PATTERN (next))); 75818334Speter} 75918334Speter#endif 76018334Speter 76118334Speter/* This is used by find_single_use to locate an rtx that contains exactly one 76218334Speter use of DEST, which is typically either a REG or CC0. It returns a 76318334Speter pointer to the innermost rtx expression containing DEST. Appearances of 76418334Speter DEST that are being used to totally replace it are not counted. */ 76518334Speter 76618334Speterstatic rtx * 767132727Skanfind_single_use_1 (rtx dest, rtx *loc) 76818334Speter{ 76918334Speter rtx x = *loc; 77018334Speter enum rtx_code code = GET_CODE (x); 77118334Speter rtx *result = 0; 77218334Speter rtx *this_result; 77318334Speter int i; 77490075Sobrien const char *fmt; 77518334Speter 77618334Speter switch (code) 77718334Speter { 77818334Speter case CONST_INT: 77918334Speter case CONST: 78018334Speter case LABEL_REF: 78118334Speter case SYMBOL_REF: 78218334Speter case CONST_DOUBLE: 78396263Sobrien case CONST_VECTOR: 78418334Speter case CLOBBER: 78518334Speter return 0; 78618334Speter 78718334Speter case SET: 78818334Speter /* If the destination is anything other than CC0, PC, a REG or a SUBREG 78918334Speter of a REG that occupies all of the REG, the insn uses DEST if 79018334Speter it is mentioned in the destination or the source. Otherwise, we 79118334Speter need just check the source. */ 79218334Speter if (GET_CODE (SET_DEST (x)) != CC0 79318334Speter && GET_CODE (SET_DEST (x)) != PC 794169699Skan && !REG_P (SET_DEST (x)) 79518334Speter && ! (GET_CODE (SET_DEST (x)) == SUBREG 796169699Skan && REG_P (SUBREG_REG (SET_DEST (x))) 79718334Speter && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x)))) 79818334Speter + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) 79918334Speter == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x))) 80018334Speter + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))) 80118334Speter break; 80218334Speter 80318334Speter return find_single_use_1 (dest, &SET_SRC (x)); 80418334Speter 80518334Speter case MEM: 80618334Speter case SUBREG: 80718334Speter return find_single_use_1 (dest, &XEXP (x, 0)); 808117404Skan 80950397Sobrien default: 81050397Sobrien break; 81118334Speter } 81218334Speter 81318334Speter /* If it wasn't one of the common cases above, check each expression and 81418334Speter vector of this code. Look for a unique usage of DEST. */ 81518334Speter 81618334Speter fmt = GET_RTX_FORMAT (code); 81718334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 81818334Speter { 81918334Speter if (fmt[i] == 'e') 82018334Speter { 82118334Speter if (dest == XEXP (x, i) 822169699Skan || (REG_P (dest) && REG_P (XEXP (x, i)) 82318334Speter && REGNO (dest) == REGNO (XEXP (x, i)))) 82418334Speter this_result = loc; 82518334Speter else 82618334Speter this_result = find_single_use_1 (dest, &XEXP (x, i)); 82718334Speter 82818334Speter if (result == 0) 82918334Speter result = this_result; 83018334Speter else if (this_result) 83118334Speter /* Duplicate usage. */ 83218334Speter return 0; 83318334Speter } 83418334Speter else if (fmt[i] == 'E') 83518334Speter { 83618334Speter int j; 83718334Speter 83818334Speter for (j = XVECLEN (x, i) - 1; j >= 0; j--) 83918334Speter { 84018334Speter if (XVECEXP (x, i, j) == dest 841169699Skan || (REG_P (dest) 842169699Skan && REG_P (XVECEXP (x, i, j)) 84318334Speter && REGNO (XVECEXP (x, i, j)) == REGNO (dest))) 84418334Speter this_result = loc; 84518334Speter else 84618334Speter this_result = find_single_use_1 (dest, &XVECEXP (x, i, j)); 84718334Speter 84818334Speter if (result == 0) 84918334Speter result = this_result; 85018334Speter else if (this_result) 85118334Speter return 0; 85218334Speter } 85318334Speter } 85418334Speter } 85518334Speter 85618334Speter return result; 85718334Speter} 85818334Speter 85918334Speter/* See if DEST, produced in INSN, is used only a single time in the 86018334Speter sequel. If so, return a pointer to the innermost rtx expression in which 86118334Speter it is used. 86218334Speter 863117404Skan If PLOC is nonzero, *PLOC is set to the insn containing the single use. 86418334Speter 86518334Speter This routine will return usually zero either before flow is called (because 86618334Speter there will be no LOG_LINKS notes) or after reload (because the REG_DEAD 86718334Speter note can't be trusted). 86818334Speter 86918334Speter If DEST is cc0_rtx, we look only at the next insn. In that case, we don't 87018334Speter care about REG_DEAD notes or LOG_LINKS. 87118334Speter 87218334Speter Otherwise, we find the single use by finding an insn that has a 87318334Speter LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is 87418334Speter only referenced once in that insn, we know that it must be the first 87518334Speter and last insn referencing DEST. */ 87618334Speter 87718334Speterrtx * 878132727Skanfind_single_use (rtx dest, rtx insn, rtx *ploc) 87918334Speter{ 88018334Speter rtx next; 88118334Speter rtx *result; 88218334Speter rtx link; 88318334Speter 88418334Speter#ifdef HAVE_cc0 88518334Speter if (dest == cc0_rtx) 88618334Speter { 88718334Speter next = NEXT_INSN (insn); 88818334Speter if (next == 0 889169699Skan || (!NONJUMP_INSN_P (next) && !JUMP_P (next))) 89018334Speter return 0; 89118334Speter 89218334Speter result = find_single_use_1 (dest, &PATTERN (next)); 89318334Speter if (result && ploc) 89418334Speter *ploc = next; 89518334Speter return result; 89618334Speter } 89718334Speter#endif 89818334Speter 899169699Skan if (reload_completed || reload_in_progress || !REG_P (dest)) 90018334Speter return 0; 90118334Speter 90218334Speter for (next = next_nonnote_insn (insn); 903169699Skan next != 0 && !LABEL_P (next); 90418334Speter next = next_nonnote_insn (next)) 90590075Sobrien if (INSN_P (next) && dead_or_set_p (next, dest)) 90618334Speter { 90718334Speter for (link = LOG_LINKS (next); link; link = XEXP (link, 1)) 90818334Speter if (XEXP (link, 0) == insn) 90918334Speter break; 91018334Speter 91118334Speter if (link) 91218334Speter { 91318334Speter result = find_single_use_1 (dest, &PATTERN (next)); 91418334Speter if (ploc) 91518334Speter *ploc = next; 91618334Speter return result; 91718334Speter } 91818334Speter } 91918334Speter 92018334Speter return 0; 92118334Speter} 92218334Speter 92318334Speter/* Return 1 if OP is a valid general operand for machine mode MODE. 92418334Speter This is either a register reference, a memory reference, 92518334Speter or a constant. In the case of a memory reference, the address 92618334Speter is checked for general validity for the target machine. 92718334Speter 92818334Speter Register and memory references must have mode MODE in order to be valid, 92918334Speter but some constants have no machine mode and are valid for any mode. 93018334Speter 93118334Speter If MODE is VOIDmode, OP is checked for validity for whatever mode 93218334Speter it has. 93318334Speter 93418334Speter The main use of this function is as a predicate in match_operand 93518334Speter expressions in the machine description. 93618334Speter 93718334Speter For an explanation of this function's behavior for registers of 93818334Speter class NO_REGS, see the comment for `register_operand'. */ 93918334Speter 94018334Speterint 941132727Skangeneral_operand (rtx op, enum machine_mode mode) 94218334Speter{ 94390075Sobrien enum rtx_code code = GET_CODE (op); 94418334Speter 94518334Speter if (mode == VOIDmode) 94618334Speter mode = GET_MODE (op); 94718334Speter 94818334Speter /* Don't accept CONST_INT or anything similar 94918334Speter if the caller wants something floating. */ 95018334Speter if (GET_MODE (op) == VOIDmode && mode != VOIDmode 95118334Speter && GET_MODE_CLASS (mode) != MODE_INT 95218334Speter && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) 95318334Speter return 0; 95418334Speter 95590075Sobrien if (GET_CODE (op) == CONST_INT 956117404Skan && mode != VOIDmode 95790075Sobrien && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) 95890075Sobrien return 0; 95990075Sobrien 96018334Speter if (CONSTANT_P (op)) 96190075Sobrien return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode 96290075Sobrien || mode == VOIDmode) 96318334Speter && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) 96418334Speter && LEGITIMATE_CONSTANT_P (op)); 96518334Speter 96618334Speter /* Except for certain constants with VOIDmode, already checked for, 96718334Speter OP's mode must match MODE if MODE specifies a mode. */ 96818334Speter 96918334Speter if (GET_MODE (op) != mode) 97018334Speter return 0; 97118334Speter 97218334Speter if (code == SUBREG) 97318334Speter { 97499396Sobrien rtx sub = SUBREG_REG (op); 97599396Sobrien 97618334Speter#ifdef INSN_SCHEDULING 97718334Speter /* On machines that have insn scheduling, we want all memory 978169699Skan reference to be explicit, so outlaw paradoxical SUBREGs. 979169699Skan However, we must allow them after reload so that they can 980169699Skan get cleaned up by cleanup_subreg_operands. */ 981169699Skan if (!reload_completed && MEM_P (sub) 98299396Sobrien && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub))) 98318334Speter return 0; 98418334Speter#endif 98590075Sobrien /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory 98690075Sobrien may result in incorrect reference. We should simplify all valid 98790075Sobrien subregs of MEM anyway. But allow this after reload because we 988117404Skan might be called from cleanup_subreg_operands. 98918334Speter 99090075Sobrien ??? This is a kludge. */ 99190075Sobrien if (!reload_completed && SUBREG_BYTE (op) != 0 992169699Skan && MEM_P (sub)) 993117404Skan return 0; 99490075Sobrien 99599396Sobrien /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally 996132727Skan create such rtl, and we must reject it. */ 997169699Skan if (SCALAR_FLOAT_MODE_P (GET_MODE (op)) 99899396Sobrien && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub))) 99999396Sobrien return 0; 100099396Sobrien 100199396Sobrien op = sub; 100218334Speter code = GET_CODE (op); 100318334Speter } 100418334Speter 100518334Speter if (code == REG) 100618334Speter /* A register whose class is NO_REGS is not a general operand. */ 100718334Speter return (REGNO (op) >= FIRST_PSEUDO_REGISTER 100818334Speter || REGNO_REG_CLASS (REGNO (op)) != NO_REGS); 100918334Speter 101018334Speter if (code == MEM) 101118334Speter { 101290075Sobrien rtx y = XEXP (op, 0); 101390075Sobrien 101418334Speter if (! volatile_ok && MEM_VOLATILE_P (op)) 101518334Speter return 0; 101690075Sobrien 1017169699Skan /* Use the mem's mode, since it will be reloaded thus. */ 1018169699Skan if (memory_address_p (GET_MODE (op), y)) 101950397Sobrien return 1; 102018334Speter } 102150397Sobrien 102218334Speter return 0; 102318334Speter} 102418334Speter 102518334Speter/* Return 1 if OP is a valid memory address for a memory reference 102618334Speter of mode MODE. 102718334Speter 102818334Speter The main use of this function is as a predicate in match_operand 102918334Speter expressions in the machine description. */ 103018334Speter 103118334Speterint 1032132727Skanaddress_operand (rtx op, enum machine_mode mode) 103318334Speter{ 103418334Speter return memory_address_p (mode, op); 103518334Speter} 103618334Speter 103718334Speter/* Return 1 if OP is a register reference of mode MODE. 103818334Speter If MODE is VOIDmode, accept a register in any mode. 103918334Speter 104018334Speter The main use of this function is as a predicate in match_operand 104118334Speter expressions in the machine description. 104218334Speter 104318334Speter As a special exception, registers whose class is NO_REGS are 104418334Speter not accepted by `register_operand'. The reason for this change 104518334Speter is to allow the representation of special architecture artifacts 104618334Speter (such as a condition code register) without extending the rtl 104718334Speter definitions. Since registers of class NO_REGS cannot be used 104818334Speter as registers in any case where register classes are examined, 104918334Speter it is most consistent to keep this function from accepting them. */ 105018334Speter 105118334Speterint 1052132727Skanregister_operand (rtx op, enum machine_mode mode) 105318334Speter{ 105418334Speter if (GET_MODE (op) != mode && mode != VOIDmode) 105518334Speter return 0; 105618334Speter 105718334Speter if (GET_CODE (op) == SUBREG) 105818334Speter { 105999396Sobrien rtx sub = SUBREG_REG (op); 106099396Sobrien 106118334Speter /* Before reload, we can allow (SUBREG (MEM...)) as a register operand 106218334Speter because it is guaranteed to be reloaded into one. 106318334Speter Just make sure the MEM is valid in itself. 106418334Speter (Ideally, (SUBREG (MEM)...) should not exist after reload, 106518334Speter but currently it does result from (SUBREG (REG)...) where the 106618334Speter reg went on the stack.) */ 1067169699Skan if (! reload_completed && MEM_P (sub)) 106818334Speter return general_operand (op, mode); 106918334Speter 1070117404Skan#ifdef CANNOT_CHANGE_MODE_CLASS 1071169699Skan if (REG_P (sub) 107299396Sobrien && REGNO (sub) < FIRST_PSEUDO_REGISTER 1073117404Skan && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode) 107499396Sobrien && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT 107599396Sobrien && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT) 107618334Speter return 0; 107718334Speter#endif 107818334Speter 107999396Sobrien /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally 108099396Sobrien create such rtl, and we must reject it. */ 1081169699Skan if (SCALAR_FLOAT_MODE_P (GET_MODE (op)) 108299396Sobrien && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub))) 108399396Sobrien return 0; 108499396Sobrien 108599396Sobrien op = sub; 108618334Speter } 108718334Speter 108818334Speter /* We don't consider registers whose class is NO_REGS 108918334Speter to be a register operand. */ 1090169699Skan return (REG_P (op) 109118334Speter && (REGNO (op) >= FIRST_PSEUDO_REGISTER 109218334Speter || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); 109318334Speter} 109418334Speter 109590075Sobrien/* Return 1 for a register in Pmode; ignore the tested mode. */ 109690075Sobrien 109790075Sobrienint 1098132727Skanpmode_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 109990075Sobrien{ 110090075Sobrien return register_operand (op, Pmode); 110190075Sobrien} 110290075Sobrien 110318334Speter/* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH 110418334Speter or a hard register. */ 110518334Speter 110618334Speterint 1107132727Skanscratch_operand (rtx op, enum machine_mode mode) 110818334Speter{ 110990075Sobrien if (GET_MODE (op) != mode && mode != VOIDmode) 111090075Sobrien return 0; 111190075Sobrien 111290075Sobrien return (GET_CODE (op) == SCRATCH 1113169699Skan || (REG_P (op) 111490075Sobrien && REGNO (op) < FIRST_PSEUDO_REGISTER)); 111518334Speter} 111618334Speter 111718334Speter/* Return 1 if OP is a valid immediate operand for mode MODE. 111818334Speter 111918334Speter The main use of this function is as a predicate in match_operand 112018334Speter expressions in the machine description. */ 112118334Speter 112218334Speterint 1123132727Skanimmediate_operand (rtx op, enum machine_mode mode) 112418334Speter{ 112518334Speter /* Don't accept CONST_INT or anything similar 112618334Speter if the caller wants something floating. */ 112718334Speter if (GET_MODE (op) == VOIDmode && mode != VOIDmode 112818334Speter && GET_MODE_CLASS (mode) != MODE_INT 112918334Speter && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) 113018334Speter return 0; 113118334Speter 113290075Sobrien if (GET_CODE (op) == CONST_INT 1133117404Skan && mode != VOIDmode 113490075Sobrien && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) 113590075Sobrien return 0; 113690075Sobrien 113718334Speter return (CONSTANT_P (op) 113818334Speter && (GET_MODE (op) == mode || mode == VOIDmode 113918334Speter || GET_MODE (op) == VOIDmode) 114018334Speter && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) 114118334Speter && LEGITIMATE_CONSTANT_P (op)); 114218334Speter} 114318334Speter 114418334Speter/* Returns 1 if OP is an operand that is a CONST_INT. */ 114518334Speter 114618334Speterint 1147132727Skanconst_int_operand (rtx op, enum machine_mode mode) 114818334Speter{ 114990075Sobrien if (GET_CODE (op) != CONST_INT) 115090075Sobrien return 0; 115190075Sobrien 115290075Sobrien if (mode != VOIDmode 115390075Sobrien && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) 115490075Sobrien return 0; 115590075Sobrien 115690075Sobrien return 1; 115718334Speter} 115818334Speter 115918334Speter/* Returns 1 if OP is an operand that is a constant integer or constant 116018334Speter floating-point number. */ 116118334Speter 116218334Speterint 1163132727Skanconst_double_operand (rtx op, enum machine_mode mode) 116418334Speter{ 116518334Speter /* Don't accept CONST_INT or anything similar 116618334Speter if the caller wants something floating. */ 116718334Speter if (GET_MODE (op) == VOIDmode && mode != VOIDmode 116818334Speter && GET_MODE_CLASS (mode) != MODE_INT 116918334Speter && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) 117018334Speter return 0; 117118334Speter 117218334Speter return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT) 117318334Speter && (mode == VOIDmode || GET_MODE (op) == mode 117418334Speter || GET_MODE (op) == VOIDmode)); 117518334Speter} 117618334Speter 117718334Speter/* Return 1 if OP is a general operand that is not an immediate operand. */ 117818334Speter 117918334Speterint 1180132727Skannonimmediate_operand (rtx op, enum machine_mode mode) 118118334Speter{ 118218334Speter return (general_operand (op, mode) && ! CONSTANT_P (op)); 118318334Speter} 118418334Speter 118518334Speter/* Return 1 if OP is a register reference or immediate value of mode MODE. */ 118618334Speter 118718334Speterint 1188132727Skannonmemory_operand (rtx op, enum machine_mode mode) 118918334Speter{ 119018334Speter if (CONSTANT_P (op)) 119118334Speter { 119218334Speter /* Don't accept CONST_INT or anything similar 119318334Speter if the caller wants something floating. */ 119418334Speter if (GET_MODE (op) == VOIDmode && mode != VOIDmode 119518334Speter && GET_MODE_CLASS (mode) != MODE_INT 119618334Speter && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) 119718334Speter return 0; 119818334Speter 119990075Sobrien if (GET_CODE (op) == CONST_INT 1200117404Skan && mode != VOIDmode 120190075Sobrien && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) 120290075Sobrien return 0; 120390075Sobrien 120490075Sobrien return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode 120590075Sobrien || mode == VOIDmode) 120618334Speter && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op)) 120718334Speter && LEGITIMATE_CONSTANT_P (op)); 120818334Speter } 120918334Speter 121018334Speter if (GET_MODE (op) != mode && mode != VOIDmode) 121118334Speter return 0; 121218334Speter 121318334Speter if (GET_CODE (op) == SUBREG) 121418334Speter { 121518334Speter /* Before reload, we can allow (SUBREG (MEM...)) as a register operand 121618334Speter because it is guaranteed to be reloaded into one. 121718334Speter Just make sure the MEM is valid in itself. 121818334Speter (Ideally, (SUBREG (MEM)...) should not exist after reload, 121918334Speter but currently it does result from (SUBREG (REG)...) where the 122018334Speter reg went on the stack.) */ 1221169699Skan if (! reload_completed && MEM_P (SUBREG_REG (op))) 122218334Speter return general_operand (op, mode); 122318334Speter op = SUBREG_REG (op); 122418334Speter } 122518334Speter 122618334Speter /* We don't consider registers whose class is NO_REGS 122718334Speter to be a register operand. */ 1228169699Skan return (REG_P (op) 122918334Speter && (REGNO (op) >= FIRST_PSEUDO_REGISTER 123018334Speter || REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); 123118334Speter} 123218334Speter 123318334Speter/* Return 1 if OP is a valid operand that stands for pushing a 123418334Speter value of mode MODE onto the stack. 123518334Speter 123618334Speter The main use of this function is as a predicate in match_operand 123718334Speter expressions in the machine description. */ 123818334Speter 123918334Speterint 1240132727Skanpush_operand (rtx op, enum machine_mode mode) 124118334Speter{ 124290075Sobrien unsigned int rounded_size = GET_MODE_SIZE (mode); 124390075Sobrien 124490075Sobrien#ifdef PUSH_ROUNDING 124590075Sobrien rounded_size = PUSH_ROUNDING (rounded_size); 124690075Sobrien#endif 124790075Sobrien 1248169699Skan if (!MEM_P (op)) 124918334Speter return 0; 125018334Speter 125152284Sobrien if (mode != VOIDmode && GET_MODE (op) != mode) 125218334Speter return 0; 125318334Speter 125418334Speter op = XEXP (op, 0); 125518334Speter 125690075Sobrien if (rounded_size == GET_MODE_SIZE (mode)) 125790075Sobrien { 125890075Sobrien if (GET_CODE (op) != STACK_PUSH_CODE) 125990075Sobrien return 0; 126090075Sobrien } 126190075Sobrien else 126290075Sobrien { 126390075Sobrien if (GET_CODE (op) != PRE_MODIFY 126490075Sobrien || GET_CODE (XEXP (op, 1)) != PLUS 126590075Sobrien || XEXP (XEXP (op, 1), 0) != XEXP (op, 0) 126690075Sobrien || GET_CODE (XEXP (XEXP (op, 1), 1)) != CONST_INT 126790075Sobrien#ifdef STACK_GROWS_DOWNWARD 126890075Sobrien || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size 126990075Sobrien#else 1270132727Skan || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size 127190075Sobrien#endif 127290075Sobrien ) 127390075Sobrien return 0; 127490075Sobrien } 127518334Speter 127618334Speter return XEXP (op, 0) == stack_pointer_rtx; 127718334Speter} 127818334Speter 127952284Sobrien/* Return 1 if OP is a valid operand that stands for popping a 128052284Sobrien value of mode MODE off the stack. 128152284Sobrien 128252284Sobrien The main use of this function is as a predicate in match_operand 128352284Sobrien expressions in the machine description. */ 128452284Sobrien 128552284Sobrienint 1286132727Skanpop_operand (rtx op, enum machine_mode mode) 128752284Sobrien{ 1288169699Skan if (!MEM_P (op)) 128952284Sobrien return 0; 129052284Sobrien 129152284Sobrien if (mode != VOIDmode && GET_MODE (op) != mode) 129252284Sobrien return 0; 129352284Sobrien 129452284Sobrien op = XEXP (op, 0); 129552284Sobrien 129652284Sobrien if (GET_CODE (op) != STACK_POP_CODE) 129752284Sobrien return 0; 129852284Sobrien 129952284Sobrien return XEXP (op, 0) == stack_pointer_rtx; 130052284Sobrien} 130152284Sobrien 130218334Speter/* Return 1 if ADDR is a valid memory address for mode MODE. */ 130318334Speter 130418334Speterint 1305132727Skanmemory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr) 130618334Speter{ 130718334Speter GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); 130818334Speter return 0; 130918334Speter 131018334Speter win: 131118334Speter return 1; 131218334Speter} 131318334Speter 131418334Speter/* Return 1 if OP is a valid memory reference with mode MODE, 131518334Speter including a valid address. 131618334Speter 131718334Speter The main use of this function is as a predicate in match_operand 131818334Speter expressions in the machine description. */ 131918334Speter 132018334Speterint 1321132727Skanmemory_operand (rtx op, enum machine_mode mode) 132218334Speter{ 132318334Speter rtx inner; 132418334Speter 132518334Speter if (! reload_completed) 132618334Speter /* Note that no SUBREG is a memory operand before end of reload pass, 132718334Speter because (SUBREG (MEM...)) forces reloading into a register. */ 1328169699Skan return MEM_P (op) && general_operand (op, mode); 132918334Speter 133018334Speter if (mode != VOIDmode && GET_MODE (op) != mode) 133118334Speter return 0; 133218334Speter 133318334Speter inner = op; 133418334Speter if (GET_CODE (inner) == SUBREG) 133518334Speter inner = SUBREG_REG (inner); 133618334Speter 1337169699Skan return (MEM_P (inner) && general_operand (op, mode)); 133818334Speter} 133918334Speter 134018334Speter/* Return 1 if OP is a valid indirect memory reference with mode MODE; 134118334Speter that is, a memory reference whose address is a general_operand. */ 134218334Speter 134318334Speterint 1344132727Skanindirect_operand (rtx op, enum machine_mode mode) 134518334Speter{ 134618334Speter /* Before reload, a SUBREG isn't in memory (see memory_operand, above). */ 134718334Speter if (! reload_completed 1348169699Skan && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) 134918334Speter { 135090075Sobrien int offset = SUBREG_BYTE (op); 135118334Speter rtx inner = SUBREG_REG (op); 135218334Speter 135318334Speter if (mode != VOIDmode && GET_MODE (op) != mode) 135418334Speter return 0; 135518334Speter 135618334Speter /* The only way that we can have a general_operand as the resulting 135718334Speter address is if OFFSET is zero and the address already is an operand 135818334Speter or if the address is (plus Y (const_int -OFFSET)) and Y is an 135918334Speter operand. */ 136018334Speter 136118334Speter return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode)) 136218334Speter || (GET_CODE (XEXP (inner, 0)) == PLUS 136318334Speter && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT 136418334Speter && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset 136518334Speter && general_operand (XEXP (XEXP (inner, 0), 0), Pmode))); 136618334Speter } 136718334Speter 1368169699Skan return (MEM_P (op) 136918334Speter && memory_operand (op, mode) 137018334Speter && general_operand (XEXP (op, 0), Pmode)); 137118334Speter} 137218334Speter 137318334Speter/* Return 1 if this is a comparison operator. This allows the use of 137418334Speter MATCH_OPERATOR to recognize all the branch insns. */ 137518334Speter 137618334Speterint 1377132727Skancomparison_operator (rtx op, enum machine_mode mode) 137818334Speter{ 137918334Speter return ((mode == VOIDmode || GET_MODE (op) == mode) 1380169699Skan && COMPARISON_P (op)); 138118334Speter} 138218334Speter 138318334Speter/* If BODY is an insn body that uses ASM_OPERANDS, 138418334Speter return the number of operands (both input and output) in the insn. 138518334Speter Otherwise return -1. */ 138618334Speter 138718334Speterint 1388132727Skanasm_noperands (rtx body) 138918334Speter{ 139090075Sobrien switch (GET_CODE (body)) 139118334Speter { 139290075Sobrien case ASM_OPERANDS: 139390075Sobrien /* No output operands: return number of input operands. */ 139490075Sobrien return ASM_OPERANDS_INPUT_LENGTH (body); 139590075Sobrien case SET: 139690075Sobrien if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS) 139790075Sobrien /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */ 139890075Sobrien return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1; 139990075Sobrien else 140090075Sobrien return -1; 140190075Sobrien case PARALLEL: 140290075Sobrien if (GET_CODE (XVECEXP (body, 0, 0)) == SET 140390075Sobrien && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) 140418334Speter { 140590075Sobrien /* Multiple output operands, or 1 output plus some clobbers: 140690075Sobrien body is [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */ 140790075Sobrien int i; 140890075Sobrien int n_sets; 140918334Speter 141090075Sobrien /* Count backwards through CLOBBERs to determine number of SETs. */ 141190075Sobrien for (i = XVECLEN (body, 0); i > 0; i--) 141290075Sobrien { 141390075Sobrien if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET) 141490075Sobrien break; 141590075Sobrien if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER) 141690075Sobrien return -1; 141790075Sobrien } 141818334Speter 141990075Sobrien /* N_SETS is now number of output operands. */ 142090075Sobrien n_sets = i; 142190075Sobrien 142290075Sobrien /* Verify that all the SETs we have 142390075Sobrien came from a single original asm_operands insn 142490075Sobrien (so that invalid combinations are blocked). */ 142590075Sobrien for (i = 0; i < n_sets; i++) 142690075Sobrien { 142790075Sobrien rtx elt = XVECEXP (body, 0, i); 142890075Sobrien if (GET_CODE (elt) != SET) 142990075Sobrien return -1; 143090075Sobrien if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS) 143190075Sobrien return -1; 143290075Sobrien /* If these ASM_OPERANDS rtx's came from different original insns 143390075Sobrien then they aren't allowed together. */ 143490075Sobrien if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt)) 143590075Sobrien != ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0)))) 143690075Sobrien return -1; 143790075Sobrien } 143890075Sobrien return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0))) 143990075Sobrien + n_sets); 144090075Sobrien } 144190075Sobrien else if (GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) 144218334Speter { 144390075Sobrien /* 0 outputs, but some clobbers: 144490075Sobrien body is [(asm_operands ...) (clobber (reg ...))...]. */ 144590075Sobrien int i; 144618334Speter 144790075Sobrien /* Make sure all the other parallel things really are clobbers. */ 144890075Sobrien for (i = XVECLEN (body, 0) - 1; i > 0; i--) 144990075Sobrien if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) 145090075Sobrien return -1; 145118334Speter 145290075Sobrien return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0)); 145390075Sobrien } 145490075Sobrien else 145590075Sobrien return -1; 145690075Sobrien default: 145790075Sobrien return -1; 145818334Speter } 145918334Speter} 146018334Speter 146118334Speter/* Assuming BODY is an insn body that uses ASM_OPERANDS, 146218334Speter copy its operands (both input and output) into the vector OPERANDS, 146318334Speter the locations of the operands within the insn into the vector OPERAND_LOCS, 146418334Speter and the constraints for the operands into CONSTRAINTS. 146518334Speter Write the modes of the operands into MODES. 146618334Speter Return the assembler-template. 146718334Speter 146818334Speter If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0, 146918334Speter we don't store that info. */ 147018334Speter 147190075Sobrienconst char * 1472132727Skandecode_asm_operands (rtx body, rtx *operands, rtx **operand_locs, 1473132727Skan const char **constraints, enum machine_mode *modes) 147418334Speter{ 147590075Sobrien int i; 147618334Speter int noperands; 147790075Sobrien const char *template = 0; 147818334Speter 147918334Speter if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) 148018334Speter { 148118334Speter rtx asmop = SET_SRC (body); 148218334Speter /* Single output operand: BODY is (set OUTPUT (asm_operands ....)). */ 148318334Speter 148418334Speter noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1; 148518334Speter 148618334Speter for (i = 1; i < noperands; i++) 148718334Speter { 148818334Speter if (operand_locs) 148918334Speter operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1); 149018334Speter if (operands) 149118334Speter operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1); 149218334Speter if (constraints) 149318334Speter constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1); 149418334Speter if (modes) 149518334Speter modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1); 149618334Speter } 149718334Speter 149818334Speter /* The output is in the SET. 149918334Speter Its constraint is in the ASM_OPERANDS itself. */ 150018334Speter if (operands) 150118334Speter operands[0] = SET_DEST (body); 150218334Speter if (operand_locs) 150318334Speter operand_locs[0] = &SET_DEST (body); 150418334Speter if (constraints) 150518334Speter constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop); 150618334Speter if (modes) 150718334Speter modes[0] = GET_MODE (SET_DEST (body)); 150818334Speter template = ASM_OPERANDS_TEMPLATE (asmop); 150918334Speter } 151018334Speter else if (GET_CODE (body) == ASM_OPERANDS) 151118334Speter { 151218334Speter rtx asmop = body; 151318334Speter /* No output operands: BODY is (asm_operands ....). */ 151418334Speter 151518334Speter noperands = ASM_OPERANDS_INPUT_LENGTH (asmop); 151618334Speter 151718334Speter /* The input operands are found in the 1st element vector. */ 151818334Speter /* Constraints for inputs are in the 2nd element vector. */ 151918334Speter for (i = 0; i < noperands; i++) 152018334Speter { 152118334Speter if (operand_locs) 152218334Speter operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i); 152318334Speter if (operands) 152418334Speter operands[i] = ASM_OPERANDS_INPUT (asmop, i); 152518334Speter if (constraints) 152618334Speter constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); 152718334Speter if (modes) 152818334Speter modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i); 152918334Speter } 153018334Speter template = ASM_OPERANDS_TEMPLATE (asmop); 153118334Speter } 153218334Speter else if (GET_CODE (body) == PARALLEL 153390075Sobrien && GET_CODE (XVECEXP (body, 0, 0)) == SET 153490075Sobrien && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) 153518334Speter { 153618334Speter rtx asmop = SET_SRC (XVECEXP (body, 0, 0)); 153718334Speter int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */ 153818334Speter int nin = ASM_OPERANDS_INPUT_LENGTH (asmop); 153918334Speter int nout = 0; /* Does not include CLOBBERs. */ 154018334Speter 154118334Speter /* At least one output, plus some CLOBBERs. */ 154218334Speter 154318334Speter /* The outputs are in the SETs. 154418334Speter Their constraints are in the ASM_OPERANDS itself. */ 154518334Speter for (i = 0; i < nparallel; i++) 154618334Speter { 154718334Speter if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) 154818334Speter break; /* Past last SET */ 1549117404Skan 155018334Speter if (operands) 155118334Speter operands[i] = SET_DEST (XVECEXP (body, 0, i)); 155218334Speter if (operand_locs) 155318334Speter operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i)); 155418334Speter if (constraints) 155518334Speter constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1); 155618334Speter if (modes) 155718334Speter modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i))); 155818334Speter nout++; 155918334Speter } 156018334Speter 156118334Speter for (i = 0; i < nin; i++) 156218334Speter { 156318334Speter if (operand_locs) 156418334Speter operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i); 156518334Speter if (operands) 156618334Speter operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i); 156718334Speter if (constraints) 156818334Speter constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); 156918334Speter if (modes) 157018334Speter modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i); 157118334Speter } 157218334Speter 157318334Speter template = ASM_OPERANDS_TEMPLATE (asmop); 157418334Speter } 157518334Speter else if (GET_CODE (body) == PARALLEL 157618334Speter && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) 157718334Speter { 157818334Speter /* No outputs, but some CLOBBERs. */ 157918334Speter 158018334Speter rtx asmop = XVECEXP (body, 0, 0); 158118334Speter int nin = ASM_OPERANDS_INPUT_LENGTH (asmop); 158218334Speter 158318334Speter for (i = 0; i < nin; i++) 158418334Speter { 158518334Speter if (operand_locs) 158618334Speter operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i); 158718334Speter if (operands) 158818334Speter operands[i] = ASM_OPERANDS_INPUT (asmop, i); 158918334Speter if (constraints) 159018334Speter constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); 159118334Speter if (modes) 159218334Speter modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i); 159318334Speter } 159418334Speter 159518334Speter template = ASM_OPERANDS_TEMPLATE (asmop); 159618334Speter } 159718334Speter 159818334Speter return template; 159918334Speter} 160052284Sobrien 1601169699Skan/* Check if an asm_operand matches its constraints. 160252284Sobrien Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */ 160352284Sobrien 160452284Sobrienint 1605132727Skanasm_operand_ok (rtx op, const char *constraint) 160652284Sobrien{ 160752284Sobrien int result = 0; 160852284Sobrien 160952284Sobrien /* Use constrain_operands after reload. */ 1610169699Skan gcc_assert (!reload_completed); 161152284Sobrien 161252284Sobrien while (*constraint) 161352284Sobrien { 1614132727Skan char c = *constraint; 1615132727Skan int len; 161690075Sobrien switch (c) 161752284Sobrien { 1618132727Skan case ',': 1619132727Skan constraint++; 1620132727Skan continue; 162152284Sobrien case '=': 162252284Sobrien case '+': 162352284Sobrien case '*': 162452284Sobrien case '%': 162552284Sobrien case '!': 162652284Sobrien case '#': 162752284Sobrien case '&': 1628132727Skan case '?': 162952284Sobrien break; 163052284Sobrien 163152284Sobrien case '0': case '1': case '2': case '3': case '4': 163252284Sobrien case '5': case '6': case '7': case '8': case '9': 163352284Sobrien /* For best results, our caller should have given us the 163452284Sobrien proper matching constraint, but we can't actually fail 163552284Sobrien the check if they didn't. Indicate that results are 163652284Sobrien inconclusive. */ 1637132727Skan do 163890075Sobrien constraint++; 1639132727Skan while (ISDIGIT (*constraint)); 1640132727Skan if (! result) 1641132727Skan result = -1; 1642132727Skan continue; 164352284Sobrien 164452284Sobrien case 'p': 164552284Sobrien if (address_operand (op, VOIDmode)) 1646132727Skan result = 1; 164752284Sobrien break; 164852284Sobrien 164952284Sobrien case 'm': 165052284Sobrien case 'V': /* non-offsettable */ 165152284Sobrien if (memory_operand (op, VOIDmode)) 1652132727Skan result = 1; 165352284Sobrien break; 165452284Sobrien 165552284Sobrien case 'o': /* offsettable */ 165652284Sobrien if (offsettable_nonstrict_memref_p (op)) 1657132727Skan result = 1; 165852284Sobrien break; 165952284Sobrien 166052284Sobrien case '<': 166152284Sobrien /* ??? Before flow, auto inc/dec insns are not supposed to exist, 166252284Sobrien excepting those that expand_call created. Further, on some 166352284Sobrien machines which do not have generalized auto inc/dec, an inc/dec 166452284Sobrien is not a memory_operand. 166552284Sobrien 166652284Sobrien Match any memory and hope things are resolved after reload. */ 166752284Sobrien 1668169699Skan if (MEM_P (op) 166952284Sobrien && (1 167052284Sobrien || GET_CODE (XEXP (op, 0)) == PRE_DEC 1671117404Skan || GET_CODE (XEXP (op, 0)) == POST_DEC)) 1672132727Skan result = 1; 167352284Sobrien break; 167452284Sobrien 167552284Sobrien case '>': 1676169699Skan if (MEM_P (op) 167752284Sobrien && (1 167852284Sobrien || GET_CODE (XEXP (op, 0)) == PRE_INC 1679117404Skan || GET_CODE (XEXP (op, 0)) == POST_INC)) 1680132727Skan result = 1; 168152284Sobrien break; 168252284Sobrien 168352284Sobrien case 'E': 168452284Sobrien case 'F': 1685117404Skan if (GET_CODE (op) == CONST_DOUBLE 1686117404Skan || (GET_CODE (op) == CONST_VECTOR 1687117404Skan && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT)) 1688132727Skan result = 1; 168952284Sobrien break; 169052284Sobrien 169152284Sobrien case 'G': 169252284Sobrien if (GET_CODE (op) == CONST_DOUBLE 1693132727Skan && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', constraint)) 1694132727Skan result = 1; 169552284Sobrien break; 169652284Sobrien case 'H': 169752284Sobrien if (GET_CODE (op) == CONST_DOUBLE 1698132727Skan && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint)) 1699132727Skan result = 1; 170052284Sobrien break; 170152284Sobrien 170252284Sobrien case 's': 170352284Sobrien if (GET_CODE (op) == CONST_INT 170452284Sobrien || (GET_CODE (op) == CONST_DOUBLE 170552284Sobrien && GET_MODE (op) == VOIDmode)) 170652284Sobrien break; 1707132727Skan /* Fall through. */ 170852284Sobrien 170952284Sobrien case 'i': 1710169699Skan if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))) 1711132727Skan result = 1; 171252284Sobrien break; 171352284Sobrien 171452284Sobrien case 'n': 171552284Sobrien if (GET_CODE (op) == CONST_INT 171652284Sobrien || (GET_CODE (op) == CONST_DOUBLE 171752284Sobrien && GET_MODE (op) == VOIDmode)) 1718132727Skan result = 1; 171952284Sobrien break; 172052284Sobrien 172152284Sobrien case 'I': 172252284Sobrien if (GET_CODE (op) == CONST_INT 1723132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint)) 1724132727Skan result = 1; 172552284Sobrien break; 172652284Sobrien case 'J': 172752284Sobrien if (GET_CODE (op) == CONST_INT 1728132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint)) 1729132727Skan result = 1; 173052284Sobrien break; 173152284Sobrien case 'K': 173252284Sobrien if (GET_CODE (op) == CONST_INT 1733132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint)) 1734132727Skan result = 1; 173552284Sobrien break; 173652284Sobrien case 'L': 173752284Sobrien if (GET_CODE (op) == CONST_INT 1738132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint)) 1739132727Skan result = 1; 174052284Sobrien break; 174152284Sobrien case 'M': 174252284Sobrien if (GET_CODE (op) == CONST_INT 1743132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint)) 1744132727Skan result = 1; 174552284Sobrien break; 174652284Sobrien case 'N': 174752284Sobrien if (GET_CODE (op) == CONST_INT 1748132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint)) 1749132727Skan result = 1; 175052284Sobrien break; 175152284Sobrien case 'O': 175252284Sobrien if (GET_CODE (op) == CONST_INT 1753132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint)) 1754132727Skan result = 1; 175552284Sobrien break; 175652284Sobrien case 'P': 175752284Sobrien if (GET_CODE (op) == CONST_INT 1758132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint)) 1759132727Skan result = 1; 176052284Sobrien break; 176152284Sobrien 176252284Sobrien case 'X': 1763132727Skan result = 1; 1764132727Skan break; 176552284Sobrien 176652284Sobrien case 'g': 176752284Sobrien if (general_operand (op, VOIDmode)) 1768132727Skan result = 1; 176952284Sobrien break; 177052284Sobrien 177190075Sobrien default: 177290075Sobrien /* For all other letters, we first check for a register class, 177390075Sobrien otherwise it is an EXTRA_CONSTRAINT. */ 1774132727Skan if (REG_CLASS_FROM_CONSTRAINT (c, constraint) != NO_REGS) 177590075Sobrien { 177690075Sobrien case 'r': 177790075Sobrien if (GET_MODE (op) == BLKmode) 177890075Sobrien break; 177990075Sobrien if (register_operand (op, VOIDmode)) 1780132727Skan result = 1; 178190075Sobrien } 1782132727Skan#ifdef EXTRA_CONSTRAINT_STR 1783132727Skan else if (EXTRA_CONSTRAINT_STR (op, c, constraint)) 1784132727Skan result = 1; 1785132727Skan else if (EXTRA_MEMORY_CONSTRAINT (c, constraint) 1786132727Skan /* Every memory operand can be reloaded to fit. */ 1787132727Skan && memory_operand (op, VOIDmode)) 1788132727Skan result = 1; 1789132727Skan else if (EXTRA_ADDRESS_CONSTRAINT (c, constraint) 1790132727Skan /* Every address operand can be reloaded to fit. */ 1791132727Skan && address_operand (op, VOIDmode)) 1792132727Skan result = 1; 179352284Sobrien#endif 179452284Sobrien break; 179552284Sobrien } 1796132727Skan len = CONSTRAINT_LEN (c, constraint); 1797132727Skan do 1798132727Skan constraint++; 1799132727Skan while (--len && *constraint); 1800132727Skan if (len) 1801132727Skan return 0; 180252284Sobrien } 180352284Sobrien 180452284Sobrien return result; 180552284Sobrien} 180618334Speter 180718334Speter/* Given an rtx *P, if it is a sum containing an integer constant term, 180818334Speter return the location (type rtx *) of the pointer to that constant term. 180918334Speter Otherwise, return a null pointer. */ 181018334Speter 181190075Sobrienrtx * 1812132727Skanfind_constant_term_loc (rtx *p) 181318334Speter{ 181490075Sobrien rtx *tem; 181590075Sobrien enum rtx_code code = GET_CODE (*p); 181618334Speter 181718334Speter /* If *P IS such a constant term, P is its location. */ 181818334Speter 181918334Speter if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF 182018334Speter || code == CONST) 182118334Speter return p; 182218334Speter 182318334Speter /* Otherwise, if not a sum, it has no constant term. */ 182418334Speter 182518334Speter if (GET_CODE (*p) != PLUS) 182618334Speter return 0; 182718334Speter 182818334Speter /* If one of the summands is constant, return its location. */ 182918334Speter 183018334Speter if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0)) 183118334Speter && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1))) 183218334Speter return p; 183318334Speter 183418334Speter /* Otherwise, check each summand for containing a constant term. */ 183518334Speter 183618334Speter if (XEXP (*p, 0) != 0) 183718334Speter { 183818334Speter tem = find_constant_term_loc (&XEXP (*p, 0)); 183918334Speter if (tem != 0) 184018334Speter return tem; 184118334Speter } 184218334Speter 184318334Speter if (XEXP (*p, 1) != 0) 184418334Speter { 184518334Speter tem = find_constant_term_loc (&XEXP (*p, 1)); 184618334Speter if (tem != 0) 184718334Speter return tem; 184818334Speter } 184918334Speter 185018334Speter return 0; 185118334Speter} 185218334Speter 185318334Speter/* Return 1 if OP is a memory reference 185418334Speter whose address contains no side effects 185518334Speter and remains valid after the addition 185618334Speter of a positive integer less than the 185718334Speter size of the object being referenced. 185818334Speter 185918334Speter We assume that the original address is valid and do not check it. 186018334Speter 186118334Speter This uses strict_memory_address_p as a subroutine, so 186218334Speter don't use it before reload. */ 186318334Speter 186418334Speterint 1865132727Skanoffsettable_memref_p (rtx op) 186618334Speter{ 1867169699Skan return ((MEM_P (op)) 186818334Speter && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0))); 186918334Speter} 187018334Speter 187118334Speter/* Similar, but don't require a strictly valid mem ref: 187218334Speter consider pseudo-regs valid as index or base regs. */ 187318334Speter 187418334Speterint 1875132727Skanoffsettable_nonstrict_memref_p (rtx op) 187618334Speter{ 1877169699Skan return ((MEM_P (op)) 187818334Speter && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0))); 187918334Speter} 188018334Speter 188118334Speter/* Return 1 if Y is a memory address which contains no side effects 188218334Speter and would remain valid after the addition of a positive integer 188318334Speter less than the size of that mode. 188418334Speter 188518334Speter We assume that the original address is valid and do not check it. 188618334Speter We do check that it is valid for narrower modes. 188718334Speter 188818334Speter If STRICTP is nonzero, we require a strictly valid address, 188918334Speter for the sake of use in reload.c. */ 189018334Speter 189118334Speterint 1892132727Skanoffsettable_address_p (int strictp, enum machine_mode mode, rtx y) 189318334Speter{ 189490075Sobrien enum rtx_code ycode = GET_CODE (y); 189590075Sobrien rtx z; 189618334Speter rtx y1 = y; 189718334Speter rtx *y2; 1898132727Skan int (*addressp) (enum machine_mode, rtx) = 189990075Sobrien (strictp ? strict_memory_address_p : memory_address_p); 190090075Sobrien unsigned int mode_sz = GET_MODE_SIZE (mode); 190118334Speter 190218334Speter if (CONSTANT_ADDRESS_P (y)) 190318334Speter return 1; 190418334Speter 190518334Speter /* Adjusting an offsettable address involves changing to a narrower mode. 190618334Speter Make sure that's OK. */ 190718334Speter 190818334Speter if (mode_dependent_address_p (y)) 190918334Speter return 0; 191018334Speter 191190075Sobrien /* ??? How much offset does an offsettable BLKmode reference need? 191290075Sobrien Clearly that depends on the situation in which it's being used. 191390075Sobrien However, the current situation in which we test 0xffffffff is 191490075Sobrien less than ideal. Caveat user. */ 191590075Sobrien if (mode_sz == 0) 191690075Sobrien mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT; 191790075Sobrien 191818334Speter /* If the expression contains a constant term, 191918334Speter see if it remains valid when max possible offset is added. */ 192018334Speter 192118334Speter if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1))) 192218334Speter { 192318334Speter int good; 192418334Speter 192518334Speter y1 = *y2; 192690075Sobrien *y2 = plus_constant (*y2, mode_sz - 1); 192718334Speter /* Use QImode because an odd displacement may be automatically invalid 192818334Speter for any wider mode. But it should be valid for a single byte. */ 192918334Speter good = (*addressp) (QImode, y); 193018334Speter 193118334Speter /* In any case, restore old contents of memory. */ 193218334Speter *y2 = y1; 193318334Speter return good; 193418334Speter } 193518334Speter 1936169699Skan if (GET_RTX_CLASS (ycode) == RTX_AUTOINC) 193718334Speter return 0; 193818334Speter 193918334Speter /* The offset added here is chosen as the maximum offset that 194018334Speter any instruction could need to add when operating on something 194118334Speter of the specified mode. We assume that if Y and Y+c are 194290075Sobrien valid addresses then so is Y+d for all 0<d<c. adjust_address will 194390075Sobrien go inside a LO_SUM here, so we do so as well. */ 194496263Sobrien if (GET_CODE (y) == LO_SUM 194596263Sobrien && mode != BLKmode 194696263Sobrien && mode_sz <= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT) 194790075Sobrien z = gen_rtx_LO_SUM (GET_MODE (y), XEXP (y, 0), 194890075Sobrien plus_constant (XEXP (y, 1), mode_sz - 1)); 194990075Sobrien else 195090075Sobrien z = plus_constant (y, mode_sz - 1); 195118334Speter 195218334Speter /* Use QImode because an odd displacement may be automatically invalid 195318334Speter for any wider mode. But it should be valid for a single byte. */ 195418334Speter return (*addressp) (QImode, z); 195518334Speter} 195618334Speter 195718334Speter/* Return 1 if ADDR is an address-expression whose effect depends 195818334Speter on the mode of the memory reference it is used in. 195918334Speter 196018334Speter Autoincrement addressing is a typical example of mode-dependence 196118334Speter because the amount of the increment depends on the mode. */ 196218334Speter 196318334Speterint 1964132727Skanmode_dependent_address_p (rtx addr ATTRIBUTE_UNUSED /* Maybe used in GO_IF_MODE_DEPENDENT_ADDRESS. */) 196518334Speter{ 196618334Speter GO_IF_MODE_DEPENDENT_ADDRESS (addr, win); 196718334Speter return 0; 196890075Sobrien /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS. */ 196952284Sobrien win: ATTRIBUTE_UNUSED_LABEL 197018334Speter return 1; 197118334Speter} 197290075Sobrien 197390075Sobrien/* Like extract_insn, but save insn extracted and don't extract again, when 197490075Sobrien called again for the same insn expecting that recog_data still contain the 197590075Sobrien valid information. This is used primary by gen_attr infrastructure that 197690075Sobrien often does extract insn again and again. */ 197790075Sobrienvoid 1978132727Skanextract_insn_cached (rtx insn) 197918334Speter{ 198090075Sobrien if (recog_data.insn == insn && INSN_CODE (insn) >= 0) 198190075Sobrien return; 198290075Sobrien extract_insn (insn); 198390075Sobrien recog_data.insn = insn; 198418334Speter} 1985169699Skan 1986132727Skan/* Do cached extract_insn, constrain_operands and complain about failures. 198790075Sobrien Used by insn_attrtab. */ 198890075Sobrienvoid 1989132727Skanextract_constrain_insn_cached (rtx insn) 199090075Sobrien{ 199190075Sobrien extract_insn_cached (insn); 199290075Sobrien if (which_alternative == -1 199390075Sobrien && !constrain_operands (reload_completed)) 199490075Sobrien fatal_insn_not_found (insn); 199590075Sobrien} 1996169699Skan 1997132727Skan/* Do cached constrain_operands and complain about failures. */ 199890075Sobrienint 1999132727Skanconstrain_operands_cached (int strict) 200090075Sobrien{ 200190075Sobrien if (which_alternative == -1) 200290075Sobrien return constrain_operands (strict); 200390075Sobrien else 200490075Sobrien return 1; 200590075Sobrien} 200618334Speter 200790075Sobrien/* Analyze INSN and fill in recog_data. */ 200890075Sobrien 200952284Sobrienvoid 2010132727Skanextract_insn (rtx insn) 201152284Sobrien{ 201252284Sobrien int i; 201352284Sobrien int icode; 201452284Sobrien int noperands; 201552284Sobrien rtx body = PATTERN (insn); 201652284Sobrien 201790075Sobrien recog_data.insn = NULL; 201890075Sobrien recog_data.n_operands = 0; 201990075Sobrien recog_data.n_alternatives = 0; 202090075Sobrien recog_data.n_dups = 0; 202190075Sobrien which_alternative = -1; 202252284Sobrien 202352284Sobrien switch (GET_CODE (body)) 202452284Sobrien { 202552284Sobrien case USE: 202652284Sobrien case CLOBBER: 202752284Sobrien case ASM_INPUT: 202852284Sobrien case ADDR_VEC: 202952284Sobrien case ADDR_DIFF_VEC: 203052284Sobrien return; 203152284Sobrien 203252284Sobrien case SET: 203390075Sobrien if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS) 203490075Sobrien goto asm_insn; 203590075Sobrien else 203690075Sobrien goto normal_insn; 203752284Sobrien case PARALLEL: 203890075Sobrien if ((GET_CODE (XVECEXP (body, 0, 0)) == SET 203990075Sobrien && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) 204090075Sobrien || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) 204190075Sobrien goto asm_insn; 204290075Sobrien else 204390075Sobrien goto normal_insn; 204452284Sobrien case ASM_OPERANDS: 204590075Sobrien asm_insn: 204690075Sobrien recog_data.n_operands = noperands = asm_noperands (body); 204752284Sobrien if (noperands >= 0) 204852284Sobrien { 204952284Sobrien /* This insn is an `asm' with operands. */ 205052284Sobrien 205152284Sobrien /* expand_asm_operands makes sure there aren't too many operands. */ 2052169699Skan gcc_assert (noperands <= MAX_RECOG_OPERANDS); 205352284Sobrien 205452284Sobrien /* Now get the operand values and constraints out of the insn. */ 205590075Sobrien decode_asm_operands (body, recog_data.operand, 205690075Sobrien recog_data.operand_loc, 205790075Sobrien recog_data.constraints, 205890075Sobrien recog_data.operand_mode); 205952284Sobrien if (noperands > 0) 206052284Sobrien { 206190075Sobrien const char *p = recog_data.constraints[0]; 206290075Sobrien recog_data.n_alternatives = 1; 206352284Sobrien while (*p) 206490075Sobrien recog_data.n_alternatives += (*p++ == ','); 206552284Sobrien } 206652284Sobrien break; 206752284Sobrien } 206890075Sobrien fatal_insn_not_found (insn); 206952284Sobrien 207052284Sobrien default: 207190075Sobrien normal_insn: 207252284Sobrien /* Ordinary insn: recognize it, get the operands via insn_extract 207352284Sobrien and get the constraints. */ 207452284Sobrien 207552284Sobrien icode = recog_memoized (insn); 207652284Sobrien if (icode < 0) 207752284Sobrien fatal_insn_not_found (insn); 207852284Sobrien 207990075Sobrien recog_data.n_operands = noperands = insn_data[icode].n_operands; 208090075Sobrien recog_data.n_alternatives = insn_data[icode].n_alternatives; 208190075Sobrien recog_data.n_dups = insn_data[icode].n_dups; 208252284Sobrien 208352284Sobrien insn_extract (insn); 208452284Sobrien 208552284Sobrien for (i = 0; i < noperands; i++) 208652284Sobrien { 208790075Sobrien recog_data.constraints[i] = insn_data[icode].operand[i].constraint; 208890075Sobrien recog_data.operand_mode[i] = insn_data[icode].operand[i].mode; 208990075Sobrien /* VOIDmode match_operands gets mode from their real operand. */ 209090075Sobrien if (recog_data.operand_mode[i] == VOIDmode) 209190075Sobrien recog_data.operand_mode[i] = GET_MODE (recog_data.operand[i]); 209252284Sobrien } 209352284Sobrien } 209452284Sobrien for (i = 0; i < noperands; i++) 209590075Sobrien recog_data.operand_type[i] 209690075Sobrien = (recog_data.constraints[i][0] == '=' ? OP_OUT 209790075Sobrien : recog_data.constraints[i][0] == '+' ? OP_INOUT 209890075Sobrien : OP_IN); 209918334Speter 2100169699Skan gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES); 210152284Sobrien} 210252284Sobrien 210352284Sobrien/* After calling extract_insn, you can use this function to extract some 210452284Sobrien information from the constraint strings into a more usable form. 210552284Sobrien The collected data is stored in recog_op_alt. */ 210652284Sobrienvoid 2107132727Skanpreprocess_constraints (void) 210852284Sobrien{ 210952284Sobrien int i; 211052284Sobrien 211190075Sobrien for (i = 0; i < recog_data.n_operands; i++) 2112132727Skan memset (recog_op_alt[i], 0, (recog_data.n_alternatives 2113132727Skan * sizeof (struct operand_alternative))); 2114132727Skan 2115132727Skan for (i = 0; i < recog_data.n_operands; i++) 211652284Sobrien { 211752284Sobrien int j; 211852284Sobrien struct operand_alternative *op_alt; 211990075Sobrien const char *p = recog_data.constraints[i]; 212052284Sobrien 212152284Sobrien op_alt = recog_op_alt[i]; 212252284Sobrien 212390075Sobrien for (j = 0; j < recog_data.n_alternatives; j++) 212452284Sobrien { 2125169699Skan op_alt[j].cl = NO_REGS; 212652284Sobrien op_alt[j].constraint = p; 212752284Sobrien op_alt[j].matches = -1; 212852284Sobrien op_alt[j].matched = -1; 212952284Sobrien 213052284Sobrien if (*p == '\0' || *p == ',') 213152284Sobrien { 213252284Sobrien op_alt[j].anything_ok = 1; 213352284Sobrien continue; 213452284Sobrien } 213552284Sobrien 213652284Sobrien for (;;) 213752284Sobrien { 2138132727Skan char c = *p; 213952284Sobrien if (c == '#') 214052284Sobrien do 2141132727Skan c = *++p; 214252284Sobrien while (c != ',' && c != '\0'); 214352284Sobrien if (c == ',' || c == '\0') 2144132727Skan { 2145132727Skan p++; 2146132727Skan break; 2147132727Skan } 214852284Sobrien 214952284Sobrien switch (c) 215052284Sobrien { 215152284Sobrien case '=': case '+': case '*': case '%': 215252284Sobrien case 'E': case 'F': case 'G': case 'H': 215352284Sobrien case 's': case 'i': case 'n': 215452284Sobrien case 'I': case 'J': case 'K': case 'L': 215552284Sobrien case 'M': case 'N': case 'O': case 'P': 215652284Sobrien /* These don't say anything we care about. */ 215752284Sobrien break; 215852284Sobrien 215952284Sobrien case '?': 216052284Sobrien op_alt[j].reject += 6; 216152284Sobrien break; 216252284Sobrien case '!': 216352284Sobrien op_alt[j].reject += 600; 216452284Sobrien break; 216552284Sobrien case '&': 216652284Sobrien op_alt[j].earlyclobber = 1; 2167117404Skan break; 216852284Sobrien 216952284Sobrien case '0': case '1': case '2': case '3': case '4': 217052284Sobrien case '5': case '6': case '7': case '8': case '9': 217190075Sobrien { 217290075Sobrien char *end; 2173132727Skan op_alt[j].matches = strtoul (p, &end, 10); 217490075Sobrien recog_op_alt[op_alt[j].matches][j].matched = i; 217590075Sobrien p = end; 217690075Sobrien } 2177132727Skan continue; 217852284Sobrien 217952284Sobrien case 'm': 218052284Sobrien op_alt[j].memory_ok = 1; 218152284Sobrien break; 218252284Sobrien case '<': 218352284Sobrien op_alt[j].decmem_ok = 1; 218452284Sobrien break; 218552284Sobrien case '>': 218652284Sobrien op_alt[j].incmem_ok = 1; 218752284Sobrien break; 218852284Sobrien case 'V': 218952284Sobrien op_alt[j].nonoffmem_ok = 1; 219052284Sobrien break; 219152284Sobrien case 'o': 219252284Sobrien op_alt[j].offmem_ok = 1; 219352284Sobrien break; 219452284Sobrien case 'X': 219552284Sobrien op_alt[j].anything_ok = 1; 219652284Sobrien break; 219752284Sobrien 219852284Sobrien case 'p': 219990075Sobrien op_alt[j].is_address = 1; 2200169699Skan op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl] 2201169699Skan [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)]; 220252284Sobrien break; 220352284Sobrien 2204169699Skan case 'g': 2205169699Skan case 'r': 2206169699Skan op_alt[j].cl = 2207169699Skan reg_class_subunion[(int) op_alt[j].cl][(int) GENERAL_REGS]; 220852284Sobrien break; 220952284Sobrien 221052284Sobrien default: 2211132727Skan if (EXTRA_MEMORY_CONSTRAINT (c, p)) 2212117404Skan { 2213117404Skan op_alt[j].memory_ok = 1; 2214117404Skan break; 2215117404Skan } 2216132727Skan if (EXTRA_ADDRESS_CONSTRAINT (c, p)) 2217117404Skan { 2218117404Skan op_alt[j].is_address = 1; 2219169699Skan op_alt[j].cl 2220132727Skan = (reg_class_subunion 2221169699Skan [(int) op_alt[j].cl] 2222169699Skan [(int) base_reg_class (VOIDmode, ADDRESS, 2223169699Skan SCRATCH)]); 2224117404Skan break; 2225117404Skan } 2226117404Skan 2227169699Skan op_alt[j].cl 2228132727Skan = (reg_class_subunion 2229169699Skan [(int) op_alt[j].cl] 2230132727Skan [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]); 223152284Sobrien break; 223252284Sobrien } 2233132727Skan p += CONSTRAINT_LEN (c, p); 223452284Sobrien } 223552284Sobrien } 223652284Sobrien } 223752284Sobrien} 2238117404Skan 223952284Sobrien/* Check the operands of an insn against the insn's operand constraints 224018334Speter and return 1 if they are valid. 224152284Sobrien The information about the insn's operands, constraints, operand modes 224252284Sobrien etc. is obtained from the global variables set up by extract_insn. 224318334Speter 224418334Speter WHICH_ALTERNATIVE is set to a number which indicates which 224518334Speter alternative of constraints was matched: 0 for the first alternative, 224618334Speter 1 for the next, etc. 224718334Speter 2248132727Skan In addition, when two operands are required to match 224918334Speter and it happens that the output operand is (reg) while the 225018334Speter input operand is --(reg) or ++(reg) (a pre-inc or pre-dec), 225118334Speter make the output operand look like the input. 225218334Speter This is because the output operand is the one the template will print. 225318334Speter 225418334Speter This is used in final, just before printing the assembler code and by 225518334Speter the routines that determine an insn's attribute. 225618334Speter 2257117404Skan If STRICT is a positive nonzero value, it means that we have been 225818334Speter called after reload has been completed. In that case, we must 225918334Speter do all checks strictly. If it is zero, it means that we have been called 226018334Speter before reload has completed. In that case, we first try to see if we can 226118334Speter find an alternative that matches strictly. If not, we try again, this 226218334Speter time assuming that reload will fix up the insn. This provides a "best 226318334Speter guess" for the alternative and is used to compute attributes of insns prior 226418334Speter to reload. A negative value of STRICT is used for this internal call. */ 226518334Speter 226618334Speterstruct funny_match 226718334Speter{ 226818334Speter int this, other; 226918334Speter}; 227018334Speter 227118334Speterint 2272132727Skanconstrain_operands (int strict) 227318334Speter{ 227452284Sobrien const char *constraints[MAX_RECOG_OPERANDS]; 227518334Speter int matching_operands[MAX_RECOG_OPERANDS]; 227618334Speter int earlyclobber[MAX_RECOG_OPERANDS]; 227790075Sobrien int c; 227818334Speter 227918334Speter struct funny_match funny_match[MAX_RECOG_OPERANDS]; 228018334Speter int funny_match_index; 228118334Speter 228290075Sobrien which_alternative = 0; 228390075Sobrien if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0) 228418334Speter return 1; 228518334Speter 228690075Sobrien for (c = 0; c < recog_data.n_operands; c++) 228718334Speter { 228890075Sobrien constraints[c] = recog_data.constraints[c]; 228918334Speter matching_operands[c] = -1; 229018334Speter } 229118334Speter 229290075Sobrien do 229318334Speter { 2294169699Skan int seen_earlyclobber_at = -1; 229590075Sobrien int opno; 229618334Speter int lose = 0; 229718334Speter funny_match_index = 0; 229818334Speter 229990075Sobrien for (opno = 0; opno < recog_data.n_operands; opno++) 230018334Speter { 230190075Sobrien rtx op = recog_data.operand[opno]; 230218334Speter enum machine_mode mode = GET_MODE (op); 230390075Sobrien const char *p = constraints[opno]; 230418334Speter int offset = 0; 230518334Speter int win = 0; 230618334Speter int val; 2307132727Skan int len; 230818334Speter 230918334Speter earlyclobber[opno] = 0; 231018334Speter 231150397Sobrien /* A unary operator may be accepted by the predicate, but it 231250397Sobrien is irrelevant for matching constraints. */ 2313169699Skan if (UNARY_P (op)) 231450397Sobrien op = XEXP (op, 0); 231550397Sobrien 231618334Speter if (GET_CODE (op) == SUBREG) 231718334Speter { 2318169699Skan if (REG_P (SUBREG_REG (op)) 231918334Speter && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER) 232090075Sobrien offset = subreg_regno_offset (REGNO (SUBREG_REG (op)), 232190075Sobrien GET_MODE (SUBREG_REG (op)), 232290075Sobrien SUBREG_BYTE (op), 232390075Sobrien GET_MODE (op)); 232418334Speter op = SUBREG_REG (op); 232518334Speter } 232618334Speter 232718334Speter /* An empty constraint or empty alternative 232818334Speter allows anything which matched the pattern. */ 232918334Speter if (*p == 0 || *p == ',') 233018334Speter win = 1; 233118334Speter 2332132727Skan do 2333132727Skan switch (c = *p, len = CONSTRAINT_LEN (c, p), c) 233418334Speter { 2335132727Skan case '\0': 2336132727Skan len = 0; 2337132727Skan break; 2338132727Skan case ',': 2339132727Skan c = '\0'; 2340132727Skan break; 2341132727Skan 234290075Sobrien case '?': case '!': case '*': case '%': 234390075Sobrien case '=': case '+': 234418334Speter break; 234518334Speter 234618334Speter case '#': 234718334Speter /* Ignore rest of this alternative as far as 234818334Speter constraint checking is concerned. */ 2349132727Skan do 235018334Speter p++; 2351132727Skan while (*p && *p != ','); 2352132727Skan len = 0; 235318334Speter break; 235418334Speter 235518334Speter case '&': 235618334Speter earlyclobber[opno] = 1; 2357169699Skan if (seen_earlyclobber_at < 0) 2358169699Skan seen_earlyclobber_at = opno; 235918334Speter break; 236018334Speter 236190075Sobrien case '0': case '1': case '2': case '3': case '4': 236290075Sobrien case '5': case '6': case '7': case '8': case '9': 236390075Sobrien { 236490075Sobrien /* This operand must be the same as a previous one. 236590075Sobrien This kind of constraint is used for instructions such 236690075Sobrien as add when they take only two operands. 236718334Speter 236890075Sobrien Note that the lower-numbered operand is passed first. 236918334Speter 237090075Sobrien If we are not testing strictly, assume that this 237190075Sobrien constraint will be satisfied. */ 237218334Speter 237390075Sobrien char *end; 237490075Sobrien int match; 237552284Sobrien 2376132727Skan match = strtoul (p, &end, 10); 237790075Sobrien p = end; 237852284Sobrien 237990075Sobrien if (strict < 0) 238090075Sobrien val = 1; 238190075Sobrien else 238290075Sobrien { 238390075Sobrien rtx op1 = recog_data.operand[match]; 238490075Sobrien rtx op2 = recog_data.operand[opno]; 238518334Speter 238690075Sobrien /* A unary operator may be accepted by the predicate, 238790075Sobrien but it is irrelevant for matching constraints. */ 2388169699Skan if (UNARY_P (op1)) 238990075Sobrien op1 = XEXP (op1, 0); 2390169699Skan if (UNARY_P (op2)) 239190075Sobrien op2 = XEXP (op2, 0); 239290075Sobrien 239390075Sobrien val = operands_match_p (op1, op2); 239490075Sobrien } 239590075Sobrien 239690075Sobrien matching_operands[opno] = match; 239790075Sobrien matching_operands[match] = opno; 239890075Sobrien 239990075Sobrien if (val != 0) 240090075Sobrien win = 1; 240190075Sobrien 240290075Sobrien /* If output is *x and input is *--x, arrange later 240390075Sobrien to change the output to *--x as well, since the 240490075Sobrien output op is the one that will be printed. */ 240590075Sobrien if (val == 2 && strict > 0) 240690075Sobrien { 240790075Sobrien funny_match[funny_match_index].this = opno; 240890075Sobrien funny_match[funny_match_index++].other = match; 240990075Sobrien } 241090075Sobrien } 2411132727Skan len = 0; 241218334Speter break; 241318334Speter 241418334Speter case 'p': 241518334Speter /* p is used for address_operands. When we are called by 241618334Speter gen_reload, no one will have checked that the address is 241718334Speter strictly valid, i.e., that all pseudos requiring hard regs 241818334Speter have gotten them. */ 241918334Speter if (strict <= 0 242090075Sobrien || (strict_memory_address_p (recog_data.operand_mode[opno], 242152284Sobrien op))) 242218334Speter win = 1; 242318334Speter break; 242418334Speter 242518334Speter /* No need to check general_operand again; 2426169699Skan it was done in insn-recog.c. Well, except that reload 2427169699Skan doesn't check the validity of its replacements, but 2428169699Skan that should only matter when there's a bug. */ 242918334Speter case 'g': 243018334Speter /* Anything goes unless it is a REG and really has a hard reg 243118334Speter but the hard reg is not in the class GENERAL_REGS. */ 2432169699Skan if (REG_P (op)) 2433169699Skan { 2434169699Skan if (strict < 0 2435169699Skan || GENERAL_REGS == ALL_REGS 2436169699Skan || (reload_in_progress 2437169699Skan && REGNO (op) >= FIRST_PSEUDO_REGISTER) 2438169699Skan || reg_fits_class_p (op, GENERAL_REGS, offset, mode)) 2439169699Skan win = 1; 2440169699Skan } 2441169699Skan else if (strict < 0 || general_operand (op, mode)) 244218334Speter win = 1; 244318334Speter break; 244418334Speter 244518334Speter case 'X': 244650397Sobrien /* This is used for a MATCH_SCRATCH in the cases when 244750397Sobrien we don't actually need anything. So anything goes 244850397Sobrien any time. */ 244918334Speter win = 1; 245018334Speter break; 245118334Speter 245218334Speter case 'm': 2453132727Skan /* Memory operands must be valid, to the extent 2454132727Skan required by STRICT. */ 2455169699Skan if (MEM_P (op)) 2456132727Skan { 2457132727Skan if (strict > 0 2458132727Skan && !strict_memory_address_p (GET_MODE (op), 2459132727Skan XEXP (op, 0))) 2460132727Skan break; 2461132727Skan if (strict == 0 2462132727Skan && !memory_address_p (GET_MODE (op), XEXP (op, 0))) 2463132727Skan break; 2464132727Skan win = 1; 2465132727Skan } 2466132727Skan /* Before reload, accept what reload can turn into mem. */ 2467132727Skan else if (strict < 0 && CONSTANT_P (op)) 246818334Speter win = 1; 2469132727Skan /* During reload, accept a pseudo */ 2470169699Skan else if (reload_in_progress && REG_P (op) 2471132727Skan && REGNO (op) >= FIRST_PSEUDO_REGISTER) 2472132727Skan win = 1; 247318334Speter break; 247418334Speter 247518334Speter case '<': 2476169699Skan if (MEM_P (op) 247718334Speter && (GET_CODE (XEXP (op, 0)) == PRE_DEC 247818334Speter || GET_CODE (XEXP (op, 0)) == POST_DEC)) 247918334Speter win = 1; 248018334Speter break; 248118334Speter 248218334Speter case '>': 2483169699Skan if (MEM_P (op) 248418334Speter && (GET_CODE (XEXP (op, 0)) == PRE_INC 248518334Speter || GET_CODE (XEXP (op, 0)) == POST_INC)) 248618334Speter win = 1; 248718334Speter break; 248818334Speter 248918334Speter case 'E': 249018334Speter case 'F': 2491117404Skan if (GET_CODE (op) == CONST_DOUBLE 2492117404Skan || (GET_CODE (op) == CONST_VECTOR 2493117404Skan && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT)) 249418334Speter win = 1; 249518334Speter break; 249618334Speter 249718334Speter case 'G': 249818334Speter case 'H': 249918334Speter if (GET_CODE (op) == CONST_DOUBLE 2500132727Skan && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p)) 250118334Speter win = 1; 250218334Speter break; 250318334Speter 250418334Speter case 's': 250518334Speter if (GET_CODE (op) == CONST_INT 250618334Speter || (GET_CODE (op) == CONST_DOUBLE 250718334Speter && GET_MODE (op) == VOIDmode)) 250818334Speter break; 250918334Speter case 'i': 251018334Speter if (CONSTANT_P (op)) 251118334Speter win = 1; 251218334Speter break; 251318334Speter 251418334Speter case 'n': 251518334Speter if (GET_CODE (op) == CONST_INT 251618334Speter || (GET_CODE (op) == CONST_DOUBLE 251718334Speter && GET_MODE (op) == VOIDmode)) 251818334Speter win = 1; 251918334Speter break; 252018334Speter 252118334Speter case 'I': 252218334Speter case 'J': 252318334Speter case 'K': 252418334Speter case 'L': 252518334Speter case 'M': 252618334Speter case 'N': 252718334Speter case 'O': 252818334Speter case 'P': 252918334Speter if (GET_CODE (op) == CONST_INT 2530132727Skan && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p)) 253118334Speter win = 1; 253218334Speter break; 253318334Speter 253418334Speter case 'V': 2535169699Skan if (MEM_P (op) 253650397Sobrien && ((strict > 0 && ! offsettable_memref_p (op)) 253750397Sobrien || (strict < 0 2538169699Skan && !(CONSTANT_P (op) || MEM_P (op))) 253950397Sobrien || (reload_in_progress 2540169699Skan && !(REG_P (op) 254150397Sobrien && REGNO (op) >= FIRST_PSEUDO_REGISTER)))) 254218334Speter win = 1; 254318334Speter break; 254418334Speter 254518334Speter case 'o': 254618334Speter if ((strict > 0 && offsettable_memref_p (op)) 254718334Speter || (strict == 0 && offsettable_nonstrict_memref_p (op)) 254818334Speter /* Before reload, accept what reload can handle. */ 254918334Speter || (strict < 0 2550169699Skan && (CONSTANT_P (op) || MEM_P (op))) 255118334Speter /* During reload, accept a pseudo */ 2552169699Skan || (reload_in_progress && REG_P (op) 255318334Speter && REGNO (op) >= FIRST_PSEUDO_REGISTER)) 255418334Speter win = 1; 255518334Speter break; 255618334Speter 255718334Speter default: 255890075Sobrien { 2559169699Skan enum reg_class cl; 256090075Sobrien 2561169699Skan cl = (c == 'r' 2562132727Skan ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p)); 2563169699Skan if (cl != NO_REGS) 256490075Sobrien { 256590075Sobrien if (strict < 0 256690075Sobrien || (strict == 0 2567169699Skan && REG_P (op) 256890075Sobrien && REGNO (op) >= FIRST_PSEUDO_REGISTER) 256990075Sobrien || (strict == 0 && GET_CODE (op) == SCRATCH) 2570169699Skan || (REG_P (op) 2571169699Skan && reg_fits_class_p (op, cl, offset, mode))) 257290075Sobrien win = 1; 257390075Sobrien } 2574132727Skan#ifdef EXTRA_CONSTRAINT_STR 2575132727Skan else if (EXTRA_CONSTRAINT_STR (op, c, p)) 257690075Sobrien win = 1; 2577117404Skan 2578132727Skan else if (EXTRA_MEMORY_CONSTRAINT (c, p) 2579132727Skan /* Every memory operand can be reloaded to fit. */ 2580169699Skan && ((strict < 0 && MEM_P (op)) 2581132727Skan /* Before reload, accept what reload can turn 2582132727Skan into mem. */ 2583132727Skan || (strict < 0 && CONSTANT_P (op)) 2584132727Skan /* During reload, accept a pseudo */ 2585169699Skan || (reload_in_progress && REG_P (op) 2586132727Skan && REGNO (op) >= FIRST_PSEUDO_REGISTER))) 2587132727Skan win = 1; 2588132727Skan else if (EXTRA_ADDRESS_CONSTRAINT (c, p) 2589132727Skan /* Every address operand can be reloaded to fit. */ 2590132727Skan && strict < 0) 2591132727Skan win = 1; 259290075Sobrien#endif 259390075Sobrien break; 259490075Sobrien } 259518334Speter } 2596132727Skan while (p += len, c); 259718334Speter 259818334Speter constraints[opno] = p; 259918334Speter /* If this operand did not win somehow, 260018334Speter this alternative loses. */ 260118334Speter if (! win) 260218334Speter lose = 1; 260318334Speter } 260418334Speter /* This alternative won; the operands are ok. 260518334Speter Change whichever operands this alternative says to change. */ 260618334Speter if (! lose) 260718334Speter { 260818334Speter int opno, eopno; 260918334Speter 261018334Speter /* See if any earlyclobber operand conflicts with some other 261118334Speter operand. */ 261218334Speter 2613169699Skan if (strict > 0 && seen_earlyclobber_at >= 0) 2614169699Skan for (eopno = seen_earlyclobber_at; 2615169699Skan eopno < recog_data.n_operands; 2616169699Skan eopno++) 261718334Speter /* Ignore earlyclobber operands now in memory, 261818334Speter because we would often report failure when we have 261918334Speter two memory operands, one of which was formerly a REG. */ 262018334Speter if (earlyclobber[eopno] 2621169699Skan && REG_P (recog_data.operand[eopno])) 262290075Sobrien for (opno = 0; opno < recog_data.n_operands; opno++) 2623169699Skan if ((MEM_P (recog_data.operand[opno]) 262490075Sobrien || recog_data.operand_type[opno] != OP_OUT) 262518334Speter && opno != eopno 262650397Sobrien /* Ignore things like match_operator operands. */ 262790075Sobrien && *recog_data.constraints[opno] != 0 262818334Speter && ! (matching_operands[opno] == eopno 262990075Sobrien && operands_match_p (recog_data.operand[opno], 263090075Sobrien recog_data.operand[eopno])) 263190075Sobrien && ! safe_from_earlyclobber (recog_data.operand[opno], 263290075Sobrien recog_data.operand[eopno])) 263318334Speter lose = 1; 263418334Speter 263518334Speter if (! lose) 263618334Speter { 263718334Speter while (--funny_match_index >= 0) 263818334Speter { 263990075Sobrien recog_data.operand[funny_match[funny_match_index].other] 264090075Sobrien = recog_data.operand[funny_match[funny_match_index].this]; 264118334Speter } 264218334Speter 264318334Speter return 1; 264418334Speter } 264518334Speter } 264618334Speter 264718334Speter which_alternative++; 264818334Speter } 264990075Sobrien while (which_alternative < recog_data.n_alternatives); 265018334Speter 265190075Sobrien which_alternative = -1; 265218334Speter /* If we are about to reject this, but we are not to test strictly, 265318334Speter try a very loose test. Only return failure if it fails also. */ 265418334Speter if (strict == 0) 265552284Sobrien return constrain_operands (-1); 265618334Speter else 265718334Speter return 0; 265818334Speter} 265918334Speter 266018334Speter/* Return 1 iff OPERAND (assumed to be a REG rtx) 266150397Sobrien is a hard reg in class CLASS when its regno is offset by OFFSET 266218334Speter and changed to mode MODE. 266318334Speter If REG occupies multiple hard regs, all of them must be in CLASS. */ 266418334Speter 266518334Speterint 2666169699Skanreg_fits_class_p (rtx operand, enum reg_class cl, int offset, 2667132727Skan enum machine_mode mode) 266818334Speter{ 266990075Sobrien int regno = REGNO (operand); 2670169699Skan 2671169699Skan if (cl == NO_REGS) 2672169699Skan return 0; 2673169699Skan 267418334Speter if (regno < FIRST_PSEUDO_REGISTER 2675169699Skan && TEST_HARD_REG_BIT (reg_class_contents[(int) cl], 267618334Speter regno + offset)) 267718334Speter { 267890075Sobrien int sr; 267918334Speter regno += offset; 2680169699Skan for (sr = hard_regno_nregs[regno][mode] - 1; 268118334Speter sr > 0; sr--) 2682169699Skan if (! TEST_HARD_REG_BIT (reg_class_contents[(int) cl], 268318334Speter regno + sr)) 268418334Speter break; 268518334Speter return sr == 0; 268618334Speter } 268718334Speter 268818334Speter return 0; 268918334Speter} 269052284Sobrien 2691132727Skan/* Split single instruction. Helper function for split_all_insns and 2692132727Skan split_all_insns_noflow. Return last insn in the sequence if successful, 2693132727Skan or NULL if unsuccessful. */ 2694132727Skan 269590075Sobrienstatic rtx 2696132727Skansplit_insn (rtx insn) 269752284Sobrien{ 2698132727Skan /* Split insns here to get max fine-grain parallelism. */ 2699132727Skan rtx first = PREV_INSN (insn); 2700132727Skan rtx last = try_split (PATTERN (insn), insn, 1); 270152284Sobrien 2702132727Skan if (last == insn) 2703132727Skan return NULL_RTX; 2704132727Skan 2705132727Skan /* try_split returns the NOTE that INSN became. */ 2706169699Skan SET_INSN_DELETED (insn); 2707132727Skan 2708132727Skan /* ??? Coddle to md files that generate subregs in post-reload 2709132727Skan splitters instead of computing the proper hard register. */ 2710132727Skan if (reload_completed && first != last) 271152284Sobrien { 2712132727Skan first = NEXT_INSN (first); 2713132727Skan for (;;) 271452284Sobrien { 2715132727Skan if (INSN_P (first)) 2716132727Skan cleanup_subreg_operands (first); 2717132727Skan if (first == last) 2718132727Skan break; 2719132727Skan first = NEXT_INSN (first); 272052284Sobrien } 272190075Sobrien } 2722132727Skan return last; 272390075Sobrien} 2724132727Skan 272590075Sobrien/* Split all insns in the function. If UPD_LIFE, update life info after. */ 272652284Sobrien 272790075Sobrienvoid 2728132727Skansplit_all_insns (int upd_life) 272990075Sobrien{ 273090075Sobrien sbitmap blocks; 2731117404Skan bool changed; 2732117404Skan basic_block bb; 273390075Sobrien 2734117404Skan blocks = sbitmap_alloc (last_basic_block); 273590075Sobrien sbitmap_zero (blocks); 2736117404Skan changed = false; 273790075Sobrien 2738117404Skan FOR_EACH_BB_REVERSE (bb) 273990075Sobrien { 274090075Sobrien rtx insn, next; 2741117404Skan bool finish = false; 274290075Sobrien 2743132727Skan for (insn = BB_HEAD (bb); !finish ; insn = next) 274452284Sobrien { 274590075Sobrien /* Can't use `next_real_insn' because that might go across 274690075Sobrien CODE_LABELS and short-out basic blocks. */ 274790075Sobrien next = NEXT_INSN (insn); 2748132727Skan finish = (insn == BB_END (bb)); 2749132727Skan if (INSN_P (insn)) 275052284Sobrien { 2751132727Skan rtx set = single_set (insn); 275252284Sobrien 2753132727Skan /* Don't split no-op move insns. These should silently 2754132727Skan disappear later in final. Splitting such insns would 2755132727Skan break the code that handles REG_NO_CONFLICT blocks. */ 2756132727Skan if (set && set_noop_p (set)) 2757132727Skan { 2758132727Skan /* Nops get in the way while scheduling, so delete them 2759132727Skan now if register allocation has already been done. It 2760132727Skan is too risky to try to do this before register 2761132727Skan allocation, and there are unlikely to be very many 2762132727Skan nops then anyways. */ 2763132727Skan if (reload_completed) 2764132727Skan { 2765132727Skan /* If the no-op set has a REG_UNUSED note, we need 2766132727Skan to update liveness information. */ 2767132727Skan if (find_reg_note (insn, REG_UNUSED, NULL_RTX)) 2768132727Skan { 2769132727Skan SET_BIT (blocks, bb->index); 2770132727Skan changed = true; 2771132727Skan } 2772132727Skan /* ??? Is life info affected by deleting edges? */ 2773132727Skan delete_insn_and_edges (insn); 2774132727Skan } 2775132727Skan } 2776132727Skan else 2777132727Skan { 2778132727Skan rtx last = split_insn (insn); 2779132727Skan if (last) 2780132727Skan { 2781132727Skan /* The split sequence may include barrier, but the 2782132727Skan BB boundary we are interested in will be set to 2783132727Skan previous one. */ 2784132727Skan 2785169699Skan while (BARRIER_P (last)) 2786132727Skan last = PREV_INSN (last); 2787132727Skan SET_BIT (blocks, bb->index); 2788132727Skan changed = true; 2789132727Skan } 2790132727Skan } 279152284Sobrien } 279252284Sobrien } 279390075Sobrien } 279490075Sobrien 279590075Sobrien if (changed) 279690075Sobrien { 2797117404Skan int old_last_basic_block = last_basic_block; 2798117404Skan 279990075Sobrien find_many_sub_basic_blocks (blocks); 2800117404Skan 2801117404Skan if (old_last_basic_block != last_basic_block && upd_life) 2802117404Skan blocks = sbitmap_resize (blocks, last_basic_block, 1); 280390075Sobrien } 280490075Sobrien 280590075Sobrien if (changed && upd_life) 2806117404Skan update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES, 2807169699Skan PROP_DEATH_NOTES); 2808117404Skan 280990075Sobrien#ifdef ENABLE_CHECKING 281090075Sobrien verify_flow_info (); 281190075Sobrien#endif 281290075Sobrien 281390075Sobrien sbitmap_free (blocks); 281490075Sobrien} 281590075Sobrien 2816117404Skan/* Same as split_all_insns, but do not expect CFG to be available. 2817132727Skan Used by machine dependent reorg passes. */ 281890075Sobrien 2819169699Skanunsigned int 2820132727Skansplit_all_insns_noflow (void) 282190075Sobrien{ 282290075Sobrien rtx next, insn; 282390075Sobrien 282490075Sobrien for (insn = get_insns (); insn; insn = next) 282590075Sobrien { 282690075Sobrien next = NEXT_INSN (insn); 2827132727Skan if (INSN_P (insn)) 2828132727Skan { 2829132727Skan /* Don't split no-op move insns. These should silently 2830132727Skan disappear later in final. Splitting such insns would 2831132727Skan break the code that handles REG_NO_CONFLICT blocks. */ 2832132727Skan rtx set = single_set (insn); 2833132727Skan if (set && set_noop_p (set)) 2834132727Skan { 2835132727Skan /* Nops get in the way while scheduling, so delete them 2836132727Skan now if register allocation has already been done. It 2837132727Skan is too risky to try to do this before register 2838132727Skan allocation, and there are unlikely to be very many 2839132727Skan nops then anyways. 2840132727Skan 2841132727Skan ??? Should we use delete_insn when the CFG isn't valid? */ 2842132727Skan if (reload_completed) 2843132727Skan delete_insn_and_edges (insn); 2844132727Skan } 2845132727Skan else 2846132727Skan split_insn (insn); 2847132727Skan } 284890075Sobrien } 2849169699Skan return 0; 285090075Sobrien} 285190075Sobrien 285290075Sobrien#ifdef HAVE_peephole2 285390075Sobrienstruct peep2_insn_data 285490075Sobrien{ 285590075Sobrien rtx insn; 285690075Sobrien regset live_before; 285790075Sobrien}; 285890075Sobrien 285990075Sobrienstatic struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1]; 286090075Sobrienstatic int peep2_current; 2861169699Skan/* The number of instructions available to match a peep2. */ 2862169699Skanint peep2_current_count; 286390075Sobrien 286490075Sobrien/* A non-insn marker indicating the last insn of the block. 286590075Sobrien The live_before regset for this element is correct, indicating 286690075Sobrien global_live_at_end for the block. */ 286790075Sobrien#define PEEP2_EOB pc_rtx 286890075Sobrien 286990075Sobrien/* Return the Nth non-note insn after `current', or return NULL_RTX if it 287090075Sobrien does not exist. Used by the recognizer to find the next insn to match 287190075Sobrien in a multi-insn pattern. */ 287290075Sobrien 287390075Sobrienrtx 2874132727Skanpeep2_next_insn (int n) 287590075Sobrien{ 2876169699Skan gcc_assert (n <= peep2_current_count); 287790075Sobrien 287890075Sobrien n += peep2_current; 287990075Sobrien if (n >= MAX_INSNS_PER_PEEP2 + 1) 288090075Sobrien n -= MAX_INSNS_PER_PEEP2 + 1; 288190075Sobrien 288290075Sobrien return peep2_insn_data[n].insn; 288390075Sobrien} 288490075Sobrien 288590075Sobrien/* Return true if REGNO is dead before the Nth non-note insn 288690075Sobrien after `current'. */ 288790075Sobrien 288890075Sobrienint 2889132727Skanpeep2_regno_dead_p (int ofs, int regno) 289090075Sobrien{ 2891169699Skan gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1); 289290075Sobrien 289390075Sobrien ofs += peep2_current; 289490075Sobrien if (ofs >= MAX_INSNS_PER_PEEP2 + 1) 289590075Sobrien ofs -= MAX_INSNS_PER_PEEP2 + 1; 289690075Sobrien 2897169699Skan gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX); 289890075Sobrien 289990075Sobrien return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno); 290090075Sobrien} 290190075Sobrien 290290075Sobrien/* Similarly for a REG. */ 290390075Sobrien 290490075Sobrienint 2905132727Skanpeep2_reg_dead_p (int ofs, rtx reg) 290690075Sobrien{ 290790075Sobrien int regno, n; 290890075Sobrien 2909169699Skan gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1); 291090075Sobrien 291190075Sobrien ofs += peep2_current; 291290075Sobrien if (ofs >= MAX_INSNS_PER_PEEP2 + 1) 291390075Sobrien ofs -= MAX_INSNS_PER_PEEP2 + 1; 291490075Sobrien 2915169699Skan gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX); 291690075Sobrien 291790075Sobrien regno = REGNO (reg); 2918169699Skan n = hard_regno_nregs[regno][GET_MODE (reg)]; 291990075Sobrien while (--n >= 0) 292090075Sobrien if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n)) 292190075Sobrien return 0; 292290075Sobrien return 1; 292390075Sobrien} 292490075Sobrien 292590075Sobrien/* Try to find a hard register of mode MODE, matching the register class in 292690075Sobrien CLASS_STR, which is available at the beginning of insn CURRENT_INSN and 292790075Sobrien remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX, 292890075Sobrien in which case the only condition is that the register must be available 292990075Sobrien before CURRENT_INSN. 293090075Sobrien Registers that already have bits set in REG_SET will not be considered. 293190075Sobrien 293290075Sobrien If an appropriate register is available, it will be returned and the 293390075Sobrien corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is 293490075Sobrien returned. */ 293590075Sobrien 293690075Sobrienrtx 2937132727Skanpeep2_find_free_register (int from, int to, const char *class_str, 2938132727Skan enum machine_mode mode, HARD_REG_SET *reg_set) 293990075Sobrien{ 294090075Sobrien static int search_ofs; 2941169699Skan enum reg_class cl; 294290075Sobrien HARD_REG_SET live; 294390075Sobrien int i; 294490075Sobrien 2945169699Skan gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1); 2946169699Skan gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1); 294790075Sobrien 294890075Sobrien from += peep2_current; 294990075Sobrien if (from >= MAX_INSNS_PER_PEEP2 + 1) 295090075Sobrien from -= MAX_INSNS_PER_PEEP2 + 1; 295190075Sobrien to += peep2_current; 295290075Sobrien if (to >= MAX_INSNS_PER_PEEP2 + 1) 295390075Sobrien to -= MAX_INSNS_PER_PEEP2 + 1; 295490075Sobrien 2955169699Skan gcc_assert (peep2_insn_data[from].insn != NULL_RTX); 295690075Sobrien REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before); 295790075Sobrien 295890075Sobrien while (from != to) 295990075Sobrien { 296090075Sobrien HARD_REG_SET this_live; 296190075Sobrien 296290075Sobrien if (++from >= MAX_INSNS_PER_PEEP2 + 1) 296390075Sobrien from = 0; 2964169699Skan gcc_assert (peep2_insn_data[from].insn != NULL_RTX); 296590075Sobrien REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before); 296690075Sobrien IOR_HARD_REG_SET (live, this_live); 296790075Sobrien } 296890075Sobrien 2969169699Skan cl = (class_str[0] == 'r' ? GENERAL_REGS 2970132727Skan : REG_CLASS_FROM_CONSTRAINT (class_str[0], class_str)); 297190075Sobrien 297290075Sobrien for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 297390075Sobrien { 297490075Sobrien int raw_regno, regno, success, j; 297590075Sobrien 297690075Sobrien /* Distribute the free registers as much as possible. */ 297790075Sobrien raw_regno = search_ofs + i; 297890075Sobrien if (raw_regno >= FIRST_PSEUDO_REGISTER) 297990075Sobrien raw_regno -= FIRST_PSEUDO_REGISTER; 298090075Sobrien#ifdef REG_ALLOC_ORDER 298190075Sobrien regno = reg_alloc_order[raw_regno]; 298290075Sobrien#else 298390075Sobrien regno = raw_regno; 298490075Sobrien#endif 298590075Sobrien 298690075Sobrien /* Don't allocate fixed registers. */ 298790075Sobrien if (fixed_regs[regno]) 298890075Sobrien continue; 298990075Sobrien /* Make sure the register is of the right class. */ 2990169699Skan if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno)) 299190075Sobrien continue; 299290075Sobrien /* And can support the mode we need. */ 299390075Sobrien if (! HARD_REGNO_MODE_OK (regno, mode)) 299490075Sobrien continue; 299590075Sobrien /* And that we don't create an extra save/restore. */ 299690075Sobrien if (! call_used_regs[regno] && ! regs_ever_live[regno]) 299790075Sobrien continue; 299890075Sobrien /* And we don't clobber traceback for noreturn functions. */ 299990075Sobrien if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM) 300090075Sobrien && (! reload_completed || frame_pointer_needed)) 300190075Sobrien continue; 300290075Sobrien 300390075Sobrien success = 1; 3004169699Skan for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--) 300552284Sobrien { 300690075Sobrien if (TEST_HARD_REG_BIT (*reg_set, regno + j) 300790075Sobrien || TEST_HARD_REG_BIT (live, regno + j)) 300890075Sobrien { 300990075Sobrien success = 0; 301090075Sobrien break; 301190075Sobrien } 301290075Sobrien } 301390075Sobrien if (success) 301490075Sobrien { 3015169699Skan for (j = hard_regno_nregs[regno][mode] - 1; j >= 0; j--) 301690075Sobrien SET_HARD_REG_BIT (*reg_set, regno + j); 301752284Sobrien 301890075Sobrien /* Start the next search with the next register. */ 301990075Sobrien if (++raw_regno >= FIRST_PSEUDO_REGISTER) 302090075Sobrien raw_regno = 0; 302190075Sobrien search_ofs = raw_regno; 302290075Sobrien 302390075Sobrien return gen_rtx_REG (mode, regno); 302490075Sobrien } 302590075Sobrien } 302690075Sobrien 302790075Sobrien search_ofs = 0; 302890075Sobrien return NULL_RTX; 302990075Sobrien} 303090075Sobrien 303190075Sobrien/* Perform the peephole2 optimization pass. */ 303290075Sobrien 3033169699Skanstatic void 3034169699Skanpeephole2_optimize (void) 303590075Sobrien{ 303690075Sobrien rtx insn, prev; 303790075Sobrien regset live; 3038117404Skan int i; 3039117404Skan basic_block bb; 304090075Sobrien#ifdef HAVE_conditional_execution 304190075Sobrien sbitmap blocks; 304296263Sobrien bool changed; 304390075Sobrien#endif 304496263Sobrien bool do_cleanup_cfg = false; 3045169699Skan bool do_global_life_update = false; 304696263Sobrien bool do_rebuild_jump_labels = false; 304790075Sobrien 304890075Sobrien /* Initialize the regsets we're going to use. */ 304990075Sobrien for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) 3050169699Skan peep2_insn_data[i].live_before = ALLOC_REG_SET (®_obstack); 3051169699Skan live = ALLOC_REG_SET (®_obstack); 305290075Sobrien 305390075Sobrien#ifdef HAVE_conditional_execution 3054117404Skan blocks = sbitmap_alloc (last_basic_block); 305590075Sobrien sbitmap_zero (blocks); 305696263Sobrien changed = false; 305790075Sobrien#else 305890075Sobrien count_or_remove_death_notes (NULL, 1); 305990075Sobrien#endif 306090075Sobrien 3061117404Skan FOR_EACH_BB_REVERSE (bb) 306290075Sobrien { 306390075Sobrien struct propagate_block_info *pbi; 3064169699Skan reg_set_iterator rsi; 3065169699Skan unsigned int j; 306690075Sobrien 306790075Sobrien /* Indicate that all slots except the last holds invalid data. */ 306890075Sobrien for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i) 306990075Sobrien peep2_insn_data[i].insn = NULL_RTX; 3070169699Skan peep2_current_count = 0; 307190075Sobrien 307290075Sobrien /* Indicate that the last slot contains live_after data. */ 307390075Sobrien peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB; 307490075Sobrien peep2_current = MAX_INSNS_PER_PEEP2; 307590075Sobrien 307690075Sobrien /* Start up propagation. */ 3077169699Skan COPY_REG_SET (live, bb->il.rtl->global_live_at_end); 307890075Sobrien COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live); 307990075Sobrien 308090075Sobrien#ifdef HAVE_conditional_execution 308190075Sobrien pbi = init_propagate_block_info (bb, live, NULL, NULL, 0); 308290075Sobrien#else 308390075Sobrien pbi = init_propagate_block_info (bb, live, NULL, NULL, PROP_DEATH_NOTES); 308490075Sobrien#endif 308590075Sobrien 3086132727Skan for (insn = BB_END (bb); ; insn = prev) 308790075Sobrien { 308890075Sobrien prev = PREV_INSN (insn); 308990075Sobrien if (INSN_P (insn)) 309052284Sobrien { 309196263Sobrien rtx try, before_try, x; 309290075Sobrien int match_len; 309396263Sobrien rtx note; 3094117404Skan bool was_call = false; 309590075Sobrien 309690075Sobrien /* Record this insn. */ 309790075Sobrien if (--peep2_current < 0) 309890075Sobrien peep2_current = MAX_INSNS_PER_PEEP2; 3099169699Skan if (peep2_current_count < MAX_INSNS_PER_PEEP2 3100169699Skan && peep2_insn_data[peep2_current].insn == NULL_RTX) 3101169699Skan peep2_current_count++; 310290075Sobrien peep2_insn_data[peep2_current].insn = insn; 310390075Sobrien propagate_one_insn (pbi, insn); 310490075Sobrien COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live); 310590075Sobrien 3106169699Skan if (RTX_FRAME_RELATED_P (insn)) 3107169699Skan { 3108169699Skan /* If an insn has RTX_FRAME_RELATED_P set, peephole 3109169699Skan substitution would lose the 3110169699Skan REG_FRAME_RELATED_EXPR that is attached. */ 3111169699Skan peep2_current_count = 0; 3112169699Skan try = NULL; 3113169699Skan } 3114169699Skan else 3115169699Skan /* Match the peephole. */ 3116169699Skan try = peephole2_insns (PATTERN (insn), insn, &match_len); 3117169699Skan 311890075Sobrien if (try != NULL) 311990075Sobrien { 312090075Sobrien /* If we are splitting a CALL_INSN, look for the CALL_INSN 312190075Sobrien in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other 312290075Sobrien cfg-related call notes. */ 312390075Sobrien for (i = 0; i <= match_len; ++i) 312490075Sobrien { 3125117404Skan int j; 312690075Sobrien rtx old_insn, new_insn, note; 312790075Sobrien 312890075Sobrien j = i + peep2_current; 312990075Sobrien if (j >= MAX_INSNS_PER_PEEP2 + 1) 313090075Sobrien j -= MAX_INSNS_PER_PEEP2 + 1; 313190075Sobrien old_insn = peep2_insn_data[j].insn; 3132169699Skan if (!CALL_P (old_insn)) 313390075Sobrien continue; 3134117404Skan was_call = true; 313590075Sobrien 3136117404Skan new_insn = try; 3137117404Skan while (new_insn != NULL_RTX) 3138117404Skan { 3139169699Skan if (CALL_P (new_insn)) 3140117404Skan break; 3141117404Skan new_insn = NEXT_INSN (new_insn); 3142117404Skan } 3143117404Skan 3144169699Skan gcc_assert (new_insn != NULL_RTX); 314590075Sobrien 314690075Sobrien CALL_INSN_FUNCTION_USAGE (new_insn) 314790075Sobrien = CALL_INSN_FUNCTION_USAGE (old_insn); 314890075Sobrien 314990075Sobrien for (note = REG_NOTES (old_insn); 315090075Sobrien note; 315190075Sobrien note = XEXP (note, 1)) 315290075Sobrien switch (REG_NOTE_KIND (note)) 315390075Sobrien { 315490075Sobrien case REG_NORETURN: 315590075Sobrien case REG_SETJMP: 315690075Sobrien REG_NOTES (new_insn) 315790075Sobrien = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), 315890075Sobrien XEXP (note, 0), 315990075Sobrien REG_NOTES (new_insn)); 316090075Sobrien default: 316190075Sobrien /* Discard all other reg notes. */ 316290075Sobrien break; 316390075Sobrien } 316490075Sobrien 316590075Sobrien /* Croak if there is another call in the sequence. */ 316690075Sobrien while (++i <= match_len) 316790075Sobrien { 316890075Sobrien j = i + peep2_current; 316990075Sobrien if (j >= MAX_INSNS_PER_PEEP2 + 1) 317090075Sobrien j -= MAX_INSNS_PER_PEEP2 + 1; 317190075Sobrien old_insn = peep2_insn_data[j].insn; 3172169699Skan gcc_assert (!CALL_P (old_insn)); 317390075Sobrien } 317490075Sobrien break; 317590075Sobrien } 317690075Sobrien 317790075Sobrien i = match_len + peep2_current; 317890075Sobrien if (i >= MAX_INSNS_PER_PEEP2 + 1) 317990075Sobrien i -= MAX_INSNS_PER_PEEP2 + 1; 318090075Sobrien 3181117404Skan note = find_reg_note (peep2_insn_data[i].insn, 318296263Sobrien REG_EH_REGION, NULL_RTX); 318396263Sobrien 318490075Sobrien /* Replace the old sequence with the new. */ 3185132727Skan try = emit_insn_after_setloc (try, peep2_insn_data[i].insn, 3186132727Skan INSN_LOCATOR (peep2_insn_data[i].insn)); 318796263Sobrien before_try = PREV_INSN (insn); 318890075Sobrien delete_insn_chain (insn, peep2_insn_data[i].insn); 318990075Sobrien 319096263Sobrien /* Re-insert the EH_REGION notes. */ 3191117404Skan if (note || (was_call && nonlocal_goto_handler_labels)) 319296263Sobrien { 319396263Sobrien edge eh_edge; 3194169699Skan edge_iterator ei; 319596263Sobrien 3196169699Skan FOR_EACH_EDGE (eh_edge, ei, bb->succs) 3197117404Skan if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) 319896263Sobrien break; 319996263Sobrien 320096263Sobrien for (x = try ; x != before_try ; x = PREV_INSN (x)) 3201169699Skan if (CALL_P (x) 320296263Sobrien || (flag_non_call_exceptions 320396263Sobrien && may_trap_p (PATTERN (x)) 320496263Sobrien && !find_reg_note (x, REG_EH_REGION, NULL))) 320596263Sobrien { 3206117404Skan if (note) 3207117404Skan REG_NOTES (x) 3208117404Skan = gen_rtx_EXPR_LIST (REG_EH_REGION, 3209117404Skan XEXP (note, 0), 3210117404Skan REG_NOTES (x)); 321196263Sobrien 3212132727Skan if (x != BB_END (bb) && eh_edge) 321396263Sobrien { 321496263Sobrien edge nfte, nehe; 321596263Sobrien int flags; 321696263Sobrien 321796263Sobrien nfte = split_block (bb, x); 3218117404Skan flags = (eh_edge->flags 3219117404Skan & (EDGE_EH | EDGE_ABNORMAL)); 3220169699Skan if (CALL_P (x)) 322196263Sobrien flags |= EDGE_ABNORMAL_CALL; 322296263Sobrien nehe = make_edge (nfte->src, eh_edge->dest, 322396263Sobrien flags); 322496263Sobrien 322596263Sobrien nehe->probability = eh_edge->probability; 322696263Sobrien nfte->probability 322796263Sobrien = REG_BR_PROB_BASE - nehe->probability; 322896263Sobrien 322996263Sobrien do_cleanup_cfg |= purge_dead_edges (nfte->dest); 323090075Sobrien#ifdef HAVE_conditional_execution 323196263Sobrien SET_BIT (blocks, nfte->dest->index); 323296263Sobrien changed = true; 323396263Sobrien#endif 323496263Sobrien bb = nfte->src; 323596263Sobrien eh_edge = nehe; 323696263Sobrien } 323796263Sobrien } 323896263Sobrien 323996263Sobrien /* Converting possibly trapping insn to non-trapping is 324096263Sobrien possible. Zap dummy outgoing edges. */ 324196263Sobrien do_cleanup_cfg |= purge_dead_edges (bb); 324296263Sobrien } 324396263Sobrien 324496263Sobrien#ifdef HAVE_conditional_execution 324590075Sobrien /* With conditional execution, we cannot back up the 324690075Sobrien live information so easily, since the conditional 324790075Sobrien death data structures are not so self-contained. 324890075Sobrien So record that we've made a modification to this 324990075Sobrien block and update life information at the end. */ 3250117404Skan SET_BIT (blocks, bb->index); 325196263Sobrien changed = true; 325290075Sobrien 325390075Sobrien for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) 325490075Sobrien peep2_insn_data[i].insn = NULL_RTX; 325590075Sobrien peep2_insn_data[peep2_current].insn = PEEP2_EOB; 3256169699Skan peep2_current_count = 0; 325790075Sobrien#else 325890075Sobrien /* Back up lifetime information past the end of the 325990075Sobrien newly created sequence. */ 326090075Sobrien if (++i >= MAX_INSNS_PER_PEEP2 + 1) 326190075Sobrien i = 0; 326290075Sobrien COPY_REG_SET (live, peep2_insn_data[i].live_before); 326390075Sobrien 326490075Sobrien /* Update life information for the new sequence. */ 326596263Sobrien x = try; 326690075Sobrien do 326790075Sobrien { 326896263Sobrien if (INSN_P (x)) 326990075Sobrien { 327090075Sobrien if (--i < 0) 327190075Sobrien i = MAX_INSNS_PER_PEEP2; 3272169699Skan if (peep2_current_count < MAX_INSNS_PER_PEEP2 3273169699Skan && peep2_insn_data[i].insn == NULL_RTX) 3274169699Skan peep2_current_count++; 327596263Sobrien peep2_insn_data[i].insn = x; 327696263Sobrien propagate_one_insn (pbi, x); 327790075Sobrien COPY_REG_SET (peep2_insn_data[i].live_before, live); 327890075Sobrien } 327996263Sobrien x = PREV_INSN (x); 328090075Sobrien } 328196263Sobrien while (x != prev); 328290075Sobrien 328390075Sobrien /* ??? Should verify that LIVE now matches what we 328490075Sobrien had before the new sequence. */ 328590075Sobrien 328690075Sobrien peep2_current = i; 328752284Sobrien#endif 328896263Sobrien 328996263Sobrien /* If we generated a jump instruction, it won't have 329096263Sobrien JUMP_LABEL set. Recompute after we're done. */ 329196263Sobrien for (x = try; x != before_try; x = PREV_INSN (x)) 3292169699Skan if (JUMP_P (x)) 329396263Sobrien { 329496263Sobrien do_rebuild_jump_labels = true; 329596263Sobrien break; 329696263Sobrien } 329752284Sobrien } 329852284Sobrien } 329990075Sobrien 3300132727Skan if (insn == BB_HEAD (bb)) 330190075Sobrien break; 330252284Sobrien } 330352284Sobrien 3304169699Skan /* Some peepholes can decide the don't need one or more of their 3305169699Skan inputs. If this happens, local life update is not enough. */ 3306169699Skan EXECUTE_IF_AND_COMPL_IN_BITMAP (bb->il.rtl->global_live_at_start, live, 3307169699Skan 0, j, rsi) 3308169699Skan { 3309169699Skan do_global_life_update = true; 3310169699Skan break; 3311169699Skan } 3312169699Skan 331390075Sobrien free_propagate_block_info (pbi); 331452284Sobrien } 331590075Sobrien 331690075Sobrien for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) 331790075Sobrien FREE_REG_SET (peep2_insn_data[i].live_before); 331890075Sobrien FREE_REG_SET (live); 331990075Sobrien 332096263Sobrien if (do_rebuild_jump_labels) 332196263Sobrien rebuild_jump_labels (get_insns ()); 332296263Sobrien 332396263Sobrien /* If we eliminated EH edges, we may be able to merge blocks. Further, 332496263Sobrien we've changed global life since exception handlers are no longer 332596263Sobrien reachable. */ 332696263Sobrien if (do_cleanup_cfg) 332796263Sobrien { 332896263Sobrien cleanup_cfg (0); 3329169699Skan do_global_life_update = true; 333096263Sobrien } 3331169699Skan if (do_global_life_update) 3332169699Skan update_life_info (0, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES); 333390075Sobrien#ifdef HAVE_conditional_execution 333496263Sobrien else 333596263Sobrien { 333696263Sobrien count_or_remove_death_notes (blocks, 1); 333796263Sobrien update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES); 333896263Sobrien } 333990075Sobrien sbitmap_free (blocks); 334090075Sobrien#endif 334152284Sobrien} 334290075Sobrien#endif /* HAVE_peephole2 */ 3343117404Skan 3344117404Skan/* Common predicates for use with define_bypass. */ 3345117404Skan 3346117404Skan/* True if the dependency between OUT_INSN and IN_INSN is on the store 3347117404Skan data not the address operand(s) of the store. IN_INSN must be 3348117404Skan single_set. OUT_INSN must be either a single_set or a PARALLEL with 3349117404Skan SETs inside. */ 3350117404Skan 3351117404Skanint 3352132727Skanstore_data_bypass_p (rtx out_insn, rtx in_insn) 3353117404Skan{ 3354117404Skan rtx out_set, in_set; 3355117404Skan 3356117404Skan in_set = single_set (in_insn); 3357169699Skan gcc_assert (in_set); 3358117404Skan 3359169699Skan if (!MEM_P (SET_DEST (in_set))) 3360117404Skan return false; 3361117404Skan 3362117404Skan out_set = single_set (out_insn); 3363117404Skan if (out_set) 3364117404Skan { 3365117404Skan if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set))) 3366117404Skan return false; 3367117404Skan } 3368117404Skan else 3369117404Skan { 3370117404Skan rtx out_pat; 3371117404Skan int i; 3372117404Skan 3373117404Skan out_pat = PATTERN (out_insn); 3374169699Skan gcc_assert (GET_CODE (out_pat) == PARALLEL); 3375117404Skan 3376117404Skan for (i = 0; i < XVECLEN (out_pat, 0); i++) 3377117404Skan { 3378117404Skan rtx exp = XVECEXP (out_pat, 0, i); 3379117404Skan 3380117404Skan if (GET_CODE (exp) == CLOBBER) 3381117404Skan continue; 3382117404Skan 3383169699Skan gcc_assert (GET_CODE (exp) == SET); 3384117404Skan 3385117404Skan if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set))) 3386117404Skan return false; 3387117404Skan } 3388117404Skan } 3389117404Skan 3390117404Skan return true; 3391117404Skan} 3392117404Skan 3393117404Skan/* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE 3394117404Skan condition, and not the THEN or ELSE branch. OUT_INSN may be either a single 3395117404Skan or multiple set; IN_INSN should be single_set for truth, but for convenience 3396117404Skan of insn categorization may be any JUMP or CALL insn. */ 3397117404Skan 3398117404Skanint 3399132727Skanif_test_bypass_p (rtx out_insn, rtx in_insn) 3400117404Skan{ 3401117404Skan rtx out_set, in_set; 3402117404Skan 3403117404Skan in_set = single_set (in_insn); 3404117404Skan if (! in_set) 3405117404Skan { 3406169699Skan gcc_assert (JUMP_P (in_insn) || CALL_P (in_insn)); 3407169699Skan return false; 3408117404Skan } 3409117404Skan 3410117404Skan if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE) 3411117404Skan return false; 3412117404Skan in_set = SET_SRC (in_set); 3413117404Skan 3414117404Skan out_set = single_set (out_insn); 3415117404Skan if (out_set) 3416117404Skan { 3417117404Skan if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1)) 3418117404Skan || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2))) 3419117404Skan return false; 3420117404Skan } 3421117404Skan else 3422117404Skan { 3423117404Skan rtx out_pat; 3424117404Skan int i; 3425117404Skan 3426117404Skan out_pat = PATTERN (out_insn); 3427169699Skan gcc_assert (GET_CODE (out_pat) == PARALLEL); 3428117404Skan 3429117404Skan for (i = 0; i < XVECLEN (out_pat, 0); i++) 3430117404Skan { 3431117404Skan rtx exp = XVECEXP (out_pat, 0, i); 3432117404Skan 3433117404Skan if (GET_CODE (exp) == CLOBBER) 3434117404Skan continue; 3435117404Skan 3436169699Skan gcc_assert (GET_CODE (exp) == SET); 3437117404Skan 3438117404Skan if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1)) 3439117404Skan || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2))) 3440117404Skan return false; 3441117404Skan } 3442117404Skan } 3443117404Skan 3444117404Skan return true; 3445117404Skan} 3446169699Skan 3447169699Skanstatic bool 3448169699Skangate_handle_peephole2 (void) 3449169699Skan{ 3450169699Skan return (optimize > 0 && flag_peephole2); 3451169699Skan} 3452169699Skan 3453169699Skanstatic unsigned int 3454169699Skanrest_of_handle_peephole2 (void) 3455169699Skan{ 3456169699Skan#ifdef HAVE_peephole2 3457169699Skan peephole2_optimize (); 3458169699Skan#endif 3459169699Skan return 0; 3460169699Skan} 3461169699Skan 3462169699Skanstruct tree_opt_pass pass_peephole2 = 3463169699Skan{ 3464169699Skan "peephole2", /* name */ 3465169699Skan gate_handle_peephole2, /* gate */ 3466169699Skan rest_of_handle_peephole2, /* execute */ 3467169699Skan NULL, /* sub */ 3468169699Skan NULL, /* next */ 3469169699Skan 0, /* static_pass_number */ 3470169699Skan TV_PEEPHOLE2, /* tv_id */ 3471169699Skan 0, /* properties_required */ 3472169699Skan 0, /* properties_provided */ 3473169699Skan 0, /* properties_destroyed */ 3474169699Skan 0, /* todo_flags_start */ 3475169699Skan TODO_dump_func, /* todo_flags_finish */ 3476169699Skan 'z' /* letter */ 3477169699Skan}; 3478169699Skan 3479169699Skanstatic unsigned int 3480169699Skanrest_of_handle_split_all_insns (void) 3481169699Skan{ 3482169699Skan split_all_insns (1); 3483169699Skan return 0; 3484169699Skan} 3485169699Skan 3486169699Skanstruct tree_opt_pass pass_split_all_insns = 3487169699Skan{ 3488169699Skan "split1", /* name */ 3489169699Skan NULL, /* gate */ 3490169699Skan rest_of_handle_split_all_insns, /* execute */ 3491169699Skan NULL, /* sub */ 3492169699Skan NULL, /* next */ 3493169699Skan 0, /* static_pass_number */ 3494169699Skan 0, /* tv_id */ 3495169699Skan 0, /* properties_required */ 3496169699Skan 0, /* properties_provided */ 3497169699Skan 0, /* properties_destroyed */ 3498169699Skan 0, /* todo_flags_start */ 3499169699Skan TODO_dump_func, /* todo_flags_finish */ 3500169699Skan 0 /* letter */ 3501169699Skan}; 3502169699Skan 3503169699Skan/* The placement of the splitting that we do for shorten_branches 3504169699Skan depends on whether regstack is used by the target or not. */ 3505169699Skanstatic bool 3506169699Skangate_do_final_split (void) 3507169699Skan{ 3508169699Skan#if defined (HAVE_ATTR_length) && !defined (STACK_REGS) 3509169699Skan return 1; 3510169699Skan#else 3511169699Skan return 0; 3512169699Skan#endif 3513169699Skan} 3514169699Skan 3515169699Skanstruct tree_opt_pass pass_split_for_shorten_branches = 3516169699Skan{ 3517169699Skan "split3", /* name */ 3518169699Skan gate_do_final_split, /* gate */ 3519169699Skan split_all_insns_noflow, /* execute */ 3520169699Skan NULL, /* sub */ 3521169699Skan NULL, /* next */ 3522169699Skan 0, /* static_pass_number */ 3523169699Skan TV_SHORTEN_BRANCH, /* tv_id */ 3524169699Skan 0, /* properties_required */ 3525169699Skan 0, /* properties_provided */ 3526169699Skan 0, /* properties_destroyed */ 3527169699Skan 0, /* todo_flags_start */ 3528169699Skan TODO_dump_func, /* todo_flags_finish */ 3529169699Skan 0 /* letter */ 3530169699Skan}; 3531169699Skan 3532169699Skan 3533169699Skanstatic bool 3534169699Skangate_handle_split_before_regstack (void) 3535169699Skan{ 3536169699Skan#if defined (HAVE_ATTR_length) && defined (STACK_REGS) 3537169699Skan /* If flow2 creates new instructions which need splitting 3538169699Skan and scheduling after reload is not done, they might not be 3539169699Skan split until final which doesn't allow splitting 3540169699Skan if HAVE_ATTR_length. */ 3541169699Skan# ifdef INSN_SCHEDULING 3542169699Skan return (optimize && !flag_schedule_insns_after_reload); 3543169699Skan# else 3544169699Skan return (optimize); 3545169699Skan# endif 3546169699Skan#else 3547169699Skan return 0; 3548169699Skan#endif 3549169699Skan} 3550169699Skan 3551169699Skanstruct tree_opt_pass pass_split_before_regstack = 3552169699Skan{ 3553169699Skan "split2", /* name */ 3554169699Skan gate_handle_split_before_regstack, /* gate */ 3555169699Skan rest_of_handle_split_all_insns, /* execute */ 3556169699Skan NULL, /* sub */ 3557169699Skan NULL, /* next */ 3558169699Skan 0, /* static_pass_number */ 3559169699Skan TV_SHORTEN_BRANCH, /* tv_id */ 3560169699Skan 0, /* properties_required */ 3561169699Skan 0, /* properties_provided */ 3562169699Skan 0, /* properties_destroyed */ 3563169699Skan 0, /* todo_flags_start */ 3564169699Skan TODO_dump_func, /* todo_flags_finish */ 3565169699Skan 0 /* letter */ 3566169699Skan}; 3567