1169689Skan/* Lower complex number operations to scalar operations.
2169689Skan   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3169689Skan
4169689SkanThis file is part of GCC.
5169689Skan
6169689SkanGCC is free software; you can redistribute it and/or modify it
7169689Skanunder the terms of the GNU General Public License as published by the
8169689SkanFree Software Foundation; either version 2, or (at your option) any
9169689Skanlater version.
10169689Skan
11169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT
12169689SkanANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14169689Skanfor more details.
15169689Skan
16169689SkanYou should have received a copy of the GNU General Public License
17169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
18169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19169689Skan02110-1301, USA.  */
20169689Skan
21169689Skan#include "config.h"
22169689Skan#include "system.h"
23169689Skan#include "coretypes.h"
24169689Skan#include "tm.h"
25169689Skan#include "tree.h"
26169689Skan#include "rtl.h"
27169689Skan#include "real.h"
28169689Skan#include "flags.h"
29169689Skan#include "tree-flow.h"
30169689Skan#include "tree-gimple.h"
31169689Skan#include "tree-iterator.h"
32169689Skan#include "tree-pass.h"
33169689Skan#include "tree-ssa-propagate.h"
34169689Skan#include "diagnostic.h"
35169689Skan
36169689Skan
37169689Skan/* For each complex ssa name, a lattice value.  We're interested in finding
38169689Skan   out whether a complex number is degenerate in some way, having only real
39169689Skan   or only complex parts.  */
40169689Skan
41169689Skantypedef enum
42169689Skan{
43169689Skan  UNINITIALIZED = 0,
44169689Skan  ONLY_REAL = 1,
45169689Skan  ONLY_IMAG = 2,
46169689Skan  VARYING = 3
47169689Skan} complex_lattice_t;
48169689Skan
49169689Skan#define PAIR(a, b)  ((a) << 2 | (b))
50169689Skan
51169689SkanDEF_VEC_I(complex_lattice_t);
52169689SkanDEF_VEC_ALLOC_I(complex_lattice_t, heap);
53169689Skan
54169689Skanstatic VEC(complex_lattice_t, heap) *complex_lattice_values;
55169689Skan
56169689Skan/* For each complex variable, a pair of variables for the components exists in
57169689Skan   the hashtable.  */
58169689Skanstatic htab_t complex_variable_components;
59169689Skan
60169689Skan/* For each complex SSA_NAME, a pair of ssa names for the components.  */
61169689Skanstatic VEC(tree, heap) *complex_ssa_name_components;
62169689Skan
63169689Skan/* Lookup UID in the complex_variable_components hashtable and return the
64169689Skan   associated tree.  */
65169689Skanstatic tree
66169689Skancvc_lookup (unsigned int uid)
67169689Skan{
68169689Skan  struct int_tree_map *h, in;
69169689Skan  in.uid = uid;
70169689Skan  h = htab_find_with_hash (complex_variable_components, &in, uid);
71169689Skan  return h ? h->to : NULL;
72169689Skan}
73169689Skan
74169689Skan/* Insert the pair UID, TO into the complex_variable_components hashtable.  */
75169689Skan
76169689Skanstatic void
77169689Skancvc_insert (unsigned int uid, tree to)
78169689Skan{
79169689Skan  struct int_tree_map *h;
80169689Skan  void **loc;
81169689Skan
82169689Skan  h = XNEW (struct int_tree_map);
83169689Skan  h->uid = uid;
84169689Skan  h->to = to;
85169689Skan  loc = htab_find_slot_with_hash (complex_variable_components, h,
86169689Skan				  uid, INSERT);
87169689Skan  *(struct int_tree_map **) loc = h;
88169689Skan}
89169689Skan
90169689Skan/* Return true if T is not a zero constant.  In the case of real values,
91169689Skan   we're only interested in +0.0.  */
92169689Skan
93169689Skanstatic int
94169689Skansome_nonzerop (tree t)
95169689Skan{
96169689Skan  int zerop = false;
97169689Skan
98169689Skan  if (TREE_CODE (t) == REAL_CST)
99169689Skan    zerop = REAL_VALUES_IDENTICAL (TREE_REAL_CST (t), dconst0);
100169689Skan  else if (TREE_CODE (t) == INTEGER_CST)
101169689Skan    zerop = integer_zerop (t);
102169689Skan
103169689Skan  return !zerop;
104169689Skan}
105169689Skan
106169689Skan/* Compute a lattice value from T.  It may be a gimple_val, or, as a
107169689Skan   special exception, a COMPLEX_EXPR.  */
108169689Skan
109169689Skanstatic complex_lattice_t
110169689Skanfind_lattice_value (tree t)
111169689Skan{
112169689Skan  tree real, imag;
113169689Skan  int r, i;
114169689Skan  complex_lattice_t ret;
115169689Skan
116169689Skan  switch (TREE_CODE (t))
117169689Skan    {
118169689Skan    case SSA_NAME:
119169689Skan      return VEC_index (complex_lattice_t, complex_lattice_values,
120169689Skan			SSA_NAME_VERSION (t));
121169689Skan
122169689Skan    case COMPLEX_CST:
123169689Skan      real = TREE_REALPART (t);
124169689Skan      imag = TREE_IMAGPART (t);
125169689Skan      break;
126169689Skan
127169689Skan    case COMPLEX_EXPR:
128169689Skan      real = TREE_OPERAND (t, 0);
129169689Skan      imag = TREE_OPERAND (t, 1);
130169689Skan      break;
131169689Skan
132169689Skan    default:
133169689Skan      gcc_unreachable ();
134169689Skan    }
135169689Skan
136169689Skan  r = some_nonzerop (real);
137169689Skan  i = some_nonzerop (imag);
138169689Skan  ret = r*ONLY_REAL + i*ONLY_IMAG;
139169689Skan
140169689Skan  /* ??? On occasion we could do better than mapping 0+0i to real, but we
141169689Skan     certainly don't want to leave it UNINITIALIZED, which eventually gets
142169689Skan     mapped to VARYING.  */
143169689Skan  if (ret == UNINITIALIZED)
144169689Skan    ret = ONLY_REAL;
145169689Skan
146169689Skan  return ret;
147169689Skan}
148169689Skan
149169689Skan/* Determine if LHS is something for which we're interested in seeing
150169689Skan   simulation results.  */
151169689Skan
152169689Skanstatic bool
153169689Skanis_complex_reg (tree lhs)
154169689Skan{
155169689Skan  return TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE && is_gimple_reg (lhs);
156169689Skan}
157169689Skan
158169689Skan/* Mark the incoming parameters to the function as VARYING.  */
159169689Skan
160169689Skanstatic void
161169689Skaninit_parameter_lattice_values (void)
162169689Skan{
163169689Skan  tree parm;
164169689Skan
165169689Skan  for (parm = DECL_ARGUMENTS (cfun->decl); parm ; parm = TREE_CHAIN (parm))
166169689Skan    if (is_complex_reg (parm) && var_ann (parm) != NULL)
167169689Skan      {
168169689Skan	tree ssa_name = default_def (parm);
169169689Skan	VEC_replace (complex_lattice_t, complex_lattice_values,
170169689Skan		     SSA_NAME_VERSION (ssa_name), VARYING);
171169689Skan      }
172169689Skan}
173169689Skan
174169689Skan/* Initialize DONT_SIMULATE_AGAIN for each stmt and phi.  Return false if
175169689Skan   we found no statements we want to simulate, and thus there's nothing for
176169689Skan   the entire pass to do.  */
177169689Skan
178169689Skanstatic bool
179169689Skaninit_dont_simulate_again (void)
180169689Skan{
181169689Skan  basic_block bb;
182169689Skan  block_stmt_iterator bsi;
183169689Skan  tree phi;
184169689Skan  bool saw_a_complex_op = false;
185169689Skan
186169689Skan  FOR_EACH_BB (bb)
187169689Skan    {
188169689Skan      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
189169689Skan	DONT_SIMULATE_AGAIN (phi) = !is_complex_reg (PHI_RESULT (phi));
190169689Skan
191169689Skan      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
192169689Skan	{
193169689Skan	  tree orig_stmt, stmt, rhs = NULL;
194169689Skan	  bool dsa;
195169689Skan
196169689Skan	  orig_stmt = stmt = bsi_stmt (bsi);
197169689Skan
198169689Skan	  /* Most control-altering statements must be initially
199169689Skan	     simulated, else we won't cover the entire cfg.  */
200169689Skan	  dsa = !stmt_ends_bb_p (stmt);
201169689Skan
202169689Skan	  switch (TREE_CODE (stmt))
203169689Skan	    {
204169689Skan	    case RETURN_EXPR:
205169689Skan	      /* We don't care what the lattice value of <retval> is,
206169689Skan		 since it's never used as an input to another computation.  */
207169689Skan	      dsa = true;
208169689Skan	      stmt = TREE_OPERAND (stmt, 0);
209169689Skan	      if (!stmt || TREE_CODE (stmt) != MODIFY_EXPR)
210169689Skan		break;
211169689Skan	      /* FALLTHRU */
212169689Skan
213169689Skan	    case MODIFY_EXPR:
214169689Skan	      dsa = !is_complex_reg (TREE_OPERAND (stmt, 0));
215169689Skan	      rhs = TREE_OPERAND (stmt, 1);
216169689Skan	      break;
217169689Skan
218169689Skan	    case COND_EXPR:
219169689Skan	      rhs = TREE_OPERAND (stmt, 0);
220169689Skan	      break;
221169689Skan
222169689Skan	    default:
223169689Skan	      break;
224169689Skan	    }
225169689Skan
226169689Skan	  if (rhs)
227169689Skan	    switch (TREE_CODE (rhs))
228169689Skan	      {
229169689Skan	      case EQ_EXPR:
230169689Skan	      case NE_EXPR:
231169689Skan		rhs = TREE_OPERAND (rhs, 0);
232169689Skan		/* FALLTHRU */
233169689Skan
234169689Skan	      case PLUS_EXPR:
235169689Skan	      case MINUS_EXPR:
236169689Skan	      case MULT_EXPR:
237169689Skan	      case TRUNC_DIV_EXPR:
238169689Skan	      case CEIL_DIV_EXPR:
239169689Skan	      case FLOOR_DIV_EXPR:
240169689Skan	      case ROUND_DIV_EXPR:
241169689Skan	      case RDIV_EXPR:
242169689Skan	      case NEGATE_EXPR:
243169689Skan	      case CONJ_EXPR:
244169689Skan		if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE)
245169689Skan		  saw_a_complex_op = true;
246169689Skan		break;
247169689Skan
248169689Skan	      default:
249169689Skan		break;
250169689Skan	      }
251169689Skan
252169689Skan	  DONT_SIMULATE_AGAIN (orig_stmt) = dsa;
253169689Skan	}
254169689Skan    }
255169689Skan
256169689Skan  return saw_a_complex_op;
257169689Skan}
258169689Skan
259169689Skan
260169689Skan/* Evaluate statement STMT against the complex lattice defined above.  */
261169689Skan
262169689Skanstatic enum ssa_prop_result
263169689Skancomplex_visit_stmt (tree stmt, edge *taken_edge_p ATTRIBUTE_UNUSED,
264169689Skan		    tree *result_p)
265169689Skan{
266169689Skan  complex_lattice_t new_l, old_l, op1_l, op2_l;
267169689Skan  unsigned int ver;
268169689Skan  tree lhs, rhs;
269169689Skan
270169689Skan  if (TREE_CODE (stmt) != MODIFY_EXPR)
271169689Skan    return SSA_PROP_VARYING;
272169689Skan
273169689Skan  lhs = TREE_OPERAND (stmt, 0);
274169689Skan  rhs = TREE_OPERAND (stmt, 1);
275169689Skan
276169689Skan  /* These conditions should be satisfied due to the initial filter
277169689Skan     set up in init_dont_simulate_again.  */
278169689Skan  gcc_assert (TREE_CODE (lhs) == SSA_NAME);
279169689Skan  gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
280169689Skan
281169689Skan  *result_p = lhs;
282169689Skan  ver = SSA_NAME_VERSION (lhs);
283169689Skan  old_l = VEC_index (complex_lattice_t, complex_lattice_values, ver);
284169689Skan
285169689Skan  switch (TREE_CODE (rhs))
286169689Skan    {
287169689Skan    case SSA_NAME:
288169689Skan    case COMPLEX_EXPR:
289169689Skan    case COMPLEX_CST:
290169689Skan      new_l = find_lattice_value (rhs);
291169689Skan      break;
292169689Skan
293169689Skan    case PLUS_EXPR:
294169689Skan    case MINUS_EXPR:
295169689Skan      op1_l = find_lattice_value (TREE_OPERAND (rhs, 0));
296169689Skan      op2_l = find_lattice_value (TREE_OPERAND (rhs, 1));
297169689Skan
298169689Skan      /* We've set up the lattice values such that IOR neatly
299169689Skan	 models addition.  */
300169689Skan      new_l = op1_l | op2_l;
301169689Skan      break;
302169689Skan
303169689Skan    case MULT_EXPR:
304169689Skan    case RDIV_EXPR:
305169689Skan    case TRUNC_DIV_EXPR:
306169689Skan    case CEIL_DIV_EXPR:
307169689Skan    case FLOOR_DIV_EXPR:
308169689Skan    case ROUND_DIV_EXPR:
309169689Skan      op1_l = find_lattice_value (TREE_OPERAND (rhs, 0));
310169689Skan      op2_l = find_lattice_value (TREE_OPERAND (rhs, 1));
311169689Skan
312169689Skan      /* Obviously, if either varies, so does the result.  */
313169689Skan      if (op1_l == VARYING || op2_l == VARYING)
314169689Skan	new_l = VARYING;
315169689Skan      /* Don't prematurely promote variables if we've not yet seen
316169689Skan	 their inputs.  */
317169689Skan      else if (op1_l == UNINITIALIZED)
318169689Skan	new_l = op2_l;
319169689Skan      else if (op2_l == UNINITIALIZED)
320169689Skan	new_l = op1_l;
321169689Skan      else
322169689Skan	{
323169689Skan	  /* At this point both numbers have only one component. If the
324169689Skan	     numbers are of opposite kind, the result is imaginary,
325169689Skan	     otherwise the result is real. The add/subtract translates
326169689Skan	     the real/imag from/to 0/1; the ^ performs the comparison.  */
327169689Skan	  new_l = ((op1_l - ONLY_REAL) ^ (op2_l - ONLY_REAL)) + ONLY_REAL;
328169689Skan
329169689Skan	  /* Don't allow the lattice value to flip-flop indefinitely.  */
330169689Skan	  new_l |= old_l;
331169689Skan	}
332169689Skan      break;
333169689Skan
334169689Skan    case NEGATE_EXPR:
335169689Skan    case CONJ_EXPR:
336169689Skan      new_l = find_lattice_value (TREE_OPERAND (rhs, 0));
337169689Skan      break;
338169689Skan
339169689Skan    default:
340169689Skan      new_l = VARYING;
341169689Skan      break;
342169689Skan    }
343169689Skan
344169689Skan  /* If nothing changed this round, let the propagator know.  */
345169689Skan  if (new_l == old_l)
346169689Skan    return SSA_PROP_NOT_INTERESTING;
347169689Skan
348169689Skan  VEC_replace (complex_lattice_t, complex_lattice_values, ver, new_l);
349169689Skan  return new_l == VARYING ? SSA_PROP_VARYING : SSA_PROP_INTERESTING;
350169689Skan}
351169689Skan
352169689Skan/* Evaluate a PHI node against the complex lattice defined above.  */
353169689Skan
354169689Skanstatic enum ssa_prop_result
355169689Skancomplex_visit_phi (tree phi)
356169689Skan{
357169689Skan  complex_lattice_t new_l, old_l;
358169689Skan  unsigned int ver;
359169689Skan  tree lhs;
360169689Skan  int i;
361169689Skan
362169689Skan  lhs = PHI_RESULT (phi);
363169689Skan
364169689Skan  /* This condition should be satisfied due to the initial filter
365169689Skan     set up in init_dont_simulate_again.  */
366169689Skan  gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
367169689Skan
368169689Skan  /* We've set up the lattice values such that IOR neatly models PHI meet.  */
369169689Skan  new_l = UNINITIALIZED;
370169689Skan  for (i = PHI_NUM_ARGS (phi) - 1; i >= 0; --i)
371169689Skan    new_l |= find_lattice_value (PHI_ARG_DEF (phi, i));
372169689Skan
373169689Skan  ver = SSA_NAME_VERSION (lhs);
374169689Skan  old_l = VEC_index (complex_lattice_t, complex_lattice_values, ver);
375169689Skan
376169689Skan  if (new_l == old_l)
377169689Skan    return SSA_PROP_NOT_INTERESTING;
378169689Skan
379169689Skan  VEC_replace (complex_lattice_t, complex_lattice_values, ver, new_l);
380169689Skan  return new_l == VARYING ? SSA_PROP_VARYING : SSA_PROP_INTERESTING;
381169689Skan}
382169689Skan
383169689Skan/* Create one backing variable for a complex component of ORIG.  */
384169689Skan
385169689Skanstatic tree
386169689Skancreate_one_component_var (tree type, tree orig, const char *prefix,
387169689Skan			  const char *suffix, enum tree_code code)
388169689Skan{
389169689Skan  tree r = create_tmp_var (type, prefix);
390169689Skan  add_referenced_var (r);
391169689Skan
392169689Skan  DECL_SOURCE_LOCATION (r) = DECL_SOURCE_LOCATION (orig);
393169689Skan  DECL_ARTIFICIAL (r) = 1;
394169689Skan
395169689Skan  if (DECL_NAME (orig) && !DECL_IGNORED_P (orig))
396169689Skan    {
397169689Skan      const char *name = IDENTIFIER_POINTER (DECL_NAME (orig));
398169689Skan      tree inner_type;
399169689Skan
400169689Skan      DECL_NAME (r) = get_identifier (ACONCAT ((name, suffix, NULL)));
401169689Skan
402169689Skan      inner_type = TREE_TYPE (TREE_TYPE (orig));
403169689Skan      SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig));
404169689Skan      DECL_DEBUG_EXPR_IS_FROM (r) = 1;
405169689Skan      DECL_IGNORED_P (r) = 0;
406169689Skan      TREE_NO_WARNING (r) = TREE_NO_WARNING (orig);
407169689Skan    }
408169689Skan  else
409169689Skan    {
410169689Skan      DECL_IGNORED_P (r) = 1;
411169689Skan      TREE_NO_WARNING (r) = 1;
412169689Skan    }
413169689Skan
414169689Skan  return r;
415169689Skan}
416169689Skan
417169689Skan/* Retrieve a value for a complex component of VAR.  */
418169689Skan
419169689Skanstatic tree
420169689Skanget_component_var (tree var, bool imag_p)
421169689Skan{
422169689Skan  size_t decl_index = DECL_UID (var) * 2 + imag_p;
423169689Skan  tree ret = cvc_lookup (decl_index);
424169689Skan
425169689Skan  if (ret == NULL)
426169689Skan    {
427169689Skan      ret = create_one_component_var (TREE_TYPE (TREE_TYPE (var)), var,
428169689Skan				      imag_p ? "CI" : "CR",
429169689Skan				      imag_p ? "$imag" : "$real",
430169689Skan				      imag_p ? IMAGPART_EXPR : REALPART_EXPR);
431169689Skan      cvc_insert (decl_index, ret);
432169689Skan    }
433169689Skan
434169689Skan  return ret;
435169689Skan}
436169689Skan
437169689Skan/* Retrieve a value for a complex component of SSA_NAME.  */
438169689Skan
439169689Skanstatic tree
440169689Skanget_component_ssa_name (tree ssa_name, bool imag_p)
441169689Skan{
442169689Skan  complex_lattice_t lattice = find_lattice_value (ssa_name);
443169689Skan  size_t ssa_name_index;
444169689Skan  tree ret;
445169689Skan
446169689Skan  if (lattice == (imag_p ? ONLY_REAL : ONLY_IMAG))
447169689Skan    {
448169689Skan      tree inner_type = TREE_TYPE (TREE_TYPE (ssa_name));
449169689Skan      if (SCALAR_FLOAT_TYPE_P (inner_type))
450169689Skan	return build_real (inner_type, dconst0);
451169689Skan      else
452169689Skan	return build_int_cst (inner_type, 0);
453169689Skan    }
454169689Skan
455169689Skan  ssa_name_index = SSA_NAME_VERSION (ssa_name) * 2 + imag_p;
456169689Skan  ret = VEC_index (tree, complex_ssa_name_components, ssa_name_index);
457169689Skan  if (ret == NULL)
458169689Skan    {
459169689Skan      ret = get_component_var (SSA_NAME_VAR (ssa_name), imag_p);
460169689Skan      ret = make_ssa_name (ret, NULL);
461169689Skan
462169689Skan      /* Copy some properties from the original.  In particular, whether it
463169689Skan	 is used in an abnormal phi, and whether it's uninitialized.  */
464169689Skan      SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ret)
465169689Skan	= SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssa_name);
466169689Skan      if (TREE_CODE (SSA_NAME_VAR (ssa_name)) == VAR_DECL
467169689Skan	  && IS_EMPTY_STMT (SSA_NAME_DEF_STMT (ssa_name)))
468169689Skan	{
469169689Skan	  SSA_NAME_DEF_STMT (ret) = SSA_NAME_DEF_STMT (ssa_name);
470169689Skan	  set_default_def (SSA_NAME_VAR (ret), ret);
471169689Skan	}
472169689Skan
473169689Skan      VEC_replace (tree, complex_ssa_name_components, ssa_name_index, ret);
474169689Skan    }
475169689Skan
476169689Skan  return ret;
477169689Skan}
478169689Skan
479169689Skan/* Set a value for a complex component of SSA_NAME, return a STMT_LIST of
480169689Skan   stuff that needs doing.  */
481169689Skan
482169689Skanstatic tree
483169689Skanset_component_ssa_name (tree ssa_name, bool imag_p, tree value)
484169689Skan{
485169689Skan  complex_lattice_t lattice = find_lattice_value (ssa_name);
486169689Skan  size_t ssa_name_index;
487169689Skan  tree comp, list, last;
488169689Skan
489169689Skan  /* We know the value must be zero, else there's a bug in our lattice
490169689Skan     analysis.  But the value may well be a variable known to contain
491169689Skan     zero.  We should be safe ignoring it.  */
492169689Skan  if (lattice == (imag_p ? ONLY_REAL : ONLY_IMAG))
493169689Skan    return NULL;
494169689Skan
495169689Skan  /* If we've already assigned an SSA_NAME to this component, then this
496169689Skan     means that our walk of the basic blocks found a use before the set.
497169689Skan     This is fine.  Now we should create an initialization for the value
498169689Skan     we created earlier.  */
499169689Skan  ssa_name_index = SSA_NAME_VERSION (ssa_name) * 2 + imag_p;
500169689Skan  comp = VEC_index (tree, complex_ssa_name_components, ssa_name_index);
501169689Skan  if (comp)
502169689Skan    ;
503169689Skan
504169689Skan  /* If we've nothing assigned, and the value we're given is already stable,
505169689Skan     then install that as the value for this SSA_NAME.  This preemptively
506169689Skan     copy-propagates the value, which avoids unnecessary memory allocation.  */
507169689Skan  else if (is_gimple_min_invariant (value))
508169689Skan    {
509169689Skan      VEC_replace (tree, complex_ssa_name_components, ssa_name_index, value);
510169689Skan      return NULL;
511169689Skan    }
512169689Skan  else if (TREE_CODE (value) == SSA_NAME
513169689Skan	   && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssa_name))
514169689Skan    {
515169689Skan      /* Replace an anonymous base value with the variable from cvc_lookup.
516169689Skan	 This should result in better debug info.  */
517169689Skan      if (DECL_IGNORED_P (SSA_NAME_VAR (value))
518169689Skan	  && !DECL_IGNORED_P (SSA_NAME_VAR (ssa_name)))
519169689Skan	{
520169689Skan	  comp = get_component_var (SSA_NAME_VAR (ssa_name), imag_p);
521169689Skan	  replace_ssa_name_symbol (value, comp);
522169689Skan	}
523169689Skan
524169689Skan      VEC_replace (tree, complex_ssa_name_components, ssa_name_index, value);
525169689Skan      return NULL;
526169689Skan    }
527169689Skan
528169689Skan  /* Finally, we need to stabilize the result by installing the value into
529169689Skan     a new ssa name.  */
530169689Skan  else
531169689Skan    comp = get_component_ssa_name (ssa_name, imag_p);
532169689Skan
533169689Skan  /* Do all the work to assign VALUE to COMP.  */
534169689Skan  value = force_gimple_operand (value, &list, false, NULL);
535169689Skan  last = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, value);
536169689Skan  append_to_statement_list (last, &list);
537169689Skan
538169689Skan  gcc_assert (SSA_NAME_DEF_STMT (comp) == NULL);
539169689Skan  SSA_NAME_DEF_STMT (comp) = last;
540169689Skan
541169689Skan  return list;
542169689Skan}
543169689Skan
544169689Skan/* Extract the real or imaginary part of a complex variable or constant.
545169689Skan   Make sure that it's a proper gimple_val and gimplify it if not.
546169689Skan   Emit any new code before BSI.  */
547169689Skan
548169689Skanstatic tree
549169689Skanextract_component (block_stmt_iterator *bsi, tree t, bool imagpart_p,
550169689Skan		   bool gimple_p)
551169689Skan{
552169689Skan  switch (TREE_CODE (t))
553169689Skan    {
554169689Skan    case COMPLEX_CST:
555169689Skan      return imagpart_p ? TREE_IMAGPART (t) : TREE_REALPART (t);
556169689Skan
557169689Skan    case COMPLEX_EXPR:
558169689Skan      return TREE_OPERAND (t, imagpart_p);
559169689Skan
560169689Skan    case VAR_DECL:
561169689Skan    case RESULT_DECL:
562169689Skan    case PARM_DECL:
563169689Skan    case INDIRECT_REF:
564169689Skan    case COMPONENT_REF:
565169689Skan    case ARRAY_REF:
566169689Skan      {
567169689Skan	tree inner_type = TREE_TYPE (TREE_TYPE (t));
568169689Skan
569169689Skan	t = build1 ((imagpart_p ? IMAGPART_EXPR : REALPART_EXPR),
570169689Skan		    inner_type, unshare_expr (t));
571169689Skan
572169689Skan	if (gimple_p)
573169689Skan	  t = gimplify_val (bsi, inner_type, t);
574169689Skan
575169689Skan	return t;
576169689Skan      }
577169689Skan
578169689Skan    case SSA_NAME:
579169689Skan      return get_component_ssa_name (t, imagpart_p);
580169689Skan
581169689Skan    default:
582169689Skan      gcc_unreachable ();
583169689Skan    }
584169689Skan}
585169689Skan
586169689Skan/* Update the complex components of the ssa name on the lhs of STMT.  */
587169689Skan
588169689Skanstatic void
589169689Skanupdate_complex_components (block_stmt_iterator *bsi, tree stmt, tree r, tree i)
590169689Skan{
591169689Skan  tree lhs = TREE_OPERAND (stmt, 0);
592169689Skan  tree list;
593169689Skan
594169689Skan  list = set_component_ssa_name (lhs, false, r);
595169689Skan  if (list)
596169689Skan    bsi_insert_after (bsi, list, BSI_CONTINUE_LINKING);
597169689Skan
598169689Skan  list = set_component_ssa_name (lhs, true, i);
599169689Skan  if (list)
600169689Skan    bsi_insert_after (bsi, list, BSI_CONTINUE_LINKING);
601169689Skan}
602169689Skan
603169689Skanstatic void
604169689Skanupdate_complex_components_on_edge (edge e, tree lhs, tree r, tree i)
605169689Skan{
606169689Skan  tree list;
607169689Skan
608169689Skan  list = set_component_ssa_name (lhs, false, r);
609169689Skan  if (list)
610169689Skan    bsi_insert_on_edge (e, list);
611169689Skan
612169689Skan  list = set_component_ssa_name (lhs, true, i);
613169689Skan  if (list)
614169689Skan    bsi_insert_on_edge (e, list);
615169689Skan}
616169689Skan
617169689Skan/* Update an assignment to a complex variable in place.  */
618169689Skan
619169689Skanstatic void
620169689Skanupdate_complex_assignment (block_stmt_iterator *bsi, tree r, tree i)
621169689Skan{
622169689Skan  tree stmt, mod;
623169689Skan  tree type;
624169689Skan
625169689Skan  mod = stmt = bsi_stmt (*bsi);
626169689Skan  if (TREE_CODE (stmt) == RETURN_EXPR)
627169689Skan    mod = TREE_OPERAND (mod, 0);
628169689Skan  else if (in_ssa_p)
629169689Skan    update_complex_components (bsi, stmt, r, i);
630169689Skan
631169689Skan  type = TREE_TYPE (TREE_OPERAND (mod, 1));
632169689Skan  TREE_OPERAND (mod, 1) = build2 (COMPLEX_EXPR, type, r, i);
633169689Skan  update_stmt (stmt);
634169689Skan}
635169689Skan
636169689Skan/* Generate code at the entry point of the function to initialize the
637169689Skan   component variables for a complex parameter.  */
638169689Skan
639169689Skanstatic void
640169689Skanupdate_parameter_components (void)
641169689Skan{
642169689Skan  edge entry_edge = single_succ_edge (ENTRY_BLOCK_PTR);
643169689Skan  tree parm;
644169689Skan
645169689Skan  for (parm = DECL_ARGUMENTS (cfun->decl); parm ; parm = TREE_CHAIN (parm))
646169689Skan    {
647169689Skan      tree type = TREE_TYPE (parm);
648169689Skan      tree ssa_name, r, i;
649169689Skan
650169689Skan      if (TREE_CODE (type) != COMPLEX_TYPE || !is_gimple_reg (parm))
651169689Skan	continue;
652169689Skan
653169689Skan      type = TREE_TYPE (type);
654169689Skan      ssa_name = default_def (parm);
655169689Skan      if (!ssa_name)
656169689Skan	continue;
657169689Skan
658169689Skan      r = build1 (REALPART_EXPR, type, ssa_name);
659169689Skan      i = build1 (IMAGPART_EXPR, type, ssa_name);
660169689Skan      update_complex_components_on_edge (entry_edge, ssa_name, r, i);
661169689Skan    }
662169689Skan}
663169689Skan
664169689Skan/* Generate code to set the component variables of a complex variable
665169689Skan   to match the PHI statements in block BB.  */
666169689Skan
667169689Skanstatic void
668169689Skanupdate_phi_components (basic_block bb)
669169689Skan{
670169689Skan  tree phi;
671169689Skan
672169689Skan  for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
673169689Skan    if (is_complex_reg (PHI_RESULT (phi)))
674169689Skan      {
675169689Skan	tree lr, li, pr = NULL, pi = NULL;
676169689Skan	unsigned int i, n;
677169689Skan
678169689Skan	lr = get_component_ssa_name (PHI_RESULT (phi), false);
679169689Skan	if (TREE_CODE (lr) == SSA_NAME)
680169689Skan	  {
681169689Skan	    pr = create_phi_node (lr, bb);
682169689Skan	    SSA_NAME_DEF_STMT (lr) = pr;
683169689Skan	  }
684169689Skan
685169689Skan	li = get_component_ssa_name (PHI_RESULT (phi), true);
686169689Skan	if (TREE_CODE (li) == SSA_NAME)
687169689Skan	  {
688169689Skan	    pi = create_phi_node (li, bb);
689169689Skan	    SSA_NAME_DEF_STMT (li) = pi;
690169689Skan	  }
691169689Skan
692169689Skan	for (i = 0, n = PHI_NUM_ARGS (phi); i < n; ++i)
693169689Skan	  {
694169689Skan	    tree comp, arg = PHI_ARG_DEF (phi, i);
695169689Skan	    if (pr)
696169689Skan	      {
697169689Skan		comp = extract_component (NULL, arg, false, false);
698169689Skan		SET_PHI_ARG_DEF (pr, i, comp);
699169689Skan	      }
700169689Skan	    if (pi)
701169689Skan	      {
702169689Skan		comp = extract_component (NULL, arg, true, false);
703169689Skan		SET_PHI_ARG_DEF (pi, i, comp);
704169689Skan	      }
705169689Skan	  }
706169689Skan      }
707169689Skan}
708169689Skan
709169689Skan/* Mark each virtual op in STMT for ssa update.  */
710169689Skan
711169689Skanstatic void
712169689Skanupdate_all_vops (tree stmt)
713169689Skan{
714169689Skan  ssa_op_iter iter;
715169689Skan  tree sym;
716169689Skan
717169689Skan  FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_ALL_VIRTUALS)
718169689Skan    {
719169689Skan      if (TREE_CODE (sym) == SSA_NAME)
720169689Skan	sym = SSA_NAME_VAR (sym);
721169689Skan      mark_sym_for_renaming (sym);
722169689Skan    }
723169689Skan}
724169689Skan
725169689Skan/* Expand a complex move to scalars.  */
726169689Skan
727169689Skanstatic void
728169689Skanexpand_complex_move (block_stmt_iterator *bsi, tree stmt, tree type,
729169689Skan		     tree lhs, tree rhs)
730169689Skan{
731169689Skan  tree inner_type = TREE_TYPE (type);
732169689Skan  tree r, i;
733169689Skan
734169689Skan  if (TREE_CODE (lhs) == SSA_NAME)
735169689Skan    {
736169689Skan      if (is_ctrl_altering_stmt (bsi_stmt (*bsi)))
737169689Skan	{
738169689Skan	  edge_iterator ei;
739169689Skan	  edge e;
740169689Skan
741169689Skan	  /* The value is not assigned on the exception edges, so we need not
742169689Skan	     concern ourselves there.  We do need to update on the fallthru
743169689Skan	     edge.  Find it.  */
744169689Skan	  FOR_EACH_EDGE (e, ei, bsi->bb->succs)
745169689Skan	    if (e->flags & EDGE_FALLTHRU)
746169689Skan	      goto found_fallthru;
747169689Skan	  gcc_unreachable ();
748169689Skan	found_fallthru:
749169689Skan
750169689Skan	  r = build1 (REALPART_EXPR, inner_type, lhs);
751169689Skan	  i = build1 (IMAGPART_EXPR, inner_type, lhs);
752169689Skan	  update_complex_components_on_edge (e, lhs, r, i);
753169689Skan	}
754169689Skan      else if (TREE_CODE (rhs) == CALL_EXPR || TREE_SIDE_EFFECTS (rhs))
755169689Skan	{
756169689Skan	  r = build1 (REALPART_EXPR, inner_type, lhs);
757169689Skan	  i = build1 (IMAGPART_EXPR, inner_type, lhs);
758169689Skan	  update_complex_components (bsi, stmt, r, i);
759169689Skan	}
760169689Skan      else
761169689Skan	{
762169689Skan	  update_all_vops (bsi_stmt (*bsi));
763169689Skan	  r = extract_component (bsi, rhs, 0, true);
764169689Skan	  i = extract_component (bsi, rhs, 1, true);
765169689Skan	  update_complex_assignment (bsi, r, i);
766169689Skan	}
767169689Skan    }
768169689Skan  else if (TREE_CODE (rhs) == SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
769169689Skan    {
770169689Skan      tree x;
771169689Skan
772169689Skan      r = extract_component (bsi, rhs, 0, false);
773169689Skan      i = extract_component (bsi, rhs, 1, false);
774169689Skan
775169689Skan      x = build1 (REALPART_EXPR, inner_type, unshare_expr (lhs));
776169689Skan      x = build2 (MODIFY_EXPR, inner_type, x, r);
777169689Skan      bsi_insert_before (bsi, x, BSI_SAME_STMT);
778169689Skan
779169689Skan      if (stmt == bsi_stmt (*bsi))
780169689Skan	{
781169689Skan	  x = build1 (IMAGPART_EXPR, inner_type, unshare_expr (lhs));
782169689Skan	  TREE_OPERAND (stmt, 0) = x;
783169689Skan	  TREE_OPERAND (stmt, 1) = i;
784169689Skan	  TREE_TYPE (stmt) = inner_type;
785169689Skan	}
786169689Skan      else
787169689Skan	{
788169689Skan	  x = build1 (IMAGPART_EXPR, inner_type, unshare_expr (lhs));
789169689Skan	  x = build2 (MODIFY_EXPR, inner_type, x, i);
790169689Skan	  bsi_insert_before (bsi, x, BSI_SAME_STMT);
791169689Skan
792169689Skan	  stmt = bsi_stmt (*bsi);
793169689Skan	  gcc_assert (TREE_CODE (stmt) == RETURN_EXPR);
794169689Skan	  TREE_OPERAND (stmt, 0) = lhs;
795169689Skan	}
796169689Skan
797169689Skan      update_all_vops (stmt);
798169689Skan      update_stmt (stmt);
799169689Skan    }
800169689Skan}
801169689Skan
802169689Skan/* Expand complex addition to scalars:
803169689Skan	a + b = (ar + br) + i(ai + bi)
804169689Skan	a - b = (ar - br) + i(ai + bi)
805169689Skan*/
806169689Skan
807169689Skanstatic void
808169689Skanexpand_complex_addition (block_stmt_iterator *bsi, tree inner_type,
809169689Skan			 tree ar, tree ai, tree br, tree bi,
810169689Skan			 enum tree_code code,
811169689Skan			 complex_lattice_t al, complex_lattice_t bl)
812169689Skan{
813169689Skan  tree rr, ri;
814169689Skan
815169689Skan  switch (PAIR (al, bl))
816169689Skan    {
817169689Skan    case PAIR (ONLY_REAL, ONLY_REAL):
818169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ar, br);
819169689Skan      ri = ai;
820169689Skan      break;
821169689Skan
822169689Skan    case PAIR (ONLY_REAL, ONLY_IMAG):
823169689Skan      rr = ar;
824169689Skan      if (code == MINUS_EXPR)
825169689Skan	ri = gimplify_build2 (bsi, MINUS_EXPR, inner_type, ai, bi);
826169689Skan      else
827169689Skan	ri = bi;
828169689Skan      break;
829169689Skan
830169689Skan    case PAIR (ONLY_IMAG, ONLY_REAL):
831169689Skan      if (code == MINUS_EXPR)
832169689Skan	rr = gimplify_build2 (bsi, MINUS_EXPR, inner_type, ar, br);
833169689Skan      else
834169689Skan	rr = br;
835169689Skan      ri = ai;
836169689Skan      break;
837169689Skan
838169689Skan    case PAIR (ONLY_IMAG, ONLY_IMAG):
839169689Skan      rr = ar;
840169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ai, bi);
841169689Skan      break;
842169689Skan
843169689Skan    case PAIR (VARYING, ONLY_REAL):
844169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ar, br);
845169689Skan      ri = ai;
846169689Skan      break;
847169689Skan
848169689Skan    case PAIR (VARYING, ONLY_IMAG):
849169689Skan      rr = ar;
850169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ai, bi);
851169689Skan      break;
852169689Skan
853169689Skan    case PAIR (ONLY_REAL, VARYING):
854169689Skan      if (code == MINUS_EXPR)
855169689Skan	goto general;
856169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ar, br);
857169689Skan      ri = bi;
858169689Skan      break;
859169689Skan
860169689Skan    case PAIR (ONLY_IMAG, VARYING):
861169689Skan      if (code == MINUS_EXPR)
862169689Skan	goto general;
863169689Skan      rr = br;
864169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ai, bi);
865169689Skan      break;
866169689Skan
867169689Skan    case PAIR (VARYING, VARYING):
868169689Skan    general:
869169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ar, br);
870169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ai, bi);
871169689Skan      break;
872169689Skan
873169689Skan    default:
874169689Skan      gcc_unreachable ();
875169689Skan    }
876169689Skan
877169689Skan  update_complex_assignment (bsi, rr, ri);
878169689Skan}
879169689Skan
880169689Skan/* Expand a complex multiplication or division to a libcall to the c99
881169689Skan   compliant routines.  */
882169689Skan
883169689Skanstatic void
884169689Skanexpand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai,
885169689Skan			tree br, tree bi, enum tree_code code)
886169689Skan{
887169689Skan  enum machine_mode mode;
888169689Skan  enum built_in_function bcode;
889169689Skan  tree args, fn, stmt, type;
890169689Skan
891169689Skan  args = tree_cons (NULL, bi, NULL);
892169689Skan  args = tree_cons (NULL, br, args);
893169689Skan  args = tree_cons (NULL, ai, args);
894169689Skan  args = tree_cons (NULL, ar, args);
895169689Skan
896169689Skan  stmt = bsi_stmt (*bsi);
897169689Skan  type = TREE_TYPE (TREE_OPERAND (stmt, 1));
898169689Skan
899169689Skan  mode = TYPE_MODE (type);
900169689Skan  gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
901169689Skan  if (code == MULT_EXPR)
902169689Skan    bcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
903169689Skan  else if (code == RDIV_EXPR)
904169689Skan    bcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
905169689Skan  else
906169689Skan    gcc_unreachable ();
907169689Skan  fn = built_in_decls[bcode];
908169689Skan
909169689Skan  TREE_OPERAND (stmt, 1)
910169689Skan    = build3 (CALL_EXPR, type, build_fold_addr_expr (fn), args, NULL);
911169689Skan  update_stmt (stmt);
912169689Skan
913169689Skan  if (in_ssa_p)
914169689Skan    {
915169689Skan      tree lhs = TREE_OPERAND (stmt, 0);
916169689Skan      type = TREE_TYPE (type);
917169689Skan      update_complex_components (bsi, stmt,
918169689Skan				 build1 (REALPART_EXPR, type, lhs),
919169689Skan				 build1 (IMAGPART_EXPR, type, lhs));
920169689Skan    }
921169689Skan}
922169689Skan
923169689Skan/* Expand complex multiplication to scalars:
924169689Skan	a * b = (ar*br - ai*bi) + i(ar*bi + br*ai)
925169689Skan*/
926169689Skan
927169689Skanstatic void
928169689Skanexpand_complex_multiplication (block_stmt_iterator *bsi, tree inner_type,
929169689Skan			       tree ar, tree ai, tree br, tree bi,
930169689Skan			       complex_lattice_t al, complex_lattice_t bl)
931169689Skan{
932169689Skan  tree rr, ri;
933169689Skan
934169689Skan  if (al < bl)
935169689Skan    {
936169689Skan      complex_lattice_t tl;
937169689Skan      rr = ar, ar = br, br = rr;
938169689Skan      ri = ai, ai = bi, bi = ri;
939169689Skan      tl = al, al = bl, bl = tl;
940169689Skan    }
941169689Skan
942169689Skan  switch (PAIR (al, bl))
943169689Skan    {
944169689Skan    case PAIR (ONLY_REAL, ONLY_REAL):
945169689Skan      rr = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br);
946169689Skan      ri = ai;
947169689Skan      break;
948169689Skan
949169689Skan    case PAIR (ONLY_IMAG, ONLY_REAL):
950169689Skan      rr = ar;
951169689Skan      if (TREE_CODE (ai) == REAL_CST
952169689Skan	  && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst1))
953169689Skan	ri = br;
954169689Skan      else
955169689Skan	ri = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, br);
956169689Skan      break;
957169689Skan
958169689Skan    case PAIR (ONLY_IMAG, ONLY_IMAG):
959169689Skan      rr = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi);
960169689Skan      rr = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, rr);
961169689Skan      ri = ar;
962169689Skan      break;
963169689Skan
964169689Skan    case PAIR (VARYING, ONLY_REAL):
965169689Skan      rr = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br);
966169689Skan      ri = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, br);
967169689Skan      break;
968169689Skan
969169689Skan    case PAIR (VARYING, ONLY_IMAG):
970169689Skan      rr = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi);
971169689Skan      rr = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, rr);
972169689Skan      ri = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, bi);
973169689Skan      break;
974169689Skan
975169689Skan    case PAIR (VARYING, VARYING):
976169689Skan      if (flag_complex_method == 2 && SCALAR_FLOAT_TYPE_P (inner_type))
977169689Skan	{
978169689Skan	  expand_complex_libcall (bsi, ar, ai, br, bi, MULT_EXPR);
979169689Skan	  return;
980169689Skan	}
981169689Skan      else
982169689Skan	{
983169689Skan	  tree t1, t2, t3, t4;
984169689Skan
985169689Skan	  t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br);
986169689Skan	  t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi);
987169689Skan	  t3 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, bi);
988169689Skan
989169689Skan	  /* Avoid expanding redundant multiplication for the common
990169689Skan	     case of squaring a complex number.  */
991169689Skan	  if (ar == br && ai == bi)
992169689Skan	    t4 = t3;
993169689Skan	  else
994169689Skan	    t4 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, br);
995169689Skan
996169689Skan	  rr = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, t2);
997169689Skan	  ri = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t3, t4);
998169689Skan	}
999169689Skan      break;
1000169689Skan
1001169689Skan    default:
1002169689Skan      gcc_unreachable ();
1003169689Skan    }
1004169689Skan
1005169689Skan  update_complex_assignment (bsi, rr, ri);
1006169689Skan}
1007169689Skan
1008169689Skan/* Expand complex division to scalars, straightforward algorithm.
1009169689Skan	a / b = ((ar*br + ai*bi)/t) + i((ai*br - ar*bi)/t)
1010169689Skan	    t = br*br + bi*bi
1011169689Skan*/
1012169689Skan
1013169689Skanstatic void
1014169689Skanexpand_complex_div_straight (block_stmt_iterator *bsi, tree inner_type,
1015169689Skan			     tree ar, tree ai, tree br, tree bi,
1016169689Skan			     enum tree_code code)
1017169689Skan{
1018169689Skan  tree rr, ri, div, t1, t2, t3;
1019169689Skan
1020169689Skan  t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, br, br);
1021169689Skan  t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, bi, bi);
1022169689Skan  div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, t2);
1023169689Skan
1024169689Skan  t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br);
1025169689Skan  t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi);
1026169689Skan  t3 = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, t2);
1027169689Skan  rr = gimplify_build2 (bsi, code, inner_type, t3, div);
1028169689Skan
1029169689Skan  t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, br);
1030169689Skan  t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, bi);
1031169689Skan  t3 = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, t2);
1032169689Skan  ri = gimplify_build2 (bsi, code, inner_type, t3, div);
1033169689Skan
1034169689Skan  update_complex_assignment (bsi, rr, ri);
1035169689Skan}
1036169689Skan
1037169689Skan/* Expand complex division to scalars, modified algorithm to minimize
1038169689Skan   overflow with wide input ranges.  */
1039169689Skan
1040169689Skanstatic void
1041169689Skanexpand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
1042169689Skan			 tree ar, tree ai, tree br, tree bi,
1043169689Skan			 enum tree_code code)
1044169689Skan{
1045169689Skan  tree rr, ri, ratio, div, t1, t2, tr, ti, cond;
1046169689Skan  basic_block bb_cond, bb_true, bb_false, bb_join;
1047169689Skan
1048169689Skan  /* Examine |br| < |bi|, and branch.  */
1049169689Skan  t1 = gimplify_build1 (bsi, ABS_EXPR, inner_type, br);
1050169689Skan  t2 = gimplify_build1 (bsi, ABS_EXPR, inner_type, bi);
1051169689Skan  cond = fold_build2 (LT_EXPR, boolean_type_node, t1, t2);
1052169689Skan  STRIP_NOPS (cond);
1053169689Skan
1054169689Skan  bb_cond = bb_true = bb_false = bb_join = NULL;
1055169689Skan  rr = ri = tr = ti = NULL;
1056169689Skan  if (!TREE_CONSTANT (cond))
1057169689Skan    {
1058169689Skan      edge e;
1059169689Skan
1060169689Skan      cond = build3 (COND_EXPR, void_type_node, cond, NULL_TREE, NULL_TREE);
1061169689Skan      bsi_insert_before (bsi, cond, BSI_SAME_STMT);
1062169689Skan
1063169689Skan      /* Split the original block, and create the TRUE and FALSE blocks.  */
1064169689Skan      e = split_block (bsi->bb, cond);
1065169689Skan      bb_cond = e->src;
1066169689Skan      bb_join = e->dest;
1067169689Skan      bb_true = create_empty_bb (bb_cond);
1068169689Skan      bb_false = create_empty_bb (bb_true);
1069169689Skan
1070169689Skan      t1 = build1 (GOTO_EXPR, void_type_node, tree_block_label (bb_true));
1071169689Skan      t2 = build1 (GOTO_EXPR, void_type_node, tree_block_label (bb_false));
1072169689Skan      COND_EXPR_THEN (cond) = t1;
1073169689Skan      COND_EXPR_ELSE (cond) = t2;
1074169689Skan
1075169689Skan      /* Wire the blocks together.  */
1076169689Skan      e->flags = EDGE_TRUE_VALUE;
1077169689Skan      redirect_edge_succ (e, bb_true);
1078169689Skan      make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE);
1079169689Skan      make_edge (bb_true, bb_join, EDGE_FALLTHRU);
1080169689Skan      make_edge (bb_false, bb_join, EDGE_FALLTHRU);
1081169689Skan
1082169689Skan      /* Update dominance info.  Note that bb_join's data was
1083169689Skan         updated by split_block.  */
1084169689Skan      if (dom_info_available_p (CDI_DOMINATORS))
1085169689Skan        {
1086169689Skan          set_immediate_dominator (CDI_DOMINATORS, bb_true, bb_cond);
1087169689Skan          set_immediate_dominator (CDI_DOMINATORS, bb_false, bb_cond);
1088169689Skan        }
1089169689Skan
1090169689Skan      rr = make_rename_temp (inner_type, NULL);
1091169689Skan      ri = make_rename_temp (inner_type, NULL);
1092169689Skan    }
1093169689Skan
1094169689Skan  /* In the TRUE branch, we compute
1095169689Skan      ratio = br/bi;
1096169689Skan      div = (br * ratio) + bi;
1097169689Skan      tr = (ar * ratio) + ai;
1098169689Skan      ti = (ai * ratio) - ar;
1099169689Skan      tr = tr / div;
1100169689Skan      ti = ti / div;  */
1101169689Skan  if (bb_true || integer_nonzerop (cond))
1102169689Skan    {
1103169689Skan      if (bb_true)
1104169689Skan	{
1105169689Skan	  *bsi = bsi_last (bb_true);
1106169689Skan	  bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
1107169689Skan	}
1108169689Skan
1109169689Skan      ratio = gimplify_build2 (bsi, code, inner_type, br, bi);
1110169689Skan
1111169689Skan      t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, br, ratio);
1112169689Skan      div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, bi);
1113169689Skan
1114169689Skan      t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio);
1115169689Skan      tr = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, ai);
1116169689Skan
1117169689Skan      t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
1118169689Skan      ti = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, ar);
1119169689Skan
1120169689Skan      tr = gimplify_build2 (bsi, code, inner_type, tr, div);
1121169689Skan      ti = gimplify_build2 (bsi, code, inner_type, ti, div);
1122169689Skan
1123169689Skan     if (bb_true)
1124169689Skan       {
1125169689Skan	 t1 = build2 (MODIFY_EXPR, inner_type, rr, tr);
1126169689Skan	 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
1127169689Skan	 t1 = build2 (MODIFY_EXPR, inner_type, ri, ti);
1128169689Skan	 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
1129169689Skan	 bsi_remove (bsi, true);
1130169689Skan       }
1131169689Skan    }
1132169689Skan
1133169689Skan  /* In the FALSE branch, we compute
1134169689Skan      ratio = d/c;
1135169689Skan      divisor = (d * ratio) + c;
1136169689Skan      tr = (b * ratio) + a;
1137169689Skan      ti = b - (a * ratio);
1138169689Skan      tr = tr / div;
1139169689Skan      ti = ti / div;  */
1140169689Skan  if (bb_false || integer_zerop (cond))
1141169689Skan    {
1142169689Skan      if (bb_false)
1143169689Skan	{
1144169689Skan	  *bsi = bsi_last (bb_false);
1145169689Skan	  bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
1146169689Skan	}
1147169689Skan
1148169689Skan      ratio = gimplify_build2 (bsi, code, inner_type, bi, br);
1149169689Skan
1150169689Skan      t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, bi, ratio);
1151169689Skan      div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, br);
1152169689Skan
1153169689Skan      t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
1154169689Skan      tr = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, ar);
1155169689Skan
1156169689Skan      t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio);
1157169689Skan      ti = gimplify_build2 (bsi, MINUS_EXPR, inner_type, ai, t1);
1158169689Skan
1159169689Skan      tr = gimplify_build2 (bsi, code, inner_type, tr, div);
1160169689Skan      ti = gimplify_build2 (bsi, code, inner_type, ti, div);
1161169689Skan
1162169689Skan     if (bb_false)
1163169689Skan       {
1164169689Skan	 t1 = build2 (MODIFY_EXPR, inner_type, rr, tr);
1165169689Skan	 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
1166169689Skan	 t1 = build2 (MODIFY_EXPR, inner_type, ri, ti);
1167169689Skan	 bsi_insert_before (bsi, t1, BSI_SAME_STMT);
1168169689Skan	 bsi_remove (bsi, true);
1169169689Skan       }
1170169689Skan    }
1171169689Skan
1172169689Skan  if (bb_join)
1173169689Skan    *bsi = bsi_start (bb_join);
1174169689Skan  else
1175169689Skan    rr = tr, ri = ti;
1176169689Skan
1177169689Skan  update_complex_assignment (bsi, rr, ri);
1178169689Skan}
1179169689Skan
1180169689Skan/* Expand complex division to scalars.  */
1181169689Skan
1182169689Skanstatic void
1183169689Skanexpand_complex_division (block_stmt_iterator *bsi, tree inner_type,
1184169689Skan			 tree ar, tree ai, tree br, tree bi,
1185169689Skan			 enum tree_code code,
1186169689Skan			 complex_lattice_t al, complex_lattice_t bl)
1187169689Skan{
1188169689Skan  tree rr, ri;
1189169689Skan
1190169689Skan  switch (PAIR (al, bl))
1191169689Skan    {
1192169689Skan    case PAIR (ONLY_REAL, ONLY_REAL):
1193169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ar, br);
1194169689Skan      ri = ai;
1195169689Skan      break;
1196169689Skan
1197169689Skan    case PAIR (ONLY_REAL, ONLY_IMAG):
1198169689Skan      rr = ai;
1199169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ar, bi);
1200169689Skan      ri = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ri);
1201169689Skan      break;
1202169689Skan
1203169689Skan    case PAIR (ONLY_IMAG, ONLY_REAL):
1204169689Skan      rr = ar;
1205169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ai, br);
1206169689Skan      break;
1207169689Skan
1208169689Skan    case PAIR (ONLY_IMAG, ONLY_IMAG):
1209169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ai, bi);
1210169689Skan      ri = ar;
1211169689Skan      break;
1212169689Skan
1213169689Skan    case PAIR (VARYING, ONLY_REAL):
1214169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ar, br);
1215169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ai, br);
1216169689Skan      break;
1217169689Skan
1218169689Skan    case PAIR (VARYING, ONLY_IMAG):
1219169689Skan      rr = gimplify_build2 (bsi, code, inner_type, ai, bi);
1220169689Skan      ri = gimplify_build2 (bsi, code, inner_type, ar, bi);
1221169689Skan      ri = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ri);
1222169689Skan
1223169689Skan    case PAIR (ONLY_REAL, VARYING):
1224169689Skan    case PAIR (ONLY_IMAG, VARYING):
1225169689Skan    case PAIR (VARYING, VARYING):
1226169689Skan      switch (flag_complex_method)
1227169689Skan	{
1228169689Skan	case 0:
1229169689Skan	  /* straightforward implementation of complex divide acceptable.  */
1230169689Skan	  expand_complex_div_straight (bsi, inner_type, ar, ai, br, bi, code);
1231169689Skan	  break;
1232169689Skan
1233169689Skan	case 2:
1234169689Skan	  if (SCALAR_FLOAT_TYPE_P (inner_type))
1235169689Skan	    {
1236169689Skan	      expand_complex_libcall (bsi, ar, ai, br, bi, code);
1237169689Skan	      break;
1238169689Skan	    }
1239169689Skan	  /* FALLTHRU */
1240169689Skan
1241169689Skan	case 1:
1242169689Skan	  /* wide ranges of inputs must work for complex divide.  */
1243169689Skan	  expand_complex_div_wide (bsi, inner_type, ar, ai, br, bi, code);
1244169689Skan	  break;
1245169689Skan
1246169689Skan	default:
1247169689Skan	  gcc_unreachable ();
1248169689Skan	}
1249169689Skan      return;
1250169689Skan
1251169689Skan    default:
1252169689Skan      gcc_unreachable ();
1253169689Skan    }
1254169689Skan
1255169689Skan  update_complex_assignment (bsi, rr, ri);
1256169689Skan}
1257169689Skan
1258169689Skan/* Expand complex negation to scalars:
1259169689Skan	-a = (-ar) + i(-ai)
1260169689Skan*/
1261169689Skan
1262169689Skanstatic void
1263169689Skanexpand_complex_negation (block_stmt_iterator *bsi, tree inner_type,
1264169689Skan			 tree ar, tree ai)
1265169689Skan{
1266169689Skan  tree rr, ri;
1267169689Skan
1268169689Skan  rr = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ar);
1269169689Skan  ri = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ai);
1270169689Skan
1271169689Skan  update_complex_assignment (bsi, rr, ri);
1272169689Skan}
1273169689Skan
1274169689Skan/* Expand complex conjugate to scalars:
1275169689Skan	~a = (ar) + i(-ai)
1276169689Skan*/
1277169689Skan
1278169689Skanstatic void
1279169689Skanexpand_complex_conjugate (block_stmt_iterator *bsi, tree inner_type,
1280169689Skan			  tree ar, tree ai)
1281169689Skan{
1282169689Skan  tree ri;
1283169689Skan
1284169689Skan  ri = gimplify_build1 (bsi, NEGATE_EXPR, inner_type, ai);
1285169689Skan
1286169689Skan  update_complex_assignment (bsi, ar, ri);
1287169689Skan}
1288169689Skan
1289169689Skan/* Expand complex comparison (EQ or NE only).  */
1290169689Skan
1291169689Skanstatic void
1292169689Skanexpand_complex_comparison (block_stmt_iterator *bsi, tree ar, tree ai,
1293169689Skan			   tree br, tree bi, enum tree_code code)
1294169689Skan{
1295169689Skan  tree cr, ci, cc, stmt, expr, type;
1296169689Skan
1297169689Skan  cr = gimplify_build2 (bsi, code, boolean_type_node, ar, br);
1298169689Skan  ci = gimplify_build2 (bsi, code, boolean_type_node, ai, bi);
1299169689Skan  cc = gimplify_build2 (bsi,
1300169689Skan			(code == EQ_EXPR ? TRUTH_AND_EXPR : TRUTH_OR_EXPR),
1301169689Skan			boolean_type_node, cr, ci);
1302169689Skan
1303169689Skan  stmt = expr = bsi_stmt (*bsi);
1304169689Skan
1305169689Skan  switch (TREE_CODE (stmt))
1306169689Skan    {
1307169689Skan    case RETURN_EXPR:
1308169689Skan      expr = TREE_OPERAND (stmt, 0);
1309169689Skan      /* FALLTHRU */
1310169689Skan    case MODIFY_EXPR:
1311169689Skan      type = TREE_TYPE (TREE_OPERAND (expr, 1));
1312169689Skan      TREE_OPERAND (expr, 1) = fold_convert (type, cc);
1313169689Skan      break;
1314169689Skan    case COND_EXPR:
1315169689Skan      TREE_OPERAND (stmt, 0) = cc;
1316169689Skan      break;
1317169689Skan    default:
1318169689Skan      gcc_unreachable ();
1319169689Skan    }
1320169689Skan
1321169689Skan  update_stmt (stmt);
1322169689Skan}
1323169689Skan
1324169689Skan/* Process one statement.  If we identify a complex operation, expand it.  */
1325169689Skan
1326169689Skanstatic void
1327169689Skanexpand_complex_operations_1 (block_stmt_iterator *bsi)
1328169689Skan{
1329169689Skan  tree stmt = bsi_stmt (*bsi);
1330169689Skan  tree rhs, type, inner_type;
1331169689Skan  tree ac, ar, ai, bc, br, bi;
1332169689Skan  complex_lattice_t al, bl;
1333169689Skan  enum tree_code code;
1334169689Skan
1335169689Skan  switch (TREE_CODE (stmt))
1336169689Skan    {
1337169689Skan    case RETURN_EXPR:
1338169689Skan      stmt = TREE_OPERAND (stmt, 0);
1339169689Skan      if (!stmt)
1340169689Skan	return;
1341169689Skan      if (TREE_CODE (stmt) != MODIFY_EXPR)
1342169689Skan	return;
1343169689Skan      /* FALLTHRU */
1344169689Skan
1345169689Skan    case MODIFY_EXPR:
1346169689Skan      rhs = TREE_OPERAND (stmt, 1);
1347169689Skan      break;
1348169689Skan
1349169689Skan    case COND_EXPR:
1350169689Skan      rhs = TREE_OPERAND (stmt, 0);
1351169689Skan      break;
1352169689Skan
1353169689Skan    default:
1354169689Skan      return;
1355169689Skan    }
1356169689Skan
1357169689Skan  type = TREE_TYPE (rhs);
1358169689Skan  code = TREE_CODE (rhs);
1359169689Skan
1360169689Skan  /* Initial filter for operations we handle.  */
1361169689Skan  switch (code)
1362169689Skan    {
1363169689Skan    case PLUS_EXPR:
1364169689Skan    case MINUS_EXPR:
1365169689Skan    case MULT_EXPR:
1366169689Skan    case TRUNC_DIV_EXPR:
1367169689Skan    case CEIL_DIV_EXPR:
1368169689Skan    case FLOOR_DIV_EXPR:
1369169689Skan    case ROUND_DIV_EXPR:
1370169689Skan    case RDIV_EXPR:
1371169689Skan    case NEGATE_EXPR:
1372169689Skan    case CONJ_EXPR:
1373169689Skan      if (TREE_CODE (type) != COMPLEX_TYPE)
1374169689Skan	return;
1375169689Skan      inner_type = TREE_TYPE (type);
1376169689Skan      break;
1377169689Skan
1378169689Skan    case EQ_EXPR:
1379169689Skan    case NE_EXPR:
1380169689Skan      inner_type = TREE_TYPE (TREE_OPERAND (rhs, 1));
1381169689Skan      if (TREE_CODE (inner_type) != COMPLEX_TYPE)
1382169689Skan	return;
1383169689Skan      break;
1384169689Skan
1385169689Skan    default:
1386169689Skan      {
1387169689Skan	tree lhs = TREE_OPERAND (stmt, 0);
1388169689Skan	tree rhs = TREE_OPERAND (stmt, 1);
1389169689Skan
1390169689Skan	if (TREE_CODE (type) == COMPLEX_TYPE)
1391169689Skan	  expand_complex_move (bsi, stmt, type, lhs, rhs);
1392169689Skan	else if ((TREE_CODE (rhs) == REALPART_EXPR
1393169689Skan		  || TREE_CODE (rhs) == IMAGPART_EXPR)
1394169689Skan		 && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
1395169689Skan	  {
1396169689Skan	    TREE_OPERAND (stmt, 1)
1397169689Skan	      = extract_component (bsi, TREE_OPERAND (rhs, 0),
1398169689Skan				   TREE_CODE (rhs) == IMAGPART_EXPR, false);
1399169689Skan	    update_stmt (stmt);
1400169689Skan	  }
1401169689Skan      }
1402169689Skan      return;
1403169689Skan    }
1404169689Skan
1405169689Skan  /* Extract the components of the two complex values.  Make sure and
1406169689Skan     handle the common case of the same value used twice specially.  */
1407169689Skan  ac = TREE_OPERAND (rhs, 0);
1408169689Skan  ar = extract_component (bsi, ac, 0, true);
1409169689Skan  ai = extract_component (bsi, ac, 1, true);
1410169689Skan
1411169689Skan  if (TREE_CODE_CLASS (code) == tcc_unary)
1412169689Skan    bc = br = bi = NULL;
1413169689Skan  else
1414169689Skan    {
1415169689Skan      bc = TREE_OPERAND (rhs, 1);
1416169689Skan      if (ac == bc)
1417169689Skan	br = ar, bi = ai;
1418169689Skan      else
1419169689Skan	{
1420169689Skan	  br = extract_component (bsi, bc, 0, true);
1421169689Skan	  bi = extract_component (bsi, bc, 1, true);
1422169689Skan	}
1423169689Skan    }
1424169689Skan
1425169689Skan  if (in_ssa_p)
1426169689Skan    {
1427169689Skan      al = find_lattice_value (ac);
1428169689Skan      if (al == UNINITIALIZED)
1429169689Skan	al = VARYING;
1430169689Skan
1431169689Skan      if (TREE_CODE_CLASS (code) == tcc_unary)
1432169689Skan	bl = UNINITIALIZED;
1433169689Skan      else if (ac == bc)
1434169689Skan	bl = al;
1435169689Skan      else
1436169689Skan	{
1437169689Skan	  bl = find_lattice_value (bc);
1438169689Skan	  if (bl == UNINITIALIZED)
1439169689Skan	    bl = VARYING;
1440169689Skan	}
1441169689Skan    }
1442169689Skan  else
1443169689Skan    al = bl = VARYING;
1444169689Skan
1445169689Skan  switch (code)
1446169689Skan    {
1447169689Skan    case PLUS_EXPR:
1448169689Skan    case MINUS_EXPR:
1449169689Skan      expand_complex_addition (bsi, inner_type, ar, ai, br, bi, code, al, bl);
1450169689Skan      break;
1451169689Skan
1452169689Skan    case MULT_EXPR:
1453169689Skan      expand_complex_multiplication (bsi, inner_type, ar, ai, br, bi, al, bl);
1454169689Skan      break;
1455169689Skan
1456169689Skan    case TRUNC_DIV_EXPR:
1457169689Skan    case CEIL_DIV_EXPR:
1458169689Skan    case FLOOR_DIV_EXPR:
1459169689Skan    case ROUND_DIV_EXPR:
1460169689Skan    case RDIV_EXPR:
1461169689Skan      expand_complex_division (bsi, inner_type, ar, ai, br, bi, code, al, bl);
1462169689Skan      break;
1463169689Skan
1464169689Skan    case NEGATE_EXPR:
1465169689Skan      expand_complex_negation (bsi, inner_type, ar, ai);
1466169689Skan      break;
1467169689Skan
1468169689Skan    case CONJ_EXPR:
1469169689Skan      expand_complex_conjugate (bsi, inner_type, ar, ai);
1470169689Skan      break;
1471169689Skan
1472169689Skan    case EQ_EXPR:
1473169689Skan    case NE_EXPR:
1474169689Skan      expand_complex_comparison (bsi, ar, ai, br, bi, code);
1475169689Skan      break;
1476169689Skan
1477169689Skan    default:
1478169689Skan      gcc_unreachable ();
1479169689Skan    }
1480169689Skan}
1481169689Skan
1482169689Skan
1483169689Skan/* Entry point for complex operation lowering during optimization.  */
1484169689Skan
1485169689Skanstatic unsigned int
1486169689Skantree_lower_complex (void)
1487169689Skan{
1488169689Skan  int old_last_basic_block;
1489169689Skan  block_stmt_iterator bsi;
1490169689Skan  basic_block bb;
1491169689Skan
1492169689Skan  if (!init_dont_simulate_again ())
1493169689Skan    return 0;
1494169689Skan
1495169689Skan  complex_lattice_values = VEC_alloc (complex_lattice_t, heap, num_ssa_names);
1496169689Skan  VEC_safe_grow (complex_lattice_t, heap,
1497169689Skan		 complex_lattice_values, num_ssa_names);
1498169689Skan  memset (VEC_address (complex_lattice_t, complex_lattice_values), 0,
1499169689Skan	  num_ssa_names * sizeof(complex_lattice_t));
1500169689Skan
1501169689Skan  init_parameter_lattice_values ();
1502169689Skan  ssa_propagate (complex_visit_stmt, complex_visit_phi);
1503169689Skan
1504169689Skan  complex_variable_components = htab_create (10,  int_tree_map_hash,
1505169689Skan					     int_tree_map_eq, free);
1506169689Skan
1507169689Skan  complex_ssa_name_components = VEC_alloc (tree, heap, 2*num_ssa_names);
1508169689Skan  VEC_safe_grow (tree, heap, complex_ssa_name_components, 2*num_ssa_names);
1509169689Skan  memset (VEC_address (tree, complex_ssa_name_components), 0,
1510169689Skan	  2 * num_ssa_names * sizeof(tree));
1511169689Skan
1512169689Skan  update_parameter_components ();
1513169689Skan
1514169689Skan  /* ??? Ideally we'd traverse the blocks in breadth-first order.  */
1515169689Skan  old_last_basic_block = last_basic_block;
1516169689Skan  FOR_EACH_BB (bb)
1517169689Skan    {
1518169689Skan      if (bb->index >= old_last_basic_block)
1519169689Skan	continue;
1520169689Skan      update_phi_components (bb);
1521169689Skan      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
1522169689Skan	expand_complex_operations_1 (&bsi);
1523169689Skan    }
1524169689Skan
1525169689Skan  bsi_commit_edge_inserts ();
1526169689Skan
1527169689Skan  htab_delete (complex_variable_components);
1528169689Skan  VEC_free (tree, heap, complex_ssa_name_components);
1529169689Skan  VEC_free (complex_lattice_t, heap, complex_lattice_values);
1530169689Skan  return 0;
1531169689Skan}
1532169689Skan
1533169689Skanstruct tree_opt_pass pass_lower_complex =
1534169689Skan{
1535169689Skan  "cplxlower",				/* name */
1536169689Skan  0,					/* gate */
1537169689Skan  tree_lower_complex,			/* execute */
1538169689Skan  NULL,					/* sub */
1539169689Skan  NULL,					/* next */
1540169689Skan  0,					/* static_pass_number */
1541169689Skan  0,					/* tv_id */
1542169689Skan  PROP_ssa,				/* properties_required */
1543169689Skan  0,					/* properties_provided */
1544169689Skan  PROP_smt_usage,                       /* properties_destroyed */
1545169689Skan  0,					/* todo_flags_start */
1546169689Skan  TODO_dump_func | TODO_ggc_collect
1547169689Skan  | TODO_update_smt_usage
1548169689Skan  | TODO_update_ssa
1549169689Skan  | TODO_verify_stmts,		        /* todo_flags_finish */
1550169689Skan  0					/* letter */
1551169689Skan};
1552169689Skan
1553169689Skan
1554169689Skan/* Entry point for complex operation lowering without optimization.  */
1555169689Skan
1556169689Skanstatic unsigned int
1557169689Skantree_lower_complex_O0 (void)
1558169689Skan{
1559169689Skan  int old_last_basic_block = last_basic_block;
1560169689Skan  block_stmt_iterator bsi;
1561169689Skan  basic_block bb;
1562169689Skan
1563169689Skan  FOR_EACH_BB (bb)
1564169689Skan    {
1565169689Skan      if (bb->index >= old_last_basic_block)
1566169689Skan	continue;
1567169689Skan      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
1568169689Skan	expand_complex_operations_1 (&bsi);
1569169689Skan    }
1570169689Skan  return 0;
1571169689Skan}
1572169689Skan
1573169689Skanstatic bool
1574169689Skangate_no_optimization (void)
1575169689Skan{
1576169689Skan  /* With errors, normal optimization passes are not run.  If we don't
1577169689Skan     lower complex operations at all, rtl expansion will abort.  */
1578169689Skan  return optimize == 0 || sorrycount || errorcount;
1579169689Skan}
1580169689Skan
1581169689Skanstruct tree_opt_pass pass_lower_complex_O0 =
1582169689Skan{
1583169689Skan  "cplxlower0",				/* name */
1584169689Skan  gate_no_optimization,			/* gate */
1585169689Skan  tree_lower_complex_O0,		/* execute */
1586169689Skan  NULL,					/* sub */
1587169689Skan  NULL,					/* next */
1588169689Skan  0,					/* static_pass_number */
1589169689Skan  0,					/* tv_id */
1590169689Skan  PROP_cfg,				/* properties_required */
1591169689Skan  0,					/* properties_provided */
1592169689Skan  0,					/* properties_destroyed */
1593169689Skan  0,					/* todo_flags_start */
1594169689Skan  TODO_dump_func | TODO_ggc_collect
1595169689Skan    | TODO_verify_stmts,		/* todo_flags_finish */
1596169689Skan  0					/* letter */
1597169689Skan};
1598