GCC Middle and Back End API Reference
tree-complex.c File Reference

Typedefs

typedef int complex_lattice_t

Enumerations

enum  { UNINITIALIZED = 0, ONLY_REAL = 1, ONLY_IMAG = 2, VARYING = 3 }

Functions

static tree cvc_lookup ()
static void cvc_insert ()
static int some_nonzerop ()
static complex_lattice_t find_lattice_value_parts ()
static complex_lattice_t find_lattice_value ()
static bool is_complex_reg ()
static void init_parameter_lattice_values ()
static bool init_dont_simulate_again ()
static enum ssa_prop_result complex_visit_stmt (gimple stmt, edge *taken_edge_p, tree *result_p)
static enum ssa_prop_result complex_visit_phi ()
static tree create_one_component_var (tree type, tree orig, const char *prefix, const char *suffix, enum tree_code code)
static tree get_component_var ()
static tree get_component_ssa_name ()
static gimple_seq set_component_ssa_name ()
static tree extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p, bool gimple_p)
static void update_complex_components (gimple_stmt_iterator *gsi, gimple stmt, tree r, tree i)
static void update_complex_components_on_edge ()
static void update_complex_assignment ()
static void update_parameter_components ()
static void update_phi_components ()
static void expand_complex_move ()
static void expand_complex_addition (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai, tree br, tree bi, enum tree_code code, complex_lattice_t al, complex_lattice_t bl)
static void expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai, tree br, tree bi, enum tree_code code)
static void expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai, tree br, tree bi, complex_lattice_t al, complex_lattice_t bl)
static void expand_complex_div_straight (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai, tree br, tree bi, enum tree_code code)
static void expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai, tree br, tree bi, enum tree_code code)
static void expand_complex_division (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai, tree br, tree bi, enum tree_code code, complex_lattice_t al, complex_lattice_t bl)
static void expand_complex_negation (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai)
static void expand_complex_conjugate (gimple_stmt_iterator *gsi, tree inner_type, tree ar, tree ai)
static void expand_complex_comparison (gimple_stmt_iterator *gsi, tree ar, tree ai, tree br, tree bi, enum tree_code code)
static void expand_complex_asm ()
static void expand_complex_operations_1 ()
static unsigned int tree_lower_complex ()
gimple_opt_passmake_pass_lower_complex ()
static bool gate_no_optimization ()
gimple_opt_passmake_pass_lower_complex_O0 ()

Variables

static vec< complex_lattice_tcomplex_lattice_values
static int_tree_htab_type complex_variable_components
static vec< treecomplex_ssa_name_components

Typedef Documentation

typedef int complex_lattice_t
   The type complex_lattice_t holds combinations of the above
   constants.  

Enumeration Type Documentation

anonymous enum
@verbatim 

Lower complex number operations to scalar operations. Copyright (C) 2004-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/.

   For each complex ssa name, a lattice value.  We're interested in finding
   out whether a complex number is degenerate in some way, having only real
   or only complex parts.  
Enumerator:
UNINITIALIZED 
ONLY_REAL 
ONLY_IMAG 
VARYING 

Function Documentation

static enum ssa_prop_result complex_visit_phi ( )
static
   Evaluate a PHI node against the complex lattice defined above.  
     This condition should be satisfied due to the initial filter
     set up in init_dont_simulate_again.  
     We've set up the lattice values such that IOR neatly models PHI meet.  

References create_tmp_var(), and get_identifier().

static enum ssa_prop_result complex_visit_stmt ( gimple  stmt,
edge taken_edge_p,
tree result_p 
)
static
   Evaluate statement STMT against the complex lattice defined above.  
     Skip anything but GIMPLE_ASSIGN and GIMPLE_CALL with a lhs.  
     These conditions should be satisfied due to the initial filter
     set up in init_dont_simulate_again.  
         We've set up the lattice values such that IOR neatly
         models addition.  
         Obviously, if either varies, so does the result.  
         Don't prematurely promote variables if we've not yet seen
         their inputs.  
             At this point both numbers have only one component. If the
             numbers are of opposite kind, the result is imaginary,
             otherwise the result is real. The add/subtract translates
             the real/imag from/to 0/1; the ^ performs the comparison.  
             Don't allow the lattice value to flip-flop indefinitely.  
     If nothing changed this round, let the propagator know.  
static tree create_one_component_var ( tree  type,
tree  orig,
const char *  prefix,
const char *  suffix,
enum tree_code  code 
)
static
   Create one backing variable for a complex component of ORIG.  

References cvc_insert(), and cvc_lookup().

static void cvc_insert ( )
static
   Insert the pair UID, TO into the complex_variable_components hashtable.  

Referenced by create_one_component_var().

static tree cvc_lookup ( )
static
   Lookup UID in the complex_variable_components hashtable and return the
   associated tree.  

Referenced by create_one_component_var().

static void expand_complex_addition ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai,
tree  br,
tree  bi,
enum tree_code  code,
complex_lattice_t  al,
complex_lattice_t  bl 
)
static
@verbatim 

Expand complex addition to scalars: a + b = (ar + br) + i(ai + bi) a - b = (ar - br) + i(ai + bi)

static void expand_complex_asm ( )
static
   Expand inline asm that sets some complex SSA_NAMEs.  
static void expand_complex_comparison ( gimple_stmt_iterator gsi,
tree  ar,
tree  ai,
tree  br,
tree  bi,
enum tree_code  code 
)
static
   Expand complex comparison (EQ or NE only).  
static void expand_complex_conjugate ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai 
)
static
@verbatim 

Expand complex conjugate to scalars: ~a = (ar) + i(-ai)

References GSI_CONTINUE_LINKING, gsi_insert_seq_after(), and set_component_ssa_name().

static void expand_complex_div_straight ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai,
tree  br,
tree  bi,
enum tree_code  code 
)
static
@verbatim 

Keep this algorithm in sync with fold-const.c:const_binop().

Expand complex division to scalars, straightforward algorithm. a / b = ((ar*br + ai*bi)/t) + i((ai*br - ar*bi)/t) t = br*br + bi*bi

static void expand_complex_div_wide ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai,
tree  br,
tree  bi,
enum tree_code  code 
)
static
   Keep this algorithm in sync with fold-const.c:const_binop().

   Expand complex division to scalars, modified algorithm to minimize
   overflow with wide input ranges.  
     Examine |br| < |bi|, and branch.  
         Split the original block, and create the TRUE and FALSE blocks.  
         Wire the blocks together.  
         Update dominance info.  Note that bb_join's data was
         updated by split_block.  
     In the TRUE branch, we compute
      ratio = br/bi;
      div = (br * ratio) + bi;
      tr = (ar * ratio) + ai;
      ti = (ai * ratio) - ar;
      tr = tr / div;
      ti = ti / div;  
     In the FALSE branch, we compute
      ratio = d/c;
      divisor = (d * ratio) + c;
      tr = (b * ratio) + a;
      ti = b - (a * ratio);
      tr = tr / div;
      ti = ti / div;  
static void expand_complex_division ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai,
tree  br,
tree  bi,
enum tree_code  code,
complex_lattice_t  al,
complex_lattice_t  bl 
)
static
   Expand complex division to scalars.  
             straightforward implementation of complex divide acceptable.  
             FALLTHRU 
             wide ranges of inputs must work for complex divide.  
static void expand_complex_libcall ( gimple_stmt_iterator gsi,
tree  ar,
tree  ai,
tree  br,
tree  bi,
enum tree_code  code 
)
static
   Expand a complex multiplication or division to a libcall to the c99
   compliant routines.  

References dconst1, gimplify_build1(), gimplify_build2(), ONLY_REAL, and VARYING.

static void expand_complex_move ( )
static
   Expand a complex move to scalars.  
             The value is not assigned on the exception edges, so we need not
             concern ourselves there.  We do need to update on the fallthru
             edge.  Find it.  
static void expand_complex_multiplication ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai,
tree  br,
tree  bi,
complex_lattice_t  al,
complex_lattice_t  bl 
)
static
@verbatim 

Expand complex multiplication to scalars: a * b = (ar*br - ai*bi) + i(ar*bi + br*ai)

             Avoid expanding redundant multiplication for the common
             case of squaring a complex number.  
static void expand_complex_negation ( gimple_stmt_iterator gsi,
tree  inner_type,
tree  ar,
tree  ai 
)
static
@verbatim 

Expand complex negation to scalars: -a = (-ar) + i(-ai)

static void expand_complex_operations_1 ( )
static
   Process one statement.  If we identify a complex operation, expand it.  
     Initial filter for operations we handle.  
         Note, both GIMPLE_ASSIGN and GIMPLE_COND may have an EQ_EXPR
         subcode, so we need to access the operands using gimple_op.  
           GIMPLE_COND may also fallthru here, but we do not need to
           do anything with it.  
     Extract the components of the two complex values.  Make sure and
     handle the common case of the same value used twice specially.  
     GIMPLE_CALL can not get here.  
static tree extract_component ( gimple_stmt_iterator gsi,
tree  t,
bool  imagpart_p,
bool  gimple_p 
)
static
   Extract the real or imaginary part of a complex variable or constant.
   Make sure that it's a proper gimple_val and gimplify it if not.
   Emit any new code before gsi.  

References gimple_get_lhs(), GSI_CONTINUE_LINKING, gsi_insert_seq_after(), and set_component_ssa_name().

static complex_lattice_t find_lattice_value ( )
static
   Compute a lattice value from gimple_val T.  
static complex_lattice_t find_lattice_value_parts ( )
static
   Compute a lattice value from the components of a complex type REAL
   and IMAG.  
     ??? On occasion we could do better than mapping 0+0i to real, but we
     certainly don't want to leave it UNINITIALIZED, which eventually gets
     mapped to VARYING.  
static bool gate_no_optimization ( )
static
     With errors, normal optimization passes are not run.  If we don't
     lower complex operations at all, rtl expansion will abort.  
static tree get_component_ssa_name ( )
static
   Retrieve a value for a complex component of SSA_NAME.  
         Copy some properties from the original.  In particular, whether it
         is used in an abnormal phi, and whether it's uninitialized.  

Referenced by update_complex_assignment().

static tree get_component_var ( )
static
   Retrieve a value for a complex component of VAR.  

Referenced by set_component_ssa_name().

static bool init_dont_simulate_again ( )
static
   Initialize simulation state for each statement.  Return false if we
   found no statements we want to simulate, and thus there's nothing
   for the entire pass to do.  
             Most control-altering statements must be initially
             simulated, else we won't cover the entire cfg.  
                   The total store transformation performed during
                  gimplification creates such uninitialized loads
                  and we need to lower the statement to be able
                  to fix things up.  
static void init_parameter_lattice_values ( )
static
   Mark the incoming parameters to the function as VARYING.  

References gimple_phi_result(), gsi_end_p(), gsi_next(), gsi_start_phis(), gsi_stmt(), is_complex_reg(), and prop_set_simulate_again().

static bool is_complex_reg ( )
static
   Determine if LHS is something for which we're interested in seeing
   simulation results.  

Referenced by init_parameter_lattice_values(), and update_complex_assignment().

gimple_opt_pass* make_pass_lower_complex ( )
gimple_opt_pass* make_pass_lower_complex_O0 ( )
static gimple_seq set_component_ssa_name ( )
static
   Set a value for a complex component of SSA_NAME, return a
   gimple_seq of stuff that needs doing.  
     We know the value must be zero, else there's a bug in our lattice
     analysis.  But the value may well be a variable known to contain
     zero.  We should be safe ignoring it.  
     If we've already assigned an SSA_NAME to this component, then this
     means that our walk of the basic blocks found a use before the set.
     This is fine.  Now we should create an initialization for the value
     we created earlier.  
     If we've nothing assigned, and the value we're given is already stable,
     then install that as the value for this SSA_NAME.  This preemptively
     copy-propagates the value, which avoids unnecessary memory allocation.  
         Replace an anonymous base value with the variable from cvc_lookup.
         This should result in better debug info.  
     Finally, we need to stabilize the result by installing the value into
     a new ssa name.  
     Do all the work to assign VALUE to COMP.  

References get_component_var(), and replace_ssa_name_symbol().

Referenced by expand_complex_conjugate(), and extract_component().

static int some_nonzerop ( )
static
   Return true if T is not a zero constant.  In the case of real values,
   we're only interested in +0.0.  
     Operations with real or imaginary part of a complex number zero
     cannot be treated the same as operations with a real or imaginary
     operand if we care about the signs of zeros in the result.  
static unsigned int tree_lower_complex ( )
static
   Entry point for complex operation lowering during optimization.  
     ??? Ideally we'd traverse the blocks in breadth-first order.  
static void update_complex_assignment ( )
static
   Update an assignment to a complex variable in place.  

References get_component_ssa_name(), gimple_phi_result(), gsi_end_p(), gsi_next(), gsi_start_phis(), gsi_stmt(), and is_complex_reg().

static void update_complex_components ( gimple_stmt_iterator gsi,
gimple  stmt,
tree  r,
tree  i 
)
static
   Update the complex components of the ssa name on the lhs of STMT.  
static void update_complex_components_on_edge ( )
static
static void update_parameter_components ( )
static
   Generate code at the entry point of the function to initialize the
   component variables for a complex parameter.  
static void update_phi_components ( )
static
   Generate code to set the component variables of a complex variable
   to match the PHI statements in block BB.  

Variable Documentation

vec<complex_lattice_t> complex_lattice_values
static
vec<tree> complex_ssa_name_components
static
   For each complex SSA_NAME, a pair of ssa names for the components.  
int_tree_htab_type complex_variable_components
static
   For each complex variable, a pair of variables for the components exists in
   the hashtable.