GCC Middle and Back End API Reference
|
Data Structures | |
struct | stack_def |
struct | block_info_def |
Typedefs | |
typedef struct stack_def * | stack_ptr |
typedef struct block_info_def * | block_info |
Enumerations | |
enum | emit_where { EMIT_AFTER, EMIT_BEFORE } |
Variables | |
static vec< char > | stack_regs_mentioned_data |
int | regstack_completed = 0 |
static basic_block | current_block |
static bool | starting_stack_p |
static rtx | FP_mode_reg [LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE] |
static rtx | not_a_num |
static rtx | ix86_flags_rtx |
static bool | any_malformed_asm |
typedef struct block_info_def * block_info |
This is used to carry information about basic blocks. It is attached to the AUX field of the standard CFG block.
This is the basic stack record. TOP is an index into REG[] such that REG[TOP] is the top of stack. If TOP is -1 the stack is empty. If TOP is -2, REG[] is not yet initialized. Stack initialization consists of placing each live reg in array `reg' and setting `top' appropriately. REG_SET indicates which registers are live.
enum emit_where |
|
static |
Select the better of two edges E1 and E2 to use to determine the stack layout for their shared destination basic block. This is typically the more frequently executed. The edge E1 may be NULL (in which case E2 is returned), but E2 is always non-NULL.
References edge_def::count, basic_block_def::index, and edge_def::src.
Referenced by convert_regs_1().
Referenced by compensate_edge(), straighten_stack(), subst_asm_stack_regs(), and swap_to_top().
|
static |
Change the organization of the stack so that it fits a new basic block. Some registers might have to be popped, but there can never be a register live in the new block that is not now live. Insert any needed insns before or after INSN, as indicated by WHERE. OLD is the original stack layout, and NEW is the desired form. OLD is updated to reflect the code emitted, i.e., it will be the same as NEW upon return. This function will not preserve block_end[]. But that information is no longer needed once this has executed.
References EMIT_AFTER, EMIT_BEFORE, emit_insn_before(), emit_pop_insn(), emit_swap_insn(), hard_reg_set_equal_p(), live, memcpy(), not_a_num, stack_def::reg, stack_def::reg_set, slots, starting_stack_p, and stack_def::top.
|
static |
Referenced by subst_asm_stack_regs().
|
static |
There are many rules that an asm statement for stack-like regs must follow. Those rules are explained at the top of this file: the rule numbers below refer to that explanation.
References any_malformed_asm, constrain_operands(), error_for_asm(), extract_insn(), get_asm_operands_in_out(), memset(), recog_data_d::n_operands, recog_data_d::operand, operands_match_p(), preprocess_constraints(), recog_data, recog_op_alt, stack_def::reg, and which_alternative.
Referenced by subst_stack_regs_pat().
|
static |
Handle a comparison. Special care needs to be taken to avoid causing comparisons that a 387 cannot do correctly, such as EQ. Also, a pop insn may need to be emitted. The 387 does have an `fcompp' insn that can pop two regs, but it is sometimes too expensive to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to set up.
References EMIT_AFTER, emit_pop_insn(), emit_swap_insn(), find_regno_note(), get_hard_regnum(), get_true_reg(), pop_stack(), remove_regno_note(), replace_reg(), and swap_rtx_condition().
|
static |
Adjust the stack of edge E's source block on exit to match the stack of it's target block upon input. The stack layouts of both blocks should have been defined by now.
References change_stack(), edge_def::dest, dump_file, EMIT_AFTER, EMIT_BEFORE, emit_note(), end_sequence(), edge_def::flags, get_insns(), basic_block_def::index, insert_insn_on_edge(), print_stack(), stack_def::reg, edge_def::src, start_sequence(), basic_block_def::succs, and stack_def::top.
Referenced by compensate_edges().
|
static |
Traverse all non-entry edges in the CFG, and emit the necessary edge compensation code to change the stack from stack_out of the source block to the stack_in of the destination block.
References compensate_edge(), inserted, starting_stack_p, and basic_block_def::succs.
Referenced by convert_regs().
|
static |
Traverse all basic blocks in a function, converting the register references in each insn from the "flat" register file that gcc uses, to the stack-like registers the 387 uses.
References cfg_altered, cleanup_cfg(), clear_aux_for_blocks(), commit_edge_insertions(), compensate_edges(), convert_regs_2(), convert_regs_entry(), convert_regs_exit(), edge_def::dest, dump_file, fixup_abnormal_edges(), and inserted.
Referenced by reg_to_stack().
|
static |
Convert stack register references in one block. Return true if the CFG has been modified in the process.
References any_malformed_asm, better_edge(), cfg_altered, dump_file, emit_insn_after(), find_reg_note(), hard_reg_set_equal_p(), basic_block_def::index, not_a_num, basic_block_def::preds, print_stack(), propagate_stack(), purge_dead_edges(), stack_def::reg, stack_def::reg_set, edge_def::src, stack_regs_mentioned(), starting_stack_p, subst_all_stack_regs_in_debug_insn(), and subst_stack_regs().
Referenced by convert_regs_2().
|
static |
Convert registers in all blocks reachable from BLOCK. Return true if the CFG has been modified in the process.
References cfg_altered, convert_regs_1(), edge_def::dest, edge_def::flags, free(), stack, and basic_block_def::succs.
Referenced by convert_regs().
|
static |
This function was doing life analysis. We now let the regular live code do it's job, so we only need to check some extra invariants that reg-stack expects. Primary among these being that all registers are initialized before use. The function returns true when code was emitted to CFG edges and commit_edge_insertions needs to be called.
References edge_def::dest, insert_insn_on_edge(), inserted, not_a_num, stack_def::reg, and stack_def::top.
Referenced by convert_regs().
|
static |
Construct the desired stack for function exit. This will either be `empty', or the function return value at top-of-stack.
References current_function_decl, stack_def::reg, stack_def::reg_set, stack_result(), and stack_def::top.
Referenced by convert_regs().
|
static |
Emit an insn to pop virtual register REG before or after INSN. REGSTACK is the stack state after INSN and is updated to reflect this pop. WHEN is either emit_insn_before or emit_insn_after. A pop insn is represented as a SET whose destination is the register to be popped and source is the top of stack. A death note for the top of stack cases the movdf pattern to pop.
References add_reg_note(), EMIT_AFTER, emit_insn_after(), emit_insn_before(), emit_pop_insn(), get_hard_regnum(), stack_def::reg, stack_def::reg_set, and stack_def::top.
|
static |
Emit an insn before or after INSN to swap virtual register REG with the top of stack. REGSTACK is the stack state before the swap, and is updated to reflect the swap. A swap insn is represented as a PARALLEL of two patterns: each pattern moves one reg to the other. If REG is already at the top of the stack, no insn is emitted.
References any_malformed_asm, emit_insn_after(), emit_insn_before(), find_regno_note(), get_hard_regnum(), get_true_reg(), i1, limit, stack_def::reg, stack_regs_mentioned(), starting_stack_p, and stack_def::top.
Referenced by change_stack(), compare_for_stack_reg(), move_for_stack_reg(), and subst_stack_regs_pat().
|
static |
|
static |
Referenced by check_asm_stack_operands(), and subst_asm_stack_regs().
|
static |
Calculate the number of inputs and outputs in BODY, an asm_operands. N_OPERANDS is the total number of operands, and N_INPUTS and N_OUTPUTS are pointers to ints into which the results are placed.
References extract_asm_operands(), recog_data_d::n_operands, and recog_data.
|
static |
Find the hard register number of virtual register REG in REGSTACK. The hard register number is relative to the top of the stack. -1 is returned if the register is not found.
References stack_def::reg, and stack_def::top.
Referenced by compare_for_stack_reg(), emit_swap_insn(), move_for_stack_reg(), and subst_stack_regs_pat().
|
static |
Return a pointer to the REG expression within PAT. If PAT is not a REG, possible enclosed by a conversion rtx, return the inner part of PAT that stopped the search.
References subreg_regno_offset().
rtl_opt_pass* make_pass_stack_regs | ( | ) |
rtl_opt_pass* make_pass_stack_regs_run | ( | ) |
Referenced by move_nan_for_stack_reg(), and subst_stack_regs_pat().
|
static |
Handle a move to or from a stack register in PAT, which is in INSN. REGSTACK is the current stack. Return whether a control flow insn was deleted in the process.
References add_reg_note(), control_flow_insn_p(), delete_insn(), EMIT_AFTER, emit_insn_before(), emit_pop_insn(), emit_swap_insn(), find_regno_note(), get_hard_regnum(), get_true_reg(), move_nan_for_stack_reg(), stack_def::reg, stack_def::reg_set, replace_reg(), SET, and stack_def::top.
Referenced by move_for_stack_reg(), and subst_stack_regs_pat().
|
static |
A helper function which replaces INSN with a pattern that loads up a NaN into DEST, then invokes move_for_stack_reg.
References move_for_stack_reg(), and not_a_num.
Referenced by swap_rtx_condition().
|
static |
References ix86_flags_rtx, and reg_mentioned_p().
|
static |
Referenced by compare_for_stack_reg().
|
static |
Pop a register from the stack.
References stack_def::reg, stack_def::reg_set, and stack_def::top.
|
static |
Referenced by compensate_edge(), and convert_regs_1().
|
static |
Print stack configuration.
References stack_def::reg, and stack_def::top.
|
static |
Copy the stack info from the end of edge E's source block to the start of E's destination block.
References edge_def::dest, stack_def::reg, stack_def::reg_set, edge_def::src, and stack_def::top.
Referenced by convert_regs_1().
|
static |
Convert register usage from "flat" register file usage to a "stack register file. FILE is the dump file, if used. Construct a CFG and run life analysis. Then convert each insn one by one. Run a last cleanup_cfg pass, if optimizing, to eliminate code duplication created when the converter inserts pop insns on the edges.
References alloc_aux_for_blocks(), convert_regs(), df_analyze(), df_note_add_problem(), df_regs_ever_live_p(), edge_def::flags, force_const_mem(), free_aux_for_blocks(), gen_rtx_REG(), get_max_uid(), ix86_flags_rtx, mark_dfs_back_edges(), max_uid, memset(), not_a_num, basic_block_def::preds, real_nan(), stack_def::reg, and edge_def::src.
Referenced by rest_of_handle_stack_regs().
|
static |
Referenced by compare_for_stack_reg(), and subst_stack_regs_pat().
|
static |
Remove a note of type NOTE, which must be found, for register number REGNO from INSN. Remove only one such note.
|
static |
|
static |
Replace REG, which is a pointer to a stack reg RTX, with an RTX for the desired hard REGNO.
|
static |
Convert register usage from flat register file usage to a stack register file.
References reg_to_stack(), and regstack_completed.
int stack_regs_mentioned | ( | ) |
Return nonzero if INSN mentions stacked registers, else return zero.
References stack_regs_mentioned_p().
Referenced by convert_regs_1(), emit_swap_insn(), old_insns_match_p(), and subst_stack_regs().
|
static |
Forward declarations
Referenced by stack_regs_mentioned(), stack_regs_mentioned_p(), and subst_stack_regs().
|
static |
Return nonzero if any stack register is mentioned somewhere within PAT.
References stack_regs_mentioned_p().
Referenced by convert_regs_exit().
|
static |
If current function returns its result in an fp stack register, return the REG. Otherwise, return 0.
References aggregate_value_p(), and targetm.
|
static |
Reorganize the stack into ascending numbers, before this insn.
References change_stack(), EMIT_BEFORE, stack_def::reg, stack_def::reg_set, and stack_def::top.
Referenced by subst_stack_regs().
|
static |
Substitute hardware stack regs in debug insn INSN, using stack layout REGSTACK. If we can't find a hardware stack reg for any of the REGs in it, reset the debug insn.
References for_each_rtx(), and subst_stack_regs_in_debug_insn().
Referenced by convert_regs_1().
Referenced by subst_stack_regs().
|
static |
Substitute hard regnums for any stack regs in INSN, which has N_INPUTS inputs and N_OUTPUTS outputs. REGSTACK is the stack info before the insn, and is updated with changes made here. There are several requirements and assumptions about the use of stack-like regs in asm statements. These rules are enforced by record_asm_stack_regs; see comments there for details. Any asm_operands left in the RTL at this point may be assume to meet the requirements, since record_asm_stack_regs removes any problem asm.
References change_stack(), check_asm_stack_operands(), constrain_operands(), EMIT_AFTER, EMIT_BEFORE, emit_pop_insn(), extract_insn(), get_asm_operands_in_out(), get_hard_regnum(), recog_data_d::n_operands, recog_data_d::operand, recog_data_d::operand_loc, operands_match_p(), preprocess_constraints(), recog_data, recog_op_alt, stack_def::reg, reg_class_subset_p(), stack_def::reg_set, replace_reg(), stack_def::top, and which_alternative.
Referenced by convert_regs_1().
|
static |
Substitute stack hard reg numbers for stack virtual registers in INSN. Non-stack register numbers are not changed. REGSTACK is the current stack content. Insns may be emitted as needed to arrange the stack for the 387 based on the contents of the insn. Return whether a control flow insn was deleted in the process.
References asm_noperands(), EMIT_AFTER, emit_pop_insn(), find_reg_note(), n_operands, stack_def::reg_set, stack_regs_mentioned(), stack_regs_mentioned_p(), straighten_stack(), subst_asm_stack_regs(), subst_stack_regs_pat(), and stack_def::top.
|
static |
Substitute new registers in LOC, which is part of a debug insn. REGSTACK is the current register layout.
References get_hard_regnum(), and replace_reg().
Referenced by subst_all_stack_regs_in_debug_insn().
Referenced by subst_stack_regs().
|
static |
Substitute new registers in PAT, which is part of INSN. REGSTACK is the current register layout. Return whether a control flow insn was deleted in the process.
References cc0_rtx, compare_for_stack_reg(), count, EMIT_AFTER, EMIT_BEFORE, emit_insn_before(), emit_pop_insn(), emit_swap_insn(), find_reg_note(), find_regno_note(), get_hard_regnum(), get_true_reg(), move_for_stack_reg(), move_nan_for_stack_reg(), stack_def::reg, stack_def::reg_set, remove_note(), remove_regno_note(), replace_reg(), reversed_comparison_code(), SET, swap_to_top(), and stack_def::top.
|
static |
Referenced by compare_for_stack_reg(), and swap_rtx_condition().
|
static |
|
static |
Referenced by swap_rtx_condition(), and swap_rtx_condition_1().
|
static |
Swap the condition on a branch, if there is one. Return true if we found a condition to swap. False if the condition was not used as such.
References swap_condition(), and swap_rtx_condition_1().
Referenced by subst_stack_regs_pat().
|
static |
Emit an insns before INSN to swap virtual register SRC1 with the top of stack and virtual register SRC2 with second stack slot. REGSTACK is the stack state before the swaps, and is updated to reflect the swaps. A swap insn is represented as a PARALLEL of two patterns: each pattern moves one reg to the other. If SRC1 and/or SRC2 are already at the right place, no swap insn is emitted.
References change_stack(), EMIT_BEFORE, get_hard_regnum(), stack_def::reg, and stack_def::top.
|
static |
Set if we find any malformed asms in a block.
Referenced by check_asm_stack_operands(), convert_regs_1(), and emit_swap_insn().
|
static |
The block we're currently working on.
Referenced by find_control_dependence(), and prepend_lexical_block().
|
static |
This is the register file for all register after conversion.
|
static |
Referenced by next_flags_user(), reg_to_stack(), and swap_rtx_condition().
|
static |
Used to initialize uninitialized registers.
Referenced by change_stack(), convert_regs_1(), convert_regs_entry(), move_nan_for_stack_reg(), and reg_to_stack().
int regstack_completed = 0 |
Nonzero after end of regstack pass. Set to 1 or 0 by reg-stack.c.
Referenced by df_ignore_stack_reg(), rest_of_clean_state(), and rest_of_handle_stack_regs().
|
static |
Register to Stack convert for GNU compiler. Copyright (C) 1992-2013 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>.
This pass converts stack-like registers from the "flat register file" model that gcc uses, to a stack convention that the 387 uses. * The form of the input: On input, the function consists of insn that have had their registers fully allocated to a set of "virtual" registers. Note that the word "virtual" is used differently here than elsewhere in gcc: for each virtual stack reg, there is a hard reg, but the mapping between them is not known until this pass is run. On output, hard register numbers have been substituted, and various pop and exchange insns have been emitted. The hard register numbers and the virtual register numbers completely overlap - before this pass, all stack register numbers are virtual, and afterward they are all hard. The virtual registers can be manipulated normally by gcc, and their semantics are the same as for normal registers. After the hard register numbers are substituted, the semantics of an insn containing stack-like regs are not the same as for an insn with normal regs: for instance, it is not safe to delete an insn that appears to be a no-op move. In general, no insn containing hard regs should be changed after this pass is done. * The form of the output: After this pass, hard register numbers represent the distance from the current top of stack to the desired register. A reference to FIRST_STACK_REG references the top of stack, FIRST_STACK_REG + 1, represents the register just below that, and so forth. Also, REG_DEAD notes indicate whether or not a stack register should be popped. A "swap" insn looks like a parallel of two patterns, where each pattern is a SET: one sets A to B, the other B to A. A "push" or "load" insn is a SET whose SET_DEST is FIRST_STACK_REG and whose SET_DEST is REG or MEM. Any other SET_DEST, such as PLUS, will replace the existing stack top, not push a new value. A store insn is a SET whose SET_DEST is FIRST_STACK_REG, and whose SET_SRC is REG or MEM. The case where the SET_SRC and SET_DEST are both FIRST_STACK_REG appears ambiguous. As a special case, the presence of a REG_DEAD note for FIRST_STACK_REG differentiates between a load insn and a pop. If a REG_DEAD is present, the insn represents a "pop" that discards the top of the register stack. If there is no REG_DEAD note, then the insn represents a "dup" or a push of the current top of stack onto the stack. * Methodology: Existing REG_DEAD and REG_UNUSED notes for stack registers are deleted and recreated from scratch. REG_DEAD is never created for a SET_DEST, only REG_UNUSED. * asm_operands: There are several rules on the usage of stack-like regs in asm_operands insns. These rules apply only to the operands that are stack-like regs: 1. Given a set of input regs that die in an asm_operands, it is necessary to know which are implicitly popped by the asm, and which must be explicitly popped by gcc. An input reg that is implicitly popped by the asm must be explicitly clobbered, unless it is constrained to match an output operand. 2. For any input reg that is implicitly popped by an asm, it is necessary to know how to adjust the stack to compensate for the pop. If any non-popped input is closer to the top of the reg-stack than the implicitly popped reg, it would not be possible to know what the stack looked like - it's not clear how the rest of the stack "slides up". All implicitly popped input regs must be closer to the top of the reg-stack than any input that is not implicitly popped. 3. It is possible that if an input dies in an insn, reload might use the input reg for an output reload. Consider this example: asm ("foo" : "=t" (a) : "f" (b)); This asm says that input B is not popped by the asm, and that the asm pushes a result onto the reg-stack, i.e., the stack is one deeper after the asm than it was before. But, it is possible that reload will think that it can use the same reg for both the input and the output, if input B dies in this insn. If any input operand uses the "f" constraint, all output reg constraints must use the "&" earlyclobber. The asm above would be written as asm ("foo" : "=&t" (a) : "f" (b)); 4. Some operands need to be in particular places on the stack. All output operands fall in this category - there is no other way to know which regs the outputs appear in unless the user indicates this in the constraints. Output operands must specifically indicate which reg an output appears in after an asm. "=f" is not allowed: the operand constraints must select a class with a single reg. 5. Output operands may not be "inserted" between existing stack regs. Since no 387 opcode uses a read/write operand, all output operands are dead before the asm_operands, and are pushed by the asm_operands. It makes no sense to push anywhere but the top of the reg-stack. Output operands must start at the top of the reg-stack: output operands may not "skip" a reg. 6. Some asm statements may need extra stack space for internal calculations. This can be guaranteed by clobbering stack registers unrelated to the inputs and outputs. Here are a couple of reasonable asms to want to write. This asm takes one input, which is internally popped, and produces two outputs. asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp)); This asm takes two inputs, which are popped by the fyl2xp1 opcode, and replaces them with one output. The user must code the "st(1)" clobber for reg-stack.c to know that fyl2xp1 pops both inputs. asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");
We use this array to cache info about insns, because otherwise we spend too much time in stack_regs_mentioned_p. Indexed by insn UIDs. A value of zero is uninitialized, one indicates the insn uses stack registers, two indicates the insn does not use stack registers.
|
static |
In the current_block, whether we're processing the first register stack or call instruction, i.e. the regstack is currently the same as BLOCK_INFO(current_block)->stack_in.
Referenced by change_stack(), compensate_edges(), convert_regs_1(), and emit_swap_insn().