reg-stack.c revision 52284
118334Speter/* Register to Stack convert for GNU compiler. 252284Sobrien Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. 318334Speter 418334SpeterThis file is part of GNU CC. 518334Speter 618334SpeterGNU CC is free software; you can redistribute it and/or modify 718334Speterit under the terms of the GNU General Public License as published by 818334Speterthe Free Software Foundation; either version 2, or (at your option) 918334Speterany later version. 1018334Speter 1118334SpeterGNU CC is distributed in the hope that it will be useful, 1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1418334SpeterGNU General Public License for more details. 1518334Speter 1618334SpeterYou should have received a copy of the GNU General Public License 1718334Speteralong with GNU CC; see the file COPYING. If not, write to 1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330, 1918334SpeterBoston, MA 02111-1307, USA. */ 2018334Speter 2118334Speter/* This pass converts stack-like registers from the "flat register 2218334Speter file" model that gcc uses, to a stack convention that the 387 uses. 2318334Speter 2418334Speter * The form of the input: 2518334Speter 2618334Speter On input, the function consists of insn that have had their 2718334Speter registers fully allocated to a set of "virtual" registers. Note that 2818334Speter the word "virtual" is used differently here than elsewhere in gcc: for 2918334Speter each virtual stack reg, there is a hard reg, but the mapping between 3018334Speter them is not known until this pass is run. On output, hard register 3118334Speter numbers have been substituted, and various pop and exchange insns have 3218334Speter been emitted. The hard register numbers and the virtual register 3318334Speter numbers completely overlap - before this pass, all stack register 3418334Speter numbers are virtual, and afterward they are all hard. 3518334Speter 3618334Speter The virtual registers can be manipulated normally by gcc, and their 3718334Speter semantics are the same as for normal registers. After the hard 3818334Speter register numbers are substituted, the semantics of an insn containing 3918334Speter stack-like regs are not the same as for an insn with normal regs: for 4018334Speter instance, it is not safe to delete an insn that appears to be a no-op 4118334Speter move. In general, no insn containing hard regs should be changed 4218334Speter after this pass is done. 4318334Speter 4418334Speter * The form of the output: 4518334Speter 4618334Speter After this pass, hard register numbers represent the distance from 4718334Speter the current top of stack to the desired register. A reference to 4818334Speter FIRST_STACK_REG references the top of stack, FIRST_STACK_REG + 1, 4918334Speter represents the register just below that, and so forth. Also, REG_DEAD 5018334Speter notes indicate whether or not a stack register should be popped. 5118334Speter 5218334Speter A "swap" insn looks like a parallel of two patterns, where each 5318334Speter pattern is a SET: one sets A to B, the other B to A. 5418334Speter 5518334Speter A "push" or "load" insn is a SET whose SET_DEST is FIRST_STACK_REG 5618334Speter and whose SET_DEST is REG or MEM. Any other SET_DEST, such as PLUS, 5718334Speter will replace the existing stack top, not push a new value. 5818334Speter 5918334Speter A store insn is a SET whose SET_DEST is FIRST_STACK_REG, and whose 6018334Speter SET_SRC is REG or MEM. 6118334Speter 6218334Speter The case where the SET_SRC and SET_DEST are both FIRST_STACK_REG 6318334Speter appears ambiguous. As a special case, the presence of a REG_DEAD note 6418334Speter for FIRST_STACK_REG differentiates between a load insn and a pop. 6518334Speter 6618334Speter If a REG_DEAD is present, the insn represents a "pop" that discards 6718334Speter the top of the register stack. If there is no REG_DEAD note, then the 6818334Speter insn represents a "dup" or a push of the current top of stack onto the 6918334Speter stack. 7018334Speter 7118334Speter * Methodology: 7218334Speter 7318334Speter Existing REG_DEAD and REG_UNUSED notes for stack registers are 7418334Speter deleted and recreated from scratch. REG_DEAD is never created for a 7518334Speter SET_DEST, only REG_UNUSED. 7618334Speter 7718334Speter * asm_operands: 7818334Speter 7918334Speter There are several rules on the usage of stack-like regs in 8018334Speter asm_operands insns. These rules apply only to the operands that are 8118334Speter stack-like regs: 8218334Speter 8318334Speter 1. Given a set of input regs that die in an asm_operands, it is 8418334Speter necessary to know which are implicitly popped by the asm, and 8518334Speter which must be explicitly popped by gcc. 8618334Speter 8718334Speter An input reg that is implicitly popped by the asm must be 8818334Speter explicitly clobbered, unless it is constrained to match an 8918334Speter output operand. 9018334Speter 9118334Speter 2. For any input reg that is implicitly popped by an asm, it is 9218334Speter necessary to know how to adjust the stack to compensate for the pop. 9318334Speter If any non-popped input is closer to the top of the reg-stack than 9418334Speter the implicitly popped reg, it would not be possible to know what the 9518334Speter stack looked like - it's not clear how the rest of the stack "slides 9618334Speter up". 9718334Speter 9818334Speter All implicitly popped input regs must be closer to the top of 9918334Speter the reg-stack than any input that is not implicitly popped. 10018334Speter 10118334Speter 3. It is possible that if an input dies in an insn, reload might 10218334Speter use the input reg for an output reload. Consider this example: 10318334Speter 10418334Speter asm ("foo" : "=t" (a) : "f" (b)); 10518334Speter 10618334Speter This asm says that input B is not popped by the asm, and that 10718334Speter the asm pushes a result onto the reg-stack, ie, the stack is one 10818334Speter deeper after the asm than it was before. But, it is possible that 10918334Speter reload will think that it can use the same reg for both the input and 11018334Speter the output, if input B dies in this insn. 11118334Speter 11218334Speter If any input operand uses the "f" constraint, all output reg 11318334Speter constraints must use the "&" earlyclobber. 11418334Speter 11518334Speter The asm above would be written as 11618334Speter 11718334Speter asm ("foo" : "=&t" (a) : "f" (b)); 11818334Speter 11918334Speter 4. Some operands need to be in particular places on the stack. All 12018334Speter output operands fall in this category - there is no other way to 12118334Speter know which regs the outputs appear in unless the user indicates 12218334Speter this in the constraints. 12318334Speter 12418334Speter Output operands must specifically indicate which reg an output 12518334Speter appears in after an asm. "=f" is not allowed: the operand 12618334Speter constraints must select a class with a single reg. 12718334Speter 12818334Speter 5. Output operands may not be "inserted" between existing stack regs. 12918334Speter Since no 387 opcode uses a read/write operand, all output operands 13018334Speter are dead before the asm_operands, and are pushed by the asm_operands. 13118334Speter It makes no sense to push anywhere but the top of the reg-stack. 13218334Speter 13318334Speter Output operands must start at the top of the reg-stack: output 13418334Speter operands may not "skip" a reg. 13518334Speter 13618334Speter 6. Some asm statements may need extra stack space for internal 13718334Speter calculations. This can be guaranteed by clobbering stack registers 13818334Speter unrelated to the inputs and outputs. 13918334Speter 14018334Speter Here are a couple of reasonable asms to want to write. This asm 14118334Speter takes one input, which is internally popped, and produces two outputs. 14218334Speter 14318334Speter asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp)); 14418334Speter 14518334Speter This asm takes two inputs, which are popped by the fyl2xp1 opcode, 14618334Speter and replaces them with one output. The user must code the "st(1)" 14718334Speter clobber for reg-stack.c to know that fyl2xp1 pops both inputs. 14818334Speter 14918334Speter asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)"); 15018334Speter 15118334Speter */ 15218334Speter 15318334Speter#include "config.h" 15450397Sobrien#include "system.h" 15518334Speter#include "tree.h" 15618334Speter#include "rtl.h" 15718334Speter#include "insn-config.h" 15818334Speter#include "regs.h" 15918334Speter#include "hard-reg-set.h" 16018334Speter#include "flags.h" 16150397Sobrien#include "insn-flags.h" 16252284Sobrien#include "recog.h" 16350397Sobrien#include "toplev.h" 16452284Sobrien#include "varray.h" 16518334Speter 16618334Speter#ifdef STACK_REGS 16718334Speter 16818334Speter#define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1) 16918334Speter 17018334Speter/* This is the basic stack record. TOP is an index into REG[] such 17118334Speter that REG[TOP] is the top of stack. If TOP is -1 the stack is empty. 17218334Speter 17318334Speter If TOP is -2, REG[] is not yet initialized. Stack initialization 17418334Speter consists of placing each live reg in array `reg' and setting `top' 17518334Speter appropriately. 17618334Speter 17718334Speter REG_SET indicates which registers are live. */ 17818334Speter 17918334Spetertypedef struct stack_def 18018334Speter{ 18118334Speter int top; /* index to top stack element */ 18218334Speter HARD_REG_SET reg_set; /* set of live registers */ 18318334Speter char reg[REG_STACK_SIZE]; /* register - stack mapping */ 18418334Speter} *stack; 18518334Speter 18618334Speter/* highest instruction uid */ 18718334Speterstatic int max_uid = 0; 18818334Speter 18918334Speter/* Number of basic blocks in the current function. */ 19018334Speterstatic int blocks; 19118334Speter 19218334Speter/* Element N is first insn in basic block N. 19318334Speter This info lasts until we finish compiling the function. */ 19418334Speterstatic rtx *block_begin; 19518334Speter 19618334Speter/* Element N is last insn in basic block N. 19718334Speter This info lasts until we finish compiling the function. */ 19818334Speterstatic rtx *block_end; 19918334Speter 20018334Speter/* Element N is nonzero if control can drop into basic block N */ 20118334Speterstatic char *block_drops_in; 20218334Speter 20318334Speter/* Element N says all about the stack at entry block N */ 20418334Speterstatic stack block_stack_in; 20518334Speter 20618334Speter/* Element N says all about the stack life at the end of block N */ 20718334Speterstatic HARD_REG_SET *block_out_reg_set; 20818334Speter 20918334Speter/* This is where the BLOCK_NUM values are really stored. This is set 21018334Speter up by find_blocks and used there and in life_analysis. It can be used 21118334Speter later, but only to look up an insn that is the head or tail of some 21218334Speter block. life_analysis and the stack register conversion process can 21350397Sobrien add insns within a block. */ 21418334Speterstatic int *block_number; 21518334Speter 21652284Sobrien/* We use this array to cache info about insns, because otherwise we 21752284Sobrien spend too much time in stack_regs_mentioned_p. 21852284Sobrien 21952284Sobrien Indexed by insn UIDs. A value of zero is uninitialized, one indicates 22052284Sobrien the insn uses stack registers, two indicates the insn does not use 22152284Sobrien stack registers. */ 22252284Sobrienstatic varray_type stack_regs_mentioned_data; 22352284Sobrien 22418334Speter/* This is the register file for all register after conversion */ 22518334Speterstatic rtx 22618334Speter FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE]; 22718334Speter 22818334Speter#define FP_MODE_REG(regno,mode) \ 22918334Speter (FP_mode_reg[(regno)-FIRST_STACK_REG][(int)(mode)]) 23018334Speter 23118334Speter/* Get the basic block number of an insn. See note at block_number 23250397Sobrien definition are validity of this information. */ 23318334Speter 23452284Sobrienstatic int BLOCK_NUM PROTO((rtx)); 23518334Speter 23652284Sobrien#ifdef __GNUC__ 23752284Sobrien__inline__ 23852284Sobrien#endif 23952284Sobrienstatic int 24052284SobrienBLOCK_NUM(insn) 24152284Sobrien rtx insn; 24252284Sobrien{ 24352284Sobrien int tmp = INSN_UID (insn); 24452284Sobrien if (tmp > max_uid) 24552284Sobrien abort (); 24652284Sobrien tmp = block_number[tmp]; 24752284Sobrien if (tmp < 0) 24852284Sobrien abort (); 24952284Sobrien return tmp; 25052284Sobrien} 25152284Sobrien 25218334Speterextern rtx forced_labels; 25318334Speter 25418334Speter/* Forward declarations */ 25518334Speter 25650397Sobrienstatic void mark_regs_pat PROTO((rtx, HARD_REG_SET *)); 25750397Sobrienstatic void straighten_stack PROTO((rtx, stack)); 25850397Sobrienstatic void pop_stack PROTO((stack, int)); 25950397Sobrienstatic void record_label_references PROTO((rtx, rtx)); 26050397Sobrienstatic rtx *get_true_reg PROTO((rtx *)); 26150397Sobrien 26252284Sobrienstatic void record_asm_reg_life PROTO((rtx, stack)); 26350397Sobrienstatic void record_reg_life_pat PROTO((rtx, HARD_REG_SET *, 26450397Sobrien HARD_REG_SET *, int)); 26552284Sobrienstatic int get_asm_operand_n_inputs PROTO((rtx)); 26650397Sobrienstatic void record_reg_life PROTO((rtx, int, stack)); 26750397Sobrienstatic void find_blocks PROTO((rtx)); 26850397Sobrienstatic rtx stack_result PROTO((tree)); 26950397Sobrienstatic void stack_reg_life_analysis PROTO((rtx, HARD_REG_SET *)); 27050397Sobrienstatic void replace_reg PROTO((rtx *, int)); 27150397Sobrienstatic void remove_regno_note PROTO((rtx, enum reg_note, int)); 27250397Sobrienstatic int get_hard_regnum PROTO((stack, rtx)); 27350397Sobrienstatic void delete_insn_for_stacker PROTO((rtx)); 27450397Sobrienstatic rtx emit_pop_insn PROTO((rtx, stack, rtx, rtx (*) ())); 27550397Sobrienstatic void emit_swap_insn PROTO((rtx, stack, rtx)); 27650397Sobrienstatic void move_for_stack_reg PROTO((rtx, stack, rtx)); 27750397Sobrienstatic void swap_rtx_condition PROTO((rtx)); 27850397Sobrienstatic void compare_for_stack_reg PROTO((rtx, stack, rtx)); 27950397Sobrienstatic void subst_stack_regs_pat PROTO((rtx, stack, rtx)); 28052284Sobrienstatic void subst_asm_stack_regs PROTO((rtx, stack)); 28150397Sobrienstatic void subst_stack_regs PROTO((rtx, stack)); 28250397Sobrienstatic void change_stack PROTO((rtx, stack, stack, rtx (*) ())); 28350397Sobrien 28450397Sobrienstatic void goto_block_pat PROTO((rtx, stack, rtx)); 28550397Sobrienstatic void convert_regs PROTO((void)); 28650397Sobrienstatic void print_blocks PROTO((FILE *, rtx, rtx)); 28750397Sobrienstatic void dump_stack_info PROTO((FILE *)); 28852284Sobrienstatic int check_stack_regs_mentioned PROTO((rtx insn)); 28918334Speter 29052284Sobrien/* Initialize stack_regs_mentioned_data for INSN (growing the virtual array 29152284Sobrien if needed. Return nonzero if INSN mentions stacked registers. */ 29252284Sobrien 29352284Sobrienstatic int 29452284Sobriencheck_stack_regs_mentioned (insn) 29552284Sobrien rtx insn; 29652284Sobrien{ 29752284Sobrien unsigned int uid = INSN_UID (insn); 29852284Sobrien if (uid >= VARRAY_SIZE (stack_regs_mentioned_data)) 29952284Sobrien /* Allocate some extra size to avoid too many reallocs, but 30052284Sobrien do not grow exponentially. */ 30152284Sobrien VARRAY_GROW (stack_regs_mentioned_data, uid + uid / 20); 30252284Sobrien if (stack_regs_mentioned_p (PATTERN (insn))) 30352284Sobrien { 30452284Sobrien VARRAY_CHAR (stack_regs_mentioned_data, uid) = 1; 30552284Sobrien return 1; 30652284Sobrien } 30752284Sobrien else 30852284Sobrien VARRAY_CHAR (stack_regs_mentioned_data, uid) = 2; 30952284Sobrien return 0; 31052284Sobrien} 31152284Sobrien 31252284Sobrien/* Return nonzero if INSN mentions stacked registers, else return 31352284Sobrien zero. */ 31452284Sobrien 31552284Sobrienint 31652284Sobrienstack_regs_mentioned (insn) 31752284Sobrien rtx insn; 31852284Sobrien{ 31952284Sobrien unsigned int uid; 32052284Sobrien if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') 32152284Sobrien return 0; 32252284Sobrien uid = INSN_UID (insn); 32352284Sobrien if (uid >= VARRAY_SIZE (stack_regs_mentioned_data) 32452284Sobrien || ! VARRAY_CHAR (stack_regs_mentioned_data, uid)) 32552284Sobrien return (check_stack_regs_mentioned (insn)); 32652284Sobrien return VARRAY_CHAR (stack_regs_mentioned_data, uid) == 1; 32752284Sobrien} 32852284Sobrien 32952284Sobrien 33018334Speter/* Mark all registers needed for this pattern. */ 33118334Speter 33218334Speterstatic void 33318334Spetermark_regs_pat (pat, set) 33418334Speter rtx pat; 33518334Speter HARD_REG_SET *set; 33618334Speter{ 33718334Speter enum machine_mode mode; 33818334Speter register int regno; 33918334Speter register int count; 34018334Speter 34118334Speter if (GET_CODE (pat) == SUBREG) 34218334Speter { 34318334Speter mode = GET_MODE (pat); 34418334Speter regno = SUBREG_WORD (pat); 34518334Speter regno += REGNO (SUBREG_REG (pat)); 34618334Speter } 34718334Speter else 34818334Speter regno = REGNO (pat), mode = GET_MODE (pat); 34918334Speter 35018334Speter for (count = HARD_REGNO_NREGS (regno, mode); 35118334Speter count; count--, regno++) 35218334Speter SET_HARD_REG_BIT (*set, regno); 35318334Speter} 35418334Speter 35518334Speter/* Reorganise the stack into ascending numbers, 35618334Speter after this insn. */ 35718334Speter 35818334Speterstatic void 35918334Speterstraighten_stack (insn, regstack) 36018334Speter rtx insn; 36118334Speter stack regstack; 36218334Speter{ 36318334Speter struct stack_def temp_stack; 36418334Speter int top; 36518334Speter 36650397Sobrien /* If there is only a single register on the stack, then the stack is 36750397Sobrien already in increasing order and no reorganization is needed. 36850397Sobrien 36950397Sobrien Similarly if the stack is empty. */ 37050397Sobrien if (regstack->top <= 0) 37150397Sobrien return; 37250397Sobrien 37318334Speter temp_stack.reg_set = regstack->reg_set; 37418334Speter 37518334Speter for (top = temp_stack.top = regstack->top; top >= 0; top--) 37618334Speter temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top; 37718334Speter 37818334Speter change_stack (insn, regstack, &temp_stack, emit_insn_after); 37918334Speter} 38050397Sobrien 38150397Sobrien/* Pop a register from the stack */ 38250397Sobrien 38350397Sobrienstatic void 38450397Sobrienpop_stack (regstack, regno) 38550397Sobrien stack regstack; 38650397Sobrien int regno; 38750397Sobrien{ 38850397Sobrien int top = regstack->top; 38950397Sobrien 39050397Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, regno); 39150397Sobrien regstack->top--; 39250397Sobrien /* If regno was not at the top of stack then adjust stack */ 39350397Sobrien if (regstack->reg [top] != regno) 39450397Sobrien { 39550397Sobrien int i; 39650397Sobrien for (i = regstack->top; i >= 0; i--) 39750397Sobrien if (regstack->reg [i] == regno) 39850397Sobrien { 39950397Sobrien int j; 40050397Sobrien for (j = i; j < top; j++) 40150397Sobrien regstack->reg [j] = regstack->reg [j + 1]; 40250397Sobrien break; 40350397Sobrien } 40450397Sobrien } 40550397Sobrien} 40618334Speter 40718334Speter/* Return non-zero if any stack register is mentioned somewhere within PAT. */ 40818334Speter 40918334Speterint 41018334Speterstack_regs_mentioned_p (pat) 41118334Speter rtx pat; 41218334Speter{ 41318334Speter register char *fmt; 41418334Speter register int i; 41518334Speter 41618334Speter if (STACK_REG_P (pat)) 41718334Speter return 1; 41818334Speter 41918334Speter fmt = GET_RTX_FORMAT (GET_CODE (pat)); 42018334Speter for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) 42118334Speter { 42218334Speter if (fmt[i] == 'E') 42318334Speter { 42418334Speter register int j; 42518334Speter 42618334Speter for (j = XVECLEN (pat, i) - 1; j >= 0; j--) 42718334Speter if (stack_regs_mentioned_p (XVECEXP (pat, i, j))) 42818334Speter return 1; 42918334Speter } 43018334Speter else if (fmt[i] == 'e' && stack_regs_mentioned_p (XEXP (pat, i))) 43118334Speter return 1; 43218334Speter } 43318334Speter 43418334Speter return 0; 43518334Speter} 43618334Speter 43718334Speter/* Convert register usage from "flat" register file usage to a "stack 43818334Speter register file. FIRST is the first insn in the function, FILE is the 43918334Speter dump file, if used. 44018334Speter 44118334Speter First compute the beginning and end of each basic block. Do a 44218334Speter register life analysis on the stack registers, recording the result 44318334Speter for the head and tail of each basic block. The convert each insn one 44418334Speter by one. Run a last jump_optimize() pass, if optimizing, to eliminate 44518334Speter any cross-jumping created when the converter inserts pop insns.*/ 44618334Speter 44718334Spetervoid 44818334Speterreg_to_stack (first, file) 44918334Speter rtx first; 45018334Speter FILE *file; 45118334Speter{ 45218334Speter register rtx insn; 45318334Speter register int i; 45418334Speter int stack_reg_seen = 0; 45518334Speter enum machine_mode mode; 45618334Speter HARD_REG_SET stackentry; 45718334Speter 45852284Sobrien max_uid = get_max_uid (); 45952284Sobrien VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1, 46052284Sobrien "stack_regs_mentioned cache"); 46152284Sobrien 46218334Speter CLEAR_HARD_REG_SET (stackentry); 46318334Speter 46418334Speter { 46550397Sobrien static int initialised; 46618334Speter if (!initialised) 46718334Speter { 46818334Speter#if 0 46918334Speter initialised = 1; /* This array can not have been previously 47018334Speter initialised, because the rtx's are 47118334Speter thrown away between compilations of 47218334Speter functions. */ 47318334Speter#endif 47418334Speter for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) 47518334Speter { 47618334Speter for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; 47718334Speter mode = GET_MODE_WIDER_MODE (mode)) 47850397Sobrien FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i); 47918334Speter for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT); mode != VOIDmode; 48018334Speter mode = GET_MODE_WIDER_MODE (mode)) 48150397Sobrien FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i); 48218334Speter } 48318334Speter } 48418334Speter } 48518334Speter 48618334Speter /* Count the basic blocks. Also find maximum insn uid. */ 48718334Speter { 48818334Speter register RTX_CODE prev_code = BARRIER; 48918334Speter register RTX_CODE code; 49050397Sobrien register int before_function_beg = 1; 49118334Speter 49218334Speter max_uid = 0; 49318334Speter blocks = 0; 49418334Speter for (insn = first; insn; insn = NEXT_INSN (insn)) 49518334Speter { 49618334Speter /* Note that this loop must select the same block boundaries 49718334Speter as code in find_blocks. Also note that this code is not the 49818334Speter same as that used in flow.c. */ 49918334Speter 50018334Speter if (INSN_UID (insn) > max_uid) 50118334Speter max_uid = INSN_UID (insn); 50218334Speter 50318334Speter code = GET_CODE (insn); 50418334Speter 50518334Speter if (code == CODE_LABEL 50618334Speter || (prev_code != INSN 50718334Speter && prev_code != CALL_INSN 50818334Speter && prev_code != CODE_LABEL 50918334Speter && GET_RTX_CLASS (code) == 'i')) 51018334Speter blocks++; 51118334Speter 51218334Speter if (code == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) 51318334Speter before_function_beg = 0; 51418334Speter 51518334Speter /* Remember whether or not this insn mentions an FP regs. 51650397Sobrien Check JUMP_INSNs too, in case someone creates a funny PARALLEL. */ 51718334Speter 51818334Speter if (GET_RTX_CLASS (code) == 'i' 51918334Speter && stack_regs_mentioned_p (PATTERN (insn))) 52018334Speter { 52118334Speter stack_reg_seen = 1; 52252284Sobrien VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 1; 52318334Speter 52418334Speter /* Note any register passing parameters. */ 52518334Speter 52618334Speter if (before_function_beg && code == INSN 52718334Speter && GET_CODE (PATTERN (insn)) == USE) 52850397Sobrien record_reg_life_pat (PATTERN (insn), (HARD_REG_SET *) 0, 52918334Speter &stackentry, 1); 53018334Speter } 53118334Speter else 53252284Sobrien VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2; 53318334Speter 53418334Speter if (code == CODE_LABEL) 53518334Speter LABEL_REFS (insn) = insn; /* delete old chain */ 53618334Speter 53718334Speter if (code != NOTE) 53818334Speter prev_code = code; 53918334Speter } 54018334Speter } 54118334Speter 54218334Speter /* If no stack register reference exists in this insn, there isn't 54318334Speter anything to convert. */ 54418334Speter 54518334Speter if (! stack_reg_seen) 54652284Sobrien { 54752284Sobrien VARRAY_FREE (stack_regs_mentioned_data); 54852284Sobrien return; 54952284Sobrien } 55018334Speter 55150397Sobrien /* If there are stack registers, there must be at least one block. */ 55218334Speter 55318334Speter if (! blocks) 55418334Speter abort (); 55518334Speter 55618334Speter /* Allocate some tables that last till end of compiling this function 55750397Sobrien and some needed only in find_blocks and life_analysis. */ 55818334Speter 55918334Speter block_begin = (rtx *) alloca (blocks * sizeof (rtx)); 56018334Speter block_end = (rtx *) alloca (blocks * sizeof (rtx)); 56118334Speter block_drops_in = (char *) alloca (blocks); 56218334Speter 56318334Speter block_stack_in = (stack) alloca (blocks * sizeof (struct stack_def)); 56418334Speter block_out_reg_set = (HARD_REG_SET *) alloca (blocks * sizeof (HARD_REG_SET)); 56518334Speter bzero ((char *) block_stack_in, blocks * sizeof (struct stack_def)); 56618334Speter bzero ((char *) block_out_reg_set, blocks * sizeof (HARD_REG_SET)); 56718334Speter 56818334Speter block_number = (int *) alloca ((max_uid + 1) * sizeof (int)); 56952284Sobrien memset (block_number, -1, (max_uid + 1) * sizeof (int)); 57018334Speter 57118334Speter find_blocks (first); 57218334Speter stack_reg_life_analysis (first, &stackentry); 57318334Speter 57418334Speter /* Dump the life analysis debug information before jump 57518334Speter optimization, as that will destroy the LABEL_REFS we keep the 57650397Sobrien information in. */ 57718334Speter 57818334Speter if (file) 57918334Speter dump_stack_info (file); 58018334Speter 58118334Speter convert_regs (); 58218334Speter 58318334Speter if (optimize) 58418334Speter jump_optimize (first, 2, 0, 0); 58552284Sobrien 58652284Sobrien VARRAY_FREE (stack_regs_mentioned_data); 58718334Speter} 58818334Speter 58918334Speter/* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the 59018334Speter label's chain of references, and note which insn contains each 59150397Sobrien reference. */ 59218334Speter 59318334Speterstatic void 59418334Speterrecord_label_references (insn, pat) 59518334Speter rtx insn, pat; 59618334Speter{ 59718334Speter register enum rtx_code code = GET_CODE (pat); 59818334Speter register int i; 59918334Speter register char *fmt; 60018334Speter 60118334Speter if (code == LABEL_REF) 60218334Speter { 60318334Speter register rtx label = XEXP (pat, 0); 60418334Speter register rtx ref; 60518334Speter 60618334Speter if (GET_CODE (label) != CODE_LABEL) 60718334Speter abort (); 60818334Speter 60950397Sobrien /* If this is an undefined label, LABEL_REFS (label) contains 61050397Sobrien garbage. */ 61150397Sobrien if (INSN_UID (label) == 0) 61250397Sobrien return; 61318334Speter 61450397Sobrien /* Don't make a duplicate in the code_label's chain. */ 61550397Sobrien 61618334Speter for (ref = LABEL_REFS (label); 61718334Speter ref && ref != label; 61818334Speter ref = LABEL_NEXTREF (ref)) 61918334Speter if (CONTAINING_INSN (ref) == insn) 62018334Speter return; 62118334Speter 62218334Speter CONTAINING_INSN (pat) = insn; 62318334Speter LABEL_NEXTREF (pat) = LABEL_REFS (label); 62418334Speter LABEL_REFS (label) = pat; 62518334Speter 62618334Speter return; 62718334Speter } 62818334Speter 62918334Speter fmt = GET_RTX_FORMAT (code); 63018334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 63118334Speter { 63218334Speter if (fmt[i] == 'e') 63318334Speter record_label_references (insn, XEXP (pat, i)); 63418334Speter if (fmt[i] == 'E') 63518334Speter { 63618334Speter register int j; 63718334Speter for (j = 0; j < XVECLEN (pat, i); j++) 63818334Speter record_label_references (insn, XVECEXP (pat, i, j)); 63918334Speter } 64018334Speter } 64118334Speter} 64218334Speter 64318334Speter/* Return a pointer to the REG expression within PAT. If PAT is not a 64418334Speter REG, possible enclosed by a conversion rtx, return the inner part of 64550397Sobrien PAT that stopped the search. */ 64618334Speter 64718334Speterstatic rtx * 64818334Speterget_true_reg (pat) 64918334Speter rtx *pat; 65018334Speter{ 65118334Speter for (;;) 65218334Speter switch (GET_CODE (*pat)) 65318334Speter { 65418334Speter case SUBREG: 65518334Speter /* eliminate FP subregister accesses in favour of the 65650397Sobrien actual FP register in use. */ 65718334Speter { 65818334Speter rtx subreg; 65918334Speter if (FP_REG_P (subreg = SUBREG_REG (*pat))) 66018334Speter { 66118334Speter *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat), 66218334Speter GET_MODE (subreg)); 66318334Speter default: 66418334Speter return pat; 66518334Speter } 66618334Speter } 66718334Speter case FLOAT: 66818334Speter case FIX: 66918334Speter case FLOAT_EXTEND: 67018334Speter pat = & XEXP (*pat, 0); 67118334Speter } 67218334Speter} 67318334Speter 67418334Speter/* Record the life info of each stack reg in INSN, updating REGSTACK. 67552284Sobrien N_INPUTS is the number of inputs; N_OUTPUTS the outputs. 67618334Speter OPERANDS is an array of all operands for the insn, and is assumed to 67718334Speter contain all output operands, then all inputs operands. 67818334Speter 67918334Speter There are many rules that an asm statement for stack-like regs must 68018334Speter follow. Those rules are explained at the top of this file: the rule 68150397Sobrien numbers below refer to that explanation. */ 68218334Speter 68318334Speterstatic void 68452284Sobrienrecord_asm_reg_life (insn, regstack) 68518334Speter rtx insn; 68618334Speter stack regstack; 68718334Speter{ 68818334Speter int i; 68918334Speter int n_clobbers; 69018334Speter int malformed_asm = 0; 69118334Speter rtx body = PATTERN (insn); 69218334Speter 69318334Speter int reg_used_as_output[FIRST_PSEUDO_REGISTER]; 69418334Speter int implicitly_dies[FIRST_PSEUDO_REGISTER]; 69552284Sobrien int alt; 69618334Speter 69718334Speter rtx *clobber_reg; 69852284Sobrien int n_inputs, n_outputs; 69918334Speter 70018334Speter /* Find out what the constraints require. If no constraint 70118334Speter alternative matches, this asm is malformed. */ 70252284Sobrien extract_insn (insn); 70352284Sobrien constrain_operands (1); 70452284Sobrien alt = which_alternative; 70518334Speter 70652284Sobrien preprocess_constraints (); 70752284Sobrien 70852284Sobrien n_inputs = get_asm_operand_n_inputs (body); 70952284Sobrien n_outputs = recog_n_operands - n_inputs; 71052284Sobrien 71152284Sobrien if (alt < 0) 71252284Sobrien { 71352284Sobrien malformed_asm = 1; 71452284Sobrien /* Avoid further trouble with this insn. */ 71552284Sobrien PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx); 71652284Sobrien VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2; 71752284Sobrien return; 71852284Sobrien } 71952284Sobrien 72050397Sobrien /* Strip SUBREGs here to make the following code simpler. */ 72152284Sobrien for (i = 0; i < recog_n_operands; i++) 72252284Sobrien if (GET_CODE (recog_operand[i]) == SUBREG 72352284Sobrien && GET_CODE (SUBREG_REG (recog_operand[i])) == REG) 72452284Sobrien recog_operand[i] = SUBREG_REG (recog_operand[i]); 72518334Speter 72618334Speter /* Set up CLOBBER_REG. */ 72718334Speter 72818334Speter n_clobbers = 0; 72918334Speter 73018334Speter if (GET_CODE (body) == PARALLEL) 73118334Speter { 73252284Sobrien clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx)); 73318334Speter 73418334Speter for (i = 0; i < XVECLEN (body, 0); i++) 73518334Speter if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) 73618334Speter { 73718334Speter rtx clobber = XVECEXP (body, 0, i); 73818334Speter rtx reg = XEXP (clobber, 0); 73918334Speter 74018334Speter if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) 74118334Speter reg = SUBREG_REG (reg); 74218334Speter 74318334Speter if (STACK_REG_P (reg)) 74418334Speter { 74518334Speter clobber_reg[n_clobbers] = reg; 74618334Speter n_clobbers++; 74718334Speter } 74818334Speter } 74918334Speter } 75018334Speter 75118334Speter /* Enforce rule #4: Output operands must specifically indicate which 75218334Speter reg an output appears in after an asm. "=f" is not allowed: the 75318334Speter operand constraints must select a class with a single reg. 75418334Speter 75518334Speter Also enforce rule #5: Output operands must start at the top of 75650397Sobrien the reg-stack: output operands may not "skip" a reg. */ 75718334Speter 75818334Speter bzero ((char *) reg_used_as_output, sizeof (reg_used_as_output)); 75918334Speter for (i = 0; i < n_outputs; i++) 76052284Sobrien if (STACK_REG_P (recog_operand[i])) 76150397Sobrien { 76252284Sobrien if (reg_class_size[(int) recog_op_alt[i][alt].class] != 1) 76350397Sobrien { 76450397Sobrien error_for_asm (insn, "Output constraint %d must specify a single register", i); 76550397Sobrien malformed_asm = 1; 76650397Sobrien } 76750397Sobrien else 76852284Sobrien reg_used_as_output[REGNO (recog_operand[i])] = 1; 76950397Sobrien } 77018334Speter 77118334Speter 77218334Speter /* Search for first non-popped reg. */ 77318334Speter for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++) 77418334Speter if (! reg_used_as_output[i]) 77518334Speter break; 77618334Speter 77718334Speter /* If there are any other popped regs, that's an error. */ 77818334Speter for (; i < LAST_STACK_REG + 1; i++) 77918334Speter if (reg_used_as_output[i]) 78018334Speter break; 78118334Speter 78218334Speter if (i != LAST_STACK_REG + 1) 78318334Speter { 78418334Speter error_for_asm (insn, "Output regs must be grouped at top of stack"); 78518334Speter malformed_asm = 1; 78618334Speter } 78718334Speter 78818334Speter /* Enforce rule #2: All implicitly popped input regs must be closer 78918334Speter to the top of the reg-stack than any input that is not implicitly 79050397Sobrien popped. */ 79118334Speter 79218334Speter bzero ((char *) implicitly_dies, sizeof (implicitly_dies)); 79352284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 79452284Sobrien if (STACK_REG_P (recog_operand[i])) 79518334Speter { 79618334Speter /* An input reg is implicitly popped if it is tied to an 79750397Sobrien output, or if there is a CLOBBER for it. */ 79818334Speter int j; 79918334Speter 80018334Speter for (j = 0; j < n_clobbers; j++) 80152284Sobrien if (operands_match_p (clobber_reg[j], recog_operand[i])) 80218334Speter break; 80318334Speter 80452284Sobrien if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0) 80552284Sobrien implicitly_dies[REGNO (recog_operand[i])] = 1; 80618334Speter } 80718334Speter 80818334Speter /* Search for first non-popped reg. */ 80918334Speter for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++) 81018334Speter if (! implicitly_dies[i]) 81118334Speter break; 81218334Speter 81318334Speter /* If there are any other popped regs, that's an error. */ 81418334Speter for (; i < LAST_STACK_REG + 1; i++) 81518334Speter if (implicitly_dies[i]) 81618334Speter break; 81718334Speter 81818334Speter if (i != LAST_STACK_REG + 1) 81918334Speter { 82018334Speter error_for_asm (insn, 82118334Speter "Implicitly popped regs must be grouped at top of stack"); 82218334Speter malformed_asm = 1; 82318334Speter } 82418334Speter 82518334Speter /* Enfore rule #3: If any input operand uses the "f" constraint, all 82618334Speter output constraints must use the "&" earlyclobber. 82718334Speter 82818334Speter ??? Detect this more deterministically by having constraint_asm_operands 82950397Sobrien record any earlyclobber. */ 83018334Speter 83152284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 83252284Sobrien if (recog_op_alt[i][alt].matches == -1) 83318334Speter { 83418334Speter int j; 83518334Speter 83618334Speter for (j = 0; j < n_outputs; j++) 83752284Sobrien if (operands_match_p (recog_operand[j], recog_operand[i])) 83818334Speter { 83918334Speter error_for_asm (insn, 84018334Speter "Output operand %d must use `&' constraint", j); 84118334Speter malformed_asm = 1; 84218334Speter } 84318334Speter } 84418334Speter 84518334Speter if (malformed_asm) 84618334Speter { 84718334Speter /* Avoid further trouble with this insn. */ 84850397Sobrien PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx); 84952284Sobrien VARRAY_CHAR (stack_regs_mentioned_data, INSN_UID (insn)) = 2; 85018334Speter return; 85118334Speter } 85218334Speter 85318334Speter /* Process all outputs */ 85418334Speter for (i = 0; i < n_outputs; i++) 85518334Speter { 85652284Sobrien rtx op = recog_operand[i]; 85718334Speter 85818334Speter if (! STACK_REG_P (op)) 85950397Sobrien { 86050397Sobrien if (stack_regs_mentioned_p (op)) 86150397Sobrien abort (); 86250397Sobrien else 86350397Sobrien continue; 86450397Sobrien } 86518334Speter 86618334Speter /* Each destination is dead before this insn. If the 86718334Speter destination is not used after this insn, record this with 86818334Speter REG_UNUSED. */ 86918334Speter 87018334Speter if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (op))) 87150397Sobrien REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED, op, 87250397Sobrien REG_NOTES (insn)); 87318334Speter 87418334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (op)); 87518334Speter } 87618334Speter 87718334Speter /* Process all inputs */ 87852284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 87918334Speter { 88052284Sobrien rtx op = recog_operand[i]; 88152284Sobrien if (! STACK_REG_P (op)) 88250397Sobrien { 88352284Sobrien if (stack_regs_mentioned_p (op)) 88450397Sobrien abort (); 88550397Sobrien else 88650397Sobrien continue; 88750397Sobrien } 88818334Speter 88918334Speter /* If an input is dead after the insn, record a death note. 89018334Speter But don't record a death note if there is already a death note, 89118334Speter or if the input is also an output. */ 89218334Speter 89352284Sobrien if (! TEST_HARD_REG_BIT (regstack->reg_set, REGNO (op)) 89452284Sobrien && recog_op_alt[i][alt].matches == -1 89552284Sobrien && find_regno_note (insn, REG_DEAD, REGNO (op)) == NULL_RTX) 89652284Sobrien REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, op, REG_NOTES (insn)); 89718334Speter 89852284Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (op)); 89918334Speter } 90018334Speter} 90118334Speter 90218334Speter/* Scan PAT, which is part of INSN, and record registers appearing in 90318334Speter a SET_DEST in DEST, and other registers in SRC. 90418334Speter 90518334Speter This function does not know about SET_DESTs that are both input and 90650397Sobrien output (such as ZERO_EXTRACT) - this cannot happen on a 387. */ 90718334Speter 90818334Speterstatic void 90918334Speterrecord_reg_life_pat (pat, src, dest, douse) 91018334Speter rtx pat; 91118334Speter HARD_REG_SET *src, *dest; 91218334Speter int douse; 91318334Speter{ 91418334Speter register char *fmt; 91518334Speter register int i; 91618334Speter 91718334Speter if (STACK_REG_P (pat) 91850397Sobrien || (GET_CODE (pat) == SUBREG && STACK_REG_P (SUBREG_REG (pat)))) 91918334Speter { 92018334Speter if (src) 92118334Speter mark_regs_pat (pat, src); 92218334Speter 92318334Speter if (dest) 92418334Speter mark_regs_pat (pat, dest); 92518334Speter 92618334Speter return; 92718334Speter } 92818334Speter 92918334Speter if (GET_CODE (pat) == SET) 93018334Speter { 93118334Speter record_reg_life_pat (XEXP (pat, 0), NULL_PTR, dest, 0); 93218334Speter record_reg_life_pat (XEXP (pat, 1), src, NULL_PTR, 0); 93318334Speter return; 93418334Speter } 93518334Speter 93650397Sobrien /* We don't need to consider either of these cases. */ 93750397Sobrien if ((GET_CODE (pat) == USE && !douse) || GET_CODE (pat) == CLOBBER) 93818334Speter return; 93918334Speter 94018334Speter fmt = GET_RTX_FORMAT (GET_CODE (pat)); 94118334Speter for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) 94218334Speter { 94318334Speter if (fmt[i] == 'E') 94418334Speter { 94518334Speter register int j; 94618334Speter 94718334Speter for (j = XVECLEN (pat, i) - 1; j >= 0; j--) 94818334Speter record_reg_life_pat (XVECEXP (pat, i, j), src, dest, 0); 94918334Speter } 95018334Speter else if (fmt[i] == 'e') 95118334Speter record_reg_life_pat (XEXP (pat, i), src, dest, 0); 95218334Speter } 95318334Speter} 95418334Speter 95518334Speter/* Calculate the number of inputs and outputs in BODY, an 95618334Speter asm_operands. N_OPERANDS is the total number of operands, and 95718334Speter N_INPUTS and N_OUTPUTS are pointers to ints into which the results are 95850397Sobrien placed. */ 95918334Speter 96052284Sobrienstatic int 96152284Sobrienget_asm_operand_n_inputs (body) 96218334Speter rtx body; 96318334Speter{ 96418334Speter if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) 96552284Sobrien return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)); 96618334Speter 96718334Speter else if (GET_CODE (body) == ASM_OPERANDS) 96852284Sobrien return ASM_OPERANDS_INPUT_LENGTH (body); 96918334Speter 97018334Speter else if (GET_CODE (body) == PARALLEL 97118334Speter && GET_CODE (XVECEXP (body, 0, 0)) == SET) 97252284Sobrien return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0))); 97318334Speter 97418334Speter else if (GET_CODE (body) == PARALLEL 97518334Speter && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) 97652284Sobrien return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0)); 97718334Speter 97852284Sobrien abort (); 97918334Speter} 98018334Speter 98118334Speter/* Scan INSN, which is in BLOCK, and record the life & death of stack 98218334Speter registers in REGSTACK. This function is called to process insns from 98318334Speter the last insn in a block to the first. The actual scanning is done in 98418334Speter record_reg_life_pat. 98518334Speter 98618334Speter If a register is live after a CALL_INSN, but is not a value return 98718334Speter register for that CALL_INSN, then code is emitted to initialize that 98818334Speter register. The block_end[] data is kept accurate. 98918334Speter 99018334Speter Existing death and unset notes for stack registers are deleted 99150397Sobrien before processing the insn. */ 99218334Speter 99318334Speterstatic void 99418334Speterrecord_reg_life (insn, block, regstack) 99518334Speter rtx insn; 99618334Speter int block; 99718334Speter stack regstack; 99818334Speter{ 99918334Speter rtx note, *note_link; 100018334Speter int n_operands; 100118334Speter 100218334Speter if ((GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN) 100318334Speter || INSN_DELETED_P (insn)) 100418334Speter return; 100518334Speter 100618334Speter /* Strip death notes for stack regs from this insn */ 100718334Speter 100818334Speter note_link = ®_NOTES(insn); 100918334Speter for (note = *note_link; note; note = XEXP (note, 1)) 101018334Speter if (STACK_REG_P (XEXP (note, 0)) 101118334Speter && (REG_NOTE_KIND (note) == REG_DEAD 101218334Speter || REG_NOTE_KIND (note) == REG_UNUSED)) 101318334Speter *note_link = XEXP (note, 1); 101418334Speter else 101518334Speter note_link = &XEXP (note, 1); 101618334Speter 101750397Sobrien /* Process all patterns in the insn. */ 101818334Speter 101918334Speter n_operands = asm_noperands (PATTERN (insn)); 102018334Speter if (n_operands >= 0) 102118334Speter { 102252284Sobrien record_asm_reg_life (insn, regstack); 102318334Speter return; 102418334Speter } 102518334Speter 102618334Speter { 102718334Speter HARD_REG_SET src, dest; 102818334Speter int regno; 102918334Speter 103018334Speter CLEAR_HARD_REG_SET (src); 103118334Speter CLEAR_HARD_REG_SET (dest); 103218334Speter 103318334Speter if (GET_CODE (insn) == CALL_INSN) 103418334Speter for (note = CALL_INSN_FUNCTION_USAGE (insn); 103518334Speter note; 103618334Speter note = XEXP (note, 1)) 103718334Speter if (GET_CODE (XEXP (note, 0)) == USE) 103818334Speter record_reg_life_pat (SET_DEST (XEXP (note, 0)), &src, NULL_PTR, 0); 103918334Speter 104018334Speter record_reg_life_pat (PATTERN (insn), &src, &dest, 0); 104118334Speter for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++) 104218334Speter if (! TEST_HARD_REG_BIT (regstack->reg_set, regno)) 104318334Speter { 104418334Speter if (TEST_HARD_REG_BIT (src, regno) 104518334Speter && ! TEST_HARD_REG_BIT (dest, regno)) 104650397Sobrien REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, 104750397Sobrien FP_MODE_REG (regno, DFmode), 104850397Sobrien REG_NOTES (insn)); 104918334Speter else if (TEST_HARD_REG_BIT (dest, regno)) 105050397Sobrien REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_UNUSED, 105150397Sobrien FP_MODE_REG (regno, DFmode), 105250397Sobrien REG_NOTES (insn)); 105318334Speter } 105418334Speter 105518334Speter if (GET_CODE (insn) == CALL_INSN) 105618334Speter { 105718334Speter int reg; 105818334Speter 105918334Speter /* There might be a reg that is live after a function call. 106018334Speter Initialize it to zero so that the program does not crash. See 106150397Sobrien comment towards the end of stack_reg_life_analysis(). */ 106218334Speter 106318334Speter for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++) 106418334Speter if (! TEST_HARD_REG_BIT (dest, reg) 106518334Speter && TEST_HARD_REG_BIT (regstack->reg_set, reg)) 106618334Speter { 106718334Speter rtx init, pat; 106818334Speter 106918334Speter /* The insn will use virtual register numbers, and so 107018334Speter convert_regs is expected to process these. But BLOCK_NUM 107118334Speter cannot be used on these insns, because they do not appear in 107250397Sobrien block_number[]. */ 107318334Speter 107450397Sobrien pat = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, DFmode), 107550397Sobrien CONST0_RTX (DFmode)); 107618334Speter init = emit_insn_after (pat, insn); 107718334Speter 107818334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, reg); 107918334Speter 108018334Speter /* If the CALL_INSN was the end of a block, move the 108150397Sobrien block_end to point to the new insn. */ 108218334Speter 108318334Speter if (block_end[block] == insn) 108418334Speter block_end[block] = init; 108518334Speter } 108618334Speter 108718334Speter /* Some regs do not survive a CALL */ 108818334Speter AND_COMPL_HARD_REG_SET (regstack->reg_set, call_used_reg_set); 108918334Speter } 109018334Speter 109118334Speter AND_COMPL_HARD_REG_SET (regstack->reg_set, dest); 109218334Speter IOR_HARD_REG_SET (regstack->reg_set, src); 109318334Speter } 109418334Speter} 109518334Speter 109618334Speter/* Find all basic blocks of the function, which starts with FIRST. 109750397Sobrien For each JUMP_INSN, build the chain of LABEL_REFS on each CODE_LABEL. */ 109818334Speter 109918334Speterstatic void 110018334Speterfind_blocks (first) 110118334Speter rtx first; 110218334Speter{ 110318334Speter register rtx insn; 110418334Speter register int block; 110518334Speter register RTX_CODE prev_code = BARRIER; 110618334Speter register RTX_CODE code; 110718334Speter rtx label_value_list = 0; 110818334Speter 110918334Speter /* Record where all the blocks start and end. 111050397Sobrien Record which basic blocks control can drop in to. */ 111118334Speter 111218334Speter block = -1; 111318334Speter for (insn = first; insn; insn = NEXT_INSN (insn)) 111418334Speter { 111518334Speter /* Note that this loop must select the same block boundaries 111618334Speter as code in reg_to_stack, but that these are not the same 111718334Speter as those selected in flow.c. */ 111818334Speter 111918334Speter code = GET_CODE (insn); 112018334Speter 112118334Speter if (code == CODE_LABEL 112218334Speter || (prev_code != INSN 112318334Speter && prev_code != CALL_INSN 112418334Speter && prev_code != CODE_LABEL 112518334Speter && GET_RTX_CLASS (code) == 'i')) 112618334Speter { 112718334Speter block_begin[++block] = insn; 112818334Speter block_end[block] = insn; 112918334Speter block_drops_in[block] = prev_code != BARRIER; 113018334Speter } 113118334Speter else if (GET_RTX_CLASS (code) == 'i') 113218334Speter block_end[block] = insn; 113318334Speter 113418334Speter if (GET_RTX_CLASS (code) == 'i') 113518334Speter { 113618334Speter rtx note; 113718334Speter 113818334Speter /* Make a list of all labels referred to other than by jumps. */ 113918334Speter for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 114018334Speter if (REG_NOTE_KIND (note) == REG_LABEL) 114150397Sobrien label_value_list = gen_rtx_EXPR_LIST (VOIDmode, XEXP (note, 0), 114250397Sobrien label_value_list); 114318334Speter } 114418334Speter 114518334Speter block_number[INSN_UID (insn)] = block; 114618334Speter 114718334Speter if (code != NOTE) 114818334Speter prev_code = code; 114918334Speter } 115018334Speter 115118334Speter if (block + 1 != blocks) 115218334Speter abort (); 115318334Speter 115418334Speter /* generate all label references to the corresponding jump insn */ 115518334Speter for (block = 0; block < blocks; block++) 115618334Speter { 115718334Speter insn = block_end[block]; 115818334Speter 115918334Speter if (GET_CODE (insn) == JUMP_INSN) 116018334Speter { 116118334Speter rtx pat = PATTERN (insn); 116218334Speter rtx x; 116318334Speter 116450397Sobrien if (computed_jump_p (insn)) 116518334Speter { 116618334Speter for (x = label_value_list; x; x = XEXP (x, 1)) 116718334Speter record_label_references (insn, 116850397Sobrien gen_rtx_LABEL_REF (VOIDmode, 116950397Sobrien XEXP (x, 0))); 117018334Speter 117118334Speter for (x = forced_labels; x; x = XEXP (x, 1)) 117218334Speter record_label_references (insn, 117350397Sobrien gen_rtx_LABEL_REF (VOIDmode, 117450397Sobrien XEXP (x, 0))); 117518334Speter } 117618334Speter 117718334Speter record_label_references (insn, pat); 117818334Speter } 117918334Speter } 118018334Speter} 118118334Speter 118218334Speter/* If current function returns its result in an fp stack register, 118318334Speter return the REG. Otherwise, return 0. */ 118418334Speter 118518334Speterstatic rtx 118618334Speterstack_result (decl) 118718334Speter tree decl; 118818334Speter{ 118918334Speter rtx result = DECL_RTL (DECL_RESULT (decl)); 119018334Speter 119118334Speter if (result != 0 119218334Speter && ! (GET_CODE (result) == REG 119318334Speter && REGNO (result) < FIRST_PSEUDO_REGISTER)) 119418334Speter { 119518334Speter#ifdef FUNCTION_OUTGOING_VALUE 119618334Speter result 119718334Speter = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl); 119818334Speter#else 119918334Speter result = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl); 120018334Speter#endif 120118334Speter } 120218334Speter 120318334Speter return result != 0 && STACK_REG_P (result) ? result : 0; 120418334Speter} 120518334Speter 120618334Speter/* Determine the which registers are live at the start of each basic 120718334Speter block of the function whose first insn is FIRST. 120818334Speter 120918334Speter First, if the function returns a real_type, mark the function 121018334Speter return type as live at each return point, as the RTL may not give any 121118334Speter hint that the register is live. 121218334Speter 121318334Speter Then, start with the last block and work back to the first block. 121418334Speter Similarly, work backwards within each block, insn by insn, recording 121518334Speter which regs are dead and which are used (and therefore live) in the 121618334Speter hard reg set of block_stack_in[]. 121718334Speter 121818334Speter After processing each basic block, if there is a label at the start 121918334Speter of the block, propagate the live registers to all jumps to this block. 122018334Speter 122118334Speter As a special case, if there are regs live in this block, that are 122218334Speter not live in a block containing a jump to this label, and the block 122318334Speter containing the jump has already been processed, we must propagate this 122418334Speter block's entry register life back to the block containing the jump, and 122518334Speter restart life analysis from there. 122618334Speter 122718334Speter In the worst case, this function may traverse the insns 122818334Speter REG_STACK_SIZE times. This is necessary, since a jump towards the end 122918334Speter of the insns may not know that a reg is live at a target that is early 123018334Speter in the insns. So we back up and start over with the new reg live. 123118334Speter 123218334Speter If there are registers that are live at the start of the function, 123318334Speter insns are emitted to initialize these registers. Something similar is 123450397Sobrien done after CALL_INSNs in record_reg_life. */ 123518334Speter 123618334Speterstatic void 123718334Speterstack_reg_life_analysis (first, stackentry) 123818334Speter rtx first; 123918334Speter HARD_REG_SET *stackentry; 124018334Speter{ 124118334Speter int reg, block; 124218334Speter struct stack_def regstack; 124318334Speter 124418334Speter { 124518334Speter rtx retvalue; 124618334Speter 124750397Sobrien if ((retvalue = stack_result (current_function_decl))) 124818334Speter { 124950397Sobrien /* Find all RETURN insns and mark them. */ 125018334Speter 125118334Speter for (block = blocks - 1; --block >= 0;) 125218334Speter if (GET_CODE (block_end[block]) == JUMP_INSN 125352284Sobrien && returnjump_p (block_end[block])) 125418334Speter mark_regs_pat (retvalue, block_out_reg_set+block); 125518334Speter 125618334Speter /* Mark off the end of last block if we "fall off" the end of the 125750397Sobrien function into the epilogue. */ 125818334Speter 125918334Speter if (GET_CODE (block_end[blocks-1]) != JUMP_INSN 126052284Sobrien || returnjump_p (block_end[blocks-1])) 126118334Speter mark_regs_pat (retvalue, block_out_reg_set+blocks-1); 126218334Speter } 126318334Speter } 126418334Speter 126518334Speter /* now scan all blocks backward for stack register use */ 126618334Speter 126718334Speter block = blocks - 1; 126818334Speter while (block >= 0) 126918334Speter { 127018334Speter register rtx insn, prev; 127118334Speter 127218334Speter /* current register status at last instruction */ 127318334Speter 127418334Speter COPY_HARD_REG_SET (regstack.reg_set, block_out_reg_set[block]); 127518334Speter 127618334Speter prev = block_end[block]; 127718334Speter do 127818334Speter { 127918334Speter insn = prev; 128018334Speter prev = PREV_INSN (insn); 128118334Speter 128218334Speter /* If the insn is a CALL_INSN, we need to ensure that 128318334Speter everything dies. But otherwise don't process unless there 128450397Sobrien are some stack regs present. */ 128518334Speter 128652284Sobrien if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN) 128718334Speter record_reg_life (insn, block, ®stack); 128818334Speter 128918334Speter } while (insn != block_begin[block]); 129018334Speter 129118334Speter /* Set the state at the start of the block. Mark that no 129250397Sobrien register mapping information known yet. */ 129318334Speter 129418334Speter COPY_HARD_REG_SET (block_stack_in[block].reg_set, regstack.reg_set); 129518334Speter block_stack_in[block].top = -2; 129618334Speter 129718334Speter /* If there is a label, propagate our register life to all jumps 129850397Sobrien to this label. */ 129918334Speter 130018334Speter if (GET_CODE (insn) == CODE_LABEL) 130118334Speter { 130218334Speter register rtx label; 130318334Speter int must_restart = 0; 130418334Speter 130518334Speter for (label = LABEL_REFS (insn); label != insn; 130618334Speter label = LABEL_NEXTREF (label)) 130718334Speter { 130818334Speter int jump_block = BLOCK_NUM (CONTAINING_INSN (label)); 130918334Speter 131018334Speter if (jump_block < block) 131118334Speter IOR_HARD_REG_SET (block_out_reg_set[jump_block], 131218334Speter block_stack_in[block].reg_set); 131318334Speter else 131418334Speter { 131518334Speter /* The block containing the jump has already been 131618334Speter processed. If there are registers that were not known 131718334Speter to be live then, but are live now, we must back up 131818334Speter and restart life analysis from that point with the new 131950397Sobrien life information. */ 132018334Speter 132118334Speter GO_IF_HARD_REG_SUBSET (block_stack_in[block].reg_set, 132218334Speter block_out_reg_set[jump_block], 132318334Speter win); 132418334Speter 132518334Speter IOR_HARD_REG_SET (block_out_reg_set[jump_block], 132618334Speter block_stack_in[block].reg_set); 132718334Speter 132818334Speter block = jump_block; 132918334Speter must_restart = 1; 133050397Sobrien break; 133118334Speter 133218334Speter win: 133318334Speter ; 133418334Speter } 133518334Speter } 133618334Speter if (must_restart) 133718334Speter continue; 133818334Speter } 133918334Speter 134018334Speter if (block_drops_in[block]) 134118334Speter IOR_HARD_REG_SET (block_out_reg_set[block-1], 134218334Speter block_stack_in[block].reg_set); 134318334Speter 134418334Speter block -= 1; 134518334Speter } 134618334Speter 134718334Speter /* If any reg is live at the start of the first block of a 134818334Speter function, then we must guarantee that the reg holds some value by 134918334Speter generating our own "load" of that register. Otherwise a 387 would 135050397Sobrien fault trying to access an empty register. */ 135118334Speter 135218334Speter /* Load zero into each live register. The fact that a register 135318334Speter appears live at the function start necessarily implies an error 135418334Speter in the user program: it means that (unless the offending code is *never* 135518334Speter executed) this program is using uninitialised floating point 135618334Speter variables. In order to keep broken code like this happy, we initialise 135718334Speter those variables with zero. 135818334Speter 135918334Speter Note that we are inserting virtual register references here: 136018334Speter these insns must be processed by convert_regs later. Also, these 136150397Sobrien insns will not be in block_number, so BLOCK_NUM() will fail for them. */ 136218334Speter 136318334Speter for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; reg--) 136418334Speter if (TEST_HARD_REG_BIT (block_stack_in[0].reg_set, reg) 136518334Speter && ! TEST_HARD_REG_BIT (*stackentry, reg)) 136618334Speter { 136718334Speter rtx init_rtx; 136818334Speter 136950397Sobrien init_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG(reg, DFmode), 137050397Sobrien CONST0_RTX (DFmode)); 137118334Speter block_begin[0] = emit_insn_after (init_rtx, first); 137218334Speter 137318334Speter CLEAR_HARD_REG_BIT (block_stack_in[0].reg_set, reg); 137418334Speter } 137518334Speter} 137618334Speter 137718334Speter/***************************************************************************** 137818334Speter This section deals with stack register substitution, and forms the second 137918334Speter pass over the RTL. 138018334Speter *****************************************************************************/ 138118334Speter 138218334Speter/* Replace REG, which is a pointer to a stack reg RTX, with an RTX for 138350397Sobrien the desired hard REGNO. */ 138418334Speter 138518334Speterstatic void 138618334Speterreplace_reg (reg, regno) 138718334Speter rtx *reg; 138818334Speter int regno; 138918334Speter{ 139018334Speter if (regno < FIRST_STACK_REG || regno > LAST_STACK_REG 139118334Speter || ! STACK_REG_P (*reg)) 139218334Speter abort (); 139318334Speter 139418334Speter switch (GET_MODE_CLASS (GET_MODE (*reg))) 139518334Speter { 139618334Speter default: abort (); 139718334Speter case MODE_FLOAT: 139818334Speter case MODE_COMPLEX_FLOAT:; 139918334Speter } 140018334Speter 140118334Speter *reg = FP_MODE_REG (regno, GET_MODE (*reg)); 140218334Speter} 140318334Speter 140418334Speter/* Remove a note of type NOTE, which must be found, for register 140550397Sobrien number REGNO from INSN. Remove only one such note. */ 140618334Speter 140718334Speterstatic void 140818334Speterremove_regno_note (insn, note, regno) 140918334Speter rtx insn; 141018334Speter enum reg_note note; 141118334Speter int regno; 141218334Speter{ 141318334Speter register rtx *note_link, this; 141418334Speter 141518334Speter note_link = ®_NOTES(insn); 141618334Speter for (this = *note_link; this; this = XEXP (this, 1)) 141718334Speter if (REG_NOTE_KIND (this) == note 141818334Speter && REG_P (XEXP (this, 0)) && REGNO (XEXP (this, 0)) == regno) 141918334Speter { 142018334Speter *note_link = XEXP (this, 1); 142118334Speter return; 142218334Speter } 142318334Speter else 142418334Speter note_link = &XEXP (this, 1); 142518334Speter 142618334Speter abort (); 142718334Speter} 142818334Speter 142918334Speter/* Find the hard register number of virtual register REG in REGSTACK. 143018334Speter The hard register number is relative to the top of the stack. -1 is 143150397Sobrien returned if the register is not found. */ 143218334Speter 143318334Speterstatic int 143418334Speterget_hard_regnum (regstack, reg) 143518334Speter stack regstack; 143618334Speter rtx reg; 143718334Speter{ 143818334Speter int i; 143918334Speter 144018334Speter if (! STACK_REG_P (reg)) 144118334Speter abort (); 144218334Speter 144318334Speter for (i = regstack->top; i >= 0; i--) 144418334Speter if (regstack->reg[i] == REGNO (reg)) 144518334Speter break; 144618334Speter 144718334Speter return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1; 144818334Speter} 144918334Speter 145018334Speter/* Delete INSN from the RTL. Mark the insn, but don't remove it from 145118334Speter the chain of insns. Doing so could confuse block_begin and block_end 145250397Sobrien if this were the only insn in the block. */ 145318334Speter 145418334Speterstatic void 145518334Speterdelete_insn_for_stacker (insn) 145618334Speter rtx insn; 145718334Speter{ 145852284Sobrien int i; 145952284Sobrien 146052284Sobrien /* Ensure that the side effects were clobbers when deleting a PARALLEL. */ 146152284Sobrien if (GET_CODE (PATTERN (insn)) == PARALLEL) 146252284Sobrien for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++) 146352284Sobrien if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) != CLOBBER) 146452284Sobrien abort (); 146552284Sobrien 146618334Speter PUT_CODE (insn, NOTE); 146718334Speter NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; 146818334Speter NOTE_SOURCE_FILE (insn) = 0; 146918334Speter} 147018334Speter 147118334Speter/* Emit an insn to pop virtual register REG before or after INSN. 147218334Speter REGSTACK is the stack state after INSN and is updated to reflect this 147352284Sobrien pop. WHEN is either emit_insn_before, emit_insn_after or NULL. 147452284Sobrien in case WHEN is NULL we don't really emit the insn, just modify stack 147552284Sobrien information. Caller is expected to emit insn himself. 147652284Sobrien 147752284Sobrien A pop insn is represented as a SET whose destination is the register to 147852284Sobrien be popped and source is the top of stack. A death note for the top of stack 147950397Sobrien cases the movdf pattern to pop. */ 148018334Speter 148118334Speterstatic rtx 148218334Speteremit_pop_insn (insn, regstack, reg, when) 148318334Speter rtx insn; 148418334Speter stack regstack; 148518334Speter rtx reg; 148618334Speter rtx (*when)(); 148718334Speter{ 148818334Speter rtx pop_insn, pop_rtx; 148918334Speter int hard_regno; 149018334Speter 149118334Speter hard_regno = get_hard_regnum (regstack, reg); 149218334Speter 149318334Speter if (hard_regno < FIRST_STACK_REG) 149418334Speter abort (); 149518334Speter 149652284Sobrien if (when) 149752284Sobrien { 149852284Sobrien pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode), 149952284Sobrien FP_MODE_REG (FIRST_STACK_REG, DFmode)); 150018334Speter 150152284Sobrien pop_insn = (*when) (pop_rtx, insn); 150218334Speter 150352284Sobrien REG_NOTES (pop_insn) = gen_rtx_EXPR_LIST (REG_DEAD, 150452284Sobrien FP_MODE_REG (FIRST_STACK_REG, 150552284Sobrien DFmode), 150652284Sobrien REG_NOTES (pop_insn)); 150752284Sobrien } 150818334Speter 150918334Speter regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)] 151018334Speter = regstack->reg[regstack->top]; 151118334Speter regstack->top -= 1; 151218334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (reg)); 151318334Speter 151418334Speter return pop_insn; 151518334Speter} 151618334Speter 151718334Speter/* Emit an insn before or after INSN to swap virtual register REG with the 151818334Speter top of stack. WHEN should be `emit_insn_before' or `emit_insn_before' 151918334Speter REGSTACK is the stack state before the swap, and is updated to reflect 152018334Speter the swap. A swap insn is represented as a PARALLEL of two patterns: 152118334Speter each pattern moves one reg to the other. 152218334Speter 152350397Sobrien If REG is already at the top of the stack, no insn is emitted. */ 152418334Speter 152518334Speterstatic void 152618334Speteremit_swap_insn (insn, regstack, reg) 152718334Speter rtx insn; 152818334Speter stack regstack; 152918334Speter rtx reg; 153018334Speter{ 153118334Speter int hard_regno; 153218334Speter rtx gen_swapdf(); 153318334Speter rtx swap_rtx, swap_insn; 153418334Speter int tmp, other_reg; /* swap regno temps */ 153518334Speter rtx i1; /* the stack-reg insn prior to INSN */ 153618334Speter rtx i1set = NULL_RTX; /* the SET rtx within I1 */ 153718334Speter 153818334Speter hard_regno = get_hard_regnum (regstack, reg); 153918334Speter 154018334Speter if (hard_regno < FIRST_STACK_REG) 154118334Speter abort (); 154218334Speter if (hard_regno == FIRST_STACK_REG) 154318334Speter return; 154418334Speter 154518334Speter other_reg = regstack->top - (hard_regno - FIRST_STACK_REG); 154618334Speter 154718334Speter tmp = regstack->reg[other_reg]; 154818334Speter regstack->reg[other_reg] = regstack->reg[regstack->top]; 154918334Speter regstack->reg[regstack->top] = tmp; 155018334Speter 155118334Speter /* Find the previous insn involving stack regs, but don't go past 155218334Speter any labels, calls or jumps. */ 155318334Speter i1 = prev_nonnote_insn (insn); 155452284Sobrien while (i1 && GET_CODE (i1) == INSN && !stack_regs_mentioned (i1)) 155518334Speter i1 = prev_nonnote_insn (i1); 155618334Speter 155718334Speter if (i1) 155818334Speter i1set = single_set (i1); 155918334Speter 156018334Speter if (i1set) 156118334Speter { 156218334Speter rtx i1src = *get_true_reg (&SET_SRC (i1set)); 156318334Speter rtx i1dest = *get_true_reg (&SET_DEST (i1set)); 156418334Speter 156518334Speter /* If the previous register stack push was from the reg we are to 156650397Sobrien swap with, omit the swap. */ 156718334Speter 156818334Speter if (GET_CODE (i1dest) == REG && REGNO (i1dest) == FIRST_STACK_REG 156918334Speter && GET_CODE (i1src) == REG && REGNO (i1src) == hard_regno - 1 157018334Speter && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX) 157118334Speter return; 157218334Speter 157318334Speter /* If the previous insn wrote to the reg we are to swap with, 157418334Speter omit the swap. */ 157518334Speter 157618334Speter if (GET_CODE (i1dest) == REG && REGNO (i1dest) == hard_regno 157718334Speter && GET_CODE (i1src) == REG && REGNO (i1src) == FIRST_STACK_REG 157818334Speter && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX) 157918334Speter return; 158018334Speter } 158118334Speter 158218334Speter if (GET_RTX_CLASS (GET_CODE (i1)) == 'i' && sets_cc0_p (PATTERN (i1))) 158318334Speter { 158418334Speter i1 = next_nonnote_insn (i1); 158518334Speter if (i1 == insn) 158618334Speter abort (); 158718334Speter } 158818334Speter 158918334Speter swap_rtx = gen_swapdf (FP_MODE_REG (hard_regno, DFmode), 159018334Speter FP_MODE_REG (FIRST_STACK_REG, DFmode)); 159118334Speter swap_insn = emit_insn_after (swap_rtx, i1); 159218334Speter} 159318334Speter 159418334Speter/* Handle a move to or from a stack register in PAT, which is in INSN. 159550397Sobrien REGSTACK is the current stack. */ 159618334Speter 159718334Speterstatic void 159818334Spetermove_for_stack_reg (insn, regstack, pat) 159918334Speter rtx insn; 160018334Speter stack regstack; 160118334Speter rtx pat; 160218334Speter{ 160318334Speter rtx *psrc = get_true_reg (&SET_SRC (pat)); 160418334Speter rtx *pdest = get_true_reg (&SET_DEST (pat)); 160518334Speter rtx src, dest; 160618334Speter rtx note; 160718334Speter 160818334Speter src = *psrc; dest = *pdest; 160918334Speter 161018334Speter if (STACK_REG_P (src) && STACK_REG_P (dest)) 161118334Speter { 161218334Speter /* Write from one stack reg to another. If SRC dies here, then 161350397Sobrien just change the register mapping and delete the insn. */ 161418334Speter 161518334Speter note = find_regno_note (insn, REG_DEAD, REGNO (src)); 161618334Speter if (note) 161718334Speter { 161818334Speter int i; 161918334Speter 162050397Sobrien /* If this is a no-op move, there must not be a REG_DEAD note. */ 162118334Speter if (REGNO (src) == REGNO (dest)) 162218334Speter abort (); 162318334Speter 162418334Speter for (i = regstack->top; i >= 0; i--) 162518334Speter if (regstack->reg[i] == REGNO (src)) 162618334Speter break; 162718334Speter 162850397Sobrien /* The source must be live, and the dest must be dead. */ 162918334Speter if (i < 0 || get_hard_regnum (regstack, dest) >= FIRST_STACK_REG) 163018334Speter abort (); 163118334Speter 163218334Speter /* It is possible that the dest is unused after this insn. 163350397Sobrien If so, just pop the src. */ 163418334Speter 163518334Speter if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) 163618334Speter { 163718334Speter emit_pop_insn (insn, regstack, src, emit_insn_after); 163818334Speter 163918334Speter delete_insn_for_stacker (insn); 164018334Speter return; 164118334Speter } 164218334Speter 164318334Speter regstack->reg[i] = REGNO (dest); 164418334Speter 164518334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); 164618334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); 164718334Speter 164818334Speter delete_insn_for_stacker (insn); 164918334Speter 165018334Speter return; 165118334Speter } 165218334Speter 165350397Sobrien /* The source reg does not die. */ 165418334Speter 165518334Speter /* If this appears to be a no-op move, delete it, or else it 165618334Speter will confuse the machine description output patterns. But if 165718334Speter it is REG_UNUSED, we must pop the reg now, as per-insn processing 165850397Sobrien for REG_UNUSED will not work for deleted insns. */ 165918334Speter 166018334Speter if (REGNO (src) == REGNO (dest)) 166118334Speter { 166218334Speter if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) 166318334Speter emit_pop_insn (insn, regstack, dest, emit_insn_after); 166418334Speter 166518334Speter delete_insn_for_stacker (insn); 166618334Speter return; 166718334Speter } 166818334Speter 166918334Speter /* The destination ought to be dead */ 167018334Speter if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG) 167118334Speter abort (); 167218334Speter 167318334Speter replace_reg (psrc, get_hard_regnum (regstack, src)); 167418334Speter 167518334Speter regstack->reg[++regstack->top] = REGNO (dest); 167618334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); 167718334Speter replace_reg (pdest, FIRST_STACK_REG); 167818334Speter } 167918334Speter else if (STACK_REG_P (src)) 168018334Speter { 168118334Speter /* Save from a stack reg to MEM, or possibly integer reg. Since 168218334Speter only top of stack may be saved, emit an exchange first if 168350397Sobrien needs be. */ 168418334Speter 168518334Speter emit_swap_insn (insn, regstack, src); 168618334Speter 168718334Speter note = find_regno_note (insn, REG_DEAD, REGNO (src)); 168818334Speter if (note) 168918334Speter { 169018334Speter replace_reg (&XEXP (note, 0), FIRST_STACK_REG); 169118334Speter regstack->top--; 169218334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); 169318334Speter } 169450397Sobrien else if (GET_MODE (src) == XFmode && regstack->top < REG_STACK_SIZE - 1) 169518334Speter { 169618334Speter /* A 387 cannot write an XFmode value to a MEM without 169718334Speter clobbering the source reg. The output code can handle 169818334Speter this by reading back the value from the MEM. 169918334Speter But it is more efficient to use a temp register if one is 170018334Speter available. Push the source value here if the register 170118334Speter stack is not full, and then write the value to memory via 170218334Speter a pop. */ 170318334Speter rtx push_rtx, push_insn; 170418334Speter rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, XFmode); 170518334Speter 170618334Speter push_rtx = gen_movxf (top_stack_reg, top_stack_reg); 170718334Speter push_insn = emit_insn_before (push_rtx, insn); 170850397Sobrien REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg, 170950397Sobrien REG_NOTES (insn)); 171018334Speter } 171118334Speter 171218334Speter replace_reg (psrc, FIRST_STACK_REG); 171318334Speter } 171418334Speter else if (STACK_REG_P (dest)) 171518334Speter { 171618334Speter /* Load from MEM, or possibly integer REG or constant, into the 171718334Speter stack regs. The actual target is always the top of the 171818334Speter stack. The stack mapping is changed to reflect that DEST is 171918334Speter now at top of stack. */ 172018334Speter 172118334Speter /* The destination ought to be dead */ 172218334Speter if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG) 172318334Speter abort (); 172418334Speter 172518334Speter if (regstack->top >= REG_STACK_SIZE) 172618334Speter abort (); 172718334Speter 172818334Speter regstack->reg[++regstack->top] = REGNO (dest); 172918334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); 173018334Speter replace_reg (pdest, FIRST_STACK_REG); 173118334Speter } 173218334Speter else 173318334Speter abort (); 173418334Speter} 173518334Speter 173650397Sobrienstatic void 173718334Speterswap_rtx_condition (pat) 173818334Speter rtx pat; 173918334Speter{ 174018334Speter register char *fmt; 174118334Speter register int i; 174218334Speter 174318334Speter if (GET_RTX_CLASS (GET_CODE (pat)) == '<') 174418334Speter { 174518334Speter PUT_CODE (pat, swap_condition (GET_CODE (pat))); 174618334Speter return; 174718334Speter } 174818334Speter 174918334Speter fmt = GET_RTX_FORMAT (GET_CODE (pat)); 175018334Speter for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) 175118334Speter { 175218334Speter if (fmt[i] == 'E') 175318334Speter { 175418334Speter register int j; 175518334Speter 175618334Speter for (j = XVECLEN (pat, i) - 1; j >= 0; j--) 175718334Speter swap_rtx_condition (XVECEXP (pat, i, j)); 175818334Speter } 175918334Speter else if (fmt[i] == 'e') 176018334Speter swap_rtx_condition (XEXP (pat, i)); 176118334Speter } 176218334Speter} 176318334Speter 176418334Speter/* Handle a comparison. Special care needs to be taken to avoid 176518334Speter causing comparisons that a 387 cannot do correctly, such as EQ. 176618334Speter 176752284Sobrien Also, a fstp instruction may need to be emitted. The 387 does have an 176818334Speter `fcompp' insn that can pop two regs, but it is sometimes too expensive 176918334Speter to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to 177052284Sobrien set up. 177152284Sobrien 177252284Sobrien We can not handle this by emiting fpop instruction after compare, because 177352284Sobrien it appears between cc0 setter and user. So we emit only 177452284Sobrien REG_DEAD note and handle it as a special case in machine description. 177552284Sobrien 177652284Sobrien This code used trick with delay_slot filling to emit pop insn after 177752284Sobrien comparsion but it didn't worked because it caused confusion with cc_status 177852284Sobrien in final pass. */ 177918334Speter 178018334Speterstatic void 178118334Spetercompare_for_stack_reg (insn, regstack, pat) 178218334Speter rtx insn; 178318334Speter stack regstack; 178418334Speter rtx pat; 178518334Speter{ 178618334Speter rtx *src1, *src2; 178718334Speter rtx src1_note, src2_note; 178850397Sobrien rtx cc0_user; 178950397Sobrien int have_cmove; 179052284Sobrien int hard_regno; 179118334Speter 179218334Speter src1 = get_true_reg (&XEXP (SET_SRC (pat), 0)); 179318334Speter src2 = get_true_reg (&XEXP (SET_SRC (pat), 1)); 179450397Sobrien cc0_user = next_cc0_user (insn); 179518334Speter 179650397Sobrien /* If the insn that uses cc0 is an FP-conditional move, then the destination 179750397Sobrien must be the top of stack */ 179850397Sobrien if (GET_CODE (PATTERN (cc0_user)) == SET 179950397Sobrien && SET_DEST (PATTERN (cc0_user)) != pc_rtx 180050397Sobrien && GET_CODE (SET_SRC (PATTERN (cc0_user))) == IF_THEN_ELSE 180150397Sobrien && (GET_MODE_CLASS (GET_MODE (SET_DEST (PATTERN (cc0_user)))) 180250397Sobrien == MODE_FLOAT)) 180350397Sobrien { 180450397Sobrien rtx *dest; 180550397Sobrien 180650397Sobrien dest = get_true_reg (&SET_DEST (PATTERN (cc0_user))); 180750397Sobrien 180850397Sobrien have_cmove = 1; 180950397Sobrien if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG 181050397Sobrien && REGNO (*dest) != regstack->reg[regstack->top]) 181150397Sobrien { 181250397Sobrien emit_swap_insn (insn, regstack, *dest); 181350397Sobrien } 181450397Sobrien } 181550397Sobrien else 181650397Sobrien have_cmove = 0; 181750397Sobrien 181818334Speter /* ??? If fxch turns out to be cheaper than fstp, give priority to 181950397Sobrien registers that die in this insn - move those to stack top first. */ 182018334Speter if (! STACK_REG_P (*src1) 182118334Speter || (STACK_REG_P (*src2) 182218334Speter && get_hard_regnum (regstack, *src2) == FIRST_STACK_REG)) 182318334Speter { 182418334Speter rtx temp, next; 182518334Speter 182618334Speter temp = XEXP (SET_SRC (pat), 0); 182718334Speter XEXP (SET_SRC (pat), 0) = XEXP (SET_SRC (pat), 1); 182818334Speter XEXP (SET_SRC (pat), 1) = temp; 182918334Speter 183018334Speter src1 = get_true_reg (&XEXP (SET_SRC (pat), 0)); 183118334Speter src2 = get_true_reg (&XEXP (SET_SRC (pat), 1)); 183218334Speter 183318334Speter next = next_cc0_user (insn); 183418334Speter if (next == NULL_RTX) 183518334Speter abort (); 183618334Speter 183718334Speter swap_rtx_condition (PATTERN (next)); 183818334Speter INSN_CODE (next) = -1; 183918334Speter INSN_CODE (insn) = -1; 184018334Speter } 184118334Speter 184250397Sobrien /* We will fix any death note later. */ 184318334Speter 184418334Speter src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 184518334Speter 184618334Speter if (STACK_REG_P (*src2)) 184718334Speter src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); 184818334Speter else 184918334Speter src2_note = NULL_RTX; 185018334Speter 185150397Sobrien if (! have_cmove) 185250397Sobrien emit_swap_insn (insn, regstack, *src1); 185318334Speter 185418334Speter replace_reg (src1, FIRST_STACK_REG); 185518334Speter 185618334Speter if (STACK_REG_P (*src2)) 185752284Sobrien { 185852284Sobrien hard_regno = get_hard_regnum (regstack, *src2); 185952284Sobrien replace_reg (src2, hard_regno); 186052284Sobrien } 186118334Speter 186218334Speter if (src1_note) 186318334Speter { 186450397Sobrien pop_stack (regstack, REGNO (XEXP (src1_note, 0))); 186518334Speter replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 186618334Speter } 186718334Speter 186818334Speter /* If the second operand dies, handle that. But if the operands are 186918334Speter the same stack register, don't bother, because only one death is 187050397Sobrien needed, and it was just handled. */ 187118334Speter 187218334Speter if (src2_note 187318334Speter && ! (STACK_REG_P (*src1) && STACK_REG_P (*src2) 187418334Speter && REGNO (*src1) == REGNO (*src2))) 187518334Speter { 187618334Speter /* As a special case, two regs may die in this insn if src2 is 187718334Speter next to top of stack and the top of stack also dies. Since 187818334Speter we have already popped src1, "next to top of stack" is really 187950397Sobrien at top (FIRST_STACK_REG) now. */ 188018334Speter 188118334Speter if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG 188218334Speter && src1_note) 188318334Speter { 188450397Sobrien pop_stack (regstack, REGNO (XEXP (src2_note, 0))); 188518334Speter replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1); 188618334Speter } 188718334Speter else 188818334Speter { 188952284Sobrien /* Pop of second operand is handled using special REG_DEAD note 189052284Sobrien because we can't emit pop insn after cc0 setter. */ 189118334Speter 189252284Sobrien emit_pop_insn (insn, regstack, XEXP (src2_note, 0), NULL); 189352284Sobrien replace_reg (&XEXP (src2_note, 0), hard_regno); 189418334Speter } 189518334Speter } 189618334Speter} 189718334Speter 189818334Speter/* Substitute new registers in PAT, which is part of INSN. REGSTACK 189950397Sobrien is the current register layout. */ 190018334Speter 190118334Speterstatic void 190218334Spetersubst_stack_regs_pat (insn, regstack, pat) 190318334Speter rtx insn; 190418334Speter stack regstack; 190518334Speter rtx pat; 190618334Speter{ 190718334Speter rtx *dest, *src; 190818334Speter rtx *src1 = (rtx *) NULL_PTR, *src2; 190918334Speter rtx src1_note, src2_note; 191018334Speter 191118334Speter if (GET_CODE (pat) != SET) 191218334Speter return; 191318334Speter 191418334Speter dest = get_true_reg (&SET_DEST (pat)); 191518334Speter src = get_true_reg (&SET_SRC (pat)); 191618334Speter 191750397Sobrien /* See if this is a `movM' pattern, and handle elsewhere if so. */ 191818334Speter 191918334Speter if (*dest != cc0_rtx 192018334Speter && (STACK_REG_P (*src) 192118334Speter || (STACK_REG_P (*dest) 192218334Speter && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM 192318334Speter || GET_CODE (*src) == CONST_DOUBLE)))) 192418334Speter move_for_stack_reg (insn, regstack, pat); 192518334Speter else 192618334Speter switch (GET_CODE (SET_SRC (pat))) 192718334Speter { 192818334Speter case COMPARE: 192918334Speter compare_for_stack_reg (insn, regstack, pat); 193018334Speter break; 193118334Speter 193218334Speter case CALL: 193318334Speter { 193418334Speter int count; 193518334Speter for (count = HARD_REGNO_NREGS (REGNO (*dest), GET_MODE (*dest)); 193618334Speter --count >= 0;) 193718334Speter { 193818334Speter regstack->reg[++regstack->top] = REGNO (*dest) + count; 193918334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count); 194018334Speter } 194118334Speter } 194218334Speter replace_reg (dest, FIRST_STACK_REG); 194318334Speter break; 194418334Speter 194518334Speter case REG: 194650397Sobrien /* This is a `tstM2' case. */ 194718334Speter if (*dest != cc0_rtx) 194818334Speter abort (); 194918334Speter 195018334Speter src1 = src; 195118334Speter 195250397Sobrien /* Fall through. */ 195318334Speter 195418334Speter case FLOAT_TRUNCATE: 195518334Speter case SQRT: 195618334Speter case ABS: 195718334Speter case NEG: 195818334Speter /* These insns only operate on the top of the stack. DEST might 195918334Speter be cc0_rtx if we're processing a tstM pattern. Also, it's 196018334Speter possible that the tstM case results in a REG_DEAD note on the 196118334Speter source. */ 196218334Speter 196318334Speter if (src1 == 0) 196418334Speter src1 = get_true_reg (&XEXP (SET_SRC (pat), 0)); 196518334Speter 196618334Speter emit_swap_insn (insn, regstack, *src1); 196718334Speter 196818334Speter src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 196918334Speter 197018334Speter if (STACK_REG_P (*dest)) 197118334Speter replace_reg (dest, FIRST_STACK_REG); 197218334Speter 197318334Speter if (src1_note) 197418334Speter { 197518334Speter replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 197618334Speter regstack->top--; 197718334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1)); 197818334Speter } 197918334Speter 198018334Speter replace_reg (src1, FIRST_STACK_REG); 198118334Speter 198218334Speter break; 198318334Speter 198418334Speter case MINUS: 198518334Speter case DIV: 198618334Speter /* On i386, reversed forms of subM3 and divM3 exist for 198718334Speter MODE_FLOAT, so the same code that works for addM3 and mulM3 198850397Sobrien can be used. */ 198918334Speter case MULT: 199018334Speter case PLUS: 199118334Speter /* These insns can accept the top of stack as a destination 199218334Speter from a stack reg or mem, or can use the top of stack as a 199318334Speter source and some other stack register (possibly top of stack) 199450397Sobrien as a destination. */ 199518334Speter 199618334Speter src1 = get_true_reg (&XEXP (SET_SRC (pat), 0)); 199718334Speter src2 = get_true_reg (&XEXP (SET_SRC (pat), 1)); 199818334Speter 199950397Sobrien /* We will fix any death note later. */ 200018334Speter 200118334Speter if (STACK_REG_P (*src1)) 200218334Speter src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 200318334Speter else 200418334Speter src1_note = NULL_RTX; 200518334Speter if (STACK_REG_P (*src2)) 200618334Speter src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); 200718334Speter else 200818334Speter src2_note = NULL_RTX; 200918334Speter 201018334Speter /* If either operand is not a stack register, then the dest 201150397Sobrien must be top of stack. */ 201218334Speter 201318334Speter if (! STACK_REG_P (*src1) || ! STACK_REG_P (*src2)) 201418334Speter emit_swap_insn (insn, regstack, *dest); 201518334Speter else 201618334Speter { 201718334Speter /* Both operands are REG. If neither operand is already 201818334Speter at the top of stack, choose to make the one that is the dest 201918334Speter the new top of stack. */ 202018334Speter 202118334Speter int src1_hard_regnum, src2_hard_regnum; 202218334Speter 202318334Speter src1_hard_regnum = get_hard_regnum (regstack, *src1); 202418334Speter src2_hard_regnum = get_hard_regnum (regstack, *src2); 202518334Speter if (src1_hard_regnum == -1 || src2_hard_regnum == -1) 202618334Speter abort (); 202718334Speter 202818334Speter if (src1_hard_regnum != FIRST_STACK_REG 202918334Speter && src2_hard_regnum != FIRST_STACK_REG) 203018334Speter emit_swap_insn (insn, regstack, *dest); 203118334Speter } 203218334Speter 203318334Speter if (STACK_REG_P (*src1)) 203418334Speter replace_reg (src1, get_hard_regnum (regstack, *src1)); 203518334Speter if (STACK_REG_P (*src2)) 203618334Speter replace_reg (src2, get_hard_regnum (regstack, *src2)); 203718334Speter 203818334Speter if (src1_note) 203918334Speter { 204018334Speter /* If the register that dies is at the top of stack, then 204118334Speter the destination is somewhere else - merely substitute it. 204218334Speter But if the reg that dies is not at top of stack, then 204318334Speter move the top of stack to the dead reg, as though we had 204450397Sobrien done the insn and then a store-with-pop. */ 204518334Speter 204618334Speter if (REGNO (XEXP (src1_note, 0)) == regstack->reg[regstack->top]) 204718334Speter { 204818334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 204918334Speter replace_reg (dest, get_hard_regnum (regstack, *dest)); 205018334Speter } 205118334Speter else 205218334Speter { 205318334Speter int regno = get_hard_regnum (regstack, XEXP (src1_note, 0)); 205418334Speter 205518334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 205618334Speter replace_reg (dest, regno); 205718334Speter 205818334Speter regstack->reg[regstack->top - (regno - FIRST_STACK_REG)] 205918334Speter = regstack->reg[regstack->top]; 206018334Speter } 206118334Speter 206218334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, 206318334Speter REGNO (XEXP (src1_note, 0))); 206418334Speter replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 206518334Speter regstack->top--; 206618334Speter } 206718334Speter else if (src2_note) 206818334Speter { 206918334Speter if (REGNO (XEXP (src2_note, 0)) == regstack->reg[regstack->top]) 207018334Speter { 207118334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 207218334Speter replace_reg (dest, get_hard_regnum (regstack, *dest)); 207318334Speter } 207418334Speter else 207518334Speter { 207618334Speter int regno = get_hard_regnum (regstack, XEXP (src2_note, 0)); 207718334Speter 207818334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 207918334Speter replace_reg (dest, regno); 208018334Speter 208118334Speter regstack->reg[regstack->top - (regno - FIRST_STACK_REG)] 208218334Speter = regstack->reg[regstack->top]; 208318334Speter } 208418334Speter 208518334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, 208618334Speter REGNO (XEXP (src2_note, 0))); 208718334Speter replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG); 208818334Speter regstack->top--; 208918334Speter } 209018334Speter else 209118334Speter { 209218334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 209318334Speter replace_reg (dest, get_hard_regnum (regstack, *dest)); 209418334Speter } 209518334Speter 209618334Speter break; 209718334Speter 209818334Speter case UNSPEC: 209918334Speter switch (XINT (SET_SRC (pat), 1)) 210018334Speter { 210118334Speter case 1: /* sin */ 210218334Speter case 2: /* cos */ 210318334Speter /* These insns only operate on the top of the stack. */ 210418334Speter 210518334Speter src1 = get_true_reg (&XVECEXP (SET_SRC (pat), 0, 0)); 210618334Speter 210718334Speter emit_swap_insn (insn, regstack, *src1); 210818334Speter 210918334Speter src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 211018334Speter 211118334Speter if (STACK_REG_P (*dest)) 211218334Speter replace_reg (dest, FIRST_STACK_REG); 211318334Speter 211418334Speter if (src1_note) 211518334Speter { 211618334Speter replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 211718334Speter regstack->top--; 211818334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1)); 211918334Speter } 212018334Speter 212118334Speter replace_reg (src1, FIRST_STACK_REG); 212218334Speter 212318334Speter break; 212418334Speter 212518334Speter default: 212618334Speter abort (); 212718334Speter } 212818334Speter break; 212918334Speter 213050397Sobrien case IF_THEN_ELSE: 213150397Sobrien /* dest has to be on stack. */ 213250397Sobrien if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG) 213350397Sobrien abort (); 213450397Sobrien 213550397Sobrien /* This insn requires the top of stack to be the destination. */ 213650397Sobrien 213750397Sobrien /* If the comparison operator is an FP comparison operator, 213850397Sobrien it is handled correctly by compare_for_stack_reg () who 213950397Sobrien will move the destination to the top of stack. But if the 214050397Sobrien comparison operator is not an FP comparison operator, we 214150397Sobrien have to handle it here. */ 214250397Sobrien if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG 214350397Sobrien && REGNO (*dest) != regstack->reg[regstack->top]) 214450397Sobrien emit_swap_insn (insn, regstack, *dest); 214550397Sobrien 214650397Sobrien src1 = get_true_reg (&XEXP (SET_SRC (pat), 1)); 214750397Sobrien src2 = get_true_reg (&XEXP (SET_SRC (pat), 2)); 214850397Sobrien 214950397Sobrien src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 215050397Sobrien src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); 215150397Sobrien 215250397Sobrien { 215350397Sobrien rtx src_note [3]; 215450397Sobrien int i; 215550397Sobrien 215650397Sobrien src_note[0] = 0; 215750397Sobrien src_note[1] = src1_note; 215850397Sobrien src_note[2] = src2_note; 215950397Sobrien 216050397Sobrien if (STACK_REG_P (*src1)) 216150397Sobrien replace_reg (src1, get_hard_regnum (regstack, *src1)); 216250397Sobrien if (STACK_REG_P (*src2)) 216350397Sobrien replace_reg (src2, get_hard_regnum (regstack, *src2)); 216450397Sobrien 216550397Sobrien for (i = 1; i <= 2; i++) 216650397Sobrien if (src_note [i]) 216750397Sobrien { 216850397Sobrien /* If the register that dies is not at the top of stack, then 216950397Sobrien move the top of stack to the dead reg */ 217050397Sobrien if (REGNO (XEXP (src_note[i], 0)) 217150397Sobrien != regstack->reg[regstack->top]) 217250397Sobrien { 217350397Sobrien remove_regno_note (insn, REG_DEAD, 217450397Sobrien REGNO (XEXP (src_note [i], 0))); 217550397Sobrien emit_pop_insn (insn, regstack, XEXP (src_note[i], 0), 217650397Sobrien emit_insn_after); 217750397Sobrien } 217850397Sobrien else 217950397Sobrien { 218050397Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, 218150397Sobrien REGNO (XEXP (src_note[i], 0))); 218250397Sobrien replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG); 218350397Sobrien regstack->top--; 218450397Sobrien } 218550397Sobrien } 218650397Sobrien } 218750397Sobrien 218850397Sobrien /* Make dest the top of stack. */ 218950397Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 219050397Sobrien replace_reg (dest, FIRST_STACK_REG); 219150397Sobrien 219250397Sobrien break; 219350397Sobrien 219418334Speter default: 219518334Speter abort (); 219618334Speter } 219718334Speter} 219818334Speter 219918334Speter/* Substitute hard regnums for any stack regs in INSN, which has 220018334Speter N_INPUTS inputs and N_OUTPUTS outputs. REGSTACK is the stack info 220152284Sobrien before the insn, and is updated with changes made here. 220218334Speter 220318334Speter There are several requirements and assumptions about the use of 220418334Speter stack-like regs in asm statements. These rules are enforced by 220518334Speter record_asm_stack_regs; see comments there for details. Any 220618334Speter asm_operands left in the RTL at this point may be assume to meet the 220718334Speter requirements, since record_asm_stack_regs removes any problem asm. */ 220818334Speter 220918334Speterstatic void 221052284Sobriensubst_asm_stack_regs (insn, regstack) 221118334Speter rtx insn; 221218334Speter stack regstack; 221318334Speter{ 221418334Speter rtx body = PATTERN (insn); 221552284Sobrien int alt; 221618334Speter 221718334Speter rtx *note_reg; /* Array of note contents */ 221818334Speter rtx **note_loc; /* Address of REG field of each note */ 221918334Speter enum reg_note *note_kind; /* The type of each note */ 222018334Speter 222118334Speter rtx *clobber_reg; 222218334Speter rtx **clobber_loc; 222318334Speter 222418334Speter struct stack_def temp_stack; 222518334Speter int n_notes; 222618334Speter int n_clobbers; 222718334Speter rtx note; 222818334Speter int i; 222952284Sobrien int n_inputs, n_outputs; 223018334Speter 223118334Speter /* Find out what the constraints required. If no constraint 223218334Speter alternative matches, that is a compiler bug: we should have caught 223318334Speter such an insn during the life analysis pass (and reload should have 223450397Sobrien caught it regardless). */ 223552284Sobrien extract_insn (insn); 223652284Sobrien constrain_operands (1); 223752284Sobrien alt = which_alternative; 223818334Speter 223952284Sobrien preprocess_constraints (); 224052284Sobrien 224152284Sobrien n_inputs = get_asm_operand_n_inputs (body); 224252284Sobrien n_outputs = recog_n_operands - n_inputs; 224352284Sobrien 224452284Sobrien if (alt < 0) 224518334Speter abort (); 224618334Speter 224750397Sobrien /* Strip SUBREGs here to make the following code simpler. */ 224852284Sobrien for (i = 0; i < recog_n_operands; i++) 224952284Sobrien if (GET_CODE (recog_operand[i]) == SUBREG 225052284Sobrien && GET_CODE (SUBREG_REG (recog_operand[i])) == REG) 225118334Speter { 225252284Sobrien recog_operand_loc[i] = & SUBREG_REG (recog_operand[i]); 225352284Sobrien recog_operand[i] = SUBREG_REG (recog_operand[i]); 225418334Speter } 225518334Speter 225618334Speter /* Set up NOTE_REG, NOTE_LOC and NOTE_KIND. */ 225718334Speter 225818334Speter for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1)) 225918334Speter i++; 226018334Speter 226118334Speter note_reg = (rtx *) alloca (i * sizeof (rtx)); 226218334Speter note_loc = (rtx **) alloca (i * sizeof (rtx *)); 226318334Speter note_kind = (enum reg_note *) alloca (i * sizeof (enum reg_note)); 226418334Speter 226518334Speter n_notes = 0; 226618334Speter for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 226718334Speter { 226818334Speter rtx reg = XEXP (note, 0); 226918334Speter rtx *loc = & XEXP (note, 0); 227018334Speter 227118334Speter if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) 227218334Speter { 227318334Speter loc = & SUBREG_REG (reg); 227418334Speter reg = SUBREG_REG (reg); 227518334Speter } 227618334Speter 227718334Speter if (STACK_REG_P (reg) 227818334Speter && (REG_NOTE_KIND (note) == REG_DEAD 227918334Speter || REG_NOTE_KIND (note) == REG_UNUSED)) 228018334Speter { 228118334Speter note_reg[n_notes] = reg; 228218334Speter note_loc[n_notes] = loc; 228318334Speter note_kind[n_notes] = REG_NOTE_KIND (note); 228418334Speter n_notes++; 228518334Speter } 228618334Speter } 228718334Speter 228818334Speter /* Set up CLOBBER_REG and CLOBBER_LOC. */ 228918334Speter 229018334Speter n_clobbers = 0; 229118334Speter 229218334Speter if (GET_CODE (body) == PARALLEL) 229318334Speter { 229452284Sobrien clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx)); 229552284Sobrien clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx *)); 229618334Speter 229718334Speter for (i = 0; i < XVECLEN (body, 0); i++) 229818334Speter if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) 229918334Speter { 230018334Speter rtx clobber = XVECEXP (body, 0, i); 230118334Speter rtx reg = XEXP (clobber, 0); 230218334Speter rtx *loc = & XEXP (clobber, 0); 230318334Speter 230418334Speter if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) 230518334Speter { 230618334Speter loc = & SUBREG_REG (reg); 230718334Speter reg = SUBREG_REG (reg); 230818334Speter } 230918334Speter 231018334Speter if (STACK_REG_P (reg)) 231118334Speter { 231218334Speter clobber_reg[n_clobbers] = reg; 231318334Speter clobber_loc[n_clobbers] = loc; 231418334Speter n_clobbers++; 231518334Speter } 231618334Speter } 231718334Speter } 231818334Speter 231918334Speter bcopy ((char *) regstack, (char *) &temp_stack, sizeof (temp_stack)); 232018334Speter 232118334Speter /* Put the input regs into the desired place in TEMP_STACK. */ 232218334Speter 232352284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 232452284Sobrien if (STACK_REG_P (recog_operand[i]) 232552284Sobrien && reg_class_subset_p (recog_op_alt[i][alt].class, 232652284Sobrien FLOAT_REGS) 232752284Sobrien && recog_op_alt[i][alt].class != FLOAT_REGS) 232818334Speter { 232918334Speter /* If an operand needs to be in a particular reg in 233018334Speter FLOAT_REGS, the constraint was either 't' or 'u'. Since 233118334Speter these constraints are for single register classes, and reload 233218334Speter guaranteed that operand[i] is already in that class, we can 233352284Sobrien just use REGNO (recog_operand[i]) to know which actual reg this 233450397Sobrien operand needs to be in. */ 233518334Speter 233652284Sobrien int regno = get_hard_regnum (&temp_stack, recog_operand[i]); 233718334Speter 233818334Speter if (regno < 0) 233918334Speter abort (); 234018334Speter 234152284Sobrien if (regno != REGNO (recog_operand[i])) 234218334Speter { 234352284Sobrien /* recog_operand[i] is not in the right place. Find it 234418334Speter and swap it with whatever is already in I's place. 234552284Sobrien K is where recog_operand[i] is now. J is where it should 234650397Sobrien be. */ 234718334Speter int j, k, temp; 234818334Speter 234918334Speter k = temp_stack.top - (regno - FIRST_STACK_REG); 235018334Speter j = (temp_stack.top 235152284Sobrien - (REGNO (recog_operand[i]) - FIRST_STACK_REG)); 235218334Speter 235318334Speter temp = temp_stack.reg[k]; 235418334Speter temp_stack.reg[k] = temp_stack.reg[j]; 235518334Speter temp_stack.reg[j] = temp; 235618334Speter } 235718334Speter } 235818334Speter 235918334Speter /* emit insns before INSN to make sure the reg-stack is in the right 236018334Speter order. */ 236118334Speter 236218334Speter change_stack (insn, regstack, &temp_stack, emit_insn_before); 236318334Speter 236418334Speter /* Make the needed input register substitutions. Do death notes and 236550397Sobrien clobbers too, because these are for inputs, not outputs. */ 236618334Speter 236752284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 236852284Sobrien if (STACK_REG_P (recog_operand[i])) 236918334Speter { 237052284Sobrien int regnum = get_hard_regnum (regstack, recog_operand[i]); 237118334Speter 237218334Speter if (regnum < 0) 237318334Speter abort (); 237418334Speter 237552284Sobrien replace_reg (recog_operand_loc[i], regnum); 237618334Speter } 237718334Speter 237818334Speter for (i = 0; i < n_notes; i++) 237918334Speter if (note_kind[i] == REG_DEAD) 238018334Speter { 238118334Speter int regnum = get_hard_regnum (regstack, note_reg[i]); 238218334Speter 238318334Speter if (regnum < 0) 238418334Speter abort (); 238518334Speter 238618334Speter replace_reg (note_loc[i], regnum); 238718334Speter } 238818334Speter 238918334Speter for (i = 0; i < n_clobbers; i++) 239018334Speter { 239118334Speter /* It's OK for a CLOBBER to reference a reg that is not live. 239218334Speter Don't try to replace it in that case. */ 239318334Speter int regnum = get_hard_regnum (regstack, clobber_reg[i]); 239418334Speter 239518334Speter if (regnum >= 0) 239618334Speter { 239718334Speter /* Sigh - clobbers always have QImode. But replace_reg knows 239818334Speter that these regs can't be MODE_INT and will abort. Just put 239918334Speter the right reg there without calling replace_reg. */ 240018334Speter 240118334Speter *clobber_loc[i] = FP_MODE_REG (regnum, DFmode); 240218334Speter } 240318334Speter } 240418334Speter 240550397Sobrien /* Now remove from REGSTACK any inputs that the asm implicitly popped. */ 240618334Speter 240752284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 240852284Sobrien if (STACK_REG_P (recog_operand[i])) 240918334Speter { 241018334Speter /* An input reg is implicitly popped if it is tied to an 241150397Sobrien output, or if there is a CLOBBER for it. */ 241218334Speter int j; 241318334Speter 241418334Speter for (j = 0; j < n_clobbers; j++) 241552284Sobrien if (operands_match_p (clobber_reg[j], recog_operand[i])) 241618334Speter break; 241718334Speter 241852284Sobrien if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0) 241918334Speter { 242052284Sobrien /* recog_operand[i] might not be at the top of stack. But that's 242152284Sobrien OK, because all we need to do is pop the right number of regs 242218334Speter off of the top of the reg-stack. record_asm_stack_regs 242318334Speter guaranteed that all implicitly popped regs were grouped 242418334Speter at the top of the reg-stack. */ 242518334Speter 242618334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, 242718334Speter regstack->reg[regstack->top]); 242818334Speter regstack->top--; 242918334Speter } 243018334Speter } 243118334Speter 243218334Speter /* Now add to REGSTACK any outputs that the asm implicitly pushed. 243318334Speter Note that there isn't any need to substitute register numbers. 243450397Sobrien ??? Explain why this is true. */ 243518334Speter 243618334Speter for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--) 243718334Speter { 243818334Speter /* See if there is an output for this hard reg. */ 243918334Speter int j; 244018334Speter 244118334Speter for (j = 0; j < n_outputs; j++) 244252284Sobrien if (STACK_REG_P (recog_operand[j]) && REGNO (recog_operand[j]) == i) 244318334Speter { 244418334Speter regstack->reg[++regstack->top] = i; 244518334Speter SET_HARD_REG_BIT (regstack->reg_set, i); 244618334Speter break; 244718334Speter } 244818334Speter } 244918334Speter 245018334Speter /* Now emit a pop insn for any REG_UNUSED output, or any REG_DEAD 245118334Speter input that the asm didn't implicitly pop. If the asm didn't 245218334Speter implicitly pop an input reg, that reg will still be live. 245318334Speter 245418334Speter Note that we can't use find_regno_note here: the register numbers 245518334Speter in the death notes have already been substituted. */ 245618334Speter 245718334Speter for (i = 0; i < n_outputs; i++) 245852284Sobrien if (STACK_REG_P (recog_operand[i])) 245918334Speter { 246018334Speter int j; 246118334Speter 246218334Speter for (j = 0; j < n_notes; j++) 246352284Sobrien if (REGNO (recog_operand[i]) == REGNO (note_reg[j]) 246418334Speter && note_kind[j] == REG_UNUSED) 246518334Speter { 246652284Sobrien insn = emit_pop_insn (insn, regstack, recog_operand[i], 246718334Speter emit_insn_after); 246818334Speter break; 246918334Speter } 247018334Speter } 247118334Speter 247252284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 247352284Sobrien if (STACK_REG_P (recog_operand[i])) 247418334Speter { 247518334Speter int j; 247618334Speter 247718334Speter for (j = 0; j < n_notes; j++) 247852284Sobrien if (REGNO (recog_operand[i]) == REGNO (note_reg[j]) 247918334Speter && note_kind[j] == REG_DEAD 248052284Sobrien && TEST_HARD_REG_BIT (regstack->reg_set, 248152284Sobrien REGNO (recog_operand[i]))) 248218334Speter { 248352284Sobrien insn = emit_pop_insn (insn, regstack, recog_operand[i], 248418334Speter emit_insn_after); 248518334Speter break; 248618334Speter } 248718334Speter } 248818334Speter} 248918334Speter 249018334Speter/* Substitute stack hard reg numbers for stack virtual registers in 249118334Speter INSN. Non-stack register numbers are not changed. REGSTACK is the 249218334Speter current stack content. Insns may be emitted as needed to arrange the 249350397Sobrien stack for the 387 based on the contents of the insn. */ 249418334Speter 249518334Speterstatic void 249618334Spetersubst_stack_regs (insn, regstack) 249718334Speter rtx insn; 249818334Speter stack regstack; 249918334Speter{ 250018334Speter register rtx *note_link, note; 250118334Speter register int i; 250218334Speter 250318334Speter if (GET_CODE (insn) == CALL_INSN) 250418334Speter { 250518334Speter int top = regstack->top; 250618334Speter 250718334Speter /* If there are any floating point parameters to be passed in 250818334Speter registers for this call, make sure they are in the right 250918334Speter order. */ 251018334Speter 251118334Speter if (top >= 0) 251218334Speter { 251318334Speter straighten_stack (PREV_INSN (insn), regstack); 251418334Speter 251518334Speter /* Now mark the arguments as dead after the call. */ 251618334Speter 251718334Speter while (regstack->top >= 0) 251818334Speter { 251918334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, FIRST_STACK_REG + regstack->top); 252018334Speter regstack->top--; 252118334Speter } 252218334Speter } 252318334Speter } 252418334Speter 252518334Speter /* Do the actual substitution if any stack regs are mentioned. 252618334Speter Since we only record whether entire insn mentions stack regs, and 252718334Speter subst_stack_regs_pat only works for patterns that contain stack regs, 252818334Speter we must check each pattern in a parallel here. A call_value_pop could 252950397Sobrien fail otherwise. */ 253018334Speter 253152284Sobrien if (stack_regs_mentioned (insn)) 253218334Speter { 253352284Sobrien int n_operands = asm_noperands (PATTERN (insn)); 253418334Speter if (n_operands >= 0) 253518334Speter { 253618334Speter /* This insn is an `asm' with operands. Decode the operands, 253718334Speter decide how many are inputs, and do register substitution. 253850397Sobrien Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */ 253918334Speter 254052284Sobrien subst_asm_stack_regs (insn, regstack); 254118334Speter return; 254218334Speter } 254318334Speter 254418334Speter if (GET_CODE (PATTERN (insn)) == PARALLEL) 254518334Speter for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) 254618334Speter { 254718334Speter if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i))) 254852284Sobrien { 254952284Sobrien subst_stack_regs_pat (insn, regstack, 255052284Sobrien XVECEXP (PATTERN (insn), 0, i)); 255152284Sobrien 255252284Sobrien /* subst_stack_regs_pat may have deleted a no-op insn. */ 255352284Sobrien if (GET_CODE (insn) == NOTE) 255452284Sobrien break; 255552284Sobrien } 255618334Speter } 255718334Speter else 255818334Speter subst_stack_regs_pat (insn, regstack, PATTERN (insn)); 255918334Speter } 256018334Speter 256118334Speter /* subst_stack_regs_pat may have deleted a no-op insn. If so, any 256250397Sobrien REG_UNUSED will already have been dealt with, so just return. */ 256318334Speter 256418334Speter if (GET_CODE (insn) == NOTE) 256518334Speter return; 256618334Speter 256718334Speter /* If there is a REG_UNUSED note on a stack register on this insn, 256818334Speter the indicated reg must be popped. The REG_UNUSED note is removed, 256918334Speter since the form of the newly emitted pop insn references the reg, 257050397Sobrien making it no longer `unset'. */ 257118334Speter 257218334Speter note_link = ®_NOTES(insn); 257318334Speter for (note = *note_link; note; note = XEXP (note, 1)) 257418334Speter if (REG_NOTE_KIND (note) == REG_UNUSED && STACK_REG_P (XEXP (note, 0))) 257518334Speter { 257618334Speter *note_link = XEXP (note, 1); 257718334Speter insn = emit_pop_insn (insn, regstack, XEXP (note, 0), emit_insn_after); 257818334Speter } 257918334Speter else 258018334Speter note_link = &XEXP (note, 1); 258118334Speter} 258218334Speter 258318334Speter/* Change the organization of the stack so that it fits a new basic 258418334Speter block. Some registers might have to be popped, but there can never be 258518334Speter a register live in the new block that is not now live. 258618334Speter 258718334Speter Insert any needed insns before or after INSN. WHEN is emit_insn_before 258818334Speter or emit_insn_after. OLD is the original stack layout, and NEW is 258918334Speter the desired form. OLD is updated to reflect the code emitted, ie, it 259018334Speter will be the same as NEW upon return. 259118334Speter 259218334Speter This function will not preserve block_end[]. But that information 259350397Sobrien is no longer needed once this has executed. */ 259418334Speter 259518334Speterstatic void 259618334Speterchange_stack (insn, old, new, when) 259718334Speter rtx insn; 259818334Speter stack old; 259918334Speter stack new; 260018334Speter rtx (*when)(); 260118334Speter{ 260218334Speter int reg; 260318334Speter 260418334Speter /* We will be inserting new insns "backwards", by calling emit_insn_before. 260518334Speter If we are to insert after INSN, find the next insn, and insert before 260618334Speter it. */ 260718334Speter 260818334Speter if (when == emit_insn_after) 260918334Speter insn = NEXT_INSN (insn); 261018334Speter 261150397Sobrien /* Pop any registers that are not needed in the new block. */ 261218334Speter 261318334Speter for (reg = old->top; reg >= 0; reg--) 261418334Speter if (! TEST_HARD_REG_BIT (new->reg_set, old->reg[reg])) 261518334Speter emit_pop_insn (insn, old, FP_MODE_REG (old->reg[reg], DFmode), 261618334Speter emit_insn_before); 261718334Speter 261818334Speter if (new->top == -2) 261918334Speter { 262018334Speter /* If the new block has never been processed, then it can inherit 262150397Sobrien the old stack order. */ 262218334Speter 262318334Speter new->top = old->top; 262418334Speter bcopy (old->reg, new->reg, sizeof (new->reg)); 262518334Speter } 262618334Speter else 262718334Speter { 262818334Speter /* This block has been entered before, and we must match the 262950397Sobrien previously selected stack order. */ 263018334Speter 263118334Speter /* By now, the only difference should be the order of the stack, 263250397Sobrien not their depth or liveliness. */ 263318334Speter 263418334Speter GO_IF_HARD_REG_EQUAL (old->reg_set, new->reg_set, win); 263518334Speter 263618334Speter abort (); 263718334Speter 263818334Speter win: 263918334Speter 264018334Speter if (old->top != new->top) 264118334Speter abort (); 264218334Speter 264352284Sobrien /* If the stack is not empty (new->top != -1), loop here emitting 264452284Sobrien swaps until the stack is correct. 264552284Sobrien 264652284Sobrien The worst case number of swaps emitted is N + 2, where N is the 264718334Speter depth of the stack. In some cases, the reg at the top of 264818334Speter stack may be correct, but swapped anyway in order to fix 264918334Speter other regs. But since we never swap any other reg away from 265050397Sobrien its correct slot, this algorithm will converge. */ 265118334Speter 265252284Sobrien if (new->top != -1) 265352284Sobrien do 265452284Sobrien { 265552284Sobrien /* Swap the reg at top of stack into the position it is 265652284Sobrien supposed to be in, until the correct top of stack appears. */ 265718334Speter 265852284Sobrien while (old->reg[old->top] != new->reg[new->top]) 265952284Sobrien { 266052284Sobrien for (reg = new->top; reg >= 0; reg--) 266152284Sobrien if (new->reg[reg] == old->reg[old->top]) 266252284Sobrien break; 266318334Speter 266452284Sobrien if (reg == -1) 266552284Sobrien abort (); 266618334Speter 266752284Sobrien emit_swap_insn (insn, old, 266852284Sobrien FP_MODE_REG (old->reg[reg], DFmode)); 266952284Sobrien } 267018334Speter 267152284Sobrien /* See if any regs remain incorrect. If so, bring an 267218334Speter incorrect reg to the top of stack, and let the while loop 267350397Sobrien above fix it. */ 267418334Speter 267552284Sobrien for (reg = new->top; reg >= 0; reg--) 267652284Sobrien if (new->reg[reg] != old->reg[reg]) 267752284Sobrien { 267852284Sobrien emit_swap_insn (insn, old, 267952284Sobrien FP_MODE_REG (old->reg[reg], DFmode)); 268052284Sobrien break; 268152284Sobrien } 268252284Sobrien } while (reg >= 0); 268318334Speter 268450397Sobrien /* At this point there must be no differences. */ 268518334Speter 268618334Speter for (reg = old->top; reg >= 0; reg--) 268718334Speter if (old->reg[reg] != new->reg[reg]) 268818334Speter abort (); 268918334Speter } 269018334Speter} 269118334Speter 269218334Speter/* Check PAT, which points to RTL in INSN, for a LABEL_REF. If it is 269318334Speter found, ensure that a jump from INSN to the code_label to which the 269418334Speter label_ref points ends up with the same stack as that at the 269518334Speter code_label. Do this by inserting insns just before the code_label to 269618334Speter pop and rotate the stack until it is in the correct order. REGSTACK 269718334Speter is the order of the register stack in INSN. 269818334Speter 269918334Speter Any code that is emitted here must not be later processed as part 270050397Sobrien of any block, as it will already contain hard register numbers. */ 270118334Speter 270218334Speterstatic void 270318334Spetergoto_block_pat (insn, regstack, pat) 270418334Speter rtx insn; 270518334Speter stack regstack; 270618334Speter rtx pat; 270718334Speter{ 270818334Speter rtx label; 270918334Speter rtx new_jump, new_label, new_barrier; 271018334Speter rtx *ref; 271118334Speter stack label_stack; 271218334Speter struct stack_def temp_stack; 271318334Speter int reg; 271418334Speter 271518334Speter switch (GET_CODE (pat)) 271618334Speter { 271718334Speter case RETURN: 271818334Speter straighten_stack (PREV_INSN (insn), regstack); 271918334Speter return; 272018334Speter default: 272118334Speter { 272218334Speter int i, j; 272318334Speter char *fmt = GET_RTX_FORMAT (GET_CODE (pat)); 272418334Speter 272518334Speter for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) 272618334Speter { 272718334Speter if (fmt[i] == 'e') 272818334Speter goto_block_pat (insn, regstack, XEXP (pat, i)); 272918334Speter if (fmt[i] == 'E') 273018334Speter for (j = 0; j < XVECLEN (pat, i); j++) 273118334Speter goto_block_pat (insn, regstack, XVECEXP (pat, i, j)); 273218334Speter } 273318334Speter return; 273418334Speter } 273518334Speter case LABEL_REF:; 273618334Speter } 273718334Speter 273818334Speter label = XEXP (pat, 0); 273918334Speter if (GET_CODE (label) != CODE_LABEL) 274018334Speter abort (); 274118334Speter 274250397Sobrien /* First, see if in fact anything needs to be done to the stack at all. */ 274318334Speter if (INSN_UID (label) <= 0) 274418334Speter return; 274518334Speter 274618334Speter label_stack = &block_stack_in[BLOCK_NUM (label)]; 274718334Speter 274818334Speter if (label_stack->top == -2) 274918334Speter { 275018334Speter /* If the target block hasn't had a stack order selected, then 275150397Sobrien we need merely ensure that no pops are needed. */ 275218334Speter 275318334Speter for (reg = regstack->top; reg >= 0; reg--) 275418334Speter if (! TEST_HARD_REG_BIT (label_stack->reg_set, regstack->reg[reg])) 275518334Speter break; 275618334Speter 275718334Speter if (reg == -1) 275818334Speter { 275950397Sobrien /* change_stack will not emit any code in this case. */ 276018334Speter 276118334Speter change_stack (label, regstack, label_stack, emit_insn_after); 276218334Speter return; 276318334Speter } 276418334Speter } 276518334Speter else if (label_stack->top == regstack->top) 276618334Speter { 276718334Speter for (reg = label_stack->top; reg >= 0; reg--) 276818334Speter if (label_stack->reg[reg] != regstack->reg[reg]) 276918334Speter break; 277018334Speter 277118334Speter if (reg == -1) 277218334Speter return; 277318334Speter } 277418334Speter 277518334Speter /* At least one insn will need to be inserted before label. Insert 277618334Speter a jump around the code we are about to emit. Emit a label for the new 277718334Speter code, and point the original insn at this new label. We can't use 277818334Speter redirect_jump here, because we're using fld[4] of the code labels as 277950397Sobrien LABEL_REF chains, no NUSES counters. */ 278018334Speter 278118334Speter new_jump = emit_jump_insn_before (gen_jump (label), label); 278218334Speter record_label_references (new_jump, PATTERN (new_jump)); 278318334Speter JUMP_LABEL (new_jump) = label; 278418334Speter 278518334Speter new_barrier = emit_barrier_after (new_jump); 278618334Speter 278718334Speter new_label = gen_label_rtx (); 278818334Speter emit_label_after (new_label, new_barrier); 278918334Speter LABEL_REFS (new_label) = new_label; 279018334Speter 279118334Speter /* The old label_ref will no longer point to the code_label if now uses, 279250397Sobrien so strip the label_ref from the code_label's chain of references. */ 279318334Speter 279418334Speter for (ref = &LABEL_REFS (label); *ref != label; ref = &LABEL_NEXTREF (*ref)) 279518334Speter if (*ref == pat) 279618334Speter break; 279718334Speter 279818334Speter if (*ref == label) 279918334Speter abort (); 280018334Speter 280118334Speter *ref = LABEL_NEXTREF (*ref); 280218334Speter 280318334Speter XEXP (pat, 0) = new_label; 280418334Speter record_label_references (insn, PATTERN (insn)); 280518334Speter 280618334Speter if (JUMP_LABEL (insn) == label) 280718334Speter JUMP_LABEL (insn) = new_label; 280818334Speter 280950397Sobrien /* Now emit the needed code. */ 281018334Speter 281118334Speter temp_stack = *regstack; 281218334Speter 281318334Speter change_stack (new_label, &temp_stack, label_stack, emit_insn_after); 281418334Speter} 281518334Speter 281618334Speter/* Traverse all basic blocks in a function, converting the register 281718334Speter references in each insn from the "flat" register file that gcc uses, to 281850397Sobrien the stack-like registers the 387 uses. */ 281918334Speter 282018334Speterstatic void 282118334Speterconvert_regs () 282218334Speter{ 282318334Speter register int block, reg; 282418334Speter register rtx insn, next; 282518334Speter struct stack_def regstack; 282618334Speter 282718334Speter for (block = 0; block < blocks; block++) 282818334Speter { 282918334Speter if (block_stack_in[block].top == -2) 283018334Speter { 283118334Speter /* This block has not been previously encountered. Choose a 283218334Speter default mapping for any stack regs live on entry */ 283318334Speter 283418334Speter block_stack_in[block].top = -1; 283518334Speter 283618334Speter for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; reg--) 283718334Speter if (TEST_HARD_REG_BIT (block_stack_in[block].reg_set, reg)) 283818334Speter block_stack_in[block].reg[++block_stack_in[block].top] = reg; 283918334Speter } 284018334Speter 284118334Speter /* Process all insns in this block. Keep track of `next' here, 284218334Speter so that we don't process any insns emitted while making 284350397Sobrien substitutions in INSN. */ 284418334Speter 284518334Speter next = block_begin[block]; 284618334Speter regstack = block_stack_in[block]; 284718334Speter do 284818334Speter { 284918334Speter insn = next; 285018334Speter next = NEXT_INSN (insn); 285118334Speter 285218334Speter /* Don't bother processing unless there is a stack reg 285318334Speter mentioned or if it's a CALL_INSN (register passing of 285450397Sobrien floating point values). */ 285518334Speter 285652284Sobrien if (stack_regs_mentioned (insn) || GET_CODE (insn) == CALL_INSN) 285718334Speter subst_stack_regs (insn, ®stack); 285818334Speter 285918334Speter } while (insn != block_end[block]); 286050397Sobrien 286150397Sobrien /* For all further actions, INSN needs to be the last insn in 286250397Sobrien this basic block. If subst_stack_regs inserted additional 286350397Sobrien instructions after INSN, it is no longer the last one at 286450397Sobrien this point. */ 286550397Sobrien next = PREV_INSN (next); 286618334Speter 286750397Sobrien /* If subst_stack_regs inserted something after a JUMP_INSN, that 286850397Sobrien is almost certainly a bug. */ 286950397Sobrien if (GET_CODE (insn) == JUMP_INSN && insn != next) 287050397Sobrien abort (); 287150397Sobrien insn = next; 287218334Speter 287350397Sobrien /* Something failed if the stack life doesn't match. */ 287450397Sobrien 287518334Speter GO_IF_HARD_REG_EQUAL (regstack.reg_set, block_out_reg_set[block], win); 287618334Speter 287718334Speter abort (); 287818334Speter 287918334Speter win: 288018334Speter 288118334Speter /* Adjust the stack of this block on exit to match the stack of 288218334Speter the target block, or copy stack information into stack of 288318334Speter jump target if the target block's stack order hasn't been set 288450397Sobrien yet. */ 288518334Speter 288618334Speter if (GET_CODE (insn) == JUMP_INSN) 288718334Speter goto_block_pat (insn, ®stack, PATTERN (insn)); 288818334Speter 288950397Sobrien /* Likewise handle the case where we fall into the next block. */ 289018334Speter 289118334Speter if ((block < blocks - 1) && block_drops_in[block+1]) 289218334Speter change_stack (insn, ®stack, &block_stack_in[block+1], 289318334Speter emit_insn_after); 289418334Speter } 289518334Speter 289618334Speter /* If the last basic block is the end of a loop, and that loop has 289718334Speter regs live at its start, then the last basic block will have regs live 289850397Sobrien at its end that need to be popped before the function returns. */ 289918334Speter 290018334Speter { 290118334Speter int value_reg_low, value_reg_high; 290218334Speter value_reg_low = value_reg_high = -1; 290318334Speter { 290418334Speter rtx retvalue; 290550397Sobrien if ((retvalue = stack_result (current_function_decl))) 290618334Speter { 290718334Speter value_reg_low = REGNO (retvalue); 290818334Speter value_reg_high = value_reg_low + 290918334Speter HARD_REGNO_NREGS (value_reg_low, GET_MODE (retvalue)) - 1; 291018334Speter } 291118334Speter 291218334Speter } 291318334Speter for (reg = regstack.top; reg >= 0; reg--) 291450397Sobrien if (regstack.reg[reg] < value_reg_low 291550397Sobrien || regstack.reg[reg] > value_reg_high) 291618334Speter insn = emit_pop_insn (insn, ®stack, 291718334Speter FP_MODE_REG (regstack.reg[reg], DFmode), 291818334Speter emit_insn_after); 291918334Speter } 292018334Speter straighten_stack (insn, ®stack); 292118334Speter} 292218334Speter 292318334Speter/* Check expression PAT, which is in INSN, for label references. if 292450397Sobrien one is found, print the block number of destination to FILE. */ 292518334Speter 292618334Speterstatic void 292718334Speterprint_blocks (file, insn, pat) 292818334Speter FILE *file; 292918334Speter rtx insn, pat; 293018334Speter{ 293118334Speter register RTX_CODE code = GET_CODE (pat); 293218334Speter register int i; 293318334Speter register char *fmt; 293418334Speter 293518334Speter if (code == LABEL_REF) 293618334Speter { 293718334Speter register rtx label = XEXP (pat, 0); 293818334Speter 293918334Speter if (GET_CODE (label) != CODE_LABEL) 294018334Speter abort (); 294118334Speter 294218334Speter fprintf (file, " %d", BLOCK_NUM (label)); 294318334Speter 294418334Speter return; 294518334Speter } 294618334Speter 294718334Speter fmt = GET_RTX_FORMAT (code); 294818334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 294918334Speter { 295018334Speter if (fmt[i] == 'e') 295118334Speter print_blocks (file, insn, XEXP (pat, i)); 295218334Speter if (fmt[i] == 'E') 295318334Speter { 295418334Speter register int j; 295518334Speter for (j = 0; j < XVECLEN (pat, i); j++) 295618334Speter print_blocks (file, insn, XVECEXP (pat, i, j)); 295718334Speter } 295818334Speter } 295918334Speter} 296018334Speter 296118334Speter/* Write information about stack registers and stack blocks into FILE. 296218334Speter This is part of making a debugging dump. */ 296350397Sobrien 296418334Speterstatic void 296518334Speterdump_stack_info (file) 296618334Speter FILE *file; 296718334Speter{ 296818334Speter register int block; 296918334Speter 297018334Speter fprintf (file, "\n%d stack blocks.\n", blocks); 297118334Speter for (block = 0; block < blocks; block++) 297218334Speter { 297318334Speter register rtx head, jump, end; 297418334Speter register int regno; 297518334Speter 297618334Speter fprintf (file, "\nStack block %d: first insn %d, last %d.\n", 297718334Speter block, INSN_UID (block_begin[block]), 297818334Speter INSN_UID (block_end[block])); 297918334Speter 298018334Speter head = block_begin[block]; 298118334Speter 298218334Speter fprintf (file, "Reached from blocks: "); 298318334Speter if (GET_CODE (head) == CODE_LABEL) 298418334Speter for (jump = LABEL_REFS (head); 298518334Speter jump != head; 298618334Speter jump = LABEL_NEXTREF (jump)) 298718334Speter { 298818334Speter register int from_block = BLOCK_NUM (CONTAINING_INSN (jump)); 298918334Speter fprintf (file, " %d", from_block); 299018334Speter } 299118334Speter if (block_drops_in[block]) 299218334Speter fprintf (file, " previous"); 299318334Speter 299418334Speter fprintf (file, "\nlive stack registers on block entry: "); 299518334Speter for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++) 299618334Speter { 299718334Speter if (TEST_HARD_REG_BIT (block_stack_in[block].reg_set, regno)) 299818334Speter fprintf (file, "%d ", regno); 299918334Speter } 300018334Speter 300118334Speter fprintf (file, "\nlive stack registers on block exit: "); 300218334Speter for (regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++) 300318334Speter { 300418334Speter if (TEST_HARD_REG_BIT (block_out_reg_set[block], regno)) 300518334Speter fprintf (file, "%d ", regno); 300618334Speter } 300718334Speter 300818334Speter end = block_end[block]; 300918334Speter 301018334Speter fprintf (file, "\nJumps to blocks: "); 301118334Speter if (GET_CODE (end) == JUMP_INSN) 301218334Speter print_blocks (file, end, PATTERN (end)); 301318334Speter 301418334Speter if (block + 1 < blocks && block_drops_in[block+1]) 301518334Speter fprintf (file, " next"); 301618334Speter else if (block + 1 == blocks 301718334Speter || (GET_CODE (end) == JUMP_INSN 301818334Speter && GET_CODE (PATTERN (end)) == RETURN)) 301918334Speter fprintf (file, " return"); 302018334Speter 302118334Speter fprintf (file, "\n"); 302218334Speter } 302318334Speter} 302418334Speter#endif /* STACK_REGS */ 3025