reg-stack.c revision 102780
118334Speter/* Register to Stack convert for GNU compiler. 290075Sobrien Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 390075Sobrien 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 418334Speter 590075Sobrien This file is part of GCC. 618334Speter 790075Sobrien GCC is free software; you can redistribute it and/or modify it 890075Sobrien under the terms of the GNU General Public License as published by 990075Sobrien the Free Software Foundation; either version 2, or (at your option) 1090075Sobrien any later version. 1118334Speter 1290075Sobrien GCC is distributed in the hope that it will be useful, but WITHOUT 1390075Sobrien ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 1490075Sobrien or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 1590075Sobrien License for more details. 1618334Speter 1790075Sobrien You should have received a copy of the GNU General Public License 1890075Sobrien along with GCC; see the file COPYING. If not, write to the Free 1990075Sobrien Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2090075Sobrien 02111-1307, USA. */ 2118334Speter 2218334Speter/* This pass converts stack-like registers from the "flat register 2318334Speter file" model that gcc uses, to a stack convention that the 387 uses. 2418334Speter 2518334Speter * The form of the input: 2618334Speter 2718334Speter On input, the function consists of insn that have had their 2818334Speter registers fully allocated to a set of "virtual" registers. Note that 2918334Speter the word "virtual" is used differently here than elsewhere in gcc: for 3018334Speter each virtual stack reg, there is a hard reg, but the mapping between 3118334Speter them is not known until this pass is run. On output, hard register 3218334Speter numbers have been substituted, and various pop and exchange insns have 3318334Speter been emitted. The hard register numbers and the virtual register 3418334Speter numbers completely overlap - before this pass, all stack register 3518334Speter numbers are virtual, and afterward they are all hard. 3618334Speter 3718334Speter The virtual registers can be manipulated normally by gcc, and their 3818334Speter semantics are the same as for normal registers. After the hard 3918334Speter register numbers are substituted, the semantics of an insn containing 4018334Speter stack-like regs are not the same as for an insn with normal regs: for 4118334Speter instance, it is not safe to delete an insn that appears to be a no-op 4218334Speter move. In general, no insn containing hard regs should be changed 4318334Speter after this pass is done. 4418334Speter 4518334Speter * The form of the output: 4618334Speter 4718334Speter After this pass, hard register numbers represent the distance from 4818334Speter the current top of stack to the desired register. A reference to 4918334Speter FIRST_STACK_REG references the top of stack, FIRST_STACK_REG + 1, 5018334Speter represents the register just below that, and so forth. Also, REG_DEAD 5118334Speter notes indicate whether or not a stack register should be popped. 5218334Speter 5318334Speter A "swap" insn looks like a parallel of two patterns, where each 5418334Speter pattern is a SET: one sets A to B, the other B to A. 5518334Speter 5618334Speter A "push" or "load" insn is a SET whose SET_DEST is FIRST_STACK_REG 5718334Speter and whose SET_DEST is REG or MEM. Any other SET_DEST, such as PLUS, 5818334Speter will replace the existing stack top, not push a new value. 5918334Speter 6018334Speter A store insn is a SET whose SET_DEST is FIRST_STACK_REG, and whose 6118334Speter SET_SRC is REG or MEM. 6218334Speter 6318334Speter The case where the SET_SRC and SET_DEST are both FIRST_STACK_REG 6418334Speter appears ambiguous. As a special case, the presence of a REG_DEAD note 6518334Speter for FIRST_STACK_REG differentiates between a load insn and a pop. 6618334Speter 6718334Speter If a REG_DEAD is present, the insn represents a "pop" that discards 6818334Speter the top of the register stack. If there is no REG_DEAD note, then the 6918334Speter insn represents a "dup" or a push of the current top of stack onto the 7018334Speter stack. 7118334Speter 7218334Speter * Methodology: 7318334Speter 7418334Speter Existing REG_DEAD and REG_UNUSED notes for stack registers are 7518334Speter deleted and recreated from scratch. REG_DEAD is never created for a 7618334Speter SET_DEST, only REG_UNUSED. 7718334Speter 7818334Speter * asm_operands: 7918334Speter 8018334Speter There are several rules on the usage of stack-like regs in 8118334Speter asm_operands insns. These rules apply only to the operands that are 8218334Speter stack-like regs: 8318334Speter 8418334Speter 1. Given a set of input regs that die in an asm_operands, it is 8518334Speter necessary to know which are implicitly popped by the asm, and 8618334Speter which must be explicitly popped by gcc. 8718334Speter 8818334Speter An input reg that is implicitly popped by the asm must be 8918334Speter explicitly clobbered, unless it is constrained to match an 9018334Speter output operand. 9118334Speter 9218334Speter 2. For any input reg that is implicitly popped by an asm, it is 9318334Speter necessary to know how to adjust the stack to compensate for the pop. 9418334Speter If any non-popped input is closer to the top of the reg-stack than 9518334Speter the implicitly popped reg, it would not be possible to know what the 9618334Speter stack looked like - it's not clear how the rest of the stack "slides 9718334Speter up". 9818334Speter 9918334Speter All implicitly popped input regs must be closer to the top of 10018334Speter the reg-stack than any input that is not implicitly popped. 10118334Speter 10218334Speter 3. It is possible that if an input dies in an insn, reload might 10318334Speter use the input reg for an output reload. Consider this example: 10418334Speter 10518334Speter asm ("foo" : "=t" (a) : "f" (b)); 10618334Speter 10718334Speter This asm says that input B is not popped by the asm, and that 10818334Speter the asm pushes a result onto the reg-stack, ie, the stack is one 10918334Speter deeper after the asm than it was before. But, it is possible that 11018334Speter reload will think that it can use the same reg for both the input and 11118334Speter the output, if input B dies in this insn. 11218334Speter 11318334Speter If any input operand uses the "f" constraint, all output reg 11418334Speter constraints must use the "&" earlyclobber. 11518334Speter 11618334Speter The asm above would be written as 11718334Speter 11818334Speter asm ("foo" : "=&t" (a) : "f" (b)); 11918334Speter 12018334Speter 4. Some operands need to be in particular places on the stack. All 12118334Speter output operands fall in this category - there is no other way to 12218334Speter know which regs the outputs appear in unless the user indicates 12318334Speter this in the constraints. 12418334Speter 12518334Speter Output operands must specifically indicate which reg an output 12618334Speter appears in after an asm. "=f" is not allowed: the operand 12718334Speter constraints must select a class with a single reg. 12818334Speter 12918334Speter 5. Output operands may not be "inserted" between existing stack regs. 13018334Speter Since no 387 opcode uses a read/write operand, all output operands 13118334Speter are dead before the asm_operands, and are pushed by the asm_operands. 13218334Speter It makes no sense to push anywhere but the top of the reg-stack. 13318334Speter 13418334Speter Output operands must start at the top of the reg-stack: output 13518334Speter operands may not "skip" a reg. 13618334Speter 13718334Speter 6. Some asm statements may need extra stack space for internal 13818334Speter calculations. This can be guaranteed by clobbering stack registers 13918334Speter unrelated to the inputs and outputs. 14018334Speter 14118334Speter Here are a couple of reasonable asms to want to write. This asm 14218334Speter takes one input, which is internally popped, and produces two outputs. 14318334Speter 14418334Speter asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp)); 14518334Speter 14618334Speter This asm takes two inputs, which are popped by the fyl2xp1 opcode, 14718334Speter and replaces them with one output. The user must code the "st(1)" 14818334Speter clobber for reg-stack.c to know that fyl2xp1 pops both inputs. 14918334Speter 15018334Speter asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)"); 15118334Speter 15290075Sobrien*/ 15318334Speter 15418334Speter#include "config.h" 15550397Sobrien#include "system.h" 15618334Speter#include "tree.h" 15718334Speter#include "rtl.h" 15890075Sobrien#include "tm_p.h" 15990075Sobrien#include "function.h" 16018334Speter#include "insn-config.h" 16118334Speter#include "regs.h" 16218334Speter#include "hard-reg-set.h" 16318334Speter#include "flags.h" 16490075Sobrien#include "toplev.h" 16552284Sobrien#include "recog.h" 16690075Sobrien#include "output.h" 16790075Sobrien#include "basic-block.h" 16852284Sobrien#include "varray.h" 16990075Sobrien#include "reload.h" 17018334Speter 17118334Speter#ifdef STACK_REGS 17218334Speter 17318334Speter#define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1) 17418334Speter 17518334Speter/* This is the basic stack record. TOP is an index into REG[] such 17618334Speter that REG[TOP] is the top of stack. If TOP is -1 the stack is empty. 17718334Speter 17818334Speter If TOP is -2, REG[] is not yet initialized. Stack initialization 17918334Speter consists of placing each live reg in array `reg' and setting `top' 18018334Speter appropriately. 18118334Speter 18218334Speter REG_SET indicates which registers are live. */ 18318334Speter 18418334Spetertypedef struct stack_def 18518334Speter{ 18618334Speter int top; /* index to top stack element */ 18718334Speter HARD_REG_SET reg_set; /* set of live registers */ 18890075Sobrien unsigned char reg[REG_STACK_SIZE];/* register - stack mapping */ 18918334Speter} *stack; 19018334Speter 19190075Sobrien/* This is used to carry information about basic blocks. It is 19290075Sobrien attached to the AUX field of the standard CFG block. */ 19318334Speter 19490075Sobrientypedef struct block_info_def 19590075Sobrien{ 19690075Sobrien struct stack_def stack_in; /* Input stack configuration. */ 19790075Sobrien struct stack_def stack_out; /* Output stack configuration. */ 19890075Sobrien HARD_REG_SET out_reg_set; /* Stack regs live on output. */ 19990075Sobrien int done; /* True if block already converted. */ 20090075Sobrien int predecessors; /* Number of predecessors that needs 20190075Sobrien to be visited. */ 20290075Sobrien} *block_info; 20318334Speter 20490075Sobrien#define BLOCK_INFO(B) ((block_info) (B)->aux) 20518334Speter 20690075Sobrien/* Passed to change_stack to indicate where to emit insns. */ 20790075Sobrienenum emit_where 20890075Sobrien{ 20990075Sobrien EMIT_AFTER, 21090075Sobrien EMIT_BEFORE 21190075Sobrien}; 21218334Speter 21352284Sobrien/* We use this array to cache info about insns, because otherwise we 21452284Sobrien spend too much time in stack_regs_mentioned_p. 21552284Sobrien 21652284Sobrien Indexed by insn UIDs. A value of zero is uninitialized, one indicates 21752284Sobrien the insn uses stack registers, two indicates the insn does not use 21852284Sobrien stack registers. */ 21952284Sobrienstatic varray_type stack_regs_mentioned_data; 22052284Sobrien 22190075Sobrien/* The block we're currently working on. */ 22290075Sobrienstatic basic_block current_block; 22390075Sobrien 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) \ 22990075Sobrien (FP_mode_reg[(regno)-FIRST_STACK_REG][(int) (mode)]) 23018334Speter 23190075Sobrien/* Used to initialize uninitialized registers. */ 23290075Sobrienstatic rtx nan; 23318334Speter 23418334Speter/* Forward declarations */ 23518334Speter 23690075Sobrienstatic int stack_regs_mentioned_p PARAMS ((rtx pat)); 23790075Sobrienstatic void straighten_stack PARAMS ((rtx, stack)); 23890075Sobrienstatic void pop_stack PARAMS ((stack, int)); 23990075Sobrienstatic rtx *get_true_reg PARAMS ((rtx *)); 24050397Sobrien 24190075Sobrienstatic int check_asm_stack_operands PARAMS ((rtx)); 24290075Sobrienstatic int get_asm_operand_n_inputs PARAMS ((rtx)); 24390075Sobrienstatic rtx stack_result PARAMS ((tree)); 24490075Sobrienstatic void replace_reg PARAMS ((rtx *, int)); 24590075Sobrienstatic void remove_regno_note PARAMS ((rtx, enum reg_note, 24690075Sobrien unsigned int)); 24790075Sobrienstatic int get_hard_regnum PARAMS ((stack, rtx)); 24890075Sobrienstatic rtx emit_pop_insn PARAMS ((rtx, stack, rtx, 24990075Sobrien enum emit_where)); 25090075Sobrienstatic void emit_swap_insn PARAMS ((rtx, stack, rtx)); 25190075Sobrienstatic void move_for_stack_reg PARAMS ((rtx, stack, rtx)); 25290075Sobrienstatic int swap_rtx_condition_1 PARAMS ((rtx)); 25390075Sobrienstatic int swap_rtx_condition PARAMS ((rtx)); 25490075Sobrienstatic void compare_for_stack_reg PARAMS ((rtx, stack, rtx)); 25590075Sobrienstatic void subst_stack_regs_pat PARAMS ((rtx, stack, rtx)); 25690075Sobrienstatic void subst_asm_stack_regs PARAMS ((rtx, stack)); 25790075Sobrienstatic void subst_stack_regs PARAMS ((rtx, stack)); 25890075Sobrienstatic void change_stack PARAMS ((rtx, stack, stack, 25990075Sobrien enum emit_where)); 26090075Sobrienstatic int convert_regs_entry PARAMS ((void)); 26190075Sobrienstatic void convert_regs_exit PARAMS ((void)); 26290075Sobrienstatic int convert_regs_1 PARAMS ((FILE *, basic_block)); 26390075Sobrienstatic int convert_regs_2 PARAMS ((FILE *, basic_block)); 26490075Sobrienstatic int convert_regs PARAMS ((FILE *)); 26590075Sobrienstatic void print_stack PARAMS ((FILE *, stack)); 26690075Sobrienstatic rtx next_flags_user PARAMS ((rtx)); 26790075Sobrienstatic void record_label_references PARAMS ((rtx, rtx)); 26890075Sobrienstatic bool compensate_edge PARAMS ((edge, FILE *)); 26918334Speter 27090075Sobrien/* Return non-zero if any stack register is mentioned somewhere within PAT. */ 27152284Sobrien 27252284Sobrienstatic int 27390075Sobrienstack_regs_mentioned_p (pat) 27490075Sobrien rtx pat; 27552284Sobrien{ 27690075Sobrien const char *fmt; 27790075Sobrien int i; 27890075Sobrien 27990075Sobrien if (STACK_REG_P (pat)) 28090075Sobrien return 1; 28190075Sobrien 28290075Sobrien fmt = GET_RTX_FORMAT (GET_CODE (pat)); 28390075Sobrien for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) 28452284Sobrien { 28590075Sobrien if (fmt[i] == 'E') 28690075Sobrien { 28790075Sobrien int j; 28890075Sobrien 28990075Sobrien for (j = XVECLEN (pat, i) - 1; j >= 0; j--) 29090075Sobrien if (stack_regs_mentioned_p (XVECEXP (pat, i, j))) 29190075Sobrien return 1; 29290075Sobrien } 29390075Sobrien else if (fmt[i] == 'e' && stack_regs_mentioned_p (XEXP (pat, i))) 29490075Sobrien return 1; 29552284Sobrien } 29690075Sobrien 29752284Sobrien return 0; 29852284Sobrien} 29952284Sobrien 30090075Sobrien/* Return nonzero if INSN mentions stacked registers, else return zero. */ 30152284Sobrien 30252284Sobrienint 30352284Sobrienstack_regs_mentioned (insn) 30452284Sobrien rtx insn; 30552284Sobrien{ 30690075Sobrien unsigned int uid, max; 30790075Sobrien int test; 30890075Sobrien 30990075Sobrien if (! INSN_P (insn) || !stack_regs_mentioned_data) 31052284Sobrien return 0; 31190075Sobrien 31252284Sobrien uid = INSN_UID (insn); 31390075Sobrien max = VARRAY_SIZE (stack_regs_mentioned_data); 31490075Sobrien if (uid >= max) 31590075Sobrien { 31690075Sobrien /* Allocate some extra size to avoid too many reallocs, but 31790075Sobrien do not grow too quickly. */ 31890075Sobrien max = uid + uid / 20; 31990075Sobrien VARRAY_GROW (stack_regs_mentioned_data, max); 32090075Sobrien } 32190075Sobrien 32290075Sobrien test = VARRAY_CHAR (stack_regs_mentioned_data, uid); 32390075Sobrien if (test == 0) 32490075Sobrien { 32590075Sobrien /* This insn has yet to be examined. Do so now. */ 32690075Sobrien test = stack_regs_mentioned_p (PATTERN (insn)) ? 1 : 2; 32790075Sobrien VARRAY_CHAR (stack_regs_mentioned_data, uid) = test; 32890075Sobrien } 32990075Sobrien 33090075Sobrien return test == 1; 33152284Sobrien} 33252284Sobrien 33390075Sobrienstatic rtx ix86_flags_rtx; 33418334Speter 33590075Sobrienstatic rtx 33690075Sobriennext_flags_user (insn) 33790075Sobrien rtx insn; 33818334Speter{ 33990075Sobrien /* Search forward looking for the first use of this value. 34090075Sobrien Stop at block boundaries. */ 34118334Speter 34290075Sobrien while (insn != current_block->end) 34390075Sobrien { 34490075Sobrien insn = NEXT_INSN (insn); 34518334Speter 34690075Sobrien if (INSN_P (insn) && reg_mentioned_p (ix86_flags_rtx, PATTERN (insn))) 34790075Sobrien return insn; 34890075Sobrien 34990075Sobrien if (GET_CODE (insn) == CALL_INSN) 35090075Sobrien return NULL_RTX; 35190075Sobrien } 35290075Sobrien return NULL_RTX; 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 37390075Sobrien COPY_HARD_REG_SET (temp_stack.reg_set, regstack->reg_set); 37418334Speter 37518334Speter for (top = temp_stack.top = regstack->top; top >= 0; top--) 37690075Sobrien temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top; 37718334Speter 37890075Sobrien change_stack (insn, regstack, &temp_stack, EMIT_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/* Convert register usage from "flat" register file usage to a "stack 40818334Speter register file. FIRST is the first insn in the function, FILE is the 40918334Speter dump file, if used. 41018334Speter 41190075Sobrien Construct a CFG and run life analysis. Then convert each insn one 41290075Sobrien by one. Run a last cleanup_cfg pass, if optimizing, to eliminate 41390075Sobrien code duplication created when the converter inserts pop insns on 41490075Sobrien the edges. */ 41518334Speter 41618334Spetervoid 41718334Speterreg_to_stack (first, file) 41818334Speter rtx first; 41918334Speter FILE *file; 42018334Speter{ 42190075Sobrien int i; 42290075Sobrien int max_uid; 42318334Speter 42490075Sobrien /* Clean up previous run. */ 42590075Sobrien if (stack_regs_mentioned_data) 42652284Sobrien { 42752284Sobrien VARRAY_FREE (stack_regs_mentioned_data); 42890075Sobrien stack_regs_mentioned_data = 0; 42952284Sobrien } 43018334Speter 43190075Sobrien if (!optimize) 43290075Sobrien split_all_insns (0); 43318334Speter 43490075Sobrien /* See if there is something to do. Flow analysis is quite 43590075Sobrien expensive so we might save some compilation time. */ 43690075Sobrien for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) 43790075Sobrien if (regs_ever_live[i]) 43890075Sobrien break; 43990075Sobrien if (i > LAST_STACK_REG) 44090075Sobrien return; 44118334Speter 44290075Sobrien /* Ok, floating point instructions exist. If not optimizing, 44390075Sobrien build the CFG and run life analysis. */ 44490075Sobrien if (!optimize) 44590075Sobrien { 44690075Sobrien find_basic_blocks (first, max_reg_num (), file); 44790075Sobrien count_or_remove_death_notes (NULL, 1); 44890075Sobrien life_analysis (first, file, PROP_DEATH_NOTES); 44990075Sobrien } 45090075Sobrien mark_dfs_back_edges (); 45118334Speter 45290075Sobrien /* Set up block info for each basic block. */ 45390075Sobrien alloc_aux_for_blocks (sizeof (struct block_info_def)); 45490075Sobrien for (i = n_basic_blocks - 1; i >= 0; --i) 45590075Sobrien { 45690075Sobrien edge e; 45790075Sobrien basic_block bb = BASIC_BLOCK (i); 45890075Sobrien for (e = bb->pred; e; e=e->pred_next) 45990075Sobrien if (!(e->flags & EDGE_DFS_BACK) 46090075Sobrien && e->src != ENTRY_BLOCK_PTR) 46190075Sobrien BLOCK_INFO (bb)->predecessors++; 46290075Sobrien } 46318334Speter 46490075Sobrien /* Create the replacement registers up front. */ 46590075Sobrien for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) 46690075Sobrien { 46790075Sobrien enum machine_mode mode; 46890075Sobrien for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); 46990075Sobrien mode != VOIDmode; 47090075Sobrien mode = GET_MODE_WIDER_MODE (mode)) 47190075Sobrien FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i); 47290075Sobrien for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT); 47390075Sobrien mode != VOIDmode; 47490075Sobrien mode = GET_MODE_WIDER_MODE (mode)) 47590075Sobrien FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i); 47690075Sobrien } 47718334Speter 47890075Sobrien ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG); 47918334Speter 48090075Sobrien /* A QNaN for initializing uninitialized variables. 48118334Speter 48290075Sobrien ??? We can't load from constant memory in PIC mode, because 48390075Sobrien we're insertting these instructions before the prologue and 48490075Sobrien the PIC register hasn't been set up. In that case, fall back 48590075Sobrien on zero, which we can get from `ldz'. */ 48618334Speter 48790075Sobrien if (flag_pic) 48890075Sobrien nan = CONST0_RTX (SFmode); 48990075Sobrien else 49090075Sobrien { 49190075Sobrien nan = gen_lowpart (SFmode, GEN_INT (0x7fc00000)); 49290075Sobrien nan = force_const_mem (SFmode, nan); 49390075Sobrien } 49418334Speter 49590075Sobrien /* Allocate a cache for stack_regs_mentioned. */ 49690075Sobrien max_uid = get_max_uid (); 49790075Sobrien VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1, 49890075Sobrien "stack_regs_mentioned cache"); 49918334Speter 50090075Sobrien convert_regs (file); 50152284Sobrien 50290075Sobrien free_aux_for_blocks (); 50318334Speter} 50418334Speter 50518334Speter/* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the 50618334Speter label's chain of references, and note which insn contains each 50750397Sobrien reference. */ 50818334Speter 50918334Speterstatic void 51018334Speterrecord_label_references (insn, pat) 51118334Speter rtx insn, pat; 51218334Speter{ 51390075Sobrien enum rtx_code code = GET_CODE (pat); 51490075Sobrien int i; 51590075Sobrien const char *fmt; 51618334Speter 51718334Speter if (code == LABEL_REF) 51818334Speter { 51990075Sobrien rtx label = XEXP (pat, 0); 52090075Sobrien rtx ref; 52118334Speter 52218334Speter if (GET_CODE (label) != CODE_LABEL) 52318334Speter abort (); 52418334Speter 52550397Sobrien /* If this is an undefined label, LABEL_REFS (label) contains 52650397Sobrien garbage. */ 52750397Sobrien if (INSN_UID (label) == 0) 52850397Sobrien return; 52918334Speter 53050397Sobrien /* Don't make a duplicate in the code_label's chain. */ 53150397Sobrien 53218334Speter for (ref = LABEL_REFS (label); 53318334Speter ref && ref != label; 53418334Speter ref = LABEL_NEXTREF (ref)) 53518334Speter if (CONTAINING_INSN (ref) == insn) 53618334Speter return; 53718334Speter 53818334Speter CONTAINING_INSN (pat) = insn; 53918334Speter LABEL_NEXTREF (pat) = LABEL_REFS (label); 54018334Speter LABEL_REFS (label) = pat; 54118334Speter 54218334Speter return; 54318334Speter } 54418334Speter 54518334Speter fmt = GET_RTX_FORMAT (code); 54618334Speter for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 54718334Speter { 54818334Speter if (fmt[i] == 'e') 54918334Speter record_label_references (insn, XEXP (pat, i)); 55018334Speter if (fmt[i] == 'E') 55118334Speter { 55290075Sobrien int j; 55318334Speter for (j = 0; j < XVECLEN (pat, i); j++) 55418334Speter record_label_references (insn, XVECEXP (pat, i, j)); 55518334Speter } 55618334Speter } 55718334Speter} 55818334Speter 55918334Speter/* Return a pointer to the REG expression within PAT. If PAT is not a 56018334Speter REG, possible enclosed by a conversion rtx, return the inner part of 56150397Sobrien PAT that stopped the search. */ 56218334Speter 56318334Speterstatic rtx * 56418334Speterget_true_reg (pat) 56518334Speter rtx *pat; 56618334Speter{ 56718334Speter for (;;) 56890075Sobrien switch (GET_CODE (*pat)) 56918334Speter { 57090075Sobrien case SUBREG: 57190075Sobrien /* Eliminate FP subregister accesses in favour of the 57290075Sobrien actual FP register in use. */ 57390075Sobrien { 57490075Sobrien rtx subreg; 57590075Sobrien if (FP_REG_P (subreg = SUBREG_REG (*pat))) 57618334Speter { 57790075Sobrien int regno_off = subreg_regno_offset (REGNO (subreg), 57890075Sobrien GET_MODE (subreg), 57990075Sobrien SUBREG_BYTE (*pat), 58090075Sobrien GET_MODE (*pat)); 58190075Sobrien *pat = FP_MODE_REG (REGNO (subreg) + regno_off, 58218334Speter GET_MODE (subreg)); 58390075Sobrien default: 58418334Speter return pat; 58518334Speter } 58690075Sobrien } 58790075Sobrien case FLOAT: 58890075Sobrien case FIX: 58990075Sobrien case FLOAT_EXTEND: 59090075Sobrien pat = & XEXP (*pat, 0); 59118334Speter } 59218334Speter} 59318334Speter 59490075Sobrien/* There are many rules that an asm statement for stack-like regs must 59518334Speter follow. Those rules are explained at the top of this file: the rule 59650397Sobrien numbers below refer to that explanation. */ 59718334Speter 59890075Sobrienstatic int 59990075Sobriencheck_asm_stack_operands (insn) 60018334Speter rtx insn; 60118334Speter{ 60218334Speter int i; 60318334Speter int n_clobbers; 60418334Speter int malformed_asm = 0; 60518334Speter rtx body = PATTERN (insn); 60618334Speter 60790075Sobrien char reg_used_as_output[FIRST_PSEUDO_REGISTER]; 60890075Sobrien char implicitly_dies[FIRST_PSEUDO_REGISTER]; 60952284Sobrien int alt; 61018334Speter 61190075Sobrien rtx *clobber_reg = 0; 61252284Sobrien int n_inputs, n_outputs; 61318334Speter 61418334Speter /* Find out what the constraints require. If no constraint 61518334Speter alternative matches, this asm is malformed. */ 61652284Sobrien extract_insn (insn); 61752284Sobrien constrain_operands (1); 61852284Sobrien alt = which_alternative; 61918334Speter 62052284Sobrien preprocess_constraints (); 62152284Sobrien 62252284Sobrien n_inputs = get_asm_operand_n_inputs (body); 62390075Sobrien n_outputs = recog_data.n_operands - n_inputs; 62452284Sobrien 62552284Sobrien if (alt < 0) 62652284Sobrien { 62752284Sobrien malformed_asm = 1; 62852284Sobrien /* Avoid further trouble with this insn. */ 62952284Sobrien PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx); 63090075Sobrien return 0; 63152284Sobrien } 63252284Sobrien 63350397Sobrien /* Strip SUBREGs here to make the following code simpler. */ 63490075Sobrien for (i = 0; i < recog_data.n_operands; i++) 63590075Sobrien if (GET_CODE (recog_data.operand[i]) == SUBREG 63690075Sobrien && GET_CODE (SUBREG_REG (recog_data.operand[i])) == REG) 63790075Sobrien recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]); 63818334Speter 63918334Speter /* Set up CLOBBER_REG. */ 64018334Speter 64118334Speter n_clobbers = 0; 64218334Speter 64318334Speter if (GET_CODE (body) == PARALLEL) 64418334Speter { 64552284Sobrien clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx)); 64618334Speter 64718334Speter for (i = 0; i < XVECLEN (body, 0); i++) 64818334Speter if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) 64918334Speter { 65018334Speter rtx clobber = XVECEXP (body, 0, i); 65118334Speter rtx reg = XEXP (clobber, 0); 65218334Speter 65318334Speter if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) 65418334Speter reg = SUBREG_REG (reg); 65518334Speter 65618334Speter if (STACK_REG_P (reg)) 65718334Speter { 65818334Speter clobber_reg[n_clobbers] = reg; 65918334Speter n_clobbers++; 66018334Speter } 66118334Speter } 66218334Speter } 66318334Speter 66418334Speter /* Enforce rule #4: Output operands must specifically indicate which 66518334Speter reg an output appears in after an asm. "=f" is not allowed: the 66618334Speter operand constraints must select a class with a single reg. 66718334Speter 66818334Speter Also enforce rule #5: Output operands must start at the top of 66950397Sobrien the reg-stack: output operands may not "skip" a reg. */ 67018334Speter 67190075Sobrien memset (reg_used_as_output, 0, sizeof (reg_used_as_output)); 67218334Speter for (i = 0; i < n_outputs; i++) 67390075Sobrien if (STACK_REG_P (recog_data.operand[i])) 67450397Sobrien { 67552284Sobrien if (reg_class_size[(int) recog_op_alt[i][alt].class] != 1) 67650397Sobrien { 67790075Sobrien error_for_asm (insn, "output constraint %d must specify a single register", i); 67850397Sobrien malformed_asm = 1; 67950397Sobrien } 68050397Sobrien else 68190075Sobrien { 68290075Sobrien int j; 68390075Sobrien 68490075Sobrien for (j = 0; j < n_clobbers; j++) 68590075Sobrien if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j])) 68690075Sobrien { 68790075Sobrien error_for_asm (insn, "output constraint %d cannot be specified together with \"%s\" clobber", 68890075Sobrien i, reg_names [REGNO (clobber_reg[j])]); 68990075Sobrien malformed_asm = 1; 69090075Sobrien break; 69190075Sobrien } 69290075Sobrien if (j == n_clobbers) 69390075Sobrien reg_used_as_output[REGNO (recog_data.operand[i])] = 1; 69490075Sobrien } 69550397Sobrien } 69618334Speter 69718334Speter 69818334Speter /* Search for first non-popped reg. */ 69918334Speter for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++) 70018334Speter if (! reg_used_as_output[i]) 70118334Speter break; 70218334Speter 70318334Speter /* If there are any other popped regs, that's an error. */ 70418334Speter for (; i < LAST_STACK_REG + 1; i++) 70518334Speter if (reg_used_as_output[i]) 70618334Speter break; 70718334Speter 70818334Speter if (i != LAST_STACK_REG + 1) 70918334Speter { 71090075Sobrien error_for_asm (insn, "output regs must be grouped at top of stack"); 71118334Speter malformed_asm = 1; 71218334Speter } 71318334Speter 71418334Speter /* Enforce rule #2: All implicitly popped input regs must be closer 71518334Speter to the top of the reg-stack than any input that is not implicitly 71650397Sobrien popped. */ 71718334Speter 71890075Sobrien memset (implicitly_dies, 0, sizeof (implicitly_dies)); 71952284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 72090075Sobrien if (STACK_REG_P (recog_data.operand[i])) 72118334Speter { 72218334Speter /* An input reg is implicitly popped if it is tied to an 72350397Sobrien output, or if there is a CLOBBER for it. */ 72418334Speter int j; 72518334Speter 72618334Speter for (j = 0; j < n_clobbers; j++) 72790075Sobrien if (operands_match_p (clobber_reg[j], recog_data.operand[i])) 72818334Speter break; 72918334Speter 73052284Sobrien if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0) 73190075Sobrien implicitly_dies[REGNO (recog_data.operand[i])] = 1; 73218334Speter } 73318334Speter 73418334Speter /* Search for first non-popped reg. */ 73518334Speter for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++) 73618334Speter if (! implicitly_dies[i]) 73718334Speter break; 73818334Speter 73918334Speter /* If there are any other popped regs, that's an error. */ 74018334Speter for (; i < LAST_STACK_REG + 1; i++) 74118334Speter if (implicitly_dies[i]) 74218334Speter break; 74318334Speter 74418334Speter if (i != LAST_STACK_REG + 1) 74518334Speter { 74618334Speter error_for_asm (insn, 74790075Sobrien "implicitly popped regs must be grouped at top of stack"); 74818334Speter malformed_asm = 1; 74918334Speter } 75018334Speter 75118334Speter /* Enfore rule #3: If any input operand uses the "f" constraint, all 75218334Speter output constraints must use the "&" earlyclobber. 75318334Speter 75490075Sobrien ??? Detect this more deterministically by having constrain_asm_operands 75550397Sobrien record any earlyclobber. */ 75618334Speter 75752284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 75852284Sobrien if (recog_op_alt[i][alt].matches == -1) 75918334Speter { 76018334Speter int j; 76118334Speter 76218334Speter for (j = 0; j < n_outputs; j++) 76390075Sobrien if (operands_match_p (recog_data.operand[j], recog_data.operand[i])) 76418334Speter { 76518334Speter error_for_asm (insn, 76690075Sobrien "output operand %d must use `&' constraint", j); 76718334Speter malformed_asm = 1; 76818334Speter } 76918334Speter } 77018334Speter 77118334Speter if (malformed_asm) 77218334Speter { 77318334Speter /* Avoid further trouble with this insn. */ 77450397Sobrien PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx); 77590075Sobrien return 0; 77618334Speter } 77718334Speter 77890075Sobrien return 1; 77918334Speter} 78018334Speter 78118334Speter/* Calculate the number of inputs and outputs in BODY, an 78218334Speter asm_operands. N_OPERANDS is the total number of operands, and 78318334Speter N_INPUTS and N_OUTPUTS are pointers to ints into which the results are 78450397Sobrien placed. */ 78518334Speter 78652284Sobrienstatic int 78752284Sobrienget_asm_operand_n_inputs (body) 78818334Speter rtx body; 78918334Speter{ 79018334Speter if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) 79152284Sobrien return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)); 79218334Speter 79318334Speter else if (GET_CODE (body) == ASM_OPERANDS) 79452284Sobrien return ASM_OPERANDS_INPUT_LENGTH (body); 79518334Speter 79618334Speter else if (GET_CODE (body) == PARALLEL 79718334Speter && GET_CODE (XVECEXP (body, 0, 0)) == SET) 79852284Sobrien return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0))); 79918334Speter 80018334Speter else if (GET_CODE (body) == PARALLEL 80118334Speter && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) 80252284Sobrien return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0)); 80318334Speter 80452284Sobrien abort (); 80518334Speter} 80618334Speter 80718334Speter/* If current function returns its result in an fp stack register, 80818334Speter return the REG. Otherwise, return 0. */ 80918334Speter 81018334Speterstatic rtx 81118334Speterstack_result (decl) 81218334Speter tree decl; 81318334Speter{ 81452750Sobrien rtx result; 81518334Speter 81652750Sobrien /* If the value is supposed to be returned in memory, then clearly 81752750Sobrien it is not returned in a stack register. */ 81852750Sobrien if (aggregate_value_p (DECL_RESULT (decl))) 81952750Sobrien return 0; 82052750Sobrien 82190075Sobrien result = DECL_RTL_IF_SET (DECL_RESULT (decl)); 82290075Sobrien if (result != 0) 82318334Speter { 82418334Speter#ifdef FUNCTION_OUTGOING_VALUE 82518334Speter result 82618334Speter = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl); 82718334Speter#else 82818334Speter result = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl); 82918334Speter#endif 83018334Speter } 83118334Speter 83218334Speter return result != 0 && STACK_REG_P (result) ? result : 0; 83318334Speter} 83418334Speter 83518334Speter 83690075Sobrien/* 83790075Sobrien * This section deals with stack register substitution, and forms the second 83890075Sobrien * pass over the RTL. 83990075Sobrien */ 84018334Speter 84118334Speter/* Replace REG, which is a pointer to a stack reg RTX, with an RTX for 84250397Sobrien the desired hard REGNO. */ 84318334Speter 84418334Speterstatic void 84518334Speterreplace_reg (reg, regno) 84618334Speter rtx *reg; 84718334Speter int regno; 84818334Speter{ 84918334Speter if (regno < FIRST_STACK_REG || regno > LAST_STACK_REG 85018334Speter || ! STACK_REG_P (*reg)) 85118334Speter abort (); 85218334Speter 85318334Speter switch (GET_MODE_CLASS (GET_MODE (*reg))) 85490075Sobrien { 85590075Sobrien default: abort (); 85690075Sobrien case MODE_FLOAT: 85790075Sobrien case MODE_COMPLEX_FLOAT:; 85890075Sobrien } 85918334Speter 86018334Speter *reg = FP_MODE_REG (regno, GET_MODE (*reg)); 86118334Speter} 86218334Speter 86318334Speter/* Remove a note of type NOTE, which must be found, for register 86450397Sobrien number REGNO from INSN. Remove only one such note. */ 86518334Speter 86618334Speterstatic void 86718334Speterremove_regno_note (insn, note, regno) 86818334Speter rtx insn; 86918334Speter enum reg_note note; 87090075Sobrien unsigned int regno; 87118334Speter{ 87290075Sobrien rtx *note_link, this; 87318334Speter 87490075Sobrien note_link = ®_NOTES (insn); 87518334Speter for (this = *note_link; this; this = XEXP (this, 1)) 87618334Speter if (REG_NOTE_KIND (this) == note 87718334Speter && REG_P (XEXP (this, 0)) && REGNO (XEXP (this, 0)) == regno) 87818334Speter { 87918334Speter *note_link = XEXP (this, 1); 88018334Speter return; 88118334Speter } 88218334Speter else 88318334Speter note_link = &XEXP (this, 1); 88418334Speter 88518334Speter abort (); 88618334Speter} 88718334Speter 88818334Speter/* Find the hard register number of virtual register REG in REGSTACK. 88918334Speter The hard register number is relative to the top of the stack. -1 is 89050397Sobrien returned if the register is not found. */ 89118334Speter 89218334Speterstatic int 89318334Speterget_hard_regnum (regstack, reg) 89418334Speter stack regstack; 89518334Speter rtx reg; 89618334Speter{ 89718334Speter int i; 89818334Speter 89918334Speter if (! STACK_REG_P (reg)) 90018334Speter abort (); 90118334Speter 90218334Speter for (i = regstack->top; i >= 0; i--) 90318334Speter if (regstack->reg[i] == REGNO (reg)) 90418334Speter break; 90518334Speter 90618334Speter return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1; 90718334Speter} 90818334Speter 90918334Speter/* Emit an insn to pop virtual register REG before or after INSN. 91018334Speter REGSTACK is the stack state after INSN and is updated to reflect this 91190075Sobrien pop. WHEN is either emit_insn_before or emit_insn_after. A pop insn 91290075Sobrien is represented as a SET whose destination is the register to be popped 91390075Sobrien and source is the top of stack. A death note for the top of stack 91450397Sobrien cases the movdf pattern to pop. */ 91518334Speter 91618334Speterstatic rtx 91790075Sobrienemit_pop_insn (insn, regstack, reg, where) 91818334Speter rtx insn; 91918334Speter stack regstack; 92018334Speter rtx reg; 92190075Sobrien enum emit_where where; 92218334Speter{ 92318334Speter rtx pop_insn, pop_rtx; 92418334Speter int hard_regno; 92518334Speter 92690075Sobrien /* For complex types take care to pop both halves. These may survive in 92790075Sobrien CLOBBER and USE expressions. */ 92890075Sobrien if (COMPLEX_MODE_P (GET_MODE (reg))) 92990075Sobrien { 93090075Sobrien rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode); 93190075Sobrien rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode); 93290075Sobrien 93390075Sobrien pop_insn = NULL_RTX; 93490075Sobrien if (get_hard_regnum (regstack, reg1) >= 0) 93590075Sobrien pop_insn = emit_pop_insn (insn, regstack, reg1, where); 93690075Sobrien if (get_hard_regnum (regstack, reg2) >= 0) 93790075Sobrien pop_insn = emit_pop_insn (insn, regstack, reg2, where); 93890075Sobrien if (!pop_insn) 93990075Sobrien abort (); 94090075Sobrien return pop_insn; 94190075Sobrien } 94290075Sobrien 94318334Speter hard_regno = get_hard_regnum (regstack, reg); 94418334Speter 94518334Speter if (hard_regno < FIRST_STACK_REG) 94618334Speter abort (); 94718334Speter 94890075Sobrien pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode), 94990075Sobrien FP_MODE_REG (FIRST_STACK_REG, DFmode)); 95018334Speter 95190075Sobrien if (where == EMIT_AFTER) 95290075Sobrien pop_insn = emit_insn_after (pop_rtx, insn); 95390075Sobrien else 95490075Sobrien pop_insn = emit_insn_before (pop_rtx, insn); 95518334Speter 95690075Sobrien REG_NOTES (pop_insn) 95790075Sobrien = gen_rtx_EXPR_LIST (REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode), 95890075Sobrien REG_NOTES (pop_insn)); 95918334Speter 96018334Speter regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)] 96118334Speter = regstack->reg[regstack->top]; 96218334Speter regstack->top -= 1; 96318334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (reg)); 96418334Speter 96518334Speter return pop_insn; 96618334Speter} 96718334Speter 96890075Sobrien/* Emit an insn before or after INSN to swap virtual register REG with 96990075Sobrien the top of stack. REGSTACK is the stack state before the swap, and 97090075Sobrien is updated to reflect the swap. A swap insn is represented as a 97190075Sobrien PARALLEL of two patterns: each pattern moves one reg to the other. 97218334Speter 97350397Sobrien If REG is already at the top of the stack, no insn is emitted. */ 97418334Speter 97518334Speterstatic void 97618334Speteremit_swap_insn (insn, regstack, reg) 97718334Speter rtx insn; 97818334Speter stack regstack; 97918334Speter rtx reg; 98018334Speter{ 98118334Speter int hard_regno; 98290075Sobrien rtx swap_rtx; 98318334Speter int tmp, other_reg; /* swap regno temps */ 98418334Speter rtx i1; /* the stack-reg insn prior to INSN */ 98518334Speter rtx i1set = NULL_RTX; /* the SET rtx within I1 */ 98618334Speter 98718334Speter hard_regno = get_hard_regnum (regstack, reg); 98818334Speter 98918334Speter if (hard_regno < FIRST_STACK_REG) 99018334Speter abort (); 99118334Speter if (hard_regno == FIRST_STACK_REG) 99218334Speter return; 99318334Speter 99418334Speter other_reg = regstack->top - (hard_regno - FIRST_STACK_REG); 99518334Speter 99618334Speter tmp = regstack->reg[other_reg]; 99718334Speter regstack->reg[other_reg] = regstack->reg[regstack->top]; 99818334Speter regstack->reg[regstack->top] = tmp; 99918334Speter 100090075Sobrien /* Find the previous insn involving stack regs, but don't pass a 100190075Sobrien block boundary. */ 100290075Sobrien i1 = NULL; 100390075Sobrien if (current_block && insn != current_block->head) 100490075Sobrien { 100590075Sobrien rtx tmp = PREV_INSN (insn); 100690075Sobrien rtx limit = PREV_INSN (current_block->head); 100790075Sobrien while (tmp != limit) 100890075Sobrien { 100990075Sobrien if (GET_CODE (tmp) == CODE_LABEL 101090075Sobrien || GET_CODE (tmp) == CALL_INSN 101190075Sobrien || NOTE_INSN_BASIC_BLOCK_P (tmp) 101290075Sobrien || (GET_CODE (tmp) == INSN 101390075Sobrien && stack_regs_mentioned (tmp))) 101490075Sobrien { 101590075Sobrien i1 = tmp; 101690075Sobrien break; 101790075Sobrien } 101890075Sobrien tmp = PREV_INSN (tmp); 101990075Sobrien } 102090075Sobrien } 102118334Speter 102290075Sobrien if (i1 != NULL_RTX 102390075Sobrien && (i1set = single_set (i1)) != NULL_RTX) 102418334Speter { 102518334Speter rtx i1src = *get_true_reg (&SET_SRC (i1set)); 102618334Speter rtx i1dest = *get_true_reg (&SET_DEST (i1set)); 102718334Speter 102818334Speter /* If the previous register stack push was from the reg we are to 102950397Sobrien swap with, omit the swap. */ 103018334Speter 103118334Speter if (GET_CODE (i1dest) == REG && REGNO (i1dest) == FIRST_STACK_REG 103290075Sobrien && GET_CODE (i1src) == REG 103390075Sobrien && REGNO (i1src) == (unsigned) hard_regno - 1 103418334Speter && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX) 103518334Speter return; 103618334Speter 103718334Speter /* If the previous insn wrote to the reg we are to swap with, 103818334Speter omit the swap. */ 103918334Speter 104090075Sobrien if (GET_CODE (i1dest) == REG && REGNO (i1dest) == (unsigned) hard_regno 104118334Speter && GET_CODE (i1src) == REG && REGNO (i1src) == FIRST_STACK_REG 104218334Speter && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX) 104318334Speter return; 104418334Speter } 104518334Speter 104690075Sobrien swap_rtx = gen_swapxf (FP_MODE_REG (hard_regno, XFmode), 104790075Sobrien FP_MODE_REG (FIRST_STACK_REG, XFmode)); 104818334Speter 104990075Sobrien if (i1) 105090075Sobrien emit_insn_after (swap_rtx, i1); 105190075Sobrien else if (current_block) 105290075Sobrien emit_insn_before (swap_rtx, current_block->head); 105390075Sobrien else 105490075Sobrien emit_insn_before (swap_rtx, insn); 105518334Speter} 105618334Speter 105718334Speter/* Handle a move to or from a stack register in PAT, which is in INSN. 105850397Sobrien REGSTACK is the current stack. */ 105918334Speter 106018334Speterstatic void 106118334Spetermove_for_stack_reg (insn, regstack, pat) 106218334Speter rtx insn; 106318334Speter stack regstack; 106418334Speter rtx pat; 106518334Speter{ 106618334Speter rtx *psrc = get_true_reg (&SET_SRC (pat)); 106718334Speter rtx *pdest = get_true_reg (&SET_DEST (pat)); 106818334Speter rtx src, dest; 106918334Speter rtx note; 107018334Speter 107118334Speter src = *psrc; dest = *pdest; 107218334Speter 107318334Speter if (STACK_REG_P (src) && STACK_REG_P (dest)) 107418334Speter { 107518334Speter /* Write from one stack reg to another. If SRC dies here, then 107650397Sobrien just change the register mapping and delete the insn. */ 107718334Speter 107818334Speter note = find_regno_note (insn, REG_DEAD, REGNO (src)); 107918334Speter if (note) 108018334Speter { 108118334Speter int i; 108218334Speter 108350397Sobrien /* If this is a no-op move, there must not be a REG_DEAD note. */ 108418334Speter if (REGNO (src) == REGNO (dest)) 108518334Speter abort (); 108618334Speter 108718334Speter for (i = regstack->top; i >= 0; i--) 108818334Speter if (regstack->reg[i] == REGNO (src)) 108918334Speter break; 109018334Speter 109150397Sobrien /* The source must be live, and the dest must be dead. */ 109218334Speter if (i < 0 || get_hard_regnum (regstack, dest) >= FIRST_STACK_REG) 109318334Speter abort (); 109418334Speter 109518334Speter /* It is possible that the dest is unused after this insn. 109650397Sobrien If so, just pop the src. */ 109718334Speter 109818334Speter if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) 109918334Speter { 110090075Sobrien emit_pop_insn (insn, regstack, src, EMIT_AFTER); 110118334Speter 110290075Sobrien delete_insn (insn); 110318334Speter return; 110418334Speter } 110518334Speter 110618334Speter regstack->reg[i] = REGNO (dest); 110718334Speter 110818334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); 110918334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); 111018334Speter 111190075Sobrien delete_insn (insn); 111218334Speter 111318334Speter return; 111418334Speter } 111518334Speter 111650397Sobrien /* The source reg does not die. */ 111718334Speter 111818334Speter /* If this appears to be a no-op move, delete it, or else it 111918334Speter will confuse the machine description output patterns. But if 112018334Speter it is REG_UNUSED, we must pop the reg now, as per-insn processing 112150397Sobrien for REG_UNUSED will not work for deleted insns. */ 112218334Speter 112318334Speter if (REGNO (src) == REGNO (dest)) 112418334Speter { 112518334Speter if (find_regno_note (insn, REG_UNUSED, REGNO (dest))) 112690075Sobrien emit_pop_insn (insn, regstack, dest, EMIT_AFTER); 112718334Speter 112890075Sobrien delete_insn (insn); 112918334Speter return; 113018334Speter } 113118334Speter 113218334Speter /* The destination ought to be dead */ 113318334Speter if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG) 113418334Speter abort (); 113518334Speter 113618334Speter replace_reg (psrc, get_hard_regnum (regstack, src)); 113718334Speter 113818334Speter regstack->reg[++regstack->top] = REGNO (dest); 113918334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); 114018334Speter replace_reg (pdest, FIRST_STACK_REG); 114118334Speter } 114218334Speter else if (STACK_REG_P (src)) 114318334Speter { 114418334Speter /* Save from a stack reg to MEM, or possibly integer reg. Since 114518334Speter only top of stack may be saved, emit an exchange first if 114650397Sobrien needs be. */ 114718334Speter 114818334Speter emit_swap_insn (insn, regstack, src); 114918334Speter 115018334Speter note = find_regno_note (insn, REG_DEAD, REGNO (src)); 115118334Speter if (note) 115218334Speter { 115318334Speter replace_reg (&XEXP (note, 0), FIRST_STACK_REG); 115418334Speter regstack->top--; 115518334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src)); 115618334Speter } 115790075Sobrien else if ((GET_MODE (src) == XFmode || GET_MODE (src) == TFmode) 115890075Sobrien && regstack->top < REG_STACK_SIZE - 1) 115918334Speter { 116018334Speter /* A 387 cannot write an XFmode value to a MEM without 116118334Speter clobbering the source reg. The output code can handle 116218334Speter this by reading back the value from the MEM. 116318334Speter But it is more efficient to use a temp register if one is 116418334Speter available. Push the source value here if the register 116518334Speter stack is not full, and then write the value to memory via 116618334Speter a pop. */ 116718334Speter rtx push_rtx, push_insn; 116890075Sobrien rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, GET_MODE (src)); 116918334Speter 117090075Sobrien if (GET_MODE (src) == TFmode) 117190075Sobrien push_rtx = gen_movtf (top_stack_reg, top_stack_reg); 117290075Sobrien else 117390075Sobrien push_rtx = gen_movxf (top_stack_reg, top_stack_reg); 117418334Speter push_insn = emit_insn_before (push_rtx, insn); 117550397Sobrien REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg, 117650397Sobrien REG_NOTES (insn)); 117718334Speter } 117818334Speter 117918334Speter replace_reg (psrc, FIRST_STACK_REG); 118018334Speter } 118118334Speter else if (STACK_REG_P (dest)) 118218334Speter { 118318334Speter /* Load from MEM, or possibly integer REG or constant, into the 118418334Speter stack regs. The actual target is always the top of the 118518334Speter stack. The stack mapping is changed to reflect that DEST is 118618334Speter now at top of stack. */ 118718334Speter 118818334Speter /* The destination ought to be dead */ 118918334Speter if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG) 119018334Speter abort (); 119118334Speter 119218334Speter if (regstack->top >= REG_STACK_SIZE) 119318334Speter abort (); 119418334Speter 119518334Speter regstack->reg[++regstack->top] = REGNO (dest); 119618334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest)); 119718334Speter replace_reg (pdest, FIRST_STACK_REG); 119818334Speter } 119918334Speter else 120018334Speter abort (); 120118334Speter} 120218334Speter 120390075Sobrien/* Swap the condition on a branch, if there is one. Return true if we 120490075Sobrien found a condition to swap. False if the condition was not used as 120590075Sobrien such. */ 120690075Sobrien 120790075Sobrienstatic int 120890075Sobrienswap_rtx_condition_1 (pat) 120918334Speter rtx pat; 121018334Speter{ 121190075Sobrien const char *fmt; 121290075Sobrien int i, r = 0; 121318334Speter 121418334Speter if (GET_RTX_CLASS (GET_CODE (pat)) == '<') 121518334Speter { 121618334Speter PUT_CODE (pat, swap_condition (GET_CODE (pat))); 121790075Sobrien r = 1; 121818334Speter } 121990075Sobrien else 122090075Sobrien { 122190075Sobrien fmt = GET_RTX_FORMAT (GET_CODE (pat)); 122290075Sobrien for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--) 122390075Sobrien { 122490075Sobrien if (fmt[i] == 'E') 122590075Sobrien { 122690075Sobrien int j; 122718334Speter 122890075Sobrien for (j = XVECLEN (pat, i) - 1; j >= 0; j--) 122990075Sobrien r |= swap_rtx_condition_1 (XVECEXP (pat, i, j)); 123090075Sobrien } 123190075Sobrien else if (fmt[i] == 'e') 123290075Sobrien r |= swap_rtx_condition_1 (XEXP (pat, i)); 123390075Sobrien } 123490075Sobrien } 123590075Sobrien 123690075Sobrien return r; 123790075Sobrien} 123890075Sobrien 123990075Sobrienstatic int 124090075Sobrienswap_rtx_condition (insn) 124190075Sobrien rtx insn; 124290075Sobrien{ 124390075Sobrien rtx pat = PATTERN (insn); 124490075Sobrien 124590075Sobrien /* We're looking for a single set to cc0 or an HImode temporary. */ 124690075Sobrien 124790075Sobrien if (GET_CODE (pat) == SET 124890075Sobrien && GET_CODE (SET_DEST (pat)) == REG 124990075Sobrien && REGNO (SET_DEST (pat)) == FLAGS_REG) 125018334Speter { 125190075Sobrien insn = next_flags_user (insn); 125290075Sobrien if (insn == NULL_RTX) 125390075Sobrien return 0; 125490075Sobrien pat = PATTERN (insn); 125590075Sobrien } 125690075Sobrien 125790075Sobrien /* See if this is, or ends in, a fnstsw, aka unspec 9. If so, we're 125890075Sobrien not doing anything with the cc value right now. We may be able to 125990075Sobrien search for one though. */ 126090075Sobrien 126190075Sobrien if (GET_CODE (pat) == SET 126290075Sobrien && GET_CODE (SET_SRC (pat)) == UNSPEC 126390075Sobrien && XINT (SET_SRC (pat), 1) == 9) 126490075Sobrien { 126590075Sobrien rtx dest = SET_DEST (pat); 126690075Sobrien 126790075Sobrien /* Search forward looking for the first use of this value. 126890075Sobrien Stop at block boundaries. */ 126990075Sobrien while (insn != current_block->end) 127018334Speter { 127190075Sobrien insn = NEXT_INSN (insn); 127290075Sobrien if (INSN_P (insn) && reg_mentioned_p (dest, insn)) 127390075Sobrien break; 127490075Sobrien if (GET_CODE (insn) == CALL_INSN) 127590075Sobrien return 0; 127690075Sobrien } 127718334Speter 127890075Sobrien /* So we've found the insn using this value. If it is anything 127990075Sobrien other than sahf, aka unspec 10, or the value does not die 128090075Sobrien (meaning we'd have to search further), then we must give up. */ 128190075Sobrien pat = PATTERN (insn); 128290075Sobrien if (GET_CODE (pat) != SET 128390075Sobrien || GET_CODE (SET_SRC (pat)) != UNSPEC 128490075Sobrien || XINT (SET_SRC (pat), 1) != 10 128590075Sobrien || ! dead_or_set_p (insn, dest)) 128690075Sobrien return 0; 128790075Sobrien 128890075Sobrien /* Now we are prepared to handle this as a normal cc0 setter. */ 128990075Sobrien insn = next_flags_user (insn); 129090075Sobrien if (insn == NULL_RTX) 129190075Sobrien return 0; 129290075Sobrien pat = PATTERN (insn); 129390075Sobrien } 129490075Sobrien 129590075Sobrien if (swap_rtx_condition_1 (pat)) 129690075Sobrien { 129790075Sobrien int fail = 0; 129890075Sobrien INSN_CODE (insn) = -1; 129990075Sobrien if (recog_memoized (insn) == -1) 130090075Sobrien fail = 1; 130190075Sobrien /* In case the flags don't die here, recurse to try fix 130290075Sobrien following user too. */ 130390075Sobrien else if (! dead_or_set_p (insn, ix86_flags_rtx)) 130490075Sobrien { 130590075Sobrien insn = next_flags_user (insn); 130690075Sobrien if (!insn || !swap_rtx_condition (insn)) 130790075Sobrien fail = 1; 130818334Speter } 130990075Sobrien if (fail) 131090075Sobrien { 131190075Sobrien swap_rtx_condition_1 (pat); 131290075Sobrien return 0; 131390075Sobrien } 131490075Sobrien return 1; 131518334Speter } 131690075Sobrien return 0; 131718334Speter} 131818334Speter 131918334Speter/* Handle a comparison. Special care needs to be taken to avoid 132018334Speter causing comparisons that a 387 cannot do correctly, such as EQ. 132118334Speter 132290075Sobrien Also, a pop insn may need to be emitted. The 387 does have an 132318334Speter `fcompp' insn that can pop two regs, but it is sometimes too expensive 132418334Speter to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to 132590075Sobrien set up. */ 132618334Speter 132718334Speterstatic void 132890075Sobriencompare_for_stack_reg (insn, regstack, pat_src) 132918334Speter rtx insn; 133018334Speter stack regstack; 133190075Sobrien rtx pat_src; 133218334Speter{ 133318334Speter rtx *src1, *src2; 133418334Speter rtx src1_note, src2_note; 133590075Sobrien rtx flags_user; 133618334Speter 133790075Sobrien src1 = get_true_reg (&XEXP (pat_src, 0)); 133890075Sobrien src2 = get_true_reg (&XEXP (pat_src, 1)); 133990075Sobrien flags_user = next_flags_user (insn); 134018334Speter 134118334Speter /* ??? If fxch turns out to be cheaper than fstp, give priority to 134250397Sobrien registers that die in this insn - move those to stack top first. */ 134390075Sobrien if ((! STACK_REG_P (*src1) 134490075Sobrien || (STACK_REG_P (*src2) 134590075Sobrien && get_hard_regnum (regstack, *src2) == FIRST_STACK_REG)) 134690075Sobrien && swap_rtx_condition (insn)) 134718334Speter { 134890075Sobrien rtx temp; 134990075Sobrien temp = XEXP (pat_src, 0); 135090075Sobrien XEXP (pat_src, 0) = XEXP (pat_src, 1); 135190075Sobrien XEXP (pat_src, 1) = temp; 135218334Speter 135390075Sobrien src1 = get_true_reg (&XEXP (pat_src, 0)); 135490075Sobrien src2 = get_true_reg (&XEXP (pat_src, 1)); 135518334Speter 135618334Speter INSN_CODE (insn) = -1; 135718334Speter } 135818334Speter 135950397Sobrien /* We will fix any death note later. */ 136018334Speter 136118334Speter src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 136218334Speter 136318334Speter if (STACK_REG_P (*src2)) 136418334Speter src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); 136518334Speter else 136618334Speter src2_note = NULL_RTX; 136718334Speter 136890075Sobrien emit_swap_insn (insn, regstack, *src1); 136918334Speter 137018334Speter replace_reg (src1, FIRST_STACK_REG); 137118334Speter 137218334Speter if (STACK_REG_P (*src2)) 137390075Sobrien replace_reg (src2, get_hard_regnum (regstack, *src2)); 137418334Speter 137518334Speter if (src1_note) 137618334Speter { 137750397Sobrien pop_stack (regstack, REGNO (XEXP (src1_note, 0))); 137818334Speter replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 137918334Speter } 138018334Speter 138118334Speter /* If the second operand dies, handle that. But if the operands are 138218334Speter the same stack register, don't bother, because only one death is 138350397Sobrien needed, and it was just handled. */ 138418334Speter 138518334Speter if (src2_note 138618334Speter && ! (STACK_REG_P (*src1) && STACK_REG_P (*src2) 138718334Speter && REGNO (*src1) == REGNO (*src2))) 138818334Speter { 138918334Speter /* As a special case, two regs may die in this insn if src2 is 139018334Speter next to top of stack and the top of stack also dies. Since 139118334Speter we have already popped src1, "next to top of stack" is really 139250397Sobrien at top (FIRST_STACK_REG) now. */ 139318334Speter 139418334Speter if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG 139518334Speter && src1_note) 139618334Speter { 139750397Sobrien pop_stack (regstack, REGNO (XEXP (src2_note, 0))); 139818334Speter replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1); 139918334Speter } 140018334Speter else 140118334Speter { 140290075Sobrien /* The 386 can only represent death of the first operand in 140390075Sobrien the case handled above. In all other cases, emit a separate 140490075Sobrien pop and remove the death note from here. */ 140518334Speter 140690075Sobrien /* link_cc0_insns (insn); */ 140790075Sobrien 140890075Sobrien remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0))); 140990075Sobrien 141090075Sobrien emit_pop_insn (insn, regstack, XEXP (src2_note, 0), 141190075Sobrien EMIT_AFTER); 141218334Speter } 141318334Speter } 141418334Speter} 141518334Speter 141618334Speter/* Substitute new registers in PAT, which is part of INSN. REGSTACK 141750397Sobrien is the current register layout. */ 141818334Speter 141918334Speterstatic void 142018334Spetersubst_stack_regs_pat (insn, regstack, pat) 142118334Speter rtx insn; 142218334Speter stack regstack; 142318334Speter rtx pat; 142418334Speter{ 142518334Speter rtx *dest, *src; 142618334Speter 142790075Sobrien switch (GET_CODE (pat)) 142890075Sobrien { 142990075Sobrien case USE: 143090075Sobrien /* Deaths in USE insns can happen in non optimizing compilation. 143190075Sobrien Handle them by popping the dying register. */ 143290075Sobrien src = get_true_reg (&XEXP (pat, 0)); 143390075Sobrien if (STACK_REG_P (*src) 143490075Sobrien && find_regno_note (insn, REG_DEAD, REGNO (*src))) 143590075Sobrien { 143690075Sobrien emit_pop_insn (insn, regstack, *src, EMIT_AFTER); 143790075Sobrien return; 143890075Sobrien } 143990075Sobrien /* ??? Uninitialized USE should not happen. */ 144090075Sobrien else if (get_hard_regnum (regstack, *src) == -1) 144190075Sobrien abort (); 144290075Sobrien break; 144318334Speter 144490075Sobrien case CLOBBER: 144590075Sobrien { 144690075Sobrien rtx note; 144718334Speter 144890075Sobrien dest = get_true_reg (&XEXP (pat, 0)); 144990075Sobrien if (STACK_REG_P (*dest)) 145090075Sobrien { 145190075Sobrien note = find_reg_note (insn, REG_DEAD, *dest); 145218334Speter 145390075Sobrien if (pat != PATTERN (insn)) 145490075Sobrien { 145590075Sobrien /* The fix_truncdi_1 pattern wants to be able to allocate 145690075Sobrien it's own scratch register. It does this by clobbering 145790075Sobrien an fp reg so that it is assured of an empty reg-stack 145890075Sobrien register. If the register is live, kill it now. 145990075Sobrien Remove the DEAD/UNUSED note so we don't try to kill it 146090075Sobrien later too. */ 146190075Sobrien 146290075Sobrien if (note) 146390075Sobrien emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE); 146490075Sobrien else 146590075Sobrien { 146690075Sobrien note = find_reg_note (insn, REG_UNUSED, *dest); 146790075Sobrien if (!note) 146890075Sobrien abort (); 146990075Sobrien } 147090075Sobrien remove_note (insn, note); 147190075Sobrien replace_reg (dest, LAST_STACK_REG); 147290075Sobrien } 147390075Sobrien else 147490075Sobrien { 147590075Sobrien /* A top-level clobber with no REG_DEAD, and no hard-regnum 147690075Sobrien indicates an uninitialized value. Because reload removed 147790075Sobrien all other clobbers, this must be due to a function 147890075Sobrien returning without a value. Load up a NaN. */ 147990075Sobrien 148090075Sobrien if (! note 148190075Sobrien && get_hard_regnum (regstack, *dest) == -1) 148290075Sobrien { 148390075Sobrien pat = gen_rtx_SET (VOIDmode, 148490075Sobrien FP_MODE_REG (REGNO (*dest), SFmode), 148590075Sobrien nan); 148690075Sobrien PATTERN (insn) = pat; 148790075Sobrien move_for_stack_reg (insn, regstack, pat); 148890075Sobrien } 148990075Sobrien if (! note && COMPLEX_MODE_P (GET_MODE (*dest)) 149090075Sobrien && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1) 149190075Sobrien { 149290075Sobrien pat = gen_rtx_SET (VOIDmode, 149390075Sobrien FP_MODE_REG (REGNO (*dest) + 1, SFmode), 149490075Sobrien nan); 149590075Sobrien PATTERN (insn) = pat; 149690075Sobrien move_for_stack_reg (insn, regstack, pat); 149790075Sobrien } 149890075Sobrien } 149990075Sobrien } 150018334Speter break; 150190075Sobrien } 150218334Speter 150390075Sobrien case SET: 150490075Sobrien { 150590075Sobrien rtx *src1 = (rtx *) 0, *src2; 150690075Sobrien rtx src1_note, src2_note; 150790075Sobrien rtx pat_src; 150890075Sobrien 150990075Sobrien dest = get_true_reg (&SET_DEST (pat)); 151090075Sobrien src = get_true_reg (&SET_SRC (pat)); 151190075Sobrien pat_src = SET_SRC (pat); 151290075Sobrien 151390075Sobrien /* See if this is a `movM' pattern, and handle elsewhere if so. */ 151490075Sobrien if (STACK_REG_P (*src) 151590075Sobrien || (STACK_REG_P (*dest) 151690075Sobrien && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM 151790075Sobrien || GET_CODE (*src) == CONST_DOUBLE))) 151890075Sobrien { 151990075Sobrien move_for_stack_reg (insn, regstack, pat); 152090075Sobrien break; 152190075Sobrien } 152290075Sobrien 152390075Sobrien switch (GET_CODE (pat_src)) 152490075Sobrien { 152590075Sobrien case COMPARE: 152690075Sobrien compare_for_stack_reg (insn, regstack, pat_src); 152790075Sobrien break; 152890075Sobrien 152990075Sobrien case CALL: 153018334Speter { 153190075Sobrien int count; 153290075Sobrien for (count = HARD_REGNO_NREGS (REGNO (*dest), GET_MODE (*dest)); 153390075Sobrien --count >= 0;) 153490075Sobrien { 153590075Sobrien regstack->reg[++regstack->top] = REGNO (*dest) + count; 153690075Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count); 153790075Sobrien } 153818334Speter } 153990075Sobrien replace_reg (dest, FIRST_STACK_REG); 154090075Sobrien break; 154118334Speter 154290075Sobrien case REG: 154390075Sobrien /* This is a `tstM2' case. */ 154490075Sobrien if (*dest != cc0_rtx) 154590075Sobrien abort (); 154690075Sobrien src1 = src; 154718334Speter 154890075Sobrien /* Fall through. */ 154918334Speter 155090075Sobrien case FLOAT_TRUNCATE: 155190075Sobrien case SQRT: 155290075Sobrien case ABS: 155390075Sobrien case NEG: 155490075Sobrien /* These insns only operate on the top of the stack. DEST might 155590075Sobrien be cc0_rtx if we're processing a tstM pattern. Also, it's 155690075Sobrien possible that the tstM case results in a REG_DEAD note on the 155790075Sobrien source. */ 155818334Speter 155990075Sobrien if (src1 == 0) 156090075Sobrien src1 = get_true_reg (&XEXP (pat_src, 0)); 156118334Speter 156290075Sobrien emit_swap_insn (insn, regstack, *src1); 156318334Speter 156490075Sobrien src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 156518334Speter 156690075Sobrien if (STACK_REG_P (*dest)) 156790075Sobrien replace_reg (dest, FIRST_STACK_REG); 156818334Speter 156990075Sobrien if (src1_note) 157090075Sobrien { 157190075Sobrien replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 157290075Sobrien regstack->top--; 157390075Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1)); 157490075Sobrien } 157518334Speter 157690075Sobrien replace_reg (src1, FIRST_STACK_REG); 157790075Sobrien break; 157818334Speter 157990075Sobrien case MINUS: 158090075Sobrien case DIV: 158190075Sobrien /* On i386, reversed forms of subM3 and divM3 exist for 158290075Sobrien MODE_FLOAT, so the same code that works for addM3 and mulM3 158390075Sobrien can be used. */ 158490075Sobrien case MULT: 158590075Sobrien case PLUS: 158690075Sobrien /* These insns can accept the top of stack as a destination 158790075Sobrien from a stack reg or mem, or can use the top of stack as a 158890075Sobrien source and some other stack register (possibly top of stack) 158990075Sobrien as a destination. */ 159018334Speter 159190075Sobrien src1 = get_true_reg (&XEXP (pat_src, 0)); 159290075Sobrien src2 = get_true_reg (&XEXP (pat_src, 1)); 159318334Speter 159490075Sobrien /* We will fix any death note later. */ 159518334Speter 159690075Sobrien if (STACK_REG_P (*src1)) 159790075Sobrien src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 159890075Sobrien else 159990075Sobrien src1_note = NULL_RTX; 160090075Sobrien if (STACK_REG_P (*src2)) 160190075Sobrien src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); 160290075Sobrien else 160390075Sobrien src2_note = NULL_RTX; 160418334Speter 160590075Sobrien /* If either operand is not a stack register, then the dest 160690075Sobrien must be top of stack. */ 160718334Speter 160890075Sobrien if (! STACK_REG_P (*src1) || ! STACK_REG_P (*src2)) 160990075Sobrien emit_swap_insn (insn, regstack, *dest); 161090075Sobrien else 161190075Sobrien { 161290075Sobrien /* Both operands are REG. If neither operand is already 161390075Sobrien at the top of stack, choose to make the one that is the dest 161490075Sobrien the new top of stack. */ 161518334Speter 161690075Sobrien int src1_hard_regnum, src2_hard_regnum; 161718334Speter 161890075Sobrien src1_hard_regnum = get_hard_regnum (regstack, *src1); 161990075Sobrien src2_hard_regnum = get_hard_regnum (regstack, *src2); 162090075Sobrien if (src1_hard_regnum == -1 || src2_hard_regnum == -1) 162190075Sobrien abort (); 162218334Speter 162390075Sobrien if (src1_hard_regnum != FIRST_STACK_REG 162490075Sobrien && src2_hard_regnum != FIRST_STACK_REG) 162590075Sobrien emit_swap_insn (insn, regstack, *dest); 162690075Sobrien } 162718334Speter 162890075Sobrien if (STACK_REG_P (*src1)) 162990075Sobrien replace_reg (src1, get_hard_regnum (regstack, *src1)); 163090075Sobrien if (STACK_REG_P (*src2)) 163190075Sobrien replace_reg (src2, get_hard_regnum (regstack, *src2)); 163218334Speter 163390075Sobrien if (src1_note) 163490075Sobrien { 163590075Sobrien rtx src1_reg = XEXP (src1_note, 0); 163618334Speter 163790075Sobrien /* If the register that dies is at the top of stack, then 163890075Sobrien the destination is somewhere else - merely substitute it. 163990075Sobrien But if the reg that dies is not at top of stack, then 164090075Sobrien move the top of stack to the dead reg, as though we had 164190075Sobrien done the insn and then a store-with-pop. */ 164218334Speter 164390075Sobrien if (REGNO (src1_reg) == regstack->reg[regstack->top]) 164490075Sobrien { 164590075Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 164690075Sobrien replace_reg (dest, get_hard_regnum (regstack, *dest)); 164790075Sobrien } 164890075Sobrien else 164990075Sobrien { 165090075Sobrien int regno = get_hard_regnum (regstack, src1_reg); 165118334Speter 165290075Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 165390075Sobrien replace_reg (dest, regno); 165490075Sobrien 165590075Sobrien regstack->reg[regstack->top - (regno - FIRST_STACK_REG)] 165690075Sobrien = regstack->reg[regstack->top]; 165790075Sobrien } 165890075Sobrien 165990075Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, 166090075Sobrien REGNO (XEXP (src1_note, 0))); 166190075Sobrien replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 166290075Sobrien regstack->top--; 166318334Speter } 166490075Sobrien else if (src2_note) 166518334Speter { 166690075Sobrien rtx src2_reg = XEXP (src2_note, 0); 166790075Sobrien if (REGNO (src2_reg) == regstack->reg[regstack->top]) 166890075Sobrien { 166990075Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 167090075Sobrien replace_reg (dest, get_hard_regnum (regstack, *dest)); 167190075Sobrien } 167290075Sobrien else 167390075Sobrien { 167490075Sobrien int regno = get_hard_regnum (regstack, src2_reg); 167518334Speter 167690075Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 167790075Sobrien replace_reg (dest, regno); 167818334Speter 167990075Sobrien regstack->reg[regstack->top - (regno - FIRST_STACK_REG)] 168090075Sobrien = regstack->reg[regstack->top]; 168190075Sobrien } 168290075Sobrien 168390075Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, 168490075Sobrien REGNO (XEXP (src2_note, 0))); 168590075Sobrien replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG); 168690075Sobrien regstack->top--; 168718334Speter } 168890075Sobrien else 168918334Speter { 169018334Speter SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 169118334Speter replace_reg (dest, get_hard_regnum (regstack, *dest)); 169218334Speter } 169390075Sobrien 169490075Sobrien /* Keep operand 1 maching with destination. */ 169590075Sobrien if (GET_RTX_CLASS (GET_CODE (pat_src)) == 'c' 169690075Sobrien && REG_P (*src1) && REG_P (*src2) 169790075Sobrien && REGNO (*src1) != REGNO (*dest)) 169890075Sobrien { 169990075Sobrien int tmp = REGNO (*src1); 170090075Sobrien replace_reg (src1, REGNO (*src2)); 170190075Sobrien replace_reg (src2, tmp); 170290075Sobrien } 170390075Sobrien break; 170490075Sobrien 170590075Sobrien case UNSPEC: 170690075Sobrien switch (XINT (pat_src, 1)) 170718334Speter { 170890075Sobrien case 1: /* sin */ 170990075Sobrien case 2: /* cos */ 171090075Sobrien /* These insns only operate on the top of the stack. */ 171118334Speter 171290075Sobrien src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); 171318334Speter 171490075Sobrien emit_swap_insn (insn, regstack, *src1); 171518334Speter 171690075Sobrien src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 171718334Speter 171890075Sobrien if (STACK_REG_P (*dest)) 171990075Sobrien replace_reg (dest, FIRST_STACK_REG); 172018334Speter 172190075Sobrien if (src1_note) 172290075Sobrien { 172390075Sobrien replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG); 172490075Sobrien regstack->top--; 172590075Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1)); 172690075Sobrien } 172718334Speter 172890075Sobrien replace_reg (src1, FIRST_STACK_REG); 172990075Sobrien break; 173018334Speter 173190075Sobrien case 10: 173290075Sobrien /* (unspec [(unspec [(compare ..)] 9)] 10) 173390075Sobrien Unspec 9 is fnstsw; unspec 10 is sahf. The combination 173490075Sobrien matches the PPRO fcomi instruction. */ 173518334Speter 173690075Sobrien pat_src = XVECEXP (pat_src, 0, 0); 173790075Sobrien if (GET_CODE (pat_src) != UNSPEC 173890075Sobrien || XINT (pat_src, 1) != 9) 173990075Sobrien abort (); 174090075Sobrien /* FALLTHRU */ 174118334Speter 174290075Sobrien case 9: 174390075Sobrien /* (unspec [(compare ..)] 9) */ 174490075Sobrien /* Combined fcomp+fnstsw generated for doing well with 174590075Sobrien CSE. When optimizing this would have been broken 174690075Sobrien up before now. */ 174718334Speter 174890075Sobrien pat_src = XVECEXP (pat_src, 0, 0); 174990075Sobrien if (GET_CODE (pat_src) != COMPARE) 175090075Sobrien abort (); 175118334Speter 175290075Sobrien compare_for_stack_reg (insn, regstack, pat_src); 175390075Sobrien break; 175418334Speter 175590075Sobrien default: 175690075Sobrien abort (); 175790075Sobrien } 175818334Speter break; 175918334Speter 176090075Sobrien case IF_THEN_ELSE: 176190075Sobrien /* This insn requires the top of stack to be the destination. */ 176218334Speter 176390075Sobrien src1 = get_true_reg (&XEXP (pat_src, 1)); 176490075Sobrien src2 = get_true_reg (&XEXP (pat_src, 2)); 176550397Sobrien 176690075Sobrien src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); 176790075Sobrien src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); 176850397Sobrien 176990075Sobrien /* If the comparison operator is an FP comparison operator, 177090075Sobrien it is handled correctly by compare_for_stack_reg () who 177190075Sobrien will move the destination to the top of stack. But if the 177290075Sobrien comparison operator is not an FP comparison operator, we 177390075Sobrien have to handle it here. */ 177490075Sobrien if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG 177590075Sobrien && REGNO (*dest) != regstack->reg[regstack->top]) 177690075Sobrien { 177790075Sobrien /* In case one of operands is the top of stack and the operands 177890075Sobrien dies, it is safe to make it the destination operand by reversing 177990075Sobrien the direction of cmove and avoid fxch. */ 178090075Sobrien if ((REGNO (*src1) == regstack->reg[regstack->top] 178190075Sobrien && src1_note) 178290075Sobrien || (REGNO (*src2) == regstack->reg[regstack->top] 178390075Sobrien && src2_note)) 178490075Sobrien { 178590075Sobrien int idx1 = (get_hard_regnum (regstack, *src1) 178690075Sobrien - FIRST_STACK_REG); 178790075Sobrien int idx2 = (get_hard_regnum (regstack, *src2) 178890075Sobrien - FIRST_STACK_REG); 178950397Sobrien 179090075Sobrien /* Make reg-stack believe that the operands are already 179190075Sobrien swapped on the stack */ 179290075Sobrien regstack->reg[regstack->top - idx1] = REGNO (*src2); 179390075Sobrien regstack->reg[regstack->top - idx2] = REGNO (*src1); 179450397Sobrien 179590075Sobrien /* Reverse condition to compensate the operand swap. 179690075Sobrien i386 do have comparison always reversible. */ 179790075Sobrien PUT_CODE (XEXP (pat_src, 0), 179890075Sobrien reversed_comparison_code (XEXP (pat_src, 0), insn)); 179990075Sobrien } 180090075Sobrien else 180190075Sobrien emit_swap_insn (insn, regstack, *dest); 180290075Sobrien } 180350397Sobrien 180490075Sobrien { 180590075Sobrien rtx src_note [3]; 180690075Sobrien int i; 180750397Sobrien 180890075Sobrien src_note[0] = 0; 180990075Sobrien src_note[1] = src1_note; 181090075Sobrien src_note[2] = src2_note; 181150397Sobrien 181290075Sobrien if (STACK_REG_P (*src1)) 181390075Sobrien replace_reg (src1, get_hard_regnum (regstack, *src1)); 181490075Sobrien if (STACK_REG_P (*src2)) 181590075Sobrien replace_reg (src2, get_hard_regnum (regstack, *src2)); 181650397Sobrien 181790075Sobrien for (i = 1; i <= 2; i++) 181890075Sobrien if (src_note [i]) 181950397Sobrien { 182090075Sobrien int regno = REGNO (XEXP (src_note[i], 0)); 182190075Sobrien 182290075Sobrien /* If the register that dies is not at the top of 182390075Sobrien stack, then move the top of stack to the dead reg */ 182490075Sobrien if (regno != regstack->reg[regstack->top]) 182590075Sobrien { 182690075Sobrien remove_regno_note (insn, REG_DEAD, regno); 182790075Sobrien emit_pop_insn (insn, regstack, XEXP (src_note[i], 0), 182890075Sobrien EMIT_AFTER); 182990075Sobrien } 183090075Sobrien else 183190075Sobrien /* Top of stack never dies, as it is the 183290075Sobrien destination. */ 183390075Sobrien abort (); 183450397Sobrien } 183590075Sobrien } 183650397Sobrien 183790075Sobrien /* Make dest the top of stack. Add dest to regstack if 183890075Sobrien not present. */ 183990075Sobrien if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG) 184090075Sobrien regstack->reg[++regstack->top] = REGNO (*dest); 184190075Sobrien SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); 184290075Sobrien replace_reg (dest, FIRST_STACK_REG); 184390075Sobrien break; 184450397Sobrien 184590075Sobrien default: 184690075Sobrien abort (); 184790075Sobrien } 184850397Sobrien break; 184990075Sobrien } 185050397Sobrien 185190075Sobrien default: 185290075Sobrien break; 185390075Sobrien } 185418334Speter} 185518334Speter 185618334Speter/* Substitute hard regnums for any stack regs in INSN, which has 185718334Speter N_INPUTS inputs and N_OUTPUTS outputs. REGSTACK is the stack info 185852284Sobrien before the insn, and is updated with changes made here. 185918334Speter 186018334Speter There are several requirements and assumptions about the use of 186118334Speter stack-like regs in asm statements. These rules are enforced by 186218334Speter record_asm_stack_regs; see comments there for details. Any 186318334Speter asm_operands left in the RTL at this point may be assume to meet the 186418334Speter requirements, since record_asm_stack_regs removes any problem asm. */ 186518334Speter 186618334Speterstatic void 186752284Sobriensubst_asm_stack_regs (insn, regstack) 186818334Speter rtx insn; 186918334Speter stack regstack; 187018334Speter{ 187118334Speter rtx body = PATTERN (insn); 187252284Sobrien int alt; 187318334Speter 187418334Speter rtx *note_reg; /* Array of note contents */ 187518334Speter rtx **note_loc; /* Address of REG field of each note */ 187618334Speter enum reg_note *note_kind; /* The type of each note */ 187718334Speter 187890075Sobrien rtx *clobber_reg = 0; 187990075Sobrien rtx **clobber_loc = 0; 188018334Speter 188118334Speter struct stack_def temp_stack; 188218334Speter int n_notes; 188318334Speter int n_clobbers; 188418334Speter rtx note; 188518334Speter int i; 188652284Sobrien int n_inputs, n_outputs; 188718334Speter 188890075Sobrien if (! check_asm_stack_operands (insn)) 188990075Sobrien return; 189090075Sobrien 189118334Speter /* Find out what the constraints required. If no constraint 189218334Speter alternative matches, that is a compiler bug: we should have caught 189390075Sobrien such an insn in check_asm_stack_operands. */ 189452284Sobrien extract_insn (insn); 189552284Sobrien constrain_operands (1); 189652284Sobrien alt = which_alternative; 189718334Speter 189852284Sobrien preprocess_constraints (); 189952284Sobrien 190052284Sobrien n_inputs = get_asm_operand_n_inputs (body); 190190075Sobrien n_outputs = recog_data.n_operands - n_inputs; 190252284Sobrien 190352284Sobrien if (alt < 0) 190418334Speter abort (); 190518334Speter 190650397Sobrien /* Strip SUBREGs here to make the following code simpler. */ 190790075Sobrien for (i = 0; i < recog_data.n_operands; i++) 190890075Sobrien if (GET_CODE (recog_data.operand[i]) == SUBREG 190990075Sobrien && GET_CODE (SUBREG_REG (recog_data.operand[i])) == REG) 191018334Speter { 191190075Sobrien recog_data.operand_loc[i] = & SUBREG_REG (recog_data.operand[i]); 191290075Sobrien recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]); 191318334Speter } 191418334Speter 191518334Speter /* Set up NOTE_REG, NOTE_LOC and NOTE_KIND. */ 191618334Speter 191718334Speter for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1)) 191818334Speter i++; 191918334Speter 192018334Speter note_reg = (rtx *) alloca (i * sizeof (rtx)); 192118334Speter note_loc = (rtx **) alloca (i * sizeof (rtx *)); 192218334Speter note_kind = (enum reg_note *) alloca (i * sizeof (enum reg_note)); 192318334Speter 192418334Speter n_notes = 0; 192518334Speter for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 192618334Speter { 192718334Speter rtx reg = XEXP (note, 0); 192818334Speter rtx *loc = & XEXP (note, 0); 192918334Speter 193018334Speter if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) 193118334Speter { 193218334Speter loc = & SUBREG_REG (reg); 193318334Speter reg = SUBREG_REG (reg); 193418334Speter } 193518334Speter 193618334Speter if (STACK_REG_P (reg) 193718334Speter && (REG_NOTE_KIND (note) == REG_DEAD 193818334Speter || REG_NOTE_KIND (note) == REG_UNUSED)) 193918334Speter { 194018334Speter note_reg[n_notes] = reg; 194118334Speter note_loc[n_notes] = loc; 194218334Speter note_kind[n_notes] = REG_NOTE_KIND (note); 194318334Speter n_notes++; 194418334Speter } 194518334Speter } 194618334Speter 194718334Speter /* Set up CLOBBER_REG and CLOBBER_LOC. */ 194818334Speter 194918334Speter n_clobbers = 0; 195018334Speter 195118334Speter if (GET_CODE (body) == PARALLEL) 195218334Speter { 195352284Sobrien clobber_reg = (rtx *) alloca (XVECLEN (body, 0) * sizeof (rtx)); 195452284Sobrien clobber_loc = (rtx **) alloca (XVECLEN (body, 0) * sizeof (rtx *)); 195518334Speter 195618334Speter for (i = 0; i < XVECLEN (body, 0); i++) 195718334Speter if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) 195818334Speter { 195918334Speter rtx clobber = XVECEXP (body, 0, i); 196018334Speter rtx reg = XEXP (clobber, 0); 196118334Speter rtx *loc = & XEXP (clobber, 0); 196218334Speter 196318334Speter if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) 196418334Speter { 196518334Speter loc = & SUBREG_REG (reg); 196618334Speter reg = SUBREG_REG (reg); 196718334Speter } 196818334Speter 196918334Speter if (STACK_REG_P (reg)) 197018334Speter { 197118334Speter clobber_reg[n_clobbers] = reg; 197218334Speter clobber_loc[n_clobbers] = loc; 197318334Speter n_clobbers++; 197418334Speter } 197518334Speter } 197618334Speter } 197718334Speter 197890075Sobrien temp_stack = *regstack; 197918334Speter 198018334Speter /* Put the input regs into the desired place in TEMP_STACK. */ 198118334Speter 198252284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 198390075Sobrien if (STACK_REG_P (recog_data.operand[i]) 198452284Sobrien && reg_class_subset_p (recog_op_alt[i][alt].class, 198552284Sobrien FLOAT_REGS) 198652284Sobrien && recog_op_alt[i][alt].class != FLOAT_REGS) 198718334Speter { 198818334Speter /* If an operand needs to be in a particular reg in 198918334Speter FLOAT_REGS, the constraint was either 't' or 'u'. Since 199090075Sobrien these constraints are for single register classes, and 199190075Sobrien reload guaranteed that operand[i] is already in that class, 199290075Sobrien we can just use REGNO (recog_data.operand[i]) to know which 199390075Sobrien actual reg this operand needs to be in. */ 199418334Speter 199590075Sobrien int regno = get_hard_regnum (&temp_stack, recog_data.operand[i]); 199618334Speter 199718334Speter if (regno < 0) 199818334Speter abort (); 199918334Speter 200090075Sobrien if ((unsigned int) regno != REGNO (recog_data.operand[i])) 200118334Speter { 200290075Sobrien /* recog_data.operand[i] is not in the right place. Find 200390075Sobrien it and swap it with whatever is already in I's place. 200490075Sobrien K is where recog_data.operand[i] is now. J is where it 200590075Sobrien should be. */ 200618334Speter int j, k, temp; 200718334Speter 200818334Speter k = temp_stack.top - (regno - FIRST_STACK_REG); 200918334Speter j = (temp_stack.top 201090075Sobrien - (REGNO (recog_data.operand[i]) - FIRST_STACK_REG)); 201118334Speter 201218334Speter temp = temp_stack.reg[k]; 201318334Speter temp_stack.reg[k] = temp_stack.reg[j]; 201418334Speter temp_stack.reg[j] = temp; 201518334Speter } 201618334Speter } 201718334Speter 201890075Sobrien /* Emit insns before INSN to make sure the reg-stack is in the right 201918334Speter order. */ 202018334Speter 202190075Sobrien change_stack (insn, regstack, &temp_stack, EMIT_BEFORE); 202218334Speter 202318334Speter /* Make the needed input register substitutions. Do death notes and 202450397Sobrien clobbers too, because these are for inputs, not outputs. */ 202518334Speter 202652284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 202790075Sobrien if (STACK_REG_P (recog_data.operand[i])) 202818334Speter { 202990075Sobrien int regnum = get_hard_regnum (regstack, recog_data.operand[i]); 203018334Speter 203118334Speter if (regnum < 0) 203218334Speter abort (); 203318334Speter 203490075Sobrien replace_reg (recog_data.operand_loc[i], regnum); 203518334Speter } 203618334Speter 203718334Speter for (i = 0; i < n_notes; i++) 203818334Speter if (note_kind[i] == REG_DEAD) 203918334Speter { 204018334Speter int regnum = get_hard_regnum (regstack, note_reg[i]); 204118334Speter 204218334Speter if (regnum < 0) 204318334Speter abort (); 204418334Speter 204518334Speter replace_reg (note_loc[i], regnum); 204618334Speter } 204718334Speter 204818334Speter for (i = 0; i < n_clobbers; i++) 204918334Speter { 205018334Speter /* It's OK for a CLOBBER to reference a reg that is not live. 205118334Speter Don't try to replace it in that case. */ 205218334Speter int regnum = get_hard_regnum (regstack, clobber_reg[i]); 205318334Speter 205418334Speter if (regnum >= 0) 205518334Speter { 205618334Speter /* Sigh - clobbers always have QImode. But replace_reg knows 205718334Speter that these regs can't be MODE_INT and will abort. Just put 205818334Speter the right reg there without calling replace_reg. */ 205918334Speter 206018334Speter *clobber_loc[i] = FP_MODE_REG (regnum, DFmode); 206118334Speter } 206218334Speter } 206318334Speter 206450397Sobrien /* Now remove from REGSTACK any inputs that the asm implicitly popped. */ 206518334Speter 206652284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 206790075Sobrien if (STACK_REG_P (recog_data.operand[i])) 206818334Speter { 206918334Speter /* An input reg is implicitly popped if it is tied to an 207050397Sobrien output, or if there is a CLOBBER for it. */ 207118334Speter int j; 207218334Speter 207318334Speter for (j = 0; j < n_clobbers; j++) 207490075Sobrien if (operands_match_p (clobber_reg[j], recog_data.operand[i])) 207518334Speter break; 207618334Speter 207752284Sobrien if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0) 207818334Speter { 207990075Sobrien /* recog_data.operand[i] might not be at the top of stack. 208090075Sobrien But that's OK, because all we need to do is pop the 208190075Sobrien right number of regs off of the top of the reg-stack. 208290075Sobrien record_asm_stack_regs guaranteed that all implicitly 208390075Sobrien popped regs were grouped at the top of the reg-stack. */ 208418334Speter 208518334Speter CLEAR_HARD_REG_BIT (regstack->reg_set, 208618334Speter regstack->reg[regstack->top]); 208718334Speter regstack->top--; 208818334Speter } 208918334Speter } 209018334Speter 209118334Speter /* Now add to REGSTACK any outputs that the asm implicitly pushed. 209218334Speter Note that there isn't any need to substitute register numbers. 209350397Sobrien ??? Explain why this is true. */ 209418334Speter 209518334Speter for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--) 209618334Speter { 209718334Speter /* See if there is an output for this hard reg. */ 209818334Speter int j; 209918334Speter 210018334Speter for (j = 0; j < n_outputs; j++) 210190075Sobrien if (STACK_REG_P (recog_data.operand[j]) 210290075Sobrien && REGNO (recog_data.operand[j]) == (unsigned) i) 210318334Speter { 210418334Speter regstack->reg[++regstack->top] = i; 210518334Speter SET_HARD_REG_BIT (regstack->reg_set, i); 210618334Speter break; 210718334Speter } 210818334Speter } 210918334Speter 211018334Speter /* Now emit a pop insn for any REG_UNUSED output, or any REG_DEAD 211118334Speter input that the asm didn't implicitly pop. If the asm didn't 211218334Speter implicitly pop an input reg, that reg will still be live. 211318334Speter 211418334Speter Note that we can't use find_regno_note here: the register numbers 211518334Speter in the death notes have already been substituted. */ 211618334Speter 211718334Speter for (i = 0; i < n_outputs; i++) 211890075Sobrien if (STACK_REG_P (recog_data.operand[i])) 211918334Speter { 212018334Speter int j; 212118334Speter 212218334Speter for (j = 0; j < n_notes; j++) 212390075Sobrien if (REGNO (recog_data.operand[i]) == REGNO (note_reg[j]) 212418334Speter && note_kind[j] == REG_UNUSED) 212518334Speter { 212690075Sobrien insn = emit_pop_insn (insn, regstack, recog_data.operand[i], 212790075Sobrien EMIT_AFTER); 212818334Speter break; 212918334Speter } 213018334Speter } 213118334Speter 213252284Sobrien for (i = n_outputs; i < n_outputs + n_inputs; i++) 213390075Sobrien if (STACK_REG_P (recog_data.operand[i])) 213418334Speter { 213518334Speter int j; 213618334Speter 213718334Speter for (j = 0; j < n_notes; j++) 213890075Sobrien if (REGNO (recog_data.operand[i]) == REGNO (note_reg[j]) 213918334Speter && note_kind[j] == REG_DEAD 214052284Sobrien && TEST_HARD_REG_BIT (regstack->reg_set, 214190075Sobrien REGNO (recog_data.operand[i]))) 214218334Speter { 214390075Sobrien insn = emit_pop_insn (insn, regstack, recog_data.operand[i], 214490075Sobrien EMIT_AFTER); 214518334Speter break; 214618334Speter } 214718334Speter } 214818334Speter} 214918334Speter 215018334Speter/* Substitute stack hard reg numbers for stack virtual registers in 215118334Speter INSN. Non-stack register numbers are not changed. REGSTACK is the 215218334Speter current stack content. Insns may be emitted as needed to arrange the 215350397Sobrien stack for the 387 based on the contents of the insn. */ 215418334Speter 215518334Speterstatic void 215618334Spetersubst_stack_regs (insn, regstack) 215718334Speter rtx insn; 215818334Speter stack regstack; 215918334Speter{ 216090075Sobrien rtx *note_link, note; 216190075Sobrien int i; 216218334Speter 216318334Speter if (GET_CODE (insn) == CALL_INSN) 216490075Sobrien { 216590075Sobrien int top = regstack->top; 216618334Speter 216790075Sobrien /* If there are any floating point parameters to be passed in 216890075Sobrien registers for this call, make sure they are in the right 216990075Sobrien order. */ 217018334Speter 217190075Sobrien if (top >= 0) 217290075Sobrien { 217390075Sobrien straighten_stack (PREV_INSN (insn), regstack); 217418334Speter 217590075Sobrien /* Now mark the arguments as dead after the call. */ 217618334Speter 217790075Sobrien while (regstack->top >= 0) 217890075Sobrien { 217990075Sobrien CLEAR_HARD_REG_BIT (regstack->reg_set, FIRST_STACK_REG + regstack->top); 218090075Sobrien regstack->top--; 218190075Sobrien } 218290075Sobrien } 218390075Sobrien } 218418334Speter 218518334Speter /* Do the actual substitution if any stack regs are mentioned. 218618334Speter Since we only record whether entire insn mentions stack regs, and 218718334Speter subst_stack_regs_pat only works for patterns that contain stack regs, 218818334Speter we must check each pattern in a parallel here. A call_value_pop could 218950397Sobrien fail otherwise. */ 219018334Speter 219152284Sobrien if (stack_regs_mentioned (insn)) 219218334Speter { 219352284Sobrien int n_operands = asm_noperands (PATTERN (insn)); 219418334Speter if (n_operands >= 0) 219518334Speter { 219618334Speter /* This insn is an `asm' with operands. Decode the operands, 219718334Speter decide how many are inputs, and do register substitution. 219850397Sobrien Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */ 219918334Speter 220052284Sobrien subst_asm_stack_regs (insn, regstack); 220118334Speter return; 220218334Speter } 220318334Speter 220418334Speter if (GET_CODE (PATTERN (insn)) == PARALLEL) 220518334Speter for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) 220618334Speter { 220718334Speter if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i))) 220890075Sobrien subst_stack_regs_pat (insn, regstack, 220990075Sobrien XVECEXP (PATTERN (insn), 0, i)); 221018334Speter } 221118334Speter else 221218334Speter subst_stack_regs_pat (insn, regstack, PATTERN (insn)); 221318334Speter } 221418334Speter 221518334Speter /* subst_stack_regs_pat may have deleted a no-op insn. If so, any 221650397Sobrien REG_UNUSED will already have been dealt with, so just return. */ 221718334Speter 221890075Sobrien if (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn)) 221918334Speter return; 222018334Speter 222118334Speter /* If there is a REG_UNUSED note on a stack register on this insn, 222218334Speter the indicated reg must be popped. The REG_UNUSED note is removed, 222318334Speter since the form of the newly emitted pop insn references the reg, 222450397Sobrien making it no longer `unset'. */ 222518334Speter 222690075Sobrien note_link = ®_NOTES (insn); 222718334Speter for (note = *note_link; note; note = XEXP (note, 1)) 222818334Speter if (REG_NOTE_KIND (note) == REG_UNUSED && STACK_REG_P (XEXP (note, 0))) 222918334Speter { 223018334Speter *note_link = XEXP (note, 1); 223190075Sobrien insn = emit_pop_insn (insn, regstack, XEXP (note, 0), EMIT_AFTER); 223218334Speter } 223318334Speter else 223418334Speter note_link = &XEXP (note, 1); 223518334Speter} 223618334Speter 223718334Speter/* Change the organization of the stack so that it fits a new basic 223818334Speter block. Some registers might have to be popped, but there can never be 223918334Speter a register live in the new block that is not now live. 224018334Speter 224190075Sobrien Insert any needed insns before or after INSN, as indicated by 224290075Sobrien WHERE. OLD is the original stack layout, and NEW is the desired 224390075Sobrien form. OLD is updated to reflect the code emitted, ie, it will be 224490075Sobrien the same as NEW upon return. 224518334Speter 224618334Speter This function will not preserve block_end[]. But that information 224750397Sobrien is no longer needed once this has executed. */ 224818334Speter 224918334Speterstatic void 225090075Sobrienchange_stack (insn, old, new, where) 225118334Speter rtx insn; 225218334Speter stack old; 225318334Speter stack new; 225490075Sobrien enum emit_where where; 225518334Speter{ 225618334Speter int reg; 225790075Sobrien int update_end = 0; 225818334Speter 225990075Sobrien /* We will be inserting new insns "backwards". If we are to insert 226090075Sobrien after INSN, find the next insn, and insert before it. */ 226118334Speter 226290075Sobrien if (where == EMIT_AFTER) 226390075Sobrien { 226490075Sobrien if (current_block && current_block->end == insn) 226590075Sobrien update_end = 1; 226690075Sobrien insn = NEXT_INSN (insn); 226790075Sobrien } 226818334Speter 226950397Sobrien /* Pop any registers that are not needed in the new block. */ 227018334Speter 227118334Speter for (reg = old->top; reg >= 0; reg--) 227218334Speter if (! TEST_HARD_REG_BIT (new->reg_set, old->reg[reg])) 227318334Speter emit_pop_insn (insn, old, FP_MODE_REG (old->reg[reg], DFmode), 227490075Sobrien EMIT_BEFORE); 227518334Speter 227618334Speter if (new->top == -2) 227718334Speter { 227818334Speter /* If the new block has never been processed, then it can inherit 227950397Sobrien the old stack order. */ 228018334Speter 228118334Speter new->top = old->top; 228290075Sobrien memcpy (new->reg, old->reg, sizeof (new->reg)); 228318334Speter } 228418334Speter else 228518334Speter { 228618334Speter /* This block has been entered before, and we must match the 228750397Sobrien previously selected stack order. */ 228818334Speter 228918334Speter /* By now, the only difference should be the order of the stack, 229050397Sobrien not their depth or liveliness. */ 229118334Speter 229218334Speter GO_IF_HARD_REG_EQUAL (old->reg_set, new->reg_set, win); 229318334Speter abort (); 229418334Speter win: 229518334Speter if (old->top != new->top) 229618334Speter abort (); 229718334Speter 229852284Sobrien /* If the stack is not empty (new->top != -1), loop here emitting 229952284Sobrien swaps until the stack is correct. 230052284Sobrien 230152284Sobrien The worst case number of swaps emitted is N + 2, where N is the 230218334Speter depth of the stack. In some cases, the reg at the top of 230318334Speter stack may be correct, but swapped anyway in order to fix 230418334Speter other regs. But since we never swap any other reg away from 230550397Sobrien its correct slot, this algorithm will converge. */ 230618334Speter 230752284Sobrien if (new->top != -1) 230852284Sobrien do 230952284Sobrien { 231052284Sobrien /* Swap the reg at top of stack into the position it is 231152284Sobrien supposed to be in, until the correct top of stack appears. */ 231218334Speter 231352284Sobrien while (old->reg[old->top] != new->reg[new->top]) 231452284Sobrien { 231552284Sobrien for (reg = new->top; reg >= 0; reg--) 231652284Sobrien if (new->reg[reg] == old->reg[old->top]) 231752284Sobrien break; 231818334Speter 231952284Sobrien if (reg == -1) 232052284Sobrien abort (); 232118334Speter 232252284Sobrien emit_swap_insn (insn, old, 232352284Sobrien FP_MODE_REG (old->reg[reg], DFmode)); 232452284Sobrien } 232518334Speter 232652284Sobrien /* See if any regs remain incorrect. If so, bring an 232718334Speter incorrect reg to the top of stack, and let the while loop 232850397Sobrien above fix it. */ 232918334Speter 233052284Sobrien for (reg = new->top; reg >= 0; reg--) 233152284Sobrien if (new->reg[reg] != old->reg[reg]) 233252284Sobrien { 233352284Sobrien emit_swap_insn (insn, old, 233452284Sobrien FP_MODE_REG (old->reg[reg], DFmode)); 233552284Sobrien break; 233652284Sobrien } 233752284Sobrien } while (reg >= 0); 233818334Speter 233950397Sobrien /* At this point there must be no differences. */ 234018334Speter 234118334Speter for (reg = old->top; reg >= 0; reg--) 234218334Speter if (old->reg[reg] != new->reg[reg]) 234318334Speter abort (); 234418334Speter } 234590075Sobrien 234690075Sobrien if (update_end) 234790075Sobrien current_block->end = PREV_INSN (insn); 234818334Speter} 234918334Speter 235090075Sobrien/* Print stack configuration. */ 235118334Speter 235218334Speterstatic void 235390075Sobrienprint_stack (file, s) 235490075Sobrien FILE *file; 235590075Sobrien stack s; 235618334Speter{ 235790075Sobrien if (! file) 235890075Sobrien return; 235918334Speter 236090075Sobrien if (s->top == -2) 236190075Sobrien fprintf (file, "uninitialized\n"); 236290075Sobrien else if (s->top == -1) 236390075Sobrien fprintf (file, "empty\n"); 236490075Sobrien else 236590075Sobrien { 236690075Sobrien int i; 236790075Sobrien fputs ("[ ", file); 236890075Sobrien for (i = 0; i <= s->top; ++i) 236990075Sobrien fprintf (file, "%d ", s->reg[i]); 237090075Sobrien fputs ("]\n", file); 237190075Sobrien } 237290075Sobrien} 237390075Sobrien 237490075Sobrien/* This function was doing life analysis. We now let the regular live 237590075Sobrien code do it's job, so we only need to check some extra invariants 237690075Sobrien that reg-stack expects. Primary among these being that all registers 237790075Sobrien are initialized before use. 237818334Speter 237990075Sobrien The function returns true when code was emitted to CFG edges and 238090075Sobrien commit_edge_insertions needs to be called. */ 238190075Sobrien 238290075Sobrienstatic int 238390075Sobrienconvert_regs_entry () 238490075Sobrien{ 238590075Sobrien int inserted = 0, i; 238690075Sobrien edge e; 238790075Sobrien 238890075Sobrien for (i = n_basic_blocks - 1; i >= 0; --i) 238990075Sobrien { 239090075Sobrien basic_block block = BASIC_BLOCK (i); 239190075Sobrien block_info bi = BLOCK_INFO (block); 239290075Sobrien int reg; 239390075Sobrien 239490075Sobrien /* Set current register status at last instruction `uninitialized'. */ 239590075Sobrien bi->stack_in.top = -2; 239690075Sobrien 239790075Sobrien /* Copy live_at_end and live_at_start into temporaries. */ 239890075Sobrien for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++) 239918334Speter { 240090075Sobrien if (REGNO_REG_SET_P (block->global_live_at_end, reg)) 240190075Sobrien SET_HARD_REG_BIT (bi->out_reg_set, reg); 240290075Sobrien if (REGNO_REG_SET_P (block->global_live_at_start, reg)) 240390075Sobrien SET_HARD_REG_BIT (bi->stack_in.reg_set, reg); 240418334Speter } 240590075Sobrien } 240618334Speter 240790075Sobrien /* Load something into each stack register live at function entry. 240890075Sobrien Such live registers can be caused by uninitialized variables or 240990075Sobrien functions not returning values on all paths. In order to keep 241090075Sobrien the push/pop code happy, and to not scrog the register stack, we 241190075Sobrien must put something in these registers. Use a QNaN. 241218334Speter 241390075Sobrien Note that we are insertting converted code here. This code is 241490075Sobrien never seen by the convert_regs pass. */ 241518334Speter 241690075Sobrien for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next) 241790075Sobrien { 241890075Sobrien basic_block block = e->dest; 241990075Sobrien block_info bi = BLOCK_INFO (block); 242090075Sobrien int reg, top = -1; 242118334Speter 242290075Sobrien for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg) 242390075Sobrien if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg)) 242490075Sobrien { 242590075Sobrien rtx init; 242690075Sobrien 242790075Sobrien bi->stack_in.reg[++top] = reg; 242890075Sobrien 242990075Sobrien init = gen_rtx_SET (VOIDmode, 243090075Sobrien FP_MODE_REG (FIRST_STACK_REG, SFmode), 243190075Sobrien nan); 243290075Sobrien insert_insn_on_edge (init, e); 243390075Sobrien inserted = 1; 243490075Sobrien } 243590075Sobrien 243690075Sobrien bi->stack_in.top = top; 243790075Sobrien } 243890075Sobrien 243990075Sobrien return inserted; 244090075Sobrien} 244190075Sobrien 244290075Sobrien/* Construct the desired stack for function exit. This will either 244390075Sobrien be `empty', or the function return value at top-of-stack. */ 244490075Sobrien 244590075Sobrienstatic void 244690075Sobrienconvert_regs_exit () 244790075Sobrien{ 244890075Sobrien int value_reg_low, value_reg_high; 244990075Sobrien stack output_stack; 245090075Sobrien rtx retvalue; 245190075Sobrien 245290075Sobrien retvalue = stack_result (current_function_decl); 245390075Sobrien value_reg_low = value_reg_high = -1; 245490075Sobrien if (retvalue) 245518334Speter { 245690075Sobrien value_reg_low = REGNO (retvalue); 245790075Sobrien value_reg_high = value_reg_low 245890075Sobrien + HARD_REGNO_NREGS (value_reg_low, GET_MODE (retvalue)) - 1; 245990075Sobrien } 246018334Speter 246190075Sobrien output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR)->stack_in; 246290075Sobrien if (value_reg_low == -1) 246390075Sobrien output_stack->top = -1; 246490075Sobrien else 246590075Sobrien { 246690075Sobrien int reg; 246790075Sobrien 246890075Sobrien output_stack->top = value_reg_high - value_reg_low; 246990075Sobrien for (reg = value_reg_low; reg <= value_reg_high; ++reg) 247090075Sobrien { 2471102780Skan output_stack->reg[value_reg_high - reg] = reg; 247290075Sobrien SET_HARD_REG_BIT (output_stack->reg_set, reg); 247390075Sobrien } 247490075Sobrien } 247590075Sobrien} 247690075Sobrien 247790075Sobrien/* Adjust the stack of this block on exit to match the stack of the 247890075Sobrien target block, or copy stack info into the stack of the successor 247990075Sobrien of the successor hasn't been processed yet. */ 248090075Sobrienstatic bool 248190075Sobriencompensate_edge (e, file) 248290075Sobrien edge e; 248390075Sobrien FILE *file; 248490075Sobrien{ 248590075Sobrien basic_block block = e->src, target = e->dest; 248690075Sobrien block_info bi = BLOCK_INFO (block); 248790075Sobrien struct stack_def regstack, tmpstack; 248890075Sobrien stack target_stack = &BLOCK_INFO (target)->stack_in; 248990075Sobrien int reg; 249090075Sobrien 249190075Sobrien current_block = block; 249290075Sobrien regstack = bi->stack_out; 249390075Sobrien if (file) 249490075Sobrien fprintf (file, "Edge %d->%d: ", block->index, target->index); 249590075Sobrien 249690075Sobrien if (target_stack->top == -2) 249790075Sobrien { 249890075Sobrien /* The target block hasn't had a stack order selected. 249990075Sobrien We need merely ensure that no pops are needed. */ 250090075Sobrien for (reg = regstack.top; reg >= 0; --reg) 250190075Sobrien if (!TEST_HARD_REG_BIT (target_stack->reg_set, regstack.reg[reg])) 250218334Speter break; 250318334Speter 250418334Speter if (reg == -1) 250518334Speter { 250690075Sobrien if (file) 250790075Sobrien fprintf (file, "new block; copying stack position\n"); 250818334Speter 250990075Sobrien /* change_stack kills values in regstack. */ 251090075Sobrien tmpstack = regstack; 251190075Sobrien 251290075Sobrien change_stack (block->end, &tmpstack, target_stack, EMIT_AFTER); 251390075Sobrien return false; 251418334Speter } 251590075Sobrien 251690075Sobrien if (file) 251790075Sobrien fprintf (file, "new block; pops needed\n"); 251818334Speter } 251990075Sobrien else 252018334Speter { 252190075Sobrien if (target_stack->top == regstack.top) 252290075Sobrien { 252390075Sobrien for (reg = target_stack->top; reg >= 0; --reg) 252490075Sobrien if (target_stack->reg[reg] != regstack.reg[reg]) 252590075Sobrien break; 252618334Speter 252790075Sobrien if (reg == -1) 252890075Sobrien { 252990075Sobrien if (file) 253090075Sobrien fprintf (file, "no changes needed\n"); 253190075Sobrien return false; 253290075Sobrien } 253390075Sobrien } 253490075Sobrien 253590075Sobrien if (file) 253690075Sobrien { 253790075Sobrien fprintf (file, "correcting stack to "); 253890075Sobrien print_stack (file, target_stack); 253990075Sobrien } 254018334Speter } 254118334Speter 254290075Sobrien /* Care for non-call EH edges specially. The normal return path have 254390075Sobrien values in registers. These will be popped en masse by the unwind 254490075Sobrien library. */ 254590075Sobrien if ((e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) == EDGE_EH) 254690075Sobrien target_stack->top = -1; 254718334Speter 254890075Sobrien /* Other calls may appear to have values live in st(0), but the 254990075Sobrien abnormal return path will not have actually loaded the values. */ 255090075Sobrien else if (e->flags & EDGE_ABNORMAL_CALL) 255190075Sobrien { 255290075Sobrien /* Assert that the lifetimes are as we expect -- one value 255390075Sobrien live at st(0) on the end of the source block, and no 255490075Sobrien values live at the beginning of the destination block. */ 255590075Sobrien HARD_REG_SET tmp; 255618334Speter 255790075Sobrien CLEAR_HARD_REG_SET (tmp); 255890075Sobrien GO_IF_HARD_REG_EQUAL (target_stack->reg_set, tmp, eh1); 255990075Sobrien abort (); 256090075Sobrien eh1: 256118334Speter 256290075Sobrien SET_HARD_REG_BIT (tmp, FIRST_STACK_REG); 256390075Sobrien GO_IF_HARD_REG_EQUAL (regstack.reg_set, tmp, eh2); 256490075Sobrien abort (); 256590075Sobrien eh2: 256618334Speter 256790075Sobrien target_stack->top = -1; 256890075Sobrien } 256918334Speter 257090075Sobrien /* It is better to output directly to the end of the block 257190075Sobrien instead of to the edge, because emit_swap can do minimal 257290075Sobrien insn scheduling. We can do this when there is only one 257390075Sobrien edge out, and it is not abnormal. */ 257490075Sobrien else if (block->succ->succ_next == NULL && !(e->flags & EDGE_ABNORMAL)) 257590075Sobrien { 257690075Sobrien /* change_stack kills values in regstack. */ 257790075Sobrien tmpstack = regstack; 257818334Speter 257990075Sobrien change_stack (block->end, &tmpstack, target_stack, 258090075Sobrien (GET_CODE (block->end) == JUMP_INSN 258190075Sobrien ? EMIT_BEFORE : EMIT_AFTER)); 258290075Sobrien } 258390075Sobrien else 258490075Sobrien { 258590075Sobrien rtx seq, after; 258618334Speter 258790075Sobrien /* We don't support abnormal edges. Global takes care to 258890075Sobrien avoid any live register across them, so we should never 258990075Sobrien have to insert instructions on such edges. */ 259090075Sobrien if (e->flags & EDGE_ABNORMAL) 259190075Sobrien abort (); 259218334Speter 259390075Sobrien current_block = NULL; 259490075Sobrien start_sequence (); 259518334Speter 259690075Sobrien /* ??? change_stack needs some point to emit insns after. 259790075Sobrien Also needed to keep gen_sequence from returning a 259890075Sobrien pattern as opposed to a sequence, which would lose 259990075Sobrien REG_DEAD notes. */ 260090075Sobrien after = emit_note (NULL, NOTE_INSN_DELETED); 260118334Speter 260290075Sobrien tmpstack = regstack; 260390075Sobrien change_stack (after, &tmpstack, target_stack, EMIT_BEFORE); 260418334Speter 260590075Sobrien seq = gen_sequence (); 260690075Sobrien end_sequence (); 260718334Speter 260890075Sobrien insert_insn_on_edge (seq, e); 260990075Sobrien return true; 261090075Sobrien } 261190075Sobrien return false; 261218334Speter} 261318334Speter 261490075Sobrien/* Convert stack register references in one block. */ 261590075Sobrien 261690075Sobrienstatic int 261790075Sobrienconvert_regs_1 (file, block) 261890075Sobrien FILE *file; 261990075Sobrien basic_block block; 262018334Speter{ 262118334Speter struct stack_def regstack; 262290075Sobrien block_info bi = BLOCK_INFO (block); 262390075Sobrien int inserted, reg; 262490075Sobrien rtx insn, next; 262590075Sobrien edge e, beste = NULL; 262618334Speter 262790075Sobrien inserted = 0; 262890075Sobrien 262990075Sobrien /* Find the edge we will copy stack from. It should be the most frequent 263090075Sobrien one as it will get cheapest after compensation code is generated, 263190075Sobrien if multiple such exists, take one with largest count, prefer critical 263290075Sobrien one (as splitting critical edges is more expensive), or one with lowest 263390075Sobrien index, to avoid random changes with different orders of the edges. */ 263490075Sobrien for (e = block->pred; e ; e = e->pred_next) 263518334Speter { 263690075Sobrien if (e->flags & EDGE_DFS_BACK) 263790075Sobrien ; 263890075Sobrien else if (! beste) 263990075Sobrien beste = e; 264090075Sobrien else if (EDGE_FREQUENCY (beste) < EDGE_FREQUENCY (e)) 264190075Sobrien beste = e; 264290075Sobrien else if (EDGE_FREQUENCY (beste) > EDGE_FREQUENCY (e)) 264390075Sobrien ; 264490075Sobrien else if (beste->count < e->count) 264590075Sobrien beste = e; 264690075Sobrien else if (beste->count > e->count) 264790075Sobrien ; 264890075Sobrien else if ((EDGE_CRITICAL_P (e) != 0) 264990075Sobrien != (EDGE_CRITICAL_P (beste) != 0)) 265018334Speter { 265190075Sobrien if (EDGE_CRITICAL_P (e)) 265290075Sobrien beste = e; 265318334Speter } 265490075Sobrien else if (e->src->index < beste->src->index) 265590075Sobrien beste = e; 265690075Sobrien } 265718334Speter 265890075Sobrien /* Entry block does have stack already initialized. */ 265990075Sobrien if (bi->stack_in.top == -2) 266090075Sobrien inserted |= compensate_edge (beste, file); 266190075Sobrien else 266290075Sobrien beste = NULL; 266390075Sobrien 266490075Sobrien current_block = block; 266518334Speter 266690075Sobrien if (file) 266790075Sobrien { 266890075Sobrien fprintf (file, "\nBasic block %d\nInput stack: ", block->index); 266990075Sobrien print_stack (file, &bi->stack_in); 267090075Sobrien } 267118334Speter 267290075Sobrien /* Process all insns in this block. Keep track of NEXT so that we 267390075Sobrien don't process insns emitted while substituting in INSN. */ 267490075Sobrien next = block->head; 267590075Sobrien regstack = bi->stack_in; 267690075Sobrien do 267790075Sobrien { 267890075Sobrien insn = next; 267990075Sobrien next = NEXT_INSN (insn); 268018334Speter 268190075Sobrien /* Ensure we have not missed a block boundary. */ 268290075Sobrien if (next == NULL) 268350397Sobrien abort (); 268490075Sobrien if (insn == block->end) 268590075Sobrien next = NULL; 268618334Speter 268790075Sobrien /* Don't bother processing unless there is a stack reg 268890075Sobrien mentioned or if it's a CALL_INSN. */ 268990075Sobrien if (stack_regs_mentioned (insn) 269090075Sobrien || GET_CODE (insn) == CALL_INSN) 269190075Sobrien { 269290075Sobrien if (file) 269390075Sobrien { 269490075Sobrien fprintf (file, " insn %d input stack: ", 269590075Sobrien INSN_UID (insn)); 269690075Sobrien print_stack (file, ®stack); 269790075Sobrien } 269890075Sobrien subst_stack_regs (insn, ®stack); 269990075Sobrien } 270090075Sobrien } 270190075Sobrien while (next); 270250397Sobrien 270390075Sobrien if (file) 270490075Sobrien { 270590075Sobrien fprintf (file, "Expected live registers ["); 270690075Sobrien for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; ++reg) 270790075Sobrien if (TEST_HARD_REG_BIT (bi->out_reg_set, reg)) 270890075Sobrien fprintf (file, " %d", reg); 270990075Sobrien fprintf (file, " ]\nOutput stack: "); 271090075Sobrien print_stack (file, ®stack); 271190075Sobrien } 271218334Speter 271390075Sobrien insn = block->end; 271490075Sobrien if (GET_CODE (insn) == JUMP_INSN) 271590075Sobrien insn = PREV_INSN (insn); 271618334Speter 271790075Sobrien /* If the function is declared to return a value, but it returns one 271890075Sobrien in only some cases, some registers might come live here. Emit 271990075Sobrien necessary moves for them. */ 272018334Speter 272190075Sobrien for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; ++reg) 272290075Sobrien { 272390075Sobrien if (TEST_HARD_REG_BIT (bi->out_reg_set, reg) 272490075Sobrien && ! TEST_HARD_REG_BIT (regstack.reg_set, reg)) 272590075Sobrien { 272690075Sobrien rtx set; 272718334Speter 272890075Sobrien if (file) 272990075Sobrien { 273090075Sobrien fprintf (file, "Emitting insn initializing reg %d\n", 273190075Sobrien reg); 273290075Sobrien } 273318334Speter 273490075Sobrien set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode), 273590075Sobrien nan); 273690075Sobrien insn = emit_insn_after (set, insn); 273790075Sobrien subst_stack_regs (insn, ®stack); 273890075Sobrien } 273918334Speter } 274018334Speter 274190075Sobrien /* Something failed if the stack lives don't match. */ 274290075Sobrien GO_IF_HARD_REG_EQUAL (regstack.reg_set, bi->out_reg_set, win); 274390075Sobrien abort (); 274490075Sobrien win: 274590075Sobrien bi->stack_out = regstack; 274618334Speter 274790075Sobrien /* Compensate the back edges, as those wasn't visited yet. */ 274890075Sobrien for (e = block->succ; e ; e = e->succ_next) 274990075Sobrien { 275090075Sobrien if (e->flags & EDGE_DFS_BACK 275190075Sobrien || (e->dest == EXIT_BLOCK_PTR)) 275290075Sobrien { 275390075Sobrien if (!BLOCK_INFO (e->dest)->done 275490075Sobrien && e->dest != block) 275590075Sobrien abort (); 275690075Sobrien inserted |= compensate_edge (e, file); 275790075Sobrien } 275890075Sobrien } 275990075Sobrien for (e = block->pred; e ; e = e->pred_next) 276090075Sobrien { 276190075Sobrien if (e != beste && !(e->flags & EDGE_DFS_BACK) 276290075Sobrien && e->src != ENTRY_BLOCK_PTR) 276390075Sobrien { 276490075Sobrien if (!BLOCK_INFO (e->src)->done) 276590075Sobrien abort (); 276690075Sobrien inserted |= compensate_edge (e, file); 276790075Sobrien } 276890075Sobrien } 276918334Speter 277090075Sobrien return inserted; 277118334Speter} 277218334Speter 277390075Sobrien/* Convert registers in all blocks reachable from BLOCK. */ 277490075Sobrien 277590075Sobrienstatic int 277690075Sobrienconvert_regs_2 (file, block) 277718334Speter FILE *file; 277890075Sobrien basic_block block; 277918334Speter{ 278090075Sobrien basic_block *stack, *sp; 278190075Sobrien int inserted; 278218334Speter 278390075Sobrien stack = (basic_block *) xmalloc (sizeof (*stack) * n_basic_blocks); 278490075Sobrien sp = stack; 278590075Sobrien 278690075Sobrien *sp++ = block; 278790075Sobrien 278890075Sobrien inserted = 0; 278990075Sobrien do 279018334Speter { 279190075Sobrien edge e; 279218334Speter 279390075Sobrien block = *--sp; 279490075Sobrien inserted |= convert_regs_1 (file, block); 279590075Sobrien BLOCK_INFO (block)->done = 1; 279618334Speter 279790075Sobrien for (e = block->succ; e ; e = e->succ_next) 279890075Sobrien if (! (e->flags & EDGE_DFS_BACK)) 279990075Sobrien { 280090075Sobrien BLOCK_INFO (e->dest)->predecessors--; 280190075Sobrien if (!BLOCK_INFO (e->dest)->predecessors) 280290075Sobrien *sp++ = e->dest; 280390075Sobrien } 280418334Speter } 280590075Sobrien while (sp != stack); 280618334Speter 280790075Sobrien return inserted; 280818334Speter} 280950397Sobrien 281090075Sobrien/* Traverse all basic blocks in a function, converting the register 281190075Sobrien references in each insn from the "flat" register file that gcc uses, 281290075Sobrien to the stack-like registers the 387 uses. */ 281390075Sobrien 281490075Sobrienstatic int 281590075Sobrienconvert_regs (file) 281618334Speter FILE *file; 281718334Speter{ 281890075Sobrien int inserted, i; 281990075Sobrien edge e; 282018334Speter 282190075Sobrien /* Initialize uninitialized registers on function entry. */ 282290075Sobrien inserted = convert_regs_entry (); 282318334Speter 282490075Sobrien /* Construct the desired stack for function exit. */ 282590075Sobrien convert_regs_exit (); 282690075Sobrien BLOCK_INFO (EXIT_BLOCK_PTR)->done = 1; 282718334Speter 282890075Sobrien /* ??? Future: process inner loops first, and give them arbitrary 282990075Sobrien initial stacks which emit_swap_insn can modify. This ought to 283090075Sobrien prevent double fxch that aften appears at the head of a loop. */ 283118334Speter 283290075Sobrien /* Process all blocks reachable from all entry points. */ 283390075Sobrien for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next) 283490075Sobrien inserted |= convert_regs_2 (file, e->dest); 283590075Sobrien 283690075Sobrien /* ??? Process all unreachable blocks. Though there's no excuse 283790075Sobrien for keeping these even when not optimizing. */ 283890075Sobrien for (i = 0; i < n_basic_blocks; ++i) 283990075Sobrien { 284090075Sobrien basic_block b = BASIC_BLOCK (i); 284190075Sobrien block_info bi = BLOCK_INFO (b); 284218334Speter 284390075Sobrien if (! bi->done) 284418334Speter { 284590075Sobrien int reg; 284618334Speter 284790075Sobrien /* Create an arbitrary input stack. */ 284890075Sobrien bi->stack_in.top = -1; 284990075Sobrien for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg) 285090075Sobrien if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg)) 285190075Sobrien bi->stack_in.reg[++bi->stack_in.top] = reg; 285290075Sobrien 285390075Sobrien inserted |= convert_regs_2 (file, b); 285418334Speter } 285590075Sobrien } 285618334Speter 285796263Sobrien fixup_abnormal_edges (); 285890075Sobrien if (inserted) 285990075Sobrien commit_edge_insertions (); 286018334Speter 286190075Sobrien if (file) 286290075Sobrien fputc ('\n', file); 286318334Speter 286490075Sobrien return inserted; 286518334Speter} 286618334Speter#endif /* STACK_REGS */ 2867