GCC Middle and Back End API Reference
fwprop.c File Reference

Enumerations

enum  { PR_CAN_APPEAR = 1, PR_HANDLE_MEM = 2, PR_OPTIMIZE_FOR_SPEED = 4 }

Functions

static df_ref get_def_for_use ()
static void process_defs ()
static void process_uses ()
static void single_def_use_enter_block (struct dom_walk_data *walk_data, basic_block bb)
static void single_def_use_leave_block (struct dom_walk_data *walk_data, basic_block bb)
static void build_single_def_use_links ()
static bool can_simplify_addr ()
static void canonicalize_address ()
static bool should_replace_address (rtx old_rtx, rtx new_rtx, enum machine_mode mode, addr_space_t as, bool speed)
static bool propagate_rtx_1 ()
static int varying_mem_p ()
static rtx propagate_rtx (rtx x, enum machine_mode mode, rtx old_rtx, rtx new_rtx, bool speed)
static bool local_ref_killed_between_p ()
static bool use_killed_between ()
static bool all_uses_available_at ()
static void register_active_defs ()
static void update_df_init ()
static void update_uses ()
static void update_df ()
static bool try_fwprop_subst ()
static bool free_load_extend ()
static bool forward_propagate_subreg ()
static bool forward_propagate_asm ()
static bool forward_propagate_and_simplify ()
static bool forward_propagate_into ()
static void fwprop_init ()
static void fwprop_done ()
static bool gate_fwprop ()
static unsigned int fwprop ()
rtl_opt_passmake_pass_rtl_fwprop ()
static unsigned int fwprop_addr ()
rtl_opt_passmake_pass_rtl_fwprop_addr ()

Variables

static int num_changes
static vec< df_refuse_def_ref
static vec< df_refreg_defs
static vec< df_refreg_defs_stack
static bitmap local_md
static bitmap local_lr
static df_refactive_defs
static sparseset active_defs_check

Enumeration Type Documentation

anonymous enum
Flags for the last parameter of propagate_rtx_1.   
Enumerator:
PR_CAN_APPEAR 
PR_HANDLE_MEM 
PR_OPTIMIZE_FOR_SPEED 

Function Documentation

static bool all_uses_available_at ( )
static
Check if all uses in DEF_INSN can be used in TARGET_INSN.  This
   would require full computation of available expressions;
   we check only restricted conditions, see use_killed_between.   

References rtx_equal_p(), and use_killed_between().

Referenced by forward_propagate_and_simplify(), and forward_propagate_subreg().

static bool can_simplify_addr ( )
static
Do not try to replace constant addresses or addresses of local and
   argument slots.  These MEM expressions are made only once and inserted
   in many instructions, as well as being used to control symbol table
   output.  It is not safe to clobber them.

   There are some uncommon cases where the address is already in a register
   for some reason, but we cannot take advantage of that because we have
   no easy way to unshare the MEM.  In addition, looking up all stack
   addresses is costly.   

Referenced by propagate_rtx_1().

static void canonicalize_address ( )
static
Returns a canonical version of X for the address, from the point of view,
   that all multiplications are represented as MULT instead of the multiply
   by a power of 2 being represented as ASHIFT.

   Every ASHIFT we find has been made by simplify_gen_binary and was not
   there before, so it is not shared.  So we can do this in place.   

References gen_int_mode(), HOST_WIDE_INT, and shift.

Referenced by propagate_rtx_1().

static bool forward_propagate_asm ( )
static
static bool forward_propagate_into ( )
static
Given a use USE of an insn, if it has a single reaching
   definition, try to forward propagate it into that insn.
   Return true if cfg cleanup will be needed.   

References function::can_throw_non_call_exceptions, cfun, DF_REF_IN_NOTE, DF_REF_READ_WRITE, find_reg_note(), forward_propagate_and_simplify(), forward_propagate_subreg(), get_def_for_use(), multiple_sets(), purge_dead_edges(), and reg_mentioned_p().

Referenced by fwprop(), and fwprop_addr().

static bool forward_propagate_subreg ( )
static
If USE is a subreg, see if it can be replaced by a pseudo.   

References all_uses_available_at(), free_load_extend(), subreg_lowpart_p(), targetm, try_fwprop_subst(), and use_reg().

Referenced by forward_propagate_into().

static bool free_load_extend ( )
static
For the given single_set INSN, containing SRC known to be a
   ZERO_EXTEND or SIGN_EXTEND of a register, return true if INSN
   is redundant due to the register being set by a LOAD_EXTEND_OP
   load from memory.   

References DF_REF_REG_USE, get_def_for_use(), rtx_equal_p(), and SET.

Referenced by forward_propagate_subreg().

static unsigned int fwprop ( )
static
static unsigned int fwprop_addr ( )
static
static bool gate_fwprop ( )
static
Main entry point.   
static df_ref get_def_for_use ( )
inlinestatic
Return the only def in USE's use-def chain, or NULL if there is
   more than one def in the chain.   

Referenced by forward_propagate_into(), free_load_extend(), and register_active_defs().

static bool local_ref_killed_between_p ( )
static
Return true if the register from reference REF is killed
   between FROM to (but not including) TO.   

Referenced by use_killed_between().

rtl_opt_pass* make_pass_rtl_fwprop ( )
rtl_opt_pass* make_pass_rtl_fwprop_addr ( )
static void process_defs ( )
static
static void process_uses ( )
static
Fill the use_def_ref vector with values for the uses in USE_REC,
   taking reaching definitions info from LOCAL_MD and REG_DEFS.
   TOP_FLAG says which artificials uses should be used, when USE_REC
   is an artificial use vector.   

References bitmap_bit_p(), and DF_REF_AT_TOP.

Referenced by single_def_use_enter_block().

static rtx propagate_rtx ( rtx  x,
enum machine_mode  mode,
rtx  old_rtx,
rtx  new_rtx,
bool  speed 
)
static
Replace all occurrences of OLD in X with NEW and try to simplify the
   resulting expression (in mode MODE).  Return a new expression if it is
   a constant, otherwise X.

   Simplifications where occurrences of NEW collapse to a constant are always
   accepted.  All simplifications are accepted if NEW is a pseudo too.
   Otherwise, we accept simplifications that have a lower or equal cost.   

References copy_rtx(), for_each_rtx(), rtl_hooks::gen_lowpart_no_emit, PR_CAN_APPEAR, PR_HANDLE_MEM, PR_OPTIMIZE_FOR_SPEED, propagate_rtx_1(), and varying_mem_p().

Referenced by forward_propagate_and_simplify(), and forward_propagate_asm().

static bool propagate_rtx_1 ( )
static
Replace all occurrences of OLD in *PX with NEW and try to simplify the
   resulting expression.  Replace *PX with a new RTL expression if an
   occurrence of OLD was found.

   This is only a wrapper around simplify-rtx.c: do not add any pattern
   matching code here.  (The sole exception is the handling of LO_SUM, but
   that is because there is no simplify_gen_* function for LO_SUM).   

References can_simplify_addr(), canonicalize_address(), PR_CAN_APPEAR, PR_HANDLE_MEM, PR_OPTIMIZE_FOR_SPEED, replace_equiv_address_nv(), RTX_BIN_ARITH, RTX_BITFIELD_OPS, RTX_COMM_ARITH, RTX_COMM_COMPARE, RTX_COMPARE, rtx_equal_p(), RTX_EXTRA, RTX_OBJ, RTX_TERNARY, RTX_UNARY, should_replace_address(), side_effects_p(), simplify_gen_binary(), simplify_gen_relational(), simplify_gen_subreg(), simplify_gen_ternary(), simplify_gen_unary(), and targetm.

Referenced by propagate_rtx().

static void register_active_defs ( )
static
Fill the ACTIVE_DEFS array with the use->def link for the registers
   mentioned in USE_REC.  Register the valid entries in ACTIVE_DEFS_CHECK
   too, for checking purposes.   

References get_def_for_use(), and sparseset_set_bit().

Referenced by update_df_init().

static bool should_replace_address ( rtx  old_rtx,
rtx  new_rtx,
enum machine_mode  mode,
addr_space_t  as,
bool  speed 
)
static
OLD is a memory address.  Return whether it is good to use NEW instead,
   for a memory access in the given MODE.   

References address_cost(), memory_address_addr_space_p(), rtx_equal_p(), and set_src_cost().

Referenced by propagate_rtx_1().

static void single_def_use_leave_block ( struct dom_walk_data walk_data,
basic_block  bb 
)
static
Pop the definitions created in this basic block when leaving its
   dominated parts.   

Referenced by build_single_def_use_links().

static bool try_fwprop_subst ( )
static
Try substituting NEW into LOC, which originated from forward propagation
   of USE's value from DEF_INSN.  SET_REG_EQUAL says whether we are
   substituting the whole SET_SRC, so we can set a REG_EQUAL note if the
   new insn is not recognized.  Return whether the substitution was
   performed.   

References cancel_changes(), confirm_change_group(), copy_rtx(), DF_REF_REG_USE, dump_file, df_insn_info::insn, num_changes, optimize_bb_for_speed_p(), print_inline_rtx(), set_src_cost(), set_unique_reg_note(), update_df(), update_df_init(), validate_unshare_change(), and verify_changes().

Referenced by forward_propagate_and_simplify(), and forward_propagate_subreg().

static void update_df ( )
static
Update the USE_DEF_REF array for the uses in INSN.  Only update note
   uses if NOTES_ONLY is true.   

References df_insn_rescan(), df_notes_rescan(), DF_REF_IN_NOTE, df_uses_create(), and update_uses().

Referenced by forward_propagate_asm(), and try_fwprop_subst().

static void update_df_init ( )
static
Build the use->def links that we use to update the dataflow info
   for new uses.  Note that building the links is very cheap and if
   it were done earlier, they could be used to rule out invalid
   propagations (in addition to what is done in all_uses_available_at).
   I'm not doing this yet, though.   

References register_active_defs(), and sparseset_clear().

Referenced by forward_propagate_asm(), and try_fwprop_subst().

static void update_uses ( )
inlinestatic
Update the USE_DEF_REF array for the given use, using the active definitions
   in the ACTIVE_DEFS array to match pseudos to their def.  

References sparseset_bit_p().

Referenced by update_df().

static bool use_killed_between ( )
static
Check if the given DEF is available in INSN.  This would require full
   computation of available expressions; we check only restricted conditions:
   - if DEF is the sole definition of its register, go ahead;
   - in the same basic block, we check for no definitions killing the
     definition of DEF_INSN;
   - if USE's basic block has DEF's basic block as the sole predecessor,
     we check if the definition is killed after DEF_INSN or before
     TARGET_INSN insn, in their respective basic blocks.   

References CDI_DOMINATORS, df_bb_regno_first_def_find(), df_bb_regno_last_def_find(), dominated_by_p(), local_ref_killed_between_p(), single_pred(), single_pred_p(), and target_bb.

Referenced by all_uses_available_at().

static int varying_mem_p ( )
static
for_each_rtx traversal function that returns 1 if BODY points to
   a non-constant mem.   

Referenced by propagate_rtx().


Variable Documentation

df_ref* active_defs
static
sparseset active_defs_check
static
bitmap local_lr
static
bitmap local_md
static
The MD bitmaps are trimmed to include only live registers to cut
   memory usage on testcases like insn-recog.c.  Track live registers
   in the basic block and do not perform forward propagation if the
   destination is a dead pseudo occurring in a note.   
int num_changes
static
@verbatim RTL-based forward propagation pass for GNU compiler.

Copyright (C) 2005-2013 Free Software Foundation, Inc. Contributed by Paolo Bonzini and Steven Bosscher.

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 does simple forward propagation and simplification when an
   operand of an insn can only come from a single def.  This pass uses
   df.c, so it is global.  However, we only do limited analysis of
   available expressions.

   1) The pass tries to propagate the source of the def into the use,
   and checks if the result is independent of the substituted value.
   For example, the high word of a (zero_extend:DI (reg:SI M)) is always
   zero, independent of the source register.

   In particular, we propagate constants into the use site.  Sometimes
   RTL expansion did not put the constant in the same insn on purpose,
   to satisfy a predicate, and the result will fail to be recognized;
   but this happens rarely and in this case we can still create a
   REG_EQUAL note.  For multi-word operations, this

      (set (subreg:SI (reg:DI 120) 0) (const_int 0))
      (set (subreg:SI (reg:DI 120) 4) (const_int -1))
      (set (subreg:SI (reg:DI 122) 0)
         (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0)))
      (set (subreg:SI (reg:DI 122) 4)
         (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4)))

   can be simplified to the much simpler

      (set (subreg:SI (reg:DI 122) 0) (subreg:SI (reg:DI 119)))
      (set (subreg:SI (reg:DI 122) 4) (const_int -1))

   This particular propagation is also effective at putting together
   complex addressing modes.  We are more aggressive inside MEMs, in
   that all definitions are propagated if the use is in a MEM; if the
   result is a valid memory address we check address_cost to decide
   whether the substitution is worthwhile.

   2) The pass propagates register copies.  This is not as effective as
   the copy propagation done by CSE's canon_reg, which works by walking
   the instruction chain, it can help the other transformations.

   We should consider removing this optimization, and instead reorder the
   RTL passes, because GCSE does this transformation too.  With some luck,
   the CSE pass at the end of rest_of_handle_gcse could also go away.

   3) The pass looks for paradoxical subregs that are actually unnecessary.
   Things like this:

     (set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
     (set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
     (set (reg:SI 122) (plus:SI (subreg:SI (reg:QI 120) 0)
                                (subreg:SI (reg:QI 121) 0)))

   are very common on machines that can only do word-sized operations.
   For each use of a paradoxical subreg (subreg:WIDER (reg:NARROW N) 0),
   if it has a single def and it is (subreg:NARROW (reg:WIDE M) 0),
   we can replace the paradoxical subreg with simply (reg:WIDE M).  The
   above will simplify this to

     (set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
     (set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
     (set (reg:SI 122) (plus:SI (reg:SI 118) (reg:SI 119)))

   where the first two insns are now dead.

   We used to use reaching definitions to find which uses have a
   single reaching definition (sounds obvious...), but this is too
   complex a problem in nasty testcases like PR33928.  Now we use the
   multiple definitions problem in df-problems.c.  The similarity
   between that problem and SSA form creation is taken further, in
   that fwprop does a dominator walk to create its chains; however,
   instead of creating a PHI function where multiple definitions meet
   I just punt and record only singleton use-def chains, which is
   all that is needed by fwprop.   

Referenced by forward_propagate_asm(), fwprop_done(), fwprop_init(), and try_fwprop_subst().

vec<df_ref> reg_defs
static
vec<df_ref> reg_defs_stack
static
vec<df_ref> use_def_ref
static