GCC Middle and Back End API Reference
auto-inc-dec.c File Reference

Data Structures

struct  inc_insn
struct  mem_insn

Enumerations

enum  form {
  FORM_PRE_ADD, FORM_PRE_INC, FORM_POST_ADD, FORM_POST_INC,
  FORM_last
}
enum  inc_state {
  INC_ZERO, INC_NEG_SIZE, INC_POS_SIZE, INC_NEG_ANY,
  INC_POS_ANY, INC_REG, INC_last
}
enum  gen_form {
  NOTHING, SIMPLE_PRE_INC, SIMPLE_POST_INC, SIMPLE_PRE_DEC,
  SIMPLE_POST_DEC, DISP_PRE, DISP_POST, REG_PRE,
  REG_POST
}

Functions

static enum inc_state set_inc_state ()
static void init_decision_table ()
static void dump_inc_insn ()
static void dump_mem_insn ()
static void move_dead_notes ()
static rtx insert_move_insn_before ()
static bool attempt_change ()
static bool try_merge ()
static rtx get_next_ref ()
static void reverse_mem ()
static void reverse_inc ()
static bool parse_add_or_inc ()
static int find_address ()
static bool find_inc ()
static bool find_mem ()
static void merge_in_block ()
static unsigned int rest_of_handle_auto_inc_dec ()
static bool gate_auto_inc_dec ()
rtl_opt_passmake_pass_inc_dec ()

Variables

static rtx mem_tmp
static bool initialized = false
static enum gen_form decision_table [INC_last][INC_last][FORM_last]
static struct inc_insn inc_insn
static struct mem_insn mem_insn
static rtxreg_next_use = NULL
static rtxreg_next_inc_use = NULL
static rtxreg_next_def = NULL

Enumeration Type Documentation

enum form
@verbatim Discovery of auto-inc and auto-dec instructions.

Copyright (C) 2006-2013 Free Software Foundation, Inc. Contributed by Kenneth Zadeck zadec.nosp@m.k@na.nosp@m.tural.nosp@m.brid.nosp@m.ge.co.nosp@m.m

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 was originally removed from flow.c. However there is
   almost nothing that remains of that code.

   There are (4) basic forms that are matched:

      (1) FORM_PRE_ADD
           a <- b + c
           ...
           *a

        becomes

           a <- b
           ...
           *(a += c) pre


      (2) FORM_PRE_INC
           a += c
           ...
           *a

        becomes

           *(a += c) pre


      (3) FORM_POST_ADD
           *a
           ...
           b <- a + c

           (For this case to be true, b must not be assigned or used between
           the *a and the assignment to b.  B must also be a Pmode reg.)

        becomes

           b <- a
           ...
           *(b += c) post


      (4) FORM_POST_INC
           *a
           ...
           a <- a + c

        becomes

           *(a += c) post

  There are three types of values of c.

    1) c is a constant equal to the width of the value being accessed by
       the pointer.  This is useful for machines that have
       HAVE_PRE_INCREMENT, HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT or
       HAVE_POST_DECREMENT defined.

    2) c is a constant not equal to the width of the value being accessed
       by the pointer.  This is useful for machines that have
       HAVE_PRE_MODIFY_DISP, HAVE_POST_MODIFY_DISP defined.

    3) c is a register.  This is useful for machines that have
       HAVE_PRE_MODIFY_REG,  HAVE_POST_MODIFY_REG

  The is one special case: if a already had an offset equal to it +-
  its width and that offset is equal to -c when the increment was
  before the ref or +c if the increment was after the ref, then if we
  can do the combination but switch the pre/post bit.   
Enumerator:
FORM_PRE_ADD 
FORM_PRE_INC 
FORM_POST_ADD 
FORM_POST_INC 
FORM_last 
enum gen_form
The eight forms that pre/post inc/dec can take.   
Enumerator:
NOTHING 
SIMPLE_PRE_INC 
SIMPLE_POST_INC 
SIMPLE_PRE_DEC 
SIMPLE_POST_DEC 
DISP_PRE 
DISP_POST 
REG_PRE 
REG_POST 
enum inc_state
The states of the second operands of mem refs and inc insns.  If no
   second operand of the mem_ref was found, it is assumed to just be
   ZERO.  SIZE is the size of the mode accessed in the memref.  The
   ANY is used for constants that are not +-size or 0.  REG is used if
   the forms are reg1 + reg2.   
Enumerator:
INC_ZERO 
INC_NEG_SIZE 
INC_POS_SIZE 
INC_NEG_ANY 
INC_POS_ANY 
INC_REG 
INC_last 

Function Documentation

static bool attempt_change ( )
static
Change mem_insn.mem_loc so that uses NEW_ADDR which has an
   increment of INC_REG.  To have reached this point, the change is a
   legitimate one from a dataflow point of view.  The only questions
   are is this a valid change to the instruction and is this a
   profitable change to the instruction.   

References add_reg_note(), delete_insn(), df_recompute_luids(), dump_file, dump_insn_slim(), inc_insn::form, FORM_last, FORM_POST_ADD, FORM_POST_INC, FORM_PRE_ADD, FORM_PRE_INC, insert_move_insn_before(), inc_insn::insn, mem_insn::insn, mem_insn::mem_loc, mem_tmp, move_dead_notes(), new_cost(), optimize_bb_for_speed_p(), inc_insn::reg0, inc_insn::reg1, inc_insn::reg1_is_const, reg_next_def, reg_next_inc_use, reg_next_use, inc_insn::reg_res, replace_equiv_address_nv(), set_rtx_cost(), set_src_cost(), and validate_change().

Referenced by try_merge().

static void dump_mem_insn ( )
static
Dump the parsed mem insn to FILE.   

References dump_insn_slim(), mem_insn::insn, mem_insn::reg0, mem_insn::reg1, mem_insn::reg1_is_const, and mem_insn::reg1_val.

Referenced by find_inc(), and merge_in_block().

static int find_address ( )
static
A recursive function that checks all of the mem uses in
   ADDRESS_OF_X to see if any single one of them is compatible with
   what has been found in inc_insn.

   -1 is returned for success.  0 is returned if nothing was found and
   1 is returned for failure.  

References HOST_WIDE_INT, mem_insn::mem_loc, mem_insn::reg0, inc_insn::reg1, mem_insn::reg1, inc_insn::reg1_is_const, mem_insn::reg1_is_const, inc_insn::reg1_val, mem_insn::reg1_val, inc_insn::reg_res, and rtx_equal_p().

Referenced by merge_in_block().

static bool find_inc ( )
static
Once a suitable mem reference has been found and the MEM_INSN
   structure has been filled in, FIND_INC is called to see if there is
   a suitable add or inc insn that follows the mem reference and
   determine if it is suitable to merge.

   In the case where the MEM_INSN has two registers in the reference,
   this function may be called recursively.  The first time looking
   for an add of the first register, and if that fails, looking for an
   add of the second register.  The FIRST_TRY parameter is used to
   only allow the parameters to be reversed once.   

References count_occurrences(), dump_file, dump_inc_insn(), dump_mem_insn(), inc_insn::form, FORM_POST_ADD, FORM_POST_INC, get_next_ref(), inc_insn::insn, mem_insn::insn, mem_insn::mem_loc, parse_add_or_inc(), inc_insn::reg0, mem_insn::reg0, inc_insn::reg1, mem_insn::reg1, inc_insn::reg1_is_const, mem_insn::reg1_is_const, inc_insn::reg1_val, mem_insn::reg1_val, reg_next_def, reg_next_inc_use, reg_next_use, reg_overlap_mentioned_p(), inc_insn::reg_res, reverse_inc(), reverse_mem(), rtx_equal_p(), targetm, and try_merge().

Referenced by find_mem().

static bool find_mem ( )
static
A recursive function that walks ADDRESS_OF_X to find all of the mem
   uses in pat that could be used as an auto inc or dec.  It then
   calls FIND_INC for each one.   

References find_inc(), mem_insn::mem_loc, mem_insn::reg0, mem_insn::reg1, mem_insn::reg1_is_const, and mem_insn::reg1_val.

Referenced by merge_in_block().

static bool gate_auto_inc_dec ( )
static
Discover auto-inc auto-dec instructions.   
static rtx get_next_ref ( )
static
Return the next insn that uses (if reg_next_use is passed in
   NEXT_ARRAY) or defines (if reg_next_def is passed in NEXT_ARRAY)
   REGNO in BB.   

Referenced by find_inc(), and merge_in_block().

static rtx insert_move_insn_before ( )
static
Create a mov insn DEST_REG <- SRC_REG and insert it before
   NEXT_INSN.   

References emit_insn_before(), emit_move_insn(), end_sequence(), get_insns(), and start_sequence().

Referenced by attempt_change().

rtl_opt_pass* make_pass_inc_dec ( )
static void move_dead_notes ( )
static
Move dead note that match PATTERN to TO_INSN from FROM_INSN.  We do
   not really care about moving any other notes from the inc or add
   insn.  Moving the REG_EQUAL and REG_EQUIV is clearly wrong and it
   does not appear that there are any other kinds of relevant notes.   

Referenced by attempt_change().

static bool parse_add_or_inc ( )
static
Return true if INSN is of a form "a = b op c" where a and b are
   regs.  op is + if c is a reg and +|- if c is a const.  Fill in
   INC_INSN with what is found.

   This function is called in two contexts, if BEFORE_MEM is true,
   this is called for each insn in the basic block.  If BEFORE_MEM is
   false, it is called for the instruction in the block that uses the
   index register for some memory reference that is currently being
   processed.   

References inc_insn::form, FORM_POST_ADD, FORM_POST_INC, FORM_PRE_ADD, FORM_PRE_INC, inc_insn::insn, inc_insn::pat, inc_insn::reg0, inc_insn::reg1, inc_insn::reg1_is_const, inc_insn::reg1_val, inc_insn::reg_res, reverse_inc(), and rtx_equal_p().

Referenced by find_inc(), and merge_in_block().

static void reverse_inc ( )
static
Reverse the operands in a inc insn.   

References inc_insn::reg0, and inc_insn::reg1.

Referenced by find_inc(), and parse_add_or_inc().

static void reverse_mem ( )
static
Reverse the operands in a mem insn.   

References mem_insn::reg0, and mem_insn::reg1.

Referenced by find_inc().

static enum inc_state set_inc_state ( )
static
static bool try_merge ( )
static
Try to combine the instruction in INC_INSN with the instruction in
   MEM_INSN.  First the form is determined using the DECISION_TABLE
   and the results of parsing the INC_INSN and the MEM_INSN.
   Assuming the form is ok, a prototype new address is built which is
   passed to ATTEMPT_CHANGE for final processing.   

References attempt_change(), dbg_cnt(), decision_table, DISP_POST, DISP_PRE, dump_file, find_regno_note(), inc_insn::form, FORM_last, FORM_POST_ADD, FORM_POST_INC, FORM_PRE_ADD, FORM_PRE_INC, INC_REG, inc_insn::insn, mem_insn::insn, mem_insn::mem_loc, NOTHING, mem_insn::reg0, inc_insn::reg1, inc_insn::reg1_is_const, mem_insn::reg1_is_const, inc_insn::reg1_state, mem_insn::reg1_state, inc_insn::reg1_val, mem_insn::reg1_val, reg_mode, REG_POST, REG_PRE, inc_insn::reg_res, set_inc_state(), SIMPLE_POST_DEC, SIMPLE_POST_INC, SIMPLE_PRE_DEC, and SIMPLE_PRE_INC.

Referenced by find_inc(), and merge_in_block().


Variable Documentation

enum gen_form decision_table[INC_last][INC_last][FORM_last]
static

Referenced by init_decision_table(), and try_merge().

struct inc_insn inc_insn
static
bool initialized = false
static
The DECISION_TABLE that describes what form, if any, the increment
   or decrement will take. It is a three dimensional table.  The first
   index is the type of constant or register found as the second
   operand of the inc insn.  The second index is the type of constant
   or register found as the second operand of the memory reference (if
   no second operand exists, 0 is used).  The third index is the form
   and location (relative to the mem reference) of inc insn.   

Referenced by alloc_aux_for_blocks(), alloc_aux_for_edges(), df_set_blocks(), dw_loc_list(), dw_sra_loc_expr(), emit_note_insn_var_location(), init_decision_table(), rest_of_handle_auto_inc_dec(), set_slot_part(), and unshare_variable().

struct mem_insn mem_insn
static
rtx mem_tmp
static
Tmp mem rtx for use in cost modeling.   

Referenced by attempt_change(), and rest_of_handle_auto_inc_dec().

rtx* reg_next_def = NULL
static
rtx* reg_next_inc_use = NULL
static
rtx* reg_next_use = NULL
static
The following three arrays contain pointers to instructions. They
   are indexed by REGNO.  At any point in the basic block where we are
   looking these three arrays contain, respectively, the next insn
   that uses REGNO, the next inc or add insn that uses REGNO and the
   next insn that sets REGNO.

   The arrays are not cleared when we move from block to block so
   whenever an insn is retrieved from these arrays, it's block number
   must be compared with the current block.

Referenced by attempt_change(), find_inc(), merge_in_block(), and rest_of_handle_auto_inc_dec().