GCC Middle and Back End API Reference
tree-complex.c File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "gimple.h"
#include "gimple-ssa.h"
#include "tree-cfg.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
#include "tree-ssanames.h"
#include "tree-dfa.h"
#include "tree-ssa.h"
#include "tree-iterator.h"
#include "tree-pass.h"
#include "tree-ssa-propagate.h"
#include "tree-hasher.h"
#include "cfgloop.h"
Include dependency graph for tree-complex.c:

Macros

#define PAIR(a, b)   ((a) << 2 | (b))

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

Macro Definition Documentation

#define PAIR (   a,
 
)    ((a) << 2 | (b))

Referenced by expand_complex_libcall().


Typedef Documentation

typedef int complex_lattice_t

The type complex_lattice_t holds combinations of the above constants.


Enumeration Type Documentation

anonymous enum

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 build1, create_tmp_var, DECL_ARTIFICIAL, DECL_HAS_DEBUG_EXPR_P, DECL_IGNORED_P, DECL_NAME, DECL_SOURCE_LOCATION, get_identifier(), IDENTIFIER_POINTER, NULL, SET_DECL_DEBUG_EXPR, and TREE_NO_WARNING.

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(), cvc_lookup(), DECL_UID, NULL, and TREE_TYPE.

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

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

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

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

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

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, PAIR, REAL_VALUES_IDENTICAL, SCALAR_FLOAT_TYPE_P, TREE_CODE, TREE_REAL_CST, 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

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

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 FOR_EACH_BB, 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 DECL_IGNORED_P, get_component_var(), NULL, replace_ssa_name_symbol(), and SSA_NAME_VAR.

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(), is_complex_reg(), NULL, and TREE_CODE.

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.