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