1169689Skan/* Forward propagation of expressions for single use variables. 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 7169689Skanit under the terms of the GNU General Public License as published by 8169689Skanthe Free Software Foundation; either version 2, or (at your option) 9169689Skanany later version. 10169689Skan 11169689SkanGCC is distributed in the hope that it will be useful, 12169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 13169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14169689SkanGNU General Public License for 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 18169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 19169689SkanBoston, MA 02110-1301, USA. */ 20169689Skan 21169689Skan#include "config.h" 22169689Skan#include "system.h" 23169689Skan#include "coretypes.h" 24169689Skan#include "tm.h" 25169689Skan#include "ggc.h" 26169689Skan#include "tree.h" 27169689Skan#include "rtl.h" 28169689Skan#include "tm_p.h" 29169689Skan#include "basic-block.h" 30169689Skan#include "timevar.h" 31169689Skan#include "diagnostic.h" 32169689Skan#include "tree-flow.h" 33169689Skan#include "tree-pass.h" 34169689Skan#include "tree-dump.h" 35169689Skan#include "langhooks.h" 36169689Skan 37169689Skan/* This pass propagates the RHS of assignment statements into use 38169689Skan sites of the LHS of the assignment. It's basically a specialized 39169689Skan form of tree combination. It is hoped all of this can disappear 40169689Skan when we have a generalized tree combiner. 41169689Skan 42169689Skan Note carefully that after propagation the resulting statement 43169689Skan must still be a proper gimple statement. Right now we simply 44169689Skan only perform propagations we know will result in valid gimple 45169689Skan code. One day we'll want to generalize this code. 46169689Skan 47169689Skan One class of common cases we handle is forward propagating a single use 48169689Skan variable into a COND_EXPR. 49169689Skan 50169689Skan bb0: 51169689Skan x = a COND b; 52169689Skan if (x) goto ... else goto ... 53169689Skan 54169689Skan Will be transformed into: 55169689Skan 56169689Skan bb0: 57169689Skan if (a COND b) goto ... else goto ... 58169689Skan 59169689Skan Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1). 60169689Skan 61169689Skan Or (assuming c1 and c2 are constants): 62169689Skan 63169689Skan bb0: 64169689Skan x = a + c1; 65169689Skan if (x EQ/NEQ c2) goto ... else goto ... 66169689Skan 67169689Skan Will be transformed into: 68169689Skan 69169689Skan bb0: 70169689Skan if (a EQ/NEQ (c2 - c1)) goto ... else goto ... 71169689Skan 72169689Skan Similarly for x = a - c1. 73169689Skan 74169689Skan Or 75169689Skan 76169689Skan bb0: 77169689Skan x = !a 78169689Skan if (x) goto ... else goto ... 79169689Skan 80169689Skan Will be transformed into: 81169689Skan 82169689Skan bb0: 83169689Skan if (a == 0) goto ... else goto ... 84169689Skan 85169689Skan Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1). 86169689Skan For these cases, we propagate A into all, possibly more than one, 87169689Skan COND_EXPRs that use X. 88169689Skan 89169689Skan Or 90169689Skan 91169689Skan bb0: 92169689Skan x = (typecast) a 93169689Skan if (x) goto ... else goto ... 94169689Skan 95169689Skan Will be transformed into: 96169689Skan 97169689Skan bb0: 98169689Skan if (a != 0) goto ... else goto ... 99169689Skan 100169689Skan (Assuming a is an integral type and x is a boolean or x is an 101169689Skan integral and a is a boolean.) 102169689Skan 103169689Skan Similarly for the tests (x == 0), (x != 0), (x == 1) and (x != 1). 104169689Skan For these cases, we propagate A into all, possibly more than one, 105169689Skan COND_EXPRs that use X. 106169689Skan 107169689Skan In addition to eliminating the variable and the statement which assigns 108169689Skan a value to the variable, we may be able to later thread the jump without 109169689Skan adding insane complexity in the dominator optimizer. 110169689Skan 111169689Skan Also note these transformations can cascade. We handle this by having 112169689Skan a worklist of COND_EXPR statements to examine. As we make a change to 113169689Skan a statement, we put it back on the worklist to examine on the next 114169689Skan iteration of the main loop. 115169689Skan 116169689Skan A second class of propagation opportunities arises for ADDR_EXPR 117169689Skan nodes. 118169689Skan 119169689Skan ptr = &x->y->z; 120169689Skan res = *ptr; 121169689Skan 122169689Skan Will get turned into 123169689Skan 124169689Skan res = x->y->z; 125169689Skan 126169689Skan Or 127169689Skan 128169689Skan ptr = &x[0]; 129169689Skan ptr2 = ptr + <constant>; 130169689Skan 131169689Skan Will get turned into 132169689Skan 133169689Skan ptr2 = &x[constant/elementsize]; 134169689Skan 135169689Skan Or 136169689Skan 137169689Skan ptr = &x[0]; 138169689Skan offset = index * element_size; 139169689Skan offset_p = (pointer) offset; 140169689Skan ptr2 = ptr + offset_p 141169689Skan 142169689Skan Will get turned into: 143169689Skan 144169689Skan ptr2 = &x[index]; 145169689Skan 146169689Skan We also propagate casts into SWITCH_EXPR and COND_EXPR conditions to 147169689Skan allow us to remove the cast and {NOT_EXPR,NEG_EXPR} into a subsequent 148169689Skan {NOT_EXPR,NEG_EXPR}. 149169689Skan 150169689Skan This will (of course) be extended as other needs arise. */ 151169689Skan 152169689Skan 153169689Skan/* Set to true if we delete EH edges during the optimization. */ 154169689Skanstatic bool cfg_changed; 155169689Skan 156169689Skan 157169689Skan/* Given an SSA_NAME VAR, return true if and only if VAR is defined by 158169689Skan a comparison. */ 159169689Skan 160169689Skanstatic bool 161169689Skanssa_name_defined_by_comparison_p (tree var) 162169689Skan{ 163169689Skan tree def = SSA_NAME_DEF_STMT (var); 164169689Skan 165169689Skan if (TREE_CODE (def) == MODIFY_EXPR) 166169689Skan { 167169689Skan tree rhs = TREE_OPERAND (def, 1); 168169689Skan return COMPARISON_CLASS_P (rhs); 169169689Skan } 170169689Skan 171169689Skan return 0; 172169689Skan} 173169689Skan 174169689Skan/* Forward propagate a single-use variable into COND once. Return a 175169689Skan new condition if successful. Return NULL_TREE otherwise. */ 176169689Skan 177169689Skanstatic tree 178169689Skanforward_propagate_into_cond_1 (tree cond, tree *test_var_p) 179169689Skan{ 180169689Skan tree new_cond = NULL_TREE; 181169689Skan enum tree_code cond_code = TREE_CODE (cond); 182169689Skan tree test_var = NULL_TREE; 183169689Skan tree def; 184169689Skan tree def_rhs; 185169689Skan 186169689Skan /* If the condition is not a lone variable or an equality test of an 187169689Skan SSA_NAME against an integral constant, then we do not have an 188169689Skan optimizable case. 189169689Skan 190169689Skan Note these conditions also ensure the COND_EXPR has no 191169689Skan virtual operands or other side effects. */ 192169689Skan if (cond_code != SSA_NAME 193169689Skan && !((cond_code == EQ_EXPR || cond_code == NE_EXPR) 194169689Skan && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME 195169689Skan && CONSTANT_CLASS_P (TREE_OPERAND (cond, 1)) 196169689Skan && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1))))) 197169689Skan return NULL_TREE; 198169689Skan 199169689Skan /* Extract the single variable used in the test into TEST_VAR. */ 200169689Skan if (cond_code == SSA_NAME) 201169689Skan test_var = cond; 202169689Skan else 203169689Skan test_var = TREE_OPERAND (cond, 0); 204169689Skan 205169689Skan /* Now get the defining statement for TEST_VAR. Skip this case if 206169689Skan it's not defined by some MODIFY_EXPR. */ 207169689Skan def = SSA_NAME_DEF_STMT (test_var); 208169689Skan if (TREE_CODE (def) != MODIFY_EXPR) 209169689Skan return NULL_TREE; 210169689Skan 211169689Skan def_rhs = TREE_OPERAND (def, 1); 212169689Skan 213169689Skan /* If TEST_VAR is set by adding or subtracting a constant 214169689Skan from an SSA_NAME, then it is interesting to us as we 215169689Skan can adjust the constant in the conditional and thus 216169689Skan eliminate the arithmetic operation. */ 217169689Skan if (TREE_CODE (def_rhs) == PLUS_EXPR 218169689Skan || TREE_CODE (def_rhs) == MINUS_EXPR) 219169689Skan { 220169689Skan tree op0 = TREE_OPERAND (def_rhs, 0); 221169689Skan tree op1 = TREE_OPERAND (def_rhs, 1); 222169689Skan 223169689Skan /* The first operand must be an SSA_NAME and the second 224169689Skan operand must be a constant. */ 225169689Skan if (TREE_CODE (op0) != SSA_NAME 226169689Skan || !CONSTANT_CLASS_P (op1) 227169689Skan || !INTEGRAL_TYPE_P (TREE_TYPE (op1))) 228169689Skan return NULL_TREE; 229169689Skan 230169689Skan /* Don't propagate if the first operand occurs in 231169689Skan an abnormal PHI. */ 232169689Skan if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)) 233169689Skan return NULL_TREE; 234169689Skan 235169689Skan if (has_single_use (test_var)) 236169689Skan { 237169689Skan enum tree_code new_code; 238169689Skan tree t; 239169689Skan 240169689Skan /* If the variable was defined via X + C, then we must 241169689Skan subtract C from the constant in the conditional. 242169689Skan Otherwise we add C to the constant in the 243169689Skan conditional. The result must fold into a valid 244169689Skan gimple operand to be optimizable. */ 245169689Skan new_code = (TREE_CODE (def_rhs) == PLUS_EXPR 246169689Skan ? MINUS_EXPR : PLUS_EXPR); 247169689Skan t = int_const_binop (new_code, TREE_OPERAND (cond, 1), op1, 0); 248169689Skan if (!is_gimple_val (t)) 249169689Skan return NULL_TREE; 250169689Skan 251169689Skan new_cond = build2 (cond_code, boolean_type_node, op0, t); 252169689Skan } 253169689Skan } 254169689Skan 255169689Skan /* These cases require comparisons of a naked SSA_NAME or 256169689Skan comparison of an SSA_NAME against zero or one. */ 257169689Skan else if (TREE_CODE (cond) == SSA_NAME 258169689Skan || integer_zerop (TREE_OPERAND (cond, 1)) 259169689Skan || integer_onep (TREE_OPERAND (cond, 1))) 260169689Skan { 261169689Skan /* If TEST_VAR is set from a relational operation 262169689Skan between two SSA_NAMEs or a combination of an SSA_NAME 263169689Skan and a constant, then it is interesting. */ 264169689Skan if (COMPARISON_CLASS_P (def_rhs)) 265169689Skan { 266169689Skan tree op0 = TREE_OPERAND (def_rhs, 0); 267169689Skan tree op1 = TREE_OPERAND (def_rhs, 1); 268169689Skan 269169689Skan /* Both operands of DEF_RHS must be SSA_NAMEs or 270169689Skan constants. */ 271169689Skan if ((TREE_CODE (op0) != SSA_NAME 272169689Skan && !is_gimple_min_invariant (op0)) 273169689Skan || (TREE_CODE (op1) != SSA_NAME 274169689Skan && !is_gimple_min_invariant (op1))) 275169689Skan return NULL_TREE; 276169689Skan 277169689Skan /* Don't propagate if the first operand occurs in 278169689Skan an abnormal PHI. */ 279169689Skan if (TREE_CODE (op0) == SSA_NAME 280169689Skan && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)) 281169689Skan return NULL_TREE; 282169689Skan 283169689Skan /* Don't propagate if the second operand occurs in 284169689Skan an abnormal PHI. */ 285169689Skan if (TREE_CODE (op1) == SSA_NAME 286169689Skan && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1)) 287169689Skan return NULL_TREE; 288169689Skan 289169689Skan if (has_single_use (test_var)) 290169689Skan { 291169689Skan /* TEST_VAR was set from a relational operator. */ 292169689Skan new_cond = build2 (TREE_CODE (def_rhs), 293169689Skan boolean_type_node, op0, op1); 294169689Skan 295169689Skan /* Invert the conditional if necessary. */ 296169689Skan if ((cond_code == EQ_EXPR 297169689Skan && integer_zerop (TREE_OPERAND (cond, 1))) 298169689Skan || (cond_code == NE_EXPR 299169689Skan && integer_onep (TREE_OPERAND (cond, 1)))) 300169689Skan { 301169689Skan new_cond = invert_truthvalue (new_cond); 302169689Skan 303169689Skan /* If we did not get a simple relational 304169689Skan expression or bare SSA_NAME, then we can 305169689Skan not optimize this case. */ 306169689Skan if (!COMPARISON_CLASS_P (new_cond) 307169689Skan && TREE_CODE (new_cond) != SSA_NAME) 308169689Skan new_cond = NULL_TREE; 309169689Skan } 310169689Skan } 311169689Skan } 312169689Skan 313169689Skan /* If TEST_VAR is set from a TRUTH_NOT_EXPR, then it 314169689Skan is interesting. */ 315169689Skan else if (TREE_CODE (def_rhs) == TRUTH_NOT_EXPR) 316169689Skan { 317169689Skan enum tree_code new_code; 318169689Skan 319169689Skan def_rhs = TREE_OPERAND (def_rhs, 0); 320169689Skan 321169689Skan /* DEF_RHS must be an SSA_NAME or constant. */ 322169689Skan if (TREE_CODE (def_rhs) != SSA_NAME 323169689Skan && !is_gimple_min_invariant (def_rhs)) 324169689Skan return NULL_TREE; 325169689Skan 326169689Skan /* Don't propagate if the operand occurs in 327169689Skan an abnormal PHI. */ 328169689Skan if (TREE_CODE (def_rhs) == SSA_NAME 329169689Skan && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def_rhs)) 330169689Skan return NULL_TREE; 331169689Skan 332169689Skan if (cond_code == SSA_NAME 333169689Skan || (cond_code == NE_EXPR 334169689Skan && integer_zerop (TREE_OPERAND (cond, 1))) 335169689Skan || (cond_code == EQ_EXPR 336169689Skan && integer_onep (TREE_OPERAND (cond, 1)))) 337169689Skan new_code = EQ_EXPR; 338169689Skan else 339169689Skan new_code = NE_EXPR; 340169689Skan 341169689Skan new_cond = build2 (new_code, boolean_type_node, def_rhs, 342169689Skan fold_convert (TREE_TYPE (def_rhs), 343169689Skan integer_zero_node)); 344169689Skan } 345169689Skan 346169689Skan /* If TEST_VAR was set from a cast of an integer type 347169689Skan to a boolean type or a cast of a boolean to an 348169689Skan integral, then it is interesting. */ 349169689Skan else if (TREE_CODE (def_rhs) == NOP_EXPR 350169689Skan || TREE_CODE (def_rhs) == CONVERT_EXPR) 351169689Skan { 352169689Skan tree outer_type; 353169689Skan tree inner_type; 354169689Skan 355169689Skan outer_type = TREE_TYPE (def_rhs); 356169689Skan inner_type = TREE_TYPE (TREE_OPERAND (def_rhs, 0)); 357169689Skan 358169689Skan if ((TREE_CODE (outer_type) == BOOLEAN_TYPE 359169689Skan && INTEGRAL_TYPE_P (inner_type)) 360169689Skan || (TREE_CODE (inner_type) == BOOLEAN_TYPE 361169689Skan && INTEGRAL_TYPE_P (outer_type))) 362169689Skan ; 363169689Skan else if (INTEGRAL_TYPE_P (outer_type) 364169689Skan && INTEGRAL_TYPE_P (inner_type) 365169689Skan && TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME 366169689Skan && ssa_name_defined_by_comparison_p (TREE_OPERAND (def_rhs, 367169689Skan 0))) 368169689Skan ; 369169689Skan else 370169689Skan return NULL_TREE; 371169689Skan 372169689Skan /* Don't propagate if the operand occurs in 373169689Skan an abnormal PHI. */ 374169689Skan if (TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME 375169689Skan && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND 376169689Skan (def_rhs, 0))) 377169689Skan return NULL_TREE; 378169689Skan 379169689Skan if (has_single_use (test_var)) 380169689Skan { 381169689Skan enum tree_code new_code; 382169689Skan tree new_arg; 383169689Skan 384169689Skan if (cond_code == SSA_NAME 385169689Skan || (cond_code == NE_EXPR 386169689Skan && integer_zerop (TREE_OPERAND (cond, 1))) 387169689Skan || (cond_code == EQ_EXPR 388169689Skan && integer_onep (TREE_OPERAND (cond, 1)))) 389169689Skan new_code = NE_EXPR; 390169689Skan else 391169689Skan new_code = EQ_EXPR; 392169689Skan 393169689Skan new_arg = TREE_OPERAND (def_rhs, 0); 394169689Skan new_cond = build2 (new_code, boolean_type_node, new_arg, 395169689Skan fold_convert (TREE_TYPE (new_arg), 396169689Skan integer_zero_node)); 397169689Skan } 398169689Skan } 399169689Skan } 400169689Skan 401169689Skan *test_var_p = test_var; 402169689Skan return new_cond; 403169689Skan} 404169689Skan 405169689Skan/* COND is a condition of the form: 406169689Skan 407169689Skan x == const or x != const 408169689Skan 409169689Skan Look back to x's defining statement and see if x is defined as 410169689Skan 411169689Skan x = (type) y; 412169689Skan 413169689Skan If const is unchanged if we convert it to type, then we can build 414169689Skan the equivalent expression: 415169689Skan 416169689Skan 417169689Skan y == const or y != const 418169689Skan 419169689Skan Which may allow further optimizations. 420169689Skan 421169689Skan Return the equivalent comparison or NULL if no such equivalent comparison 422169689Skan was found. */ 423169689Skan 424169689Skanstatic tree 425169689Skanfind_equivalent_equality_comparison (tree cond) 426169689Skan{ 427169689Skan tree op0 = TREE_OPERAND (cond, 0); 428169689Skan tree op1 = TREE_OPERAND (cond, 1); 429169689Skan tree def_stmt = SSA_NAME_DEF_STMT (op0); 430169689Skan 431169689Skan while (def_stmt 432169689Skan && TREE_CODE (def_stmt) == MODIFY_EXPR 433169689Skan && TREE_CODE (TREE_OPERAND (def_stmt, 1)) == SSA_NAME) 434169689Skan def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (def_stmt, 1)); 435169689Skan 436169689Skan /* OP0 might have been a parameter, so first make sure it 437169689Skan was defined by a MODIFY_EXPR. */ 438169689Skan if (def_stmt && TREE_CODE (def_stmt) == MODIFY_EXPR) 439169689Skan { 440169689Skan tree def_rhs = TREE_OPERAND (def_stmt, 1); 441169689Skan 442169689Skan /* If either operand to the comparison is a pointer to 443169689Skan a function, then we can not apply this optimization 444169689Skan as some targets require function pointers to be 445169689Skan canonicalized and in this case this optimization would 446169689Skan eliminate a necessary canonicalization. */ 447169689Skan if ((POINTER_TYPE_P (TREE_TYPE (op0)) 448169689Skan && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == FUNCTION_TYPE) 449169689Skan || (POINTER_TYPE_P (TREE_TYPE (op1)) 450169689Skan && TREE_CODE (TREE_TYPE (TREE_TYPE (op1))) == FUNCTION_TYPE)) 451169689Skan return NULL; 452169689Skan 453169689Skan /* Now make sure the RHS of the MODIFY_EXPR is a typecast. */ 454169689Skan if ((TREE_CODE (def_rhs) == NOP_EXPR 455169689Skan || TREE_CODE (def_rhs) == CONVERT_EXPR) 456169689Skan && TREE_CODE (TREE_OPERAND (def_rhs, 0)) == SSA_NAME) 457169689Skan { 458169689Skan tree def_rhs_inner = TREE_OPERAND (def_rhs, 0); 459169689Skan tree def_rhs_inner_type = TREE_TYPE (def_rhs_inner); 460169689Skan tree new; 461169689Skan 462169689Skan if (TYPE_PRECISION (def_rhs_inner_type) 463169689Skan > TYPE_PRECISION (TREE_TYPE (def_rhs))) 464169689Skan return NULL; 465169689Skan 466169689Skan /* If the inner type of the conversion is a pointer to 467169689Skan a function, then we can not apply this optimization 468169689Skan as some targets require function pointers to be 469169689Skan canonicalized. This optimization would result in 470169689Skan canonicalization of the pointer when it was not originally 471169689Skan needed/intended. */ 472169689Skan if (POINTER_TYPE_P (def_rhs_inner_type) 473169689Skan && TREE_CODE (TREE_TYPE (def_rhs_inner_type)) == FUNCTION_TYPE) 474169689Skan return NULL; 475169689Skan 476169689Skan /* What we want to prove is that if we convert OP1 to 477169689Skan the type of the object inside the NOP_EXPR that the 478169689Skan result is still equivalent to SRC. 479169689Skan 480169689Skan If that is true, the build and return new equivalent 481169689Skan condition which uses the source of the typecast and the 482169689Skan new constant (which has only changed its type). */ 483169689Skan new = fold_build1 (TREE_CODE (def_rhs), def_rhs_inner_type, op1); 484169689Skan STRIP_USELESS_TYPE_CONVERSION (new); 485169689Skan if (is_gimple_val (new) && tree_int_cst_equal (new, op1)) 486169689Skan return build2 (TREE_CODE (cond), TREE_TYPE (cond), 487169689Skan def_rhs_inner, new); 488169689Skan } 489169689Skan } 490169689Skan return NULL; 491169689Skan} 492169689Skan 493169689Skan/* STMT is a COND_EXPR 494169689Skan 495169689Skan This routine attempts to find equivalent forms of the condition 496169689Skan which we may be able to optimize better. */ 497169689Skan 498169689Skanstatic void 499169689Skansimplify_cond (tree stmt) 500169689Skan{ 501169689Skan tree cond = COND_EXPR_COND (stmt); 502169689Skan 503169689Skan if (COMPARISON_CLASS_P (cond)) 504169689Skan { 505169689Skan tree op0 = TREE_OPERAND (cond, 0); 506169689Skan tree op1 = TREE_OPERAND (cond, 1); 507169689Skan 508169689Skan if (TREE_CODE (op0) == SSA_NAME && is_gimple_min_invariant (op1)) 509169689Skan { 510169689Skan /* First see if we have test of an SSA_NAME against a constant 511169689Skan where the SSA_NAME is defined by an earlier typecast which 512169689Skan is irrelevant when performing tests against the given 513169689Skan constant. */ 514169689Skan if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR) 515169689Skan { 516169689Skan tree new_cond = find_equivalent_equality_comparison (cond); 517169689Skan 518169689Skan if (new_cond) 519169689Skan { 520169689Skan COND_EXPR_COND (stmt) = new_cond; 521169689Skan update_stmt (stmt); 522169689Skan } 523169689Skan } 524169689Skan } 525169689Skan } 526169689Skan} 527169689Skan 528169689Skan/* Forward propagate a single-use variable into COND_EXPR as many 529169689Skan times as possible. */ 530169689Skan 531169689Skanstatic void 532169689Skanforward_propagate_into_cond (tree cond_expr) 533169689Skan{ 534169689Skan gcc_assert (TREE_CODE (cond_expr) == COND_EXPR); 535169689Skan 536169689Skan while (1) 537169689Skan { 538169689Skan tree test_var = NULL_TREE; 539169689Skan tree cond = COND_EXPR_COND (cond_expr); 540169689Skan tree new_cond = forward_propagate_into_cond_1 (cond, &test_var); 541169689Skan 542169689Skan /* Return if unsuccessful. */ 543169689Skan if (new_cond == NULL_TREE) 544169689Skan break; 545169689Skan 546169689Skan /* Dump details. */ 547169689Skan if (dump_file && (dump_flags & TDF_DETAILS)) 548169689Skan { 549169689Skan fprintf (dump_file, " Replaced '"); 550169689Skan print_generic_expr (dump_file, cond, dump_flags); 551169689Skan fprintf (dump_file, "' with '"); 552169689Skan print_generic_expr (dump_file, new_cond, dump_flags); 553169689Skan fprintf (dump_file, "'\n"); 554169689Skan } 555169689Skan 556169689Skan COND_EXPR_COND (cond_expr) = new_cond; 557169689Skan update_stmt (cond_expr); 558169689Skan 559169689Skan if (has_zero_uses (test_var)) 560169689Skan { 561169689Skan tree def = SSA_NAME_DEF_STMT (test_var); 562169689Skan block_stmt_iterator bsi = bsi_for_stmt (def); 563169689Skan bsi_remove (&bsi, true); 564169689Skan } 565169689Skan } 566169689Skan 567169689Skan /* There are further simplifications that can be performed 568169689Skan on COND_EXPRs. Specifically, when comparing an SSA_NAME 569169689Skan against a constant where the SSA_NAME is the result of a 570169689Skan conversion. Perhaps this should be folded into the rest 571169689Skan of the COND_EXPR simplification code. */ 572169689Skan simplify_cond (cond_expr); 573169689Skan} 574169689Skan 575169689Skan/* We've just substituted an ADDR_EXPR into stmt. Update all the 576169689Skan relevant data structures to match. */ 577169689Skan 578169689Skanstatic void 579169689Skantidy_after_forward_propagate_addr (tree stmt) 580169689Skan{ 581169689Skan /* We may have turned a trapping insn into a non-trapping insn. */ 582169689Skan if (maybe_clean_or_replace_eh_stmt (stmt, stmt) 583169689Skan && tree_purge_dead_eh_edges (bb_for_stmt (stmt))) 584169689Skan cfg_changed = true; 585169689Skan 586169689Skan if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR) 587169689Skan recompute_tree_invariant_for_addr_expr (TREE_OPERAND (stmt, 1)); 588169689Skan 589169689Skan mark_new_vars_to_rename (stmt); 590169689Skan} 591169689Skan 592169689Skan/* STMT defines LHS which is contains the address of the 0th element 593169689Skan in an array. USE_STMT uses LHS to compute the address of an 594169689Skan arbitrary element within the array. The (variable) byte offset 595169689Skan of the element is contained in OFFSET. 596169689Skan 597169689Skan We walk back through the use-def chains of OFFSET to verify that 598169689Skan it is indeed computing the offset of an element within the array 599169689Skan and extract the index corresponding to the given byte offset. 600169689Skan 601169689Skan We then try to fold the entire address expression into a form 602169689Skan &array[index]. 603169689Skan 604169689Skan If we are successful, we replace the right hand side of USE_STMT 605169689Skan with the new address computation. */ 606169689Skan 607169689Skanstatic bool 608169689Skanforward_propagate_addr_into_variable_array_index (tree offset, tree lhs, 609169689Skan tree stmt, tree use_stmt) 610169689Skan{ 611169689Skan tree index; 612169689Skan 613169689Skan /* The offset must be defined by a simple MODIFY_EXPR statement. */ 614169689Skan if (TREE_CODE (offset) != MODIFY_EXPR) 615169689Skan return false; 616169689Skan 617169689Skan /* The RHS of the statement which defines OFFSET must be a gimple 618169689Skan cast of another SSA_NAME. */ 619169689Skan offset = TREE_OPERAND (offset, 1); 620169689Skan if (!is_gimple_cast (offset)) 621169689Skan return false; 622169689Skan 623169689Skan offset = TREE_OPERAND (offset, 0); 624169689Skan if (TREE_CODE (offset) != SSA_NAME) 625169689Skan return false; 626169689Skan 627169689Skan /* Get the defining statement of the offset before type 628169689Skan conversion. */ 629169689Skan offset = SSA_NAME_DEF_STMT (offset); 630169689Skan 631169689Skan /* The statement which defines OFFSET before type conversion 632169689Skan must be a simple MODIFY_EXPR. */ 633169689Skan if (TREE_CODE (offset) != MODIFY_EXPR) 634169689Skan return false; 635169689Skan 636169689Skan /* The RHS of the statement which defines OFFSET must be a 637169689Skan multiplication of an object by the size of the array elements. 638169689Skan This implicitly verifies that the size of the array elements 639169689Skan is constant. */ 640169689Skan offset = TREE_OPERAND (offset, 1); 641169689Skan if (TREE_CODE (offset) != MULT_EXPR 642169689Skan || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST 643169689Skan || !simple_cst_equal (TREE_OPERAND (offset, 1), 644169689Skan TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs))))) 645169689Skan return false; 646169689Skan 647169689Skan /* The first operand to the MULT_EXPR is the desired index. */ 648169689Skan index = TREE_OPERAND (offset, 0); 649169689Skan 650169689Skan /* Replace the pointer addition with array indexing. */ 651169689Skan TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1)); 652169689Skan TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (use_stmt, 1), 0), 1) = index; 653169689Skan 654169689Skan /* That should have created gimple, so there is no need to 655169689Skan record information to undo the propagation. */ 656169689Skan fold_stmt_inplace (use_stmt); 657169689Skan tidy_after_forward_propagate_addr (use_stmt); 658169689Skan return true; 659169689Skan} 660169689Skan 661169689Skan/* STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>. 662169689Skan 663169689Skan Try to forward propagate the ADDR_EXPR into the use USE_STMT. 664169689Skan Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF 665169689Skan node or for recovery of array indexing from pointer arithmetic. 666169689Skan 667169689Skan CHANGED is an optional pointer to a boolean variable set to true if 668169689Skan either the LHS or RHS was changed in the USE_STMT. 669169689Skan 670169689Skan Return true if the propagation was successful (the propagation can 671169689Skan be not totally successful, yet things may have been changed). */ 672169689Skan 673169689Skanstatic bool 674169689Skanforward_propagate_addr_expr_1 (tree stmt, tree use_stmt, bool *changed) 675169689Skan{ 676169689Skan tree name = TREE_OPERAND (stmt, 0); 677169689Skan tree lhs, rhs, array_ref; 678169689Skan 679169689Skan /* Strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS. 680169689Skan ADDR_EXPR will not appear on the LHS. */ 681169689Skan lhs = TREE_OPERAND (use_stmt, 0); 682169689Skan while (TREE_CODE (lhs) == COMPONENT_REF || TREE_CODE (lhs) == ARRAY_REF) 683169689Skan lhs = TREE_OPERAND (lhs, 0); 684169689Skan 685169689Skan /* Now see if the LHS node is an INDIRECT_REF using NAME. If so, 686169689Skan propagate the ADDR_EXPR into the use of NAME and fold the result. */ 687169689Skan if (TREE_CODE (lhs) == INDIRECT_REF && TREE_OPERAND (lhs, 0) == name) 688169689Skan { 689169689Skan /* This should always succeed in creating gimple, so there is 690169689Skan no need to save enough state to undo this propagation. */ 691169689Skan TREE_OPERAND (lhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1)); 692169689Skan fold_stmt_inplace (use_stmt); 693169689Skan tidy_after_forward_propagate_addr (use_stmt); 694169689Skan if (changed) 695169689Skan *changed = true; 696169689Skan } 697169689Skan 698169689Skan /* Trivial case. The use statement could be a trivial copy. We 699169689Skan go ahead and handle that case here since it's trivial and 700169689Skan removes the need to run copy-prop before this pass to get 701169689Skan the best results. Also note that by handling this case here 702169689Skan we can catch some cascading effects, ie the single use is 703169689Skan in a copy, and the copy is used later by a single INDIRECT_REF 704169689Skan for example. */ 705169689Skan else if (TREE_CODE (lhs) == SSA_NAME && TREE_OPERAND (use_stmt, 1) == name) 706169689Skan { 707169689Skan TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1)); 708169689Skan tidy_after_forward_propagate_addr (use_stmt); 709169689Skan if (changed) 710169689Skan *changed = true; 711169689Skan return true; 712169689Skan } 713169689Skan 714169689Skan /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR 715169689Skan nodes from the RHS. */ 716169689Skan rhs = TREE_OPERAND (use_stmt, 1); 717169689Skan while (TREE_CODE (rhs) == COMPONENT_REF 718169689Skan || TREE_CODE (rhs) == ARRAY_REF 719169689Skan || TREE_CODE (rhs) == ADDR_EXPR) 720169689Skan rhs = TREE_OPERAND (rhs, 0); 721169689Skan 722169689Skan /* Now see if the RHS node is an INDIRECT_REF using NAME. If so, 723169689Skan propagate the ADDR_EXPR into the use of NAME and fold the result. */ 724169689Skan if (TREE_CODE (rhs) == INDIRECT_REF && TREE_OPERAND (rhs, 0) == name) 725169689Skan { 726169689Skan /* This should always succeed in creating gimple, so there is 727169689Skan no need to save enough state to undo this propagation. */ 728169689Skan TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1)); 729169689Skan fold_stmt_inplace (use_stmt); 730169689Skan tidy_after_forward_propagate_addr (use_stmt); 731169689Skan if (changed) 732169689Skan *changed = true; 733169689Skan return true; 734169689Skan } 735169689Skan 736169689Skan /* The remaining cases are all for turning pointer arithmetic into 737169689Skan array indexing. They only apply when we have the address of 738169689Skan element zero in an array. If that is not the case then there 739169689Skan is nothing to do. */ 740169689Skan array_ref = TREE_OPERAND (TREE_OPERAND (stmt, 1), 0); 741169689Skan if (TREE_CODE (array_ref) != ARRAY_REF 742169689Skan || TREE_CODE (TREE_TYPE (TREE_OPERAND (array_ref, 0))) != ARRAY_TYPE 743169689Skan || !integer_zerop (TREE_OPERAND (array_ref, 1))) 744169689Skan return false; 745169689Skan 746169689Skan /* If the use of the ADDR_EXPR must be a PLUS_EXPR, or else there 747169689Skan is nothing to do. */ 748169689Skan if (TREE_CODE (rhs) != PLUS_EXPR) 749169689Skan return false; 750169689Skan 751169689Skan /* Try to optimize &x[0] + C where C is a multiple of the size 752169689Skan of the elements in X into &x[C/element size]. */ 753169689Skan if (TREE_OPERAND (rhs, 0) == name 754169689Skan && TREE_CODE (TREE_OPERAND (rhs, 1)) == INTEGER_CST) 755169689Skan { 756169689Skan tree orig = unshare_expr (rhs); 757169689Skan TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1)); 758169689Skan 759169689Skan /* If folding succeeds, then we have just exposed new variables 760169689Skan in USE_STMT which will need to be renamed. If folding fails, 761169689Skan then we need to put everything back the way it was. */ 762169689Skan if (fold_stmt_inplace (use_stmt)) 763169689Skan { 764169689Skan tidy_after_forward_propagate_addr (use_stmt); 765169689Skan if (changed) 766169689Skan *changed = true; 767169689Skan return true; 768169689Skan } 769169689Skan else 770169689Skan { 771169689Skan TREE_OPERAND (use_stmt, 1) = orig; 772169689Skan update_stmt (use_stmt); 773169689Skan return false; 774169689Skan } 775169689Skan } 776169689Skan 777169689Skan /* Try to optimize &x[0] + OFFSET where OFFSET is defined by 778169689Skan converting a multiplication of an index by the size of the 779169689Skan array elements, then the result is converted into the proper 780169689Skan type for the arithmetic. */ 781169689Skan if (TREE_OPERAND (rhs, 0) == name 782169689Skan && TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME 783169689Skan /* Avoid problems with IVopts creating PLUS_EXPRs with a 784169689Skan different type than their operands. */ 785169689Skan && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs))) 786169689Skan { 787169689Skan bool res; 788169689Skan tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1)); 789169689Skan 790169689Skan res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs, 791169689Skan stmt, use_stmt); 792169689Skan if (res && changed) 793169689Skan *changed = true; 794169689Skan return res; 795169689Skan } 796169689Skan 797169689Skan /* Same as the previous case, except the operands of the PLUS_EXPR 798169689Skan were reversed. */ 799169689Skan if (TREE_OPERAND (rhs, 1) == name 800169689Skan && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME 801169689Skan /* Avoid problems with IVopts creating PLUS_EXPRs with a 802169689Skan different type than their operands. */ 803169689Skan && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs))) 804169689Skan { 805169689Skan bool res; 806169689Skan tree offset_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0)); 807169689Skan res = forward_propagate_addr_into_variable_array_index (offset_stmt, lhs, 808169689Skan stmt, use_stmt); 809169689Skan if (res && changed) 810169689Skan *changed = true; 811169689Skan return res; 812169689Skan } 813169689Skan return false; 814169689Skan} 815169689Skan 816169689Skan/* STMT is a statement of the form SSA_NAME = ADDR_EXPR <whatever>. 817169689Skan SOME is a pointer to a boolean value indicating whether we 818169689Skan propagated the address expression anywhere. 819169689Skan 820169689Skan Try to forward propagate the ADDR_EXPR into all uses of the SSA_NAME. 821169689Skan Often this will allow for removal of an ADDR_EXPR and INDIRECT_REF 822169689Skan node or for recovery of array indexing from pointer arithmetic. 823169689Skan Returns true, if all uses have been propagated into. */ 824169689Skan 825169689Skanstatic bool 826169689Skanforward_propagate_addr_expr (tree stmt, bool *some) 827169689Skan{ 828169689Skan int stmt_loop_depth = bb_for_stmt (stmt)->loop_depth; 829169689Skan tree name = TREE_OPERAND (stmt, 0); 830169689Skan imm_use_iterator iter; 831169689Skan tree use_stmt; 832169689Skan bool all = true; 833169689Skan 834169689Skan FOR_EACH_IMM_USE_STMT (use_stmt, iter, name) 835169689Skan { 836169689Skan bool result; 837169689Skan 838169689Skan /* If the use is not in a simple assignment statement, then 839169689Skan there is nothing we can do. */ 840169689Skan if (TREE_CODE (use_stmt) != MODIFY_EXPR) 841169689Skan { 842169689Skan all = false; 843169689Skan continue; 844169689Skan } 845169689Skan 846169689Skan /* If the use is in a deeper loop nest, then we do not want 847169689Skan to propagate the ADDR_EXPR into the loop as that is likely 848169689Skan adding expression evaluations into the loop. */ 849169689Skan if (bb_for_stmt (use_stmt)->loop_depth > stmt_loop_depth) 850169689Skan { 851169689Skan all = false; 852169689Skan continue; 853169689Skan } 854169689Skan 855169689Skan /* If the use_stmt has side-effects, don't propagate into it. */ 856169689Skan if (stmt_ann (use_stmt)->has_volatile_ops) 857169689Skan { 858169689Skan all = false; 859169689Skan continue; 860169689Skan } 861169689Skan 862169689Skan result = forward_propagate_addr_expr_1 (stmt, use_stmt, some); 863169689Skan *some |= result; 864169689Skan all &= result; 865169689Skan } 866169689Skan 867169689Skan return all; 868169689Skan} 869169689Skan 870169689Skan/* If we have lhs = ~x (STMT), look and see if earlier we had x = ~y. 871169689Skan If so, we can change STMT into lhs = y which can later be copy 872169689Skan propagated. Similarly for negation. 873169689Skan 874169689Skan This could trivially be formulated as a forward propagation 875169689Skan to immediate uses. However, we already had an implementation 876169689Skan from DOM which used backward propagation via the use-def links. 877169689Skan 878169689Skan It turns out that backward propagation is actually faster as 879169689Skan there's less work to do for each NOT/NEG expression we find. 880169689Skan Backwards propagation needs to look at the statement in a single 881169689Skan backlink. Forward propagation needs to look at potentially more 882169689Skan than one forward link. */ 883169689Skan 884169689Skanstatic void 885169689Skansimplify_not_neg_expr (tree stmt) 886169689Skan{ 887169689Skan tree rhs = TREE_OPERAND (stmt, 1); 888169689Skan tree rhs_def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0)); 889169689Skan 890169689Skan /* See if the RHS_DEF_STMT has the same form as our statement. */ 891169689Skan if (TREE_CODE (rhs_def_stmt) == MODIFY_EXPR 892169689Skan && TREE_CODE (TREE_OPERAND (rhs_def_stmt, 1)) == TREE_CODE (rhs)) 893169689Skan { 894169689Skan tree rhs_def_operand = TREE_OPERAND (TREE_OPERAND (rhs_def_stmt, 1), 0); 895169689Skan 896169689Skan /* Verify that RHS_DEF_OPERAND is a suitable SSA_NAME. */ 897169689Skan if (TREE_CODE (rhs_def_operand) == SSA_NAME 898169689Skan && ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs_def_operand)) 899169689Skan { 900169689Skan TREE_OPERAND (stmt, 1) = rhs_def_operand; 901169689Skan update_stmt (stmt); 902169689Skan } 903169689Skan } 904169689Skan} 905169689Skan 906169689Skan/* STMT is a SWITCH_EXPR for which we attempt to find equivalent forms of 907169689Skan the condition which we may be able to optimize better. */ 908169689Skan 909169689Skanstatic void 910169689Skansimplify_switch_expr (tree stmt) 911169689Skan{ 912169689Skan tree cond = SWITCH_COND (stmt); 913169689Skan tree def, to, ti; 914169689Skan 915169689Skan /* The optimization that we really care about is removing unnecessary 916169689Skan casts. That will let us do much better in propagating the inferred 917169689Skan constant at the switch target. */ 918169689Skan if (TREE_CODE (cond) == SSA_NAME) 919169689Skan { 920169689Skan def = SSA_NAME_DEF_STMT (cond); 921169689Skan if (TREE_CODE (def) == MODIFY_EXPR) 922169689Skan { 923169689Skan def = TREE_OPERAND (def, 1); 924169689Skan if (TREE_CODE (def) == NOP_EXPR) 925169689Skan { 926169689Skan int need_precision; 927169689Skan bool fail; 928169689Skan 929169689Skan def = TREE_OPERAND (def, 0); 930169689Skan 931169689Skan#ifdef ENABLE_CHECKING 932169689Skan /* ??? Why was Jeff testing this? We are gimple... */ 933169689Skan gcc_assert (is_gimple_val (def)); 934169689Skan#endif 935169689Skan 936169689Skan to = TREE_TYPE (cond); 937169689Skan ti = TREE_TYPE (def); 938169689Skan 939169689Skan /* If we have an extension that preserves value, then we 940169689Skan can copy the source value into the switch. */ 941169689Skan 942169689Skan need_precision = TYPE_PRECISION (ti); 943169689Skan fail = false; 944169689Skan if (! INTEGRAL_TYPE_P (ti)) 945169689Skan fail = true; 946169689Skan else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti)) 947169689Skan fail = true; 948169689Skan else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti)) 949169689Skan need_precision += 1; 950169689Skan if (TYPE_PRECISION (to) < need_precision) 951169689Skan fail = true; 952169689Skan 953169689Skan if (!fail) 954169689Skan { 955169689Skan SWITCH_COND (stmt) = def; 956169689Skan update_stmt (stmt); 957169689Skan } 958169689Skan } 959169689Skan } 960169689Skan } 961169689Skan} 962169689Skan 963169689Skan/* Main entry point for the forward propagation optimizer. */ 964169689Skan 965169689Skanstatic unsigned int 966169689Skantree_ssa_forward_propagate_single_use_vars (void) 967169689Skan{ 968169689Skan basic_block bb; 969169689Skan unsigned int todoflags = 0; 970169689Skan 971169689Skan cfg_changed = false; 972169689Skan 973169689Skan FOR_EACH_BB (bb) 974169689Skan { 975169689Skan block_stmt_iterator bsi; 976169689Skan 977169689Skan /* Note we update BSI within the loop as necessary. */ 978169689Skan for (bsi = bsi_start (bb); !bsi_end_p (bsi); ) 979169689Skan { 980169689Skan tree stmt = bsi_stmt (bsi); 981169689Skan 982169689Skan /* If this statement sets an SSA_NAME to an address, 983169689Skan try to propagate the address into the uses of the SSA_NAME. */ 984169689Skan if (TREE_CODE (stmt) == MODIFY_EXPR) 985169689Skan { 986169689Skan tree lhs = TREE_OPERAND (stmt, 0); 987169689Skan tree rhs = TREE_OPERAND (stmt, 1); 988169689Skan 989169689Skan 990169689Skan if (TREE_CODE (lhs) != SSA_NAME) 991169689Skan { 992169689Skan bsi_next (&bsi); 993169689Skan continue; 994169689Skan } 995169689Skan 996169689Skan if (TREE_CODE (rhs) == ADDR_EXPR) 997169689Skan { 998169689Skan bool some = false; 999169689Skan if (forward_propagate_addr_expr (stmt, &some)) 1000169689Skan bsi_remove (&bsi, true); 1001169689Skan else 1002169689Skan bsi_next (&bsi); 1003169689Skan if (some) 1004169689Skan todoflags |= TODO_update_smt_usage; 1005169689Skan } 1006169689Skan else if ((TREE_CODE (rhs) == BIT_NOT_EXPR 1007169689Skan || TREE_CODE (rhs) == NEGATE_EXPR) 1008169689Skan && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME) 1009169689Skan { 1010169689Skan simplify_not_neg_expr (stmt); 1011169689Skan bsi_next (&bsi); 1012169689Skan } 1013169689Skan else 1014169689Skan bsi_next (&bsi); 1015169689Skan } 1016169689Skan else if (TREE_CODE (stmt) == SWITCH_EXPR) 1017169689Skan { 1018169689Skan simplify_switch_expr (stmt); 1019169689Skan bsi_next (&bsi); 1020169689Skan } 1021169689Skan else if (TREE_CODE (stmt) == COND_EXPR) 1022169689Skan { 1023169689Skan forward_propagate_into_cond (stmt); 1024169689Skan bsi_next (&bsi); 1025169689Skan } 1026169689Skan else 1027169689Skan bsi_next (&bsi); 1028169689Skan } 1029169689Skan } 1030169689Skan 1031169689Skan if (cfg_changed) 1032169689Skan cleanup_tree_cfg (); 1033169689Skan return todoflags; 1034169689Skan} 1035169689Skan 1036169689Skan 1037169689Skanstatic bool 1038169689Skangate_forwprop (void) 1039169689Skan{ 1040169689Skan return 1; 1041169689Skan} 1042169689Skan 1043169689Skanstruct tree_opt_pass pass_forwprop = { 1044169689Skan "forwprop", /* name */ 1045169689Skan gate_forwprop, /* gate */ 1046169689Skan tree_ssa_forward_propagate_single_use_vars, /* execute */ 1047169689Skan NULL, /* sub */ 1048169689Skan NULL, /* next */ 1049169689Skan 0, /* static_pass_number */ 1050169689Skan TV_TREE_FORWPROP, /* tv_id */ 1051169689Skan PROP_cfg | PROP_ssa 1052169689Skan | PROP_alias, /* properties_required */ 1053169689Skan 0, /* properties_provided */ 1054169689Skan PROP_smt_usage, /* properties_destroyed */ 1055169689Skan 0, /* todo_flags_start */ 1056169689Skan TODO_dump_func /* todo_flags_finish */ 1057169689Skan | TODO_ggc_collect 1058169689Skan | TODO_update_ssa | TODO_verify_ssa, 1059169689Skan 0 /* letter */ 1060169689Skan}; 1061