138fd1498Szrj /* Miscellaneous SSA utility functions. 238fd1498Szrj Copyright (C) 2001-2018 Free Software Foundation, Inc. 338fd1498Szrj 438fd1498Szrj This file is part of GCC. 538fd1498Szrj 638fd1498Szrj GCC is free software; you can redistribute it and/or modify 738fd1498Szrj it under the terms of the GNU General Public License as published by 838fd1498Szrj the Free Software Foundation; either version 3, or (at your option) 938fd1498Szrj any later version. 1038fd1498Szrj 1138fd1498Szrj GCC is distributed in the hope that it will be useful, 1238fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of 1338fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438fd1498Szrj GNU General Public License for more details. 1538fd1498Szrj 1638fd1498Szrj You should have received a copy of the GNU General Public License 1738fd1498Szrj along with GCC; see the file COPYING3. If not see 1838fd1498Szrj <http://www.gnu.org/licenses/>. */ 1938fd1498Szrj 2038fd1498Szrj #include "config.h" 2138fd1498Szrj #include "system.h" 2238fd1498Szrj #include "coretypes.h" 2338fd1498Szrj #include "backend.h" 2438fd1498Szrj #include "tree.h" 2538fd1498Szrj #include "gimple.h" 2638fd1498Szrj #include "cfghooks.h" 2738fd1498Szrj #include "tree-pass.h" 2838fd1498Szrj #include "ssa.h" 2938fd1498Szrj #include "gimple-pretty-print.h" 3038fd1498Szrj #include "diagnostic-core.h" 3138fd1498Szrj #include "fold-const.h" 3238fd1498Szrj #include "stor-layout.h" 3338fd1498Szrj #include "gimple-fold.h" 3438fd1498Szrj #include "gimplify.h" 3538fd1498Szrj #include "gimple-iterator.h" 3638fd1498Szrj #include "gimple-walk.h" 3738fd1498Szrj #include "tree-ssa-loop-manip.h" 3838fd1498Szrj #include "tree-into-ssa.h" 3938fd1498Szrj #include "tree-ssa.h" 4038fd1498Szrj #include "cfgloop.h" 4138fd1498Szrj #include "cfgexpand.h" 4238fd1498Szrj #include "tree-cfg.h" 4338fd1498Szrj #include "tree-dfa.h" 4438fd1498Szrj #include "stringpool.h" 4538fd1498Szrj #include "attribs.h" 4638fd1498Szrj #include "asan.h" 4738fd1498Szrj 4838fd1498Szrj /* Pointer map of variable mappings, keyed by edge. */ 4938fd1498Szrj static hash_map<edge, auto_vec<edge_var_map> > *edge_var_maps; 5038fd1498Szrj 5138fd1498Szrj 5238fd1498Szrj /* Add a mapping with PHI RESULT and PHI DEF associated with edge E. */ 5338fd1498Szrj 5438fd1498Szrj void 5538fd1498Szrj redirect_edge_var_map_add (edge e, tree result, tree def, source_location locus) 5638fd1498Szrj { 5738fd1498Szrj edge_var_map new_node; 5838fd1498Szrj 5938fd1498Szrj if (edge_var_maps == NULL) 6038fd1498Szrj edge_var_maps = new hash_map<edge, auto_vec<edge_var_map> >; 6138fd1498Szrj 6238fd1498Szrj auto_vec<edge_var_map> &slot = edge_var_maps->get_or_insert (e); 6338fd1498Szrj new_node.def = def; 6438fd1498Szrj new_node.result = result; 6538fd1498Szrj new_node.locus = locus; 6638fd1498Szrj 6738fd1498Szrj slot.safe_push (new_node); 6838fd1498Szrj } 6938fd1498Szrj 7038fd1498Szrj 7138fd1498Szrj /* Clear the var mappings in edge E. */ 7238fd1498Szrj 7338fd1498Szrj void 7438fd1498Szrj redirect_edge_var_map_clear (edge e) 7538fd1498Szrj { 7638fd1498Szrj if (!edge_var_maps) 7738fd1498Szrj return; 7838fd1498Szrj 7938fd1498Szrj auto_vec<edge_var_map> *head = edge_var_maps->get (e); 8038fd1498Szrj 8138fd1498Szrj if (head) 8238fd1498Szrj head->release (); 8338fd1498Szrj } 8438fd1498Szrj 8538fd1498Szrj 8638fd1498Szrj /* Duplicate the redirected var mappings in OLDE in NEWE. 8738fd1498Szrj 8838fd1498Szrj This assumes a hash_map can have multiple edges mapping to the same 8938fd1498Szrj var_map (many to one mapping), since we don't remove the previous mappings. 9038fd1498Szrj */ 9138fd1498Szrj 9238fd1498Szrj void 9338fd1498Szrj redirect_edge_var_map_dup (edge newe, edge olde) 9438fd1498Szrj { 9538fd1498Szrj if (!edge_var_maps) 9638fd1498Szrj return; 9738fd1498Szrj 9838fd1498Szrj auto_vec<edge_var_map> *new_head = &edge_var_maps->get_or_insert (newe); 9938fd1498Szrj auto_vec<edge_var_map> *old_head = edge_var_maps->get (olde); 10038fd1498Szrj if (!old_head) 10138fd1498Szrj return; 10238fd1498Szrj 10338fd1498Szrj new_head->safe_splice (*old_head); 10438fd1498Szrj } 10538fd1498Szrj 10638fd1498Szrj 10738fd1498Szrj /* Return the variable mappings for a given edge. If there is none, return 10838fd1498Szrj NULL. */ 10938fd1498Szrj 11038fd1498Szrj vec<edge_var_map> * 11138fd1498Szrj redirect_edge_var_map_vector (edge e) 11238fd1498Szrj { 11338fd1498Szrj /* Hey, what kind of idiot would... you'd be surprised. */ 11438fd1498Szrj if (!edge_var_maps) 11538fd1498Szrj return NULL; 11638fd1498Szrj 11738fd1498Szrj auto_vec<edge_var_map> *slot = edge_var_maps->get (e); 11838fd1498Szrj if (!slot) 11938fd1498Szrj return NULL; 12038fd1498Szrj 12138fd1498Szrj return slot; 12238fd1498Szrj } 12338fd1498Szrj 12438fd1498Szrj /* Clear the edge variable mappings. */ 12538fd1498Szrj 12638fd1498Szrj void 12738fd1498Szrj redirect_edge_var_map_empty (void) 12838fd1498Szrj { 12938fd1498Szrj if (edge_var_maps) 13038fd1498Szrj edge_var_maps->empty (); 13138fd1498Szrj } 13238fd1498Szrj 13338fd1498Szrj 13438fd1498Szrj /* Remove the corresponding arguments from the PHI nodes in E's 13538fd1498Szrj destination block and redirect it to DEST. Return redirected edge. 13638fd1498Szrj The list of removed arguments is stored in a vector accessed 13738fd1498Szrj through edge_var_maps. */ 13838fd1498Szrj 13938fd1498Szrj edge 14038fd1498Szrj ssa_redirect_edge (edge e, basic_block dest) 14138fd1498Szrj { 14238fd1498Szrj gphi_iterator gsi; 14338fd1498Szrj gphi *phi; 14438fd1498Szrj 14538fd1498Szrj redirect_edge_var_map_clear (e); 14638fd1498Szrj 14738fd1498Szrj /* Remove the appropriate PHI arguments in E's destination block. 14838fd1498Szrj If we are redirecting a copied edge the destination has not 14938fd1498Szrj got PHI argument space reserved nor an interesting argument. */ 15038fd1498Szrj if (! (e->dest->flags & BB_DUPLICATED)) 15138fd1498Szrj for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi)) 15238fd1498Szrj { 15338fd1498Szrj tree def; 15438fd1498Szrj source_location locus ; 15538fd1498Szrj 15638fd1498Szrj phi = gsi.phi (); 15738fd1498Szrj def = gimple_phi_arg_def (phi, e->dest_idx); 15838fd1498Szrj locus = gimple_phi_arg_location (phi, e->dest_idx); 15938fd1498Szrj 16038fd1498Szrj if (def == NULL_TREE) 16138fd1498Szrj continue; 16238fd1498Szrj 16338fd1498Szrj redirect_edge_var_map_add (e, gimple_phi_result (phi), def, locus); 16438fd1498Szrj } 16538fd1498Szrj 16638fd1498Szrj e = redirect_edge_succ_nodup (e, dest); 16738fd1498Szrj 16838fd1498Szrj return e; 16938fd1498Szrj } 17038fd1498Szrj 17138fd1498Szrj 17238fd1498Szrj /* Add PHI arguments queued in PENDING_STMT list on edge E to edge 17338fd1498Szrj E->dest. */ 17438fd1498Szrj 17538fd1498Szrj void 17638fd1498Szrj flush_pending_stmts (edge e) 17738fd1498Szrj { 17838fd1498Szrj gphi *phi; 17938fd1498Szrj edge_var_map *vm; 18038fd1498Szrj int i; 18138fd1498Szrj gphi_iterator gsi; 18238fd1498Szrj 18338fd1498Szrj vec<edge_var_map> *v = redirect_edge_var_map_vector (e); 18438fd1498Szrj if (!v) 18538fd1498Szrj return; 18638fd1498Szrj 18738fd1498Szrj for (gsi = gsi_start_phis (e->dest), i = 0; 18838fd1498Szrj !gsi_end_p (gsi) && v->iterate (i, &vm); 18938fd1498Szrj gsi_next (&gsi), i++) 19038fd1498Szrj { 19138fd1498Szrj tree def; 19238fd1498Szrj 19338fd1498Szrj phi = gsi.phi (); 19438fd1498Szrj def = redirect_edge_var_map_def (vm); 19538fd1498Szrj add_phi_arg (phi, def, e, redirect_edge_var_map_location (vm)); 19638fd1498Szrj } 19738fd1498Szrj 19838fd1498Szrj redirect_edge_var_map_clear (e); 19938fd1498Szrj } 20038fd1498Szrj 20138fd1498Szrj /* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a 20238fd1498Szrj GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an 20338fd1498Szrj expression with a different value. 20438fd1498Szrj 20538fd1498Szrj This will update any annotations (say debug bind stmts) referring 20638fd1498Szrj to the original LHS, so that they use the RHS instead. This is 20738fd1498Szrj done even if NLHS and LHS are the same, for it is understood that 20838fd1498Szrj the RHS will be modified afterwards, and NLHS will not be assigned 20938fd1498Szrj an equivalent value. 21038fd1498Szrj 21138fd1498Szrj Adjusting any non-annotation uses of the LHS, if needed, is a 21238fd1498Szrj responsibility of the caller. 21338fd1498Szrj 21438fd1498Szrj The effect of this call should be pretty much the same as that of 21538fd1498Szrj inserting a copy of STMT before STMT, and then removing the 21638fd1498Szrj original stmt, at which time gsi_remove() would have update 21738fd1498Szrj annotations, but using this function saves all the inserting, 21838fd1498Szrj copying and removing. */ 21938fd1498Szrj 22038fd1498Szrj void 22138fd1498Szrj gimple_replace_ssa_lhs (gimple *stmt, tree nlhs) 22238fd1498Szrj { 22338fd1498Szrj if (MAY_HAVE_DEBUG_BIND_STMTS) 22438fd1498Szrj { 22538fd1498Szrj tree lhs = gimple_get_lhs (stmt); 22638fd1498Szrj 22738fd1498Szrj gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt); 22838fd1498Szrj 22938fd1498Szrj insert_debug_temp_for_var_def (NULL, lhs); 23038fd1498Szrj } 23138fd1498Szrj 23238fd1498Szrj gimple_set_lhs (stmt, nlhs); 23338fd1498Szrj } 23438fd1498Szrj 23538fd1498Szrj 23638fd1498Szrj /* Given a tree for an expression for which we might want to emit 23738fd1498Szrj locations or values in debug information (generally a variable, but 23838fd1498Szrj we might deal with other kinds of trees in the future), return the 23938fd1498Szrj tree that should be used as the variable of a DEBUG_BIND STMT or 24038fd1498Szrj VAR_LOCATION INSN or NOTE. Return NULL if VAR is not to be tracked. */ 24138fd1498Szrj 24238fd1498Szrj tree 24338fd1498Szrj target_for_debug_bind (tree var) 24438fd1498Szrj { 24538fd1498Szrj if (!MAY_HAVE_DEBUG_BIND_STMTS) 24638fd1498Szrj return NULL_TREE; 24738fd1498Szrj 24838fd1498Szrj if (TREE_CODE (var) == SSA_NAME) 24938fd1498Szrj { 25038fd1498Szrj var = SSA_NAME_VAR (var); 25138fd1498Szrj if (var == NULL_TREE) 25238fd1498Szrj return NULL_TREE; 25338fd1498Szrj } 25438fd1498Szrj 25538fd1498Szrj if ((!VAR_P (var) || VAR_DECL_IS_VIRTUAL_OPERAND (var)) 25638fd1498Szrj && TREE_CODE (var) != PARM_DECL) 25738fd1498Szrj return NULL_TREE; 25838fd1498Szrj 25938fd1498Szrj if (DECL_HAS_VALUE_EXPR_P (var)) 26038fd1498Szrj return target_for_debug_bind (DECL_VALUE_EXPR (var)); 26138fd1498Szrj 26238fd1498Szrj if (DECL_IGNORED_P (var)) 26338fd1498Szrj return NULL_TREE; 26438fd1498Szrj 26538fd1498Szrj /* var-tracking only tracks registers. */ 26638fd1498Szrj if (!is_gimple_reg_type (TREE_TYPE (var))) 26738fd1498Szrj return NULL_TREE; 26838fd1498Szrj 26938fd1498Szrj return var; 27038fd1498Szrj } 27138fd1498Szrj 27238fd1498Szrj /* Called via walk_tree, look for SSA_NAMEs that have already been 27338fd1498Szrj released. */ 27438fd1498Szrj 27538fd1498Szrj static tree 27638fd1498Szrj find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_) 27738fd1498Szrj { 27838fd1498Szrj struct walk_stmt_info *wi = (struct walk_stmt_info *) data_; 27938fd1498Szrj 28038fd1498Szrj if (wi && wi->is_lhs) 28138fd1498Szrj return NULL_TREE; 28238fd1498Szrj 28338fd1498Szrj if (TREE_CODE (*tp) == SSA_NAME) 28438fd1498Szrj { 28538fd1498Szrj if (SSA_NAME_IN_FREE_LIST (*tp)) 28638fd1498Szrj return *tp; 28738fd1498Szrj 28838fd1498Szrj *walk_subtrees = 0; 28938fd1498Szrj } 29038fd1498Szrj else if (IS_TYPE_OR_DECL_P (*tp)) 29138fd1498Szrj *walk_subtrees = 0; 29238fd1498Szrj 29338fd1498Szrj return NULL_TREE; 29438fd1498Szrj } 29538fd1498Szrj 29638fd1498Szrj /* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced 29738fd1498Szrj by other DEBUG stmts, and replace uses of the DEF with the 29838fd1498Szrj newly-created debug temp. */ 29938fd1498Szrj 30038fd1498Szrj void 30138fd1498Szrj insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) 30238fd1498Szrj { 30338fd1498Szrj imm_use_iterator imm_iter; 30438fd1498Szrj use_operand_p use_p; 30538fd1498Szrj gimple *stmt; 30638fd1498Szrj gimple *def_stmt = NULL; 30738fd1498Szrj int usecount = 0; 30838fd1498Szrj tree value = NULL; 30938fd1498Szrj 31038fd1498Szrj if (!MAY_HAVE_DEBUG_BIND_STMTS) 31138fd1498Szrj return; 31238fd1498Szrj 31338fd1498Szrj /* If this name has already been registered for replacement, do nothing 31438fd1498Szrj as anything that uses this name isn't in SSA form. */ 31538fd1498Szrj if (name_registered_for_update_p (var)) 31638fd1498Szrj return; 31738fd1498Szrj 31838fd1498Szrj /* Check whether there are debug stmts that reference this variable and, 31938fd1498Szrj if there are, decide whether we should use a debug temp. */ 32038fd1498Szrj FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var) 32138fd1498Szrj { 32238fd1498Szrj stmt = USE_STMT (use_p); 32338fd1498Szrj 32438fd1498Szrj if (!gimple_debug_bind_p (stmt)) 32538fd1498Szrj continue; 32638fd1498Szrj 32738fd1498Szrj if (usecount++) 32838fd1498Szrj break; 32938fd1498Szrj 33038fd1498Szrj if (gimple_debug_bind_get_value (stmt) != var) 33138fd1498Szrj { 33238fd1498Szrj /* Count this as an additional use, so as to make sure we 33338fd1498Szrj use a temp unless VAR's definition has a SINGLE_RHS that 33438fd1498Szrj can be shared. */ 33538fd1498Szrj usecount++; 33638fd1498Szrj break; 33738fd1498Szrj } 33838fd1498Szrj } 33938fd1498Szrj 34038fd1498Szrj if (!usecount) 34138fd1498Szrj return; 34238fd1498Szrj 34338fd1498Szrj if (gsi) 34438fd1498Szrj def_stmt = gsi_stmt (*gsi); 34538fd1498Szrj else 34638fd1498Szrj def_stmt = SSA_NAME_DEF_STMT (var); 34738fd1498Szrj 34838fd1498Szrj /* If we didn't get an insertion point, and the stmt has already 34938fd1498Szrj been removed, we won't be able to insert the debug bind stmt, so 35038fd1498Szrj we'll have to drop debug information. */ 35138fd1498Szrj if (gimple_code (def_stmt) == GIMPLE_PHI) 35238fd1498Szrj { 35338fd1498Szrj value = degenerate_phi_result (as_a <gphi *> (def_stmt)); 35438fd1498Szrj if (value && walk_tree (&value, find_released_ssa_name, NULL, NULL)) 35538fd1498Szrj value = NULL; 35638fd1498Szrj /* error_mark_node is what fixup_noreturn_call changes PHI arguments 35738fd1498Szrj to. */ 35838fd1498Szrj else if (value == error_mark_node) 35938fd1498Szrj value = NULL; 36038fd1498Szrj } 36138fd1498Szrj else if (is_gimple_assign (def_stmt)) 36238fd1498Szrj { 36338fd1498Szrj bool no_value = false; 36438fd1498Szrj 36538fd1498Szrj if (!dom_info_available_p (CDI_DOMINATORS)) 36638fd1498Szrj { 36738fd1498Szrj struct walk_stmt_info wi; 36838fd1498Szrj 36938fd1498Szrj memset (&wi, 0, sizeof (wi)); 37038fd1498Szrj 37138fd1498Szrj /* When removing blocks without following reverse dominance 37238fd1498Szrj order, we may sometimes encounter SSA_NAMEs that have 37338fd1498Szrj already been released, referenced in other SSA_DEFs that 37438fd1498Szrj we're about to release. Consider: 37538fd1498Szrj 37638fd1498Szrj <bb X>: 37738fd1498Szrj v_1 = foo; 37838fd1498Szrj 37938fd1498Szrj <bb Y>: 38038fd1498Szrj w_2 = v_1 + bar; 38138fd1498Szrj # DEBUG w => w_2 38238fd1498Szrj 38338fd1498Szrj If we deleted BB X first, propagating the value of w_2 38438fd1498Szrj won't do us any good. It's too late to recover their 38538fd1498Szrj original definition of v_1: when it was deleted, it was 38638fd1498Szrj only referenced in other DEFs, it couldn't possibly know 38738fd1498Szrj it should have been retained, and propagating every 38838fd1498Szrj single DEF just in case it might have to be propagated 38938fd1498Szrj into a DEBUG STMT would probably be too wasteful. 39038fd1498Szrj 39138fd1498Szrj When dominator information is not readily available, we 39238fd1498Szrj check for and accept some loss of debug information. But 39338fd1498Szrj if it is available, there's no excuse for us to remove 39438fd1498Szrj blocks in the wrong order, so we don't even check for 39538fd1498Szrj dead SSA NAMEs. SSA verification shall catch any 39638fd1498Szrj errors. */ 39738fd1498Szrj if ((!gsi && !gimple_bb (def_stmt)) 39838fd1498Szrj || walk_gimple_op (def_stmt, find_released_ssa_name, &wi)) 39938fd1498Szrj no_value = true; 40038fd1498Szrj } 40138fd1498Szrj 40238fd1498Szrj if (!no_value) 40338fd1498Szrj value = gimple_assign_rhs_to_tree (def_stmt); 40438fd1498Szrj } 40538fd1498Szrj 40638fd1498Szrj if (value) 40738fd1498Szrj { 40838fd1498Szrj /* If there's a single use of VAR, and VAR is the entire debug 40938fd1498Szrj expression (usecount would have been incremented again 41038fd1498Szrj otherwise), and the definition involves only constants and 41138fd1498Szrj SSA names, then we can propagate VALUE into this single use, 41238fd1498Szrj avoiding the temp. 41338fd1498Szrj 41438fd1498Szrj We can also avoid using a temp if VALUE can be shared and 41538fd1498Szrj propagated into all uses, without generating expressions that 41638fd1498Szrj wouldn't be valid gimple RHSs. 41738fd1498Szrj 41838fd1498Szrj Other cases that would require unsharing or non-gimple RHSs 41938fd1498Szrj are deferred to a debug temp, although we could avoid temps 42038fd1498Szrj at the expense of duplication of expressions. */ 42138fd1498Szrj 42238fd1498Szrj if (CONSTANT_CLASS_P (value) 42338fd1498Szrj || gimple_code (def_stmt) == GIMPLE_PHI 42438fd1498Szrj || (usecount == 1 42538fd1498Szrj && (!gimple_assign_single_p (def_stmt) 42638fd1498Szrj || is_gimple_min_invariant (value))) 42738fd1498Szrj || is_gimple_reg (value)) 42838fd1498Szrj ; 42938fd1498Szrj else 43038fd1498Szrj { 43138fd1498Szrj gdebug *def_temp; 43238fd1498Szrj tree vexpr = make_node (DEBUG_EXPR_DECL); 43338fd1498Szrj 43438fd1498Szrj def_temp = gimple_build_debug_bind (vexpr, 43538fd1498Szrj unshare_expr (value), 43638fd1498Szrj def_stmt); 43738fd1498Szrj 43838fd1498Szrj DECL_ARTIFICIAL (vexpr) = 1; 43938fd1498Szrj TREE_TYPE (vexpr) = TREE_TYPE (value); 44038fd1498Szrj if (DECL_P (value)) 44138fd1498Szrj SET_DECL_MODE (vexpr, DECL_MODE (value)); 44238fd1498Szrj else 44338fd1498Szrj SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (value))); 44438fd1498Szrj 44538fd1498Szrj if (gsi) 44638fd1498Szrj gsi_insert_before (gsi, def_temp, GSI_SAME_STMT); 44738fd1498Szrj else 44838fd1498Szrj { 44938fd1498Szrj gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt); 45038fd1498Szrj gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT); 45138fd1498Szrj } 45238fd1498Szrj 45338fd1498Szrj value = vexpr; 45438fd1498Szrj } 45538fd1498Szrj } 45638fd1498Szrj 45738fd1498Szrj FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var) 45838fd1498Szrj { 45938fd1498Szrj if (!gimple_debug_bind_p (stmt)) 46038fd1498Szrj continue; 46138fd1498Szrj 46238fd1498Szrj if (value) 46338fd1498Szrj { 46438fd1498Szrj FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) 46538fd1498Szrj /* unshare_expr is not needed here. vexpr is either a 46638fd1498Szrj SINGLE_RHS, that can be safely shared, some other RHS 46738fd1498Szrj that was unshared when we found it had a single debug 46838fd1498Szrj use, or a DEBUG_EXPR_DECL, that can be safely 46938fd1498Szrj shared. */ 47038fd1498Szrj SET_USE (use_p, unshare_expr (value)); 47138fd1498Szrj /* If we didn't replace uses with a debug decl fold the 47238fd1498Szrj resulting expression. Otherwise we end up with invalid IL. */ 47338fd1498Szrj if (TREE_CODE (value) != DEBUG_EXPR_DECL) 47438fd1498Szrj { 47538fd1498Szrj gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 47638fd1498Szrj fold_stmt_inplace (&gsi); 47738fd1498Szrj } 47838fd1498Szrj } 47938fd1498Szrj else 48038fd1498Szrj gimple_debug_bind_reset_value (stmt); 48138fd1498Szrj 48238fd1498Szrj update_stmt (stmt); 48338fd1498Szrj } 48438fd1498Szrj } 48538fd1498Szrj 48638fd1498Szrj 48738fd1498Szrj /* Insert a DEBUG BIND stmt before STMT for each DEF referenced by 48838fd1498Szrj other DEBUG stmts, and replace uses of the DEF with the 48938fd1498Szrj newly-created debug temp. */ 49038fd1498Szrj 49138fd1498Szrj void 49238fd1498Szrj insert_debug_temps_for_defs (gimple_stmt_iterator *gsi) 49338fd1498Szrj { 49438fd1498Szrj gimple *stmt; 49538fd1498Szrj ssa_op_iter op_iter; 49638fd1498Szrj def_operand_p def_p; 49738fd1498Szrj 49838fd1498Szrj if (!MAY_HAVE_DEBUG_BIND_STMTS) 49938fd1498Szrj return; 50038fd1498Szrj 50138fd1498Szrj stmt = gsi_stmt (*gsi); 50238fd1498Szrj 50338fd1498Szrj FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF) 50438fd1498Szrj { 50538fd1498Szrj tree var = DEF_FROM_PTR (def_p); 50638fd1498Szrj 50738fd1498Szrj if (TREE_CODE (var) != SSA_NAME) 50838fd1498Szrj continue; 50938fd1498Szrj 51038fd1498Szrj insert_debug_temp_for_var_def (gsi, var); 51138fd1498Szrj } 51238fd1498Szrj } 51338fd1498Szrj 51438fd1498Szrj /* Reset all debug stmts that use SSA_NAME(s) defined in STMT. */ 51538fd1498Szrj 51638fd1498Szrj void 51738fd1498Szrj reset_debug_uses (gimple *stmt) 51838fd1498Szrj { 51938fd1498Szrj ssa_op_iter op_iter; 52038fd1498Szrj def_operand_p def_p; 52138fd1498Szrj imm_use_iterator imm_iter; 52238fd1498Szrj gimple *use_stmt; 52338fd1498Szrj 52438fd1498Szrj if (!MAY_HAVE_DEBUG_BIND_STMTS) 52538fd1498Szrj return; 52638fd1498Szrj 52738fd1498Szrj FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF) 52838fd1498Szrj { 52938fd1498Szrj tree var = DEF_FROM_PTR (def_p); 53038fd1498Szrj 53138fd1498Szrj if (TREE_CODE (var) != SSA_NAME) 53238fd1498Szrj continue; 53338fd1498Szrj 53438fd1498Szrj FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, var) 53538fd1498Szrj { 53638fd1498Szrj if (!gimple_debug_bind_p (use_stmt)) 53738fd1498Szrj continue; 53838fd1498Szrj 53938fd1498Szrj gimple_debug_bind_reset_value (use_stmt); 54038fd1498Szrj update_stmt (use_stmt); 54138fd1498Szrj } 54238fd1498Szrj } 54338fd1498Szrj } 54438fd1498Szrj 54538fd1498Szrj /* Delete SSA DEFs for SSA versions in the TOREMOVE bitmap, removing 54638fd1498Szrj dominated stmts before their dominators, so that release_ssa_defs 54738fd1498Szrj stands a chance of propagating DEFs into debug bind stmts. */ 54838fd1498Szrj 54938fd1498Szrj void 55038fd1498Szrj release_defs_bitset (bitmap toremove) 55138fd1498Szrj { 55238fd1498Szrj unsigned j; 55338fd1498Szrj bitmap_iterator bi; 55438fd1498Szrj 55538fd1498Szrj /* Performing a topological sort is probably overkill, this will 55638fd1498Szrj most likely run in slightly superlinear time, rather than the 55738fd1498Szrj pathological quadratic worst case. */ 55838fd1498Szrj while (!bitmap_empty_p (toremove)) 55938fd1498Szrj { 56038fd1498Szrj unsigned to_remove_bit = -1U; 56138fd1498Szrj EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi) 56238fd1498Szrj { 56338fd1498Szrj if (to_remove_bit != -1U) 56438fd1498Szrj { 56538fd1498Szrj bitmap_clear_bit (toremove, to_remove_bit); 56638fd1498Szrj to_remove_bit = -1U; 56738fd1498Szrj } 56838fd1498Szrj 56938fd1498Szrj bool remove_now = true; 57038fd1498Szrj tree var = ssa_name (j); 57138fd1498Szrj gimple *stmt; 57238fd1498Szrj imm_use_iterator uit; 57338fd1498Szrj 57438fd1498Szrj FOR_EACH_IMM_USE_STMT (stmt, uit, var) 57538fd1498Szrj { 57638fd1498Szrj ssa_op_iter dit; 57738fd1498Szrj def_operand_p def_p; 57838fd1498Szrj 57938fd1498Szrj /* We can't propagate PHI nodes into debug stmts. */ 58038fd1498Szrj if (gimple_code (stmt) == GIMPLE_PHI 58138fd1498Szrj || is_gimple_debug (stmt)) 58238fd1498Szrj continue; 58338fd1498Szrj 58438fd1498Szrj /* If we find another definition to remove that uses 58538fd1498Szrj the one we're looking at, defer the removal of this 58638fd1498Szrj one, so that it can be propagated into debug stmts 58738fd1498Szrj after the other is. */ 58838fd1498Szrj FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, dit, SSA_OP_DEF) 58938fd1498Szrj { 59038fd1498Szrj tree odef = DEF_FROM_PTR (def_p); 59138fd1498Szrj 59238fd1498Szrj if (bitmap_bit_p (toremove, SSA_NAME_VERSION (odef))) 59338fd1498Szrj { 59438fd1498Szrj remove_now = false; 59538fd1498Szrj break; 59638fd1498Szrj } 59738fd1498Szrj } 59838fd1498Szrj 59938fd1498Szrj if (!remove_now) 60038fd1498Szrj BREAK_FROM_IMM_USE_STMT (uit); 60138fd1498Szrj } 60238fd1498Szrj 60338fd1498Szrj if (remove_now) 60438fd1498Szrj { 60538fd1498Szrj gimple *def = SSA_NAME_DEF_STMT (var); 60638fd1498Szrj gimple_stmt_iterator gsi = gsi_for_stmt (def); 60738fd1498Szrj 60838fd1498Szrj if (gimple_code (def) == GIMPLE_PHI) 60938fd1498Szrj remove_phi_node (&gsi, true); 61038fd1498Szrj else 61138fd1498Szrj { 61238fd1498Szrj gsi_remove (&gsi, true); 61338fd1498Szrj release_defs (def); 61438fd1498Szrj } 61538fd1498Szrj 61638fd1498Szrj to_remove_bit = j; 61738fd1498Szrj } 61838fd1498Szrj } 61938fd1498Szrj if (to_remove_bit != -1U) 62038fd1498Szrj bitmap_clear_bit (toremove, to_remove_bit); 62138fd1498Szrj } 62238fd1498Szrj 62338fd1498Szrj } 62438fd1498Szrj 62538fd1498Szrj /* Verify virtual SSA form. */ 62638fd1498Szrj 62738fd1498Szrj bool 62838fd1498Szrj verify_vssa (basic_block bb, tree current_vdef, sbitmap visited) 62938fd1498Szrj { 63038fd1498Szrj bool err = false; 63138fd1498Szrj 63238fd1498Szrj if (bitmap_bit_p (visited, bb->index)) 63338fd1498Szrj return false; 63438fd1498Szrj 63538fd1498Szrj bitmap_set_bit (visited, bb->index); 63638fd1498Szrj 63738fd1498Szrj /* Pick up the single virtual PHI def. */ 63838fd1498Szrj gphi *phi = NULL; 63938fd1498Szrj for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); 64038fd1498Szrj gsi_next (&si)) 64138fd1498Szrj { 64238fd1498Szrj tree res = gimple_phi_result (si.phi ()); 64338fd1498Szrj if (virtual_operand_p (res)) 64438fd1498Szrj { 64538fd1498Szrj if (phi) 64638fd1498Szrj { 64738fd1498Szrj error ("multiple virtual PHI nodes in BB %d", bb->index); 64838fd1498Szrj print_gimple_stmt (stderr, phi, 0); 64938fd1498Szrj print_gimple_stmt (stderr, si.phi (), 0); 65038fd1498Szrj err = true; 65138fd1498Szrj } 65238fd1498Szrj else 65338fd1498Szrj phi = si.phi (); 65438fd1498Szrj } 65538fd1498Szrj } 65638fd1498Szrj if (phi) 65738fd1498Szrj { 65838fd1498Szrj current_vdef = gimple_phi_result (phi); 65938fd1498Szrj if (TREE_CODE (current_vdef) != SSA_NAME) 66038fd1498Szrj { 66138fd1498Szrj error ("virtual definition is not an SSA name"); 66238fd1498Szrj print_gimple_stmt (stderr, phi, 0); 66338fd1498Szrj err = true; 66438fd1498Szrj } 66538fd1498Szrj } 66638fd1498Szrj 66738fd1498Szrj /* Verify stmts. */ 66838fd1498Szrj for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); 66938fd1498Szrj gsi_next (&gsi)) 67038fd1498Szrj { 67138fd1498Szrj gimple *stmt = gsi_stmt (gsi); 67238fd1498Szrj tree vuse = gimple_vuse (stmt); 67338fd1498Szrj if (vuse) 67438fd1498Szrj { 67538fd1498Szrj if (vuse != current_vdef) 67638fd1498Szrj { 67738fd1498Szrj error ("stmt with wrong VUSE"); 67838fd1498Szrj print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); 67938fd1498Szrj fprintf (stderr, "expected "); 68038fd1498Szrj print_generic_expr (stderr, current_vdef); 68138fd1498Szrj fprintf (stderr, "\n"); 68238fd1498Szrj err = true; 68338fd1498Szrj } 68438fd1498Szrj tree vdef = gimple_vdef (stmt); 68538fd1498Szrj if (vdef) 68638fd1498Szrj { 68738fd1498Szrj current_vdef = vdef; 68838fd1498Szrj if (TREE_CODE (current_vdef) != SSA_NAME) 68938fd1498Szrj { 69038fd1498Szrj error ("virtual definition is not an SSA name"); 69138fd1498Szrj print_gimple_stmt (stderr, phi, 0); 69238fd1498Szrj err = true; 69338fd1498Szrj } 69438fd1498Szrj } 69538fd1498Szrj } 69638fd1498Szrj } 69738fd1498Szrj 69838fd1498Szrj /* Verify destination PHI uses and recurse. */ 69938fd1498Szrj edge_iterator ei; 70038fd1498Szrj edge e; 70138fd1498Szrj FOR_EACH_EDGE (e, ei, bb->succs) 70238fd1498Szrj { 70338fd1498Szrj gphi *phi = get_virtual_phi (e->dest); 70438fd1498Szrj if (phi 70538fd1498Szrj && PHI_ARG_DEF_FROM_EDGE (phi, e) != current_vdef) 70638fd1498Szrj { 70738fd1498Szrj error ("PHI node with wrong VUSE on edge from BB %d", 70838fd1498Szrj e->src->index); 70938fd1498Szrj print_gimple_stmt (stderr, phi, 0, TDF_VOPS); 71038fd1498Szrj fprintf (stderr, "expected "); 71138fd1498Szrj print_generic_expr (stderr, current_vdef); 71238fd1498Szrj fprintf (stderr, "\n"); 71338fd1498Szrj err = true; 71438fd1498Szrj } 71538fd1498Szrj 71638fd1498Szrj /* Recurse. */ 71738fd1498Szrj err |= verify_vssa (e->dest, current_vdef, visited); 71838fd1498Szrj } 71938fd1498Szrj 72038fd1498Szrj return err; 72138fd1498Szrj } 72238fd1498Szrj 72338fd1498Szrj /* Return true if SSA_NAME is malformed and mark it visited. 72438fd1498Szrj 72538fd1498Szrj IS_VIRTUAL is true if this SSA_NAME was found inside a virtual 72638fd1498Szrj operand. */ 72738fd1498Szrj 72838fd1498Szrj static bool 72938fd1498Szrj verify_ssa_name (tree ssa_name, bool is_virtual) 73038fd1498Szrj { 73138fd1498Szrj if (TREE_CODE (ssa_name) != SSA_NAME) 73238fd1498Szrj { 73338fd1498Szrj error ("expected an SSA_NAME object"); 73438fd1498Szrj return true; 73538fd1498Szrj } 73638fd1498Szrj 73738fd1498Szrj if (SSA_NAME_IN_FREE_LIST (ssa_name)) 73838fd1498Szrj { 73938fd1498Szrj error ("found an SSA_NAME that had been released into the free pool"); 74038fd1498Szrj return true; 74138fd1498Szrj } 74238fd1498Szrj 74338fd1498Szrj if (SSA_NAME_VAR (ssa_name) != NULL_TREE 74438fd1498Szrj && TREE_TYPE (ssa_name) != TREE_TYPE (SSA_NAME_VAR (ssa_name))) 74538fd1498Szrj { 74638fd1498Szrj error ("type mismatch between an SSA_NAME and its symbol"); 74738fd1498Szrj return true; 74838fd1498Szrj } 74938fd1498Szrj 75038fd1498Szrj if (is_virtual && !virtual_operand_p (ssa_name)) 75138fd1498Szrj { 75238fd1498Szrj error ("found a virtual definition for a GIMPLE register"); 75338fd1498Szrj return true; 75438fd1498Szrj } 75538fd1498Szrj 75638fd1498Szrj if (is_virtual && SSA_NAME_VAR (ssa_name) != gimple_vop (cfun)) 75738fd1498Szrj { 75838fd1498Szrj error ("virtual SSA name for non-VOP decl"); 75938fd1498Szrj return true; 76038fd1498Szrj } 76138fd1498Szrj 76238fd1498Szrj if (!is_virtual && virtual_operand_p (ssa_name)) 76338fd1498Szrj { 76438fd1498Szrj error ("found a real definition for a non-register"); 76538fd1498Szrj return true; 76638fd1498Szrj } 76738fd1498Szrj 76838fd1498Szrj if (SSA_NAME_IS_DEFAULT_DEF (ssa_name) 76938fd1498Szrj && !gimple_nop_p (SSA_NAME_DEF_STMT (ssa_name))) 77038fd1498Szrj { 77138fd1498Szrj error ("found a default name with a non-empty defining statement"); 77238fd1498Szrj return true; 77338fd1498Szrj } 77438fd1498Szrj 77538fd1498Szrj return false; 77638fd1498Szrj } 77738fd1498Szrj 77838fd1498Szrj 77938fd1498Szrj /* Return true if the definition of SSA_NAME at block BB is malformed. 78038fd1498Szrj 78138fd1498Szrj STMT is the statement where SSA_NAME is created. 78238fd1498Szrj 78338fd1498Szrj DEFINITION_BLOCK is an array of basic blocks indexed by SSA_NAME 78438fd1498Szrj version numbers. If DEFINITION_BLOCK[SSA_NAME_VERSION] is set, 78538fd1498Szrj it means that the block in that array slot contains the 78638fd1498Szrj definition of SSA_NAME. 78738fd1498Szrj 78838fd1498Szrj IS_VIRTUAL is true if SSA_NAME is created by a VDEF. */ 78938fd1498Szrj 79038fd1498Szrj static bool 79138fd1498Szrj verify_def (basic_block bb, basic_block *definition_block, tree ssa_name, 79238fd1498Szrj gimple *stmt, bool is_virtual) 79338fd1498Szrj { 79438fd1498Szrj if (verify_ssa_name (ssa_name, is_virtual)) 79538fd1498Szrj goto err; 79638fd1498Szrj 79738fd1498Szrj if (SSA_NAME_VAR (ssa_name) 79838fd1498Szrj && TREE_CODE (SSA_NAME_VAR (ssa_name)) == RESULT_DECL 79938fd1498Szrj && DECL_BY_REFERENCE (SSA_NAME_VAR (ssa_name))) 80038fd1498Szrj { 80138fd1498Szrj error ("RESULT_DECL should be read only when DECL_BY_REFERENCE is set"); 80238fd1498Szrj goto err; 80338fd1498Szrj } 80438fd1498Szrj 80538fd1498Szrj if (definition_block[SSA_NAME_VERSION (ssa_name)]) 80638fd1498Szrj { 80738fd1498Szrj error ("SSA_NAME created in two different blocks %i and %i", 80838fd1498Szrj definition_block[SSA_NAME_VERSION (ssa_name)]->index, bb->index); 80938fd1498Szrj goto err; 81038fd1498Szrj } 81138fd1498Szrj 81238fd1498Szrj definition_block[SSA_NAME_VERSION (ssa_name)] = bb; 81338fd1498Szrj 81438fd1498Szrj if (SSA_NAME_DEF_STMT (ssa_name) != stmt) 81538fd1498Szrj { 81638fd1498Szrj error ("SSA_NAME_DEF_STMT is wrong"); 81738fd1498Szrj fprintf (stderr, "Expected definition statement:\n"); 81838fd1498Szrj print_gimple_stmt (stderr, SSA_NAME_DEF_STMT (ssa_name), 4, TDF_VOPS); 81938fd1498Szrj fprintf (stderr, "\nActual definition statement:\n"); 82038fd1498Szrj print_gimple_stmt (stderr, stmt, 4, TDF_VOPS); 82138fd1498Szrj goto err; 82238fd1498Szrj } 82338fd1498Szrj 82438fd1498Szrj return false; 82538fd1498Szrj 82638fd1498Szrj err: 82738fd1498Szrj fprintf (stderr, "while verifying SSA_NAME "); 82838fd1498Szrj print_generic_expr (stderr, ssa_name); 82938fd1498Szrj fprintf (stderr, " in statement\n"); 83038fd1498Szrj print_gimple_stmt (stderr, stmt, 4, TDF_VOPS); 83138fd1498Szrj 83238fd1498Szrj return true; 83338fd1498Szrj } 83438fd1498Szrj 83538fd1498Szrj 83638fd1498Szrj /* Return true if the use of SSA_NAME at statement STMT in block BB is 83738fd1498Szrj malformed. 83838fd1498Szrj 83938fd1498Szrj DEF_BB is the block where SSA_NAME was found to be created. 84038fd1498Szrj 84138fd1498Szrj IDOM contains immediate dominator information for the flowgraph. 84238fd1498Szrj 84338fd1498Szrj CHECK_ABNORMAL is true if the caller wants to check whether this use 84438fd1498Szrj is flowing through an abnormal edge (only used when checking PHI 84538fd1498Szrj arguments). 84638fd1498Szrj 84738fd1498Szrj If NAMES_DEFINED_IN_BB is not NULL, it contains a bitmap of ssa names 84838fd1498Szrj that are defined before STMT in basic block BB. */ 84938fd1498Szrj 85038fd1498Szrj static bool 85138fd1498Szrj verify_use (basic_block bb, basic_block def_bb, use_operand_p use_p, 85238fd1498Szrj gimple *stmt, bool check_abnormal, bitmap names_defined_in_bb) 85338fd1498Szrj { 85438fd1498Szrj bool err = false; 85538fd1498Szrj tree ssa_name = USE_FROM_PTR (use_p); 85638fd1498Szrj 85738fd1498Szrj if (!TREE_VISITED (ssa_name)) 85838fd1498Szrj if (verify_imm_links (stderr, ssa_name)) 85938fd1498Szrj err = true; 86038fd1498Szrj 86138fd1498Szrj TREE_VISITED (ssa_name) = 1; 86238fd1498Szrj 86338fd1498Szrj if (gimple_nop_p (SSA_NAME_DEF_STMT (ssa_name)) 86438fd1498Szrj && SSA_NAME_IS_DEFAULT_DEF (ssa_name)) 86538fd1498Szrj ; /* Default definitions have empty statements. Nothing to do. */ 86638fd1498Szrj else if (!def_bb) 86738fd1498Szrj { 86838fd1498Szrj error ("missing definition"); 86938fd1498Szrj err = true; 87038fd1498Szrj } 87138fd1498Szrj else if (bb != def_bb 87238fd1498Szrj && !dominated_by_p (CDI_DOMINATORS, bb, def_bb)) 87338fd1498Szrj { 87438fd1498Szrj error ("definition in block %i does not dominate use in block %i", 87538fd1498Szrj def_bb->index, bb->index); 87638fd1498Szrj err = true; 87738fd1498Szrj } 87838fd1498Szrj else if (bb == def_bb 87938fd1498Szrj && names_defined_in_bb != NULL 88038fd1498Szrj && !bitmap_bit_p (names_defined_in_bb, SSA_NAME_VERSION (ssa_name))) 88138fd1498Szrj { 88238fd1498Szrj error ("definition in block %i follows the use", def_bb->index); 88338fd1498Szrj err = true; 88438fd1498Szrj } 88538fd1498Szrj 88638fd1498Szrj if (check_abnormal 88738fd1498Szrj && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssa_name)) 88838fd1498Szrj { 88938fd1498Szrj error ("SSA_NAME_OCCURS_IN_ABNORMAL_PHI should be set"); 89038fd1498Szrj err = true; 89138fd1498Szrj } 89238fd1498Szrj 89338fd1498Szrj /* Make sure the use is in an appropriate list by checking the previous 89438fd1498Szrj element to make sure it's the same. */ 89538fd1498Szrj if (use_p->prev == NULL) 89638fd1498Szrj { 89738fd1498Szrj error ("no immediate_use list"); 89838fd1498Szrj err = true; 89938fd1498Szrj } 90038fd1498Szrj else 90138fd1498Szrj { 90238fd1498Szrj tree listvar; 90338fd1498Szrj if (use_p->prev->use == NULL) 90438fd1498Szrj listvar = use_p->prev->loc.ssa_name; 90538fd1498Szrj else 90638fd1498Szrj listvar = USE_FROM_PTR (use_p->prev); 90738fd1498Szrj if (listvar != ssa_name) 90838fd1498Szrj { 90938fd1498Szrj error ("wrong immediate use list"); 91038fd1498Szrj err = true; 91138fd1498Szrj } 91238fd1498Szrj } 91338fd1498Szrj 91438fd1498Szrj if (err) 91538fd1498Szrj { 91638fd1498Szrj fprintf (stderr, "for SSA_NAME: "); 91738fd1498Szrj print_generic_expr (stderr, ssa_name, TDF_VOPS); 91838fd1498Szrj fprintf (stderr, " in statement:\n"); 91938fd1498Szrj print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); 92038fd1498Szrj } 92138fd1498Szrj 92238fd1498Szrj return err; 92338fd1498Szrj } 92438fd1498Szrj 92538fd1498Szrj 92638fd1498Szrj /* Return true if any of the arguments for PHI node PHI at block BB is 92738fd1498Szrj malformed. 92838fd1498Szrj 92938fd1498Szrj DEFINITION_BLOCK is an array of basic blocks indexed by SSA_NAME 93038fd1498Szrj version numbers. If DEFINITION_BLOCK[SSA_NAME_VERSION] is set, 93138fd1498Szrj it means that the block in that array slot contains the 93238fd1498Szrj definition of SSA_NAME. */ 93338fd1498Szrj 93438fd1498Szrj static bool 93538fd1498Szrj verify_phi_args (gphi *phi, basic_block bb, basic_block *definition_block) 93638fd1498Szrj { 93738fd1498Szrj edge e; 93838fd1498Szrj bool err = false; 93938fd1498Szrj size_t i, phi_num_args = gimple_phi_num_args (phi); 94038fd1498Szrj 94138fd1498Szrj if (EDGE_COUNT (bb->preds) != phi_num_args) 94238fd1498Szrj { 94338fd1498Szrj error ("incoming edge count does not match number of PHI arguments"); 94438fd1498Szrj err = true; 94538fd1498Szrj goto error; 94638fd1498Szrj } 94738fd1498Szrj 94838fd1498Szrj for (i = 0; i < phi_num_args; i++) 94938fd1498Szrj { 95038fd1498Szrj use_operand_p op_p = gimple_phi_arg_imm_use_ptr (phi, i); 95138fd1498Szrj tree op = USE_FROM_PTR (op_p); 95238fd1498Szrj 95338fd1498Szrj e = EDGE_PRED (bb, i); 95438fd1498Szrj 95538fd1498Szrj if (op == NULL_TREE) 95638fd1498Szrj { 95738fd1498Szrj error ("PHI argument is missing for edge %d->%d", 95838fd1498Szrj e->src->index, 95938fd1498Szrj e->dest->index); 96038fd1498Szrj err = true; 96138fd1498Szrj goto error; 96238fd1498Szrj } 96338fd1498Szrj 96438fd1498Szrj if (TREE_CODE (op) != SSA_NAME && !is_gimple_min_invariant (op)) 96538fd1498Szrj { 96638fd1498Szrj error ("PHI argument is not SSA_NAME, or invariant"); 96738fd1498Szrj err = true; 96838fd1498Szrj } 96938fd1498Szrj 97038fd1498Szrj if (TREE_CODE (op) == SSA_NAME) 97138fd1498Szrj { 97238fd1498Szrj err = verify_ssa_name (op, virtual_operand_p (gimple_phi_result (phi))); 97338fd1498Szrj err |= verify_use (e->src, definition_block[SSA_NAME_VERSION (op)], 97438fd1498Szrj op_p, phi, e->flags & EDGE_ABNORMAL, NULL); 97538fd1498Szrj } 97638fd1498Szrj 97738fd1498Szrj if (TREE_CODE (op) == ADDR_EXPR) 97838fd1498Szrj { 97938fd1498Szrj tree base = TREE_OPERAND (op, 0); 98038fd1498Szrj while (handled_component_p (base)) 98138fd1498Szrj base = TREE_OPERAND (base, 0); 98238fd1498Szrj if ((VAR_P (base) 98338fd1498Szrj || TREE_CODE (base) == PARM_DECL 98438fd1498Szrj || TREE_CODE (base) == RESULT_DECL) 98538fd1498Szrj && !TREE_ADDRESSABLE (base)) 98638fd1498Szrj { 98738fd1498Szrj error ("address taken, but ADDRESSABLE bit not set"); 98838fd1498Szrj err = true; 98938fd1498Szrj } 99038fd1498Szrj } 99138fd1498Szrj 99238fd1498Szrj if (e->dest != bb) 99338fd1498Szrj { 99438fd1498Szrj error ("wrong edge %d->%d for PHI argument", 99538fd1498Szrj e->src->index, e->dest->index); 99638fd1498Szrj err = true; 99738fd1498Szrj } 99838fd1498Szrj 99938fd1498Szrj if (err) 100038fd1498Szrj { 100138fd1498Szrj fprintf (stderr, "PHI argument\n"); 100238fd1498Szrj print_generic_stmt (stderr, op, TDF_VOPS); 100338fd1498Szrj goto error; 100438fd1498Szrj } 100538fd1498Szrj } 100638fd1498Szrj 100738fd1498Szrj error: 100838fd1498Szrj if (err) 100938fd1498Szrj { 101038fd1498Szrj fprintf (stderr, "for PHI node\n"); 101138fd1498Szrj print_gimple_stmt (stderr, phi, 0, TDF_VOPS|TDF_MEMSYMS); 101238fd1498Szrj } 101338fd1498Szrj 101438fd1498Szrj 101538fd1498Szrj return err; 101638fd1498Szrj } 101738fd1498Szrj 101838fd1498Szrj 101938fd1498Szrj /* Verify common invariants in the SSA web. 102038fd1498Szrj TODO: verify the variable annotations. */ 102138fd1498Szrj 102238fd1498Szrj DEBUG_FUNCTION void 102338fd1498Szrj verify_ssa (bool check_modified_stmt, bool check_ssa_operands) 102438fd1498Szrj { 102538fd1498Szrj basic_block bb; 102638fd1498Szrj basic_block *definition_block = XCNEWVEC (basic_block, num_ssa_names); 102738fd1498Szrj ssa_op_iter iter; 102838fd1498Szrj tree op; 102938fd1498Szrj enum dom_state orig_dom_state = dom_info_state (CDI_DOMINATORS); 103038fd1498Szrj auto_bitmap names_defined_in_bb; 103138fd1498Szrj 103238fd1498Szrj gcc_assert (!need_ssa_update_p (cfun)); 103338fd1498Szrj 103438fd1498Szrj timevar_push (TV_TREE_SSA_VERIFY); 103538fd1498Szrj 103638fd1498Szrj { 103738fd1498Szrj /* Keep track of SSA names present in the IL. */ 103838fd1498Szrj size_t i; 103938fd1498Szrj tree name; 104038fd1498Szrj hash_map <void *, tree> ssa_info; 104138fd1498Szrj 104238fd1498Szrj FOR_EACH_SSA_NAME (i, name, cfun) 104338fd1498Szrj { 104438fd1498Szrj gimple *stmt; 104538fd1498Szrj TREE_VISITED (name) = 0; 104638fd1498Szrj 104738fd1498Szrj verify_ssa_name (name, virtual_operand_p (name)); 104838fd1498Szrj 104938fd1498Szrj stmt = SSA_NAME_DEF_STMT (name); 105038fd1498Szrj if (!gimple_nop_p (stmt)) 105138fd1498Szrj { 105238fd1498Szrj basic_block bb = gimple_bb (stmt); 105338fd1498Szrj if (verify_def (bb, definition_block, 105438fd1498Szrj name, stmt, virtual_operand_p (name))) 105538fd1498Szrj goto err; 105638fd1498Szrj } 105738fd1498Szrj 105838fd1498Szrj void *info = NULL; 105938fd1498Szrj if (POINTER_TYPE_P (TREE_TYPE (name))) 106038fd1498Szrj info = SSA_NAME_PTR_INFO (name); 106138fd1498Szrj else if (INTEGRAL_TYPE_P (TREE_TYPE (name))) 106238fd1498Szrj info = SSA_NAME_RANGE_INFO (name); 106338fd1498Szrj if (info) 106438fd1498Szrj { 106538fd1498Szrj bool existed; 106638fd1498Szrj tree &val = ssa_info.get_or_insert (info, &existed); 106738fd1498Szrj if (existed) 106838fd1498Szrj { 106938fd1498Szrj error ("shared SSA name info"); 107038fd1498Szrj print_generic_expr (stderr, val); 107138fd1498Szrj fprintf (stderr, " and "); 107238fd1498Szrj print_generic_expr (stderr, name); 107338fd1498Szrj fprintf (stderr, "\n"); 107438fd1498Szrj goto err; 107538fd1498Szrj } 107638fd1498Szrj else 107738fd1498Szrj val = name; 107838fd1498Szrj } 107938fd1498Szrj } 108038fd1498Szrj } 108138fd1498Szrj 108238fd1498Szrj calculate_dominance_info (CDI_DOMINATORS); 108338fd1498Szrj 108438fd1498Szrj /* Now verify all the uses and make sure they agree with the definitions 108538fd1498Szrj found in the previous pass. */ 108638fd1498Szrj FOR_EACH_BB_FN (bb, cfun) 108738fd1498Szrj { 108838fd1498Szrj edge e; 108938fd1498Szrj edge_iterator ei; 109038fd1498Szrj 109138fd1498Szrj /* Make sure that all edges have a clear 'aux' field. */ 109238fd1498Szrj FOR_EACH_EDGE (e, ei, bb->preds) 109338fd1498Szrj { 109438fd1498Szrj if (e->aux) 109538fd1498Szrj { 109638fd1498Szrj error ("AUX pointer initialized for edge %d->%d", e->src->index, 109738fd1498Szrj e->dest->index); 109838fd1498Szrj goto err; 109938fd1498Szrj } 110038fd1498Szrj } 110138fd1498Szrj 110238fd1498Szrj /* Verify the arguments for every PHI node in the block. */ 110338fd1498Szrj for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 110438fd1498Szrj { 110538fd1498Szrj gphi *phi = gsi.phi (); 110638fd1498Szrj if (verify_phi_args (phi, bb, definition_block)) 110738fd1498Szrj goto err; 110838fd1498Szrj 110938fd1498Szrj bitmap_set_bit (names_defined_in_bb, 111038fd1498Szrj SSA_NAME_VERSION (gimple_phi_result (phi))); 111138fd1498Szrj } 111238fd1498Szrj 111338fd1498Szrj /* Now verify all the uses and vuses in every statement of the block. */ 111438fd1498Szrj for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); 111538fd1498Szrj gsi_next (&gsi)) 111638fd1498Szrj { 111738fd1498Szrj gimple *stmt = gsi_stmt (gsi); 111838fd1498Szrj use_operand_p use_p; 111938fd1498Szrj 112038fd1498Szrj if (check_modified_stmt && gimple_modified_p (stmt)) 112138fd1498Szrj { 112238fd1498Szrj error ("stmt (%p) marked modified after optimization pass: ", 112338fd1498Szrj (void *)stmt); 112438fd1498Szrj print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); 112538fd1498Szrj goto err; 112638fd1498Szrj } 112738fd1498Szrj 112838fd1498Szrj if (check_ssa_operands && verify_ssa_operands (cfun, stmt)) 112938fd1498Szrj { 113038fd1498Szrj print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); 113138fd1498Szrj goto err; 113238fd1498Szrj } 113338fd1498Szrj 113438fd1498Szrj if (gimple_debug_bind_p (stmt) 113538fd1498Szrj && !gimple_debug_bind_has_value_p (stmt)) 113638fd1498Szrj continue; 113738fd1498Szrj 113838fd1498Szrj FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE|SSA_OP_VUSE) 113938fd1498Szrj { 114038fd1498Szrj op = USE_FROM_PTR (use_p); 114138fd1498Szrj if (verify_use (bb, definition_block[SSA_NAME_VERSION (op)], 114238fd1498Szrj use_p, stmt, false, names_defined_in_bb)) 114338fd1498Szrj goto err; 114438fd1498Szrj } 114538fd1498Szrj 114638fd1498Szrj FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_DEFS) 114738fd1498Szrj { 114838fd1498Szrj if (SSA_NAME_DEF_STMT (op) != stmt) 114938fd1498Szrj { 115038fd1498Szrj error ("SSA_NAME_DEF_STMT is wrong"); 115138fd1498Szrj fprintf (stderr, "Expected definition statement:\n"); 115238fd1498Szrj print_gimple_stmt (stderr, stmt, 4, TDF_VOPS); 115338fd1498Szrj fprintf (stderr, "\nActual definition statement:\n"); 115438fd1498Szrj print_gimple_stmt (stderr, SSA_NAME_DEF_STMT (op), 115538fd1498Szrj 4, TDF_VOPS); 115638fd1498Szrj goto err; 115738fd1498Szrj } 115838fd1498Szrj bitmap_set_bit (names_defined_in_bb, SSA_NAME_VERSION (op)); 115938fd1498Szrj } 116038fd1498Szrj } 116138fd1498Szrj 116238fd1498Szrj bitmap_clear (names_defined_in_bb); 116338fd1498Szrj } 116438fd1498Szrj 116538fd1498Szrj free (definition_block); 116638fd1498Szrj 116738fd1498Szrj if (gimple_vop (cfun) 116838fd1498Szrj && ssa_default_def (cfun, gimple_vop (cfun))) 116938fd1498Szrj { 117038fd1498Szrj auto_sbitmap visited (last_basic_block_for_fn (cfun) + 1); 117138fd1498Szrj bitmap_clear (visited); 117238fd1498Szrj if (verify_vssa (ENTRY_BLOCK_PTR_FOR_FN (cfun), 117338fd1498Szrj ssa_default_def (cfun, gimple_vop (cfun)), visited)) 117438fd1498Szrj goto err; 117538fd1498Szrj } 117638fd1498Szrj 117738fd1498Szrj /* Restore the dominance information to its prior known state, so 117838fd1498Szrj that we do not perturb the compiler's subsequent behavior. */ 117938fd1498Szrj if (orig_dom_state == DOM_NONE) 118038fd1498Szrj free_dominance_info (CDI_DOMINATORS); 118138fd1498Szrj else 118238fd1498Szrj set_dom_info_availability (CDI_DOMINATORS, orig_dom_state); 118338fd1498Szrj 118438fd1498Szrj timevar_pop (TV_TREE_SSA_VERIFY); 118538fd1498Szrj return; 118638fd1498Szrj 118738fd1498Szrj err: 118838fd1498Szrj internal_error ("verify_ssa failed"); 118938fd1498Szrj } 119038fd1498Szrj 119138fd1498Szrj 119238fd1498Szrj /* Initialize global DFA and SSA structures. */ 119338fd1498Szrj 119438fd1498Szrj void 119538fd1498Szrj init_tree_ssa (struct function *fn) 119638fd1498Szrj { 119738fd1498Szrj fn->gimple_df = ggc_cleared_alloc<gimple_df> (); 119838fd1498Szrj fn->gimple_df->default_defs = hash_table<ssa_name_hasher>::create_ggc (20); 119938fd1498Szrj pt_solution_reset (&fn->gimple_df->escaped); 120038fd1498Szrj init_ssanames (fn, 0); 120138fd1498Szrj } 120238fd1498Szrj 120338fd1498Szrj /* Deallocate memory associated with SSA data structures for FNDECL. */ 120438fd1498Szrj 120538fd1498Szrj void 120638fd1498Szrj delete_tree_ssa (struct function *fn) 120738fd1498Szrj { 120838fd1498Szrj fini_ssanames (fn); 120938fd1498Szrj 121038fd1498Szrj /* We no longer maintain the SSA operand cache at this point. */ 121138fd1498Szrj if (ssa_operands_active (fn)) 121238fd1498Szrj fini_ssa_operands (fn); 121338fd1498Szrj 121438fd1498Szrj fn->gimple_df->default_defs->empty (); 121538fd1498Szrj fn->gimple_df->default_defs = NULL; 121638fd1498Szrj pt_solution_reset (&fn->gimple_df->escaped); 121738fd1498Szrj if (fn->gimple_df->decls_to_pointers != NULL) 121838fd1498Szrj delete fn->gimple_df->decls_to_pointers; 121938fd1498Szrj fn->gimple_df->decls_to_pointers = NULL; 122038fd1498Szrj fn->gimple_df = NULL; 122138fd1498Szrj 122238fd1498Szrj /* We no longer need the edge variable maps. */ 122338fd1498Szrj redirect_edge_var_map_empty (); 122438fd1498Szrj } 122538fd1498Szrj 122638fd1498Szrj /* Return true if EXPR is a useless type conversion, otherwise return 122738fd1498Szrj false. */ 122838fd1498Szrj 122938fd1498Szrj bool 123038fd1498Szrj tree_ssa_useless_type_conversion (tree expr) 123138fd1498Szrj { 123238fd1498Szrj /* If we have an assignment that merely uses a NOP_EXPR to change 123338fd1498Szrj the top of the RHS to the type of the LHS and the type conversion 123438fd1498Szrj is "safe", then strip away the type conversion so that we can 123538fd1498Szrj enter LHS = RHS into the const_and_copies table. */ 123638fd1498Szrj if (CONVERT_EXPR_P (expr) 123738fd1498Szrj || TREE_CODE (expr) == VIEW_CONVERT_EXPR 123838fd1498Szrj || TREE_CODE (expr) == NON_LVALUE_EXPR) 123938fd1498Szrj return useless_type_conversion_p 124038fd1498Szrj (TREE_TYPE (expr), 124138fd1498Szrj TREE_TYPE (TREE_OPERAND (expr, 0))); 124238fd1498Szrj 124338fd1498Szrj return false; 124438fd1498Szrj } 124538fd1498Szrj 124638fd1498Szrj /* Strip conversions from EXP according to 124738fd1498Szrj tree_ssa_useless_type_conversion and return the resulting 124838fd1498Szrj expression. */ 124938fd1498Szrj 125038fd1498Szrj tree 125138fd1498Szrj tree_ssa_strip_useless_type_conversions (tree exp) 125238fd1498Szrj { 125338fd1498Szrj while (tree_ssa_useless_type_conversion (exp)) 125438fd1498Szrj exp = TREE_OPERAND (exp, 0); 125538fd1498Szrj return exp; 125638fd1498Szrj } 125738fd1498Szrj 125838fd1498Szrj /* Return true if T, as SSA_NAME, has an implicit default defined value. */ 125938fd1498Szrj 126038fd1498Szrj bool 126138fd1498Szrj ssa_defined_default_def_p (tree t) 126238fd1498Szrj { 126338fd1498Szrj tree var = SSA_NAME_VAR (t); 126438fd1498Szrj 126538fd1498Szrj if (!var) 126638fd1498Szrj ; 126738fd1498Szrj /* Parameters get their initial value from the function entry. */ 126838fd1498Szrj else if (TREE_CODE (var) == PARM_DECL) 126938fd1498Szrj return true; 127038fd1498Szrj /* When returning by reference the return address is actually a hidden 127138fd1498Szrj parameter. */ 127238fd1498Szrj else if (TREE_CODE (var) == RESULT_DECL && DECL_BY_REFERENCE (var)) 127338fd1498Szrj return true; 127438fd1498Szrj /* Hard register variables get their initial value from the ether. */ 127538fd1498Szrj else if (VAR_P (var) && DECL_HARD_REGISTER (var)) 127638fd1498Szrj return true; 127738fd1498Szrj 127838fd1498Szrj return false; 127938fd1498Szrj } 128038fd1498Szrj 128138fd1498Szrj 128238fd1498Szrj /* Return true if T, an SSA_NAME, has an undefined value. PARTIAL is what 128338fd1498Szrj should be returned if the value is only partially undefined. */ 128438fd1498Szrj 128538fd1498Szrj bool 128638fd1498Szrj ssa_undefined_value_p (tree t, bool partial) 128738fd1498Szrj { 128838fd1498Szrj gimple *def_stmt; 128938fd1498Szrj 129038fd1498Szrj if (ssa_defined_default_def_p (t)) 129138fd1498Szrj return false; 129238fd1498Szrj 129338fd1498Szrj /* The value is undefined iff its definition statement is empty. */ 129438fd1498Szrj def_stmt = SSA_NAME_DEF_STMT (t); 129538fd1498Szrj if (gimple_nop_p (def_stmt)) 129638fd1498Szrj return true; 129738fd1498Szrj 129838fd1498Szrj /* Check if the complex was not only partially defined. */ 129938fd1498Szrj if (partial && is_gimple_assign (def_stmt) 130038fd1498Szrj && gimple_assign_rhs_code (def_stmt) == COMPLEX_EXPR) 130138fd1498Szrj { 130238fd1498Szrj tree rhs1, rhs2; 130338fd1498Szrj 130438fd1498Szrj rhs1 = gimple_assign_rhs1 (def_stmt); 130538fd1498Szrj rhs2 = gimple_assign_rhs2 (def_stmt); 130638fd1498Szrj return (TREE_CODE (rhs1) == SSA_NAME && ssa_undefined_value_p (rhs1)) 130738fd1498Szrj || (TREE_CODE (rhs2) == SSA_NAME && ssa_undefined_value_p (rhs2)); 130838fd1498Szrj } 130938fd1498Szrj return false; 131038fd1498Szrj } 131138fd1498Szrj 131238fd1498Szrj 131338fd1498Szrj /* Return TRUE iff STMT, a gimple statement, references an undefined 131438fd1498Szrj SSA name. */ 131538fd1498Szrj 131638fd1498Szrj bool 131738fd1498Szrj gimple_uses_undefined_value_p (gimple *stmt) 131838fd1498Szrj { 131938fd1498Szrj ssa_op_iter iter; 132038fd1498Szrj tree op; 132138fd1498Szrj 132238fd1498Szrj FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE) 132338fd1498Szrj if (ssa_undefined_value_p (op)) 132438fd1498Szrj return true; 132538fd1498Szrj 132638fd1498Szrj return false; 132738fd1498Szrj } 132838fd1498Szrj 132938fd1498Szrj 133038fd1498Szrj 133138fd1498Szrj /* If necessary, rewrite the base of the reference tree *TP from 133238fd1498Szrj a MEM_REF to a plain or converted symbol. */ 133338fd1498Szrj 133438fd1498Szrj static void 133538fd1498Szrj maybe_rewrite_mem_ref_base (tree *tp, bitmap suitable_for_renaming) 133638fd1498Szrj { 133738fd1498Szrj tree sym; 133838fd1498Szrj 133938fd1498Szrj while (handled_component_p (*tp)) 134038fd1498Szrj tp = &TREE_OPERAND (*tp, 0); 134138fd1498Szrj if (TREE_CODE (*tp) == MEM_REF 134238fd1498Szrj && TREE_CODE (TREE_OPERAND (*tp, 0)) == ADDR_EXPR 134338fd1498Szrj && (sym = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0)) 134438fd1498Szrj && DECL_P (sym) 134538fd1498Szrj && !TREE_ADDRESSABLE (sym) 134638fd1498Szrj && bitmap_bit_p (suitable_for_renaming, DECL_UID (sym)) 134738fd1498Szrj && is_gimple_reg_type (TREE_TYPE (*tp)) 134838fd1498Szrj && ! VOID_TYPE_P (TREE_TYPE (*tp))) 134938fd1498Szrj { 135038fd1498Szrj if (TREE_CODE (TREE_TYPE (sym)) == VECTOR_TYPE 135138fd1498Szrj && useless_type_conversion_p (TREE_TYPE (*tp), 135238fd1498Szrj TREE_TYPE (TREE_TYPE (sym))) 135338fd1498Szrj && multiple_of_p (sizetype, TREE_OPERAND (*tp, 1), 135438fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (*tp)))) 135538fd1498Szrj { 135638fd1498Szrj *tp = build3 (BIT_FIELD_REF, TREE_TYPE (*tp), sym, 135738fd1498Szrj TYPE_SIZE (TREE_TYPE (*tp)), 135838fd1498Szrj int_const_binop (MULT_EXPR, 135938fd1498Szrj bitsize_int (BITS_PER_UNIT), 136038fd1498Szrj TREE_OPERAND (*tp, 1))); 136138fd1498Szrj } 136238fd1498Szrj else if (TREE_CODE (TREE_TYPE (sym)) == COMPLEX_TYPE 136338fd1498Szrj && useless_type_conversion_p (TREE_TYPE (*tp), 136438fd1498Szrj TREE_TYPE (TREE_TYPE (sym)))) 136538fd1498Szrj { 136638fd1498Szrj *tp = build1 (integer_zerop (TREE_OPERAND (*tp, 1)) 136738fd1498Szrj ? REALPART_EXPR : IMAGPART_EXPR, 136838fd1498Szrj TREE_TYPE (*tp), sym); 136938fd1498Szrj } 137038fd1498Szrj else if (integer_zerop (TREE_OPERAND (*tp, 1)) 137138fd1498Szrj && DECL_SIZE (sym) == TYPE_SIZE (TREE_TYPE (*tp))) 137238fd1498Szrj { 137338fd1498Szrj if (!useless_type_conversion_p (TREE_TYPE (*tp), 137438fd1498Szrj TREE_TYPE (sym))) 137538fd1498Szrj *tp = build1 (VIEW_CONVERT_EXPR, 137638fd1498Szrj TREE_TYPE (*tp), sym); 137738fd1498Szrj else 137838fd1498Szrj *tp = sym; 137938fd1498Szrj } 138038fd1498Szrj else if (DECL_SIZE (sym) 138138fd1498Szrj && TREE_CODE (DECL_SIZE (sym)) == INTEGER_CST 138238fd1498Szrj && (known_subrange_p 138338fd1498Szrj (mem_ref_offset (*tp), 138438fd1498Szrj wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (*tp))), 138538fd1498Szrj 0, wi::to_offset (DECL_SIZE_UNIT (sym)))) 138638fd1498Szrj && (! INTEGRAL_TYPE_P (TREE_TYPE (*tp)) 138738fd1498Szrj || (wi::to_offset (TYPE_SIZE (TREE_TYPE (*tp))) 138838fd1498Szrj == TYPE_PRECISION (TREE_TYPE (*tp)))) 138938fd1498Szrj && wi::umod_trunc (wi::to_offset (TYPE_SIZE (TREE_TYPE (*tp))), 139038fd1498Szrj BITS_PER_UNIT) == 0) 139138fd1498Szrj { 139238fd1498Szrj *tp = build3 (BIT_FIELD_REF, TREE_TYPE (*tp), sym, 139338fd1498Szrj TYPE_SIZE (TREE_TYPE (*tp)), 139438fd1498Szrj wide_int_to_tree (bitsizetype, 139538fd1498Szrj mem_ref_offset (*tp) 139638fd1498Szrj << LOG2_BITS_PER_UNIT)); 139738fd1498Szrj } 139838fd1498Szrj } 139938fd1498Szrj } 140038fd1498Szrj 140138fd1498Szrj /* For a tree REF return its base if it is the base of a MEM_REF 140238fd1498Szrj that cannot be rewritten into SSA form. Otherwise return NULL_TREE. */ 140338fd1498Szrj 140438fd1498Szrj static tree 140538fd1498Szrj non_rewritable_mem_ref_base (tree ref) 140638fd1498Szrj { 140738fd1498Szrj tree base; 140838fd1498Szrj 140938fd1498Szrj /* A plain decl does not need it set. */ 141038fd1498Szrj if (DECL_P (ref)) 141138fd1498Szrj return NULL_TREE; 141238fd1498Szrj 141338fd1498Szrj if (! (base = CONST_CAST_TREE (strip_invariant_refs (ref)))) 141438fd1498Szrj { 141538fd1498Szrj base = get_base_address (ref); 141638fd1498Szrj if (DECL_P (base)) 141738fd1498Szrj return base; 141838fd1498Szrj return NULL_TREE; 141938fd1498Szrj } 142038fd1498Szrj 142138fd1498Szrj /* But watch out for MEM_REFs we cannot lower to a 142238fd1498Szrj VIEW_CONVERT_EXPR or a BIT_FIELD_REF. */ 142338fd1498Szrj if (TREE_CODE (base) == MEM_REF 142438fd1498Szrj && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR) 142538fd1498Szrj { 142638fd1498Szrj tree decl = TREE_OPERAND (TREE_OPERAND (base, 0), 0); 142738fd1498Szrj if (! DECL_P (decl)) 142838fd1498Szrj return NULL_TREE; 142938fd1498Szrj if (! is_gimple_reg_type (TREE_TYPE (base)) 143038fd1498Szrj || VOID_TYPE_P (TREE_TYPE (base)) 143138fd1498Szrj || TREE_THIS_VOLATILE (decl) != TREE_THIS_VOLATILE (base)) 143238fd1498Szrj return decl; 143338fd1498Szrj if ((TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE 143438fd1498Szrj || TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE) 143538fd1498Szrj && useless_type_conversion_p (TREE_TYPE (base), 143638fd1498Szrj TREE_TYPE (TREE_TYPE (decl))) 143738fd1498Szrj && known_ge (mem_ref_offset (base), 0) 143838fd1498Szrj && known_gt (wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))), 143938fd1498Szrj mem_ref_offset (base)) 144038fd1498Szrj && multiple_of_p (sizetype, TREE_OPERAND (base, 1), 144138fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (base)))) 144238fd1498Szrj return NULL_TREE; 144338fd1498Szrj /* For same sizes and zero offset we can use a VIEW_CONVERT_EXPR. */ 144438fd1498Szrj if (integer_zerop (TREE_OPERAND (base, 1)) 144538fd1498Szrj && DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (base))) 144638fd1498Szrj return NULL_TREE; 144738fd1498Szrj /* For integral typed extracts we can use a BIT_FIELD_REF. */ 144838fd1498Szrj if (DECL_SIZE (decl) 1449*58e805e6Szrj && TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST 145038fd1498Szrj && (known_subrange_p 145138fd1498Szrj (mem_ref_offset (base), 145238fd1498Szrj wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (base))), 145338fd1498Szrj 0, wi::to_poly_offset (DECL_SIZE_UNIT (decl)))) 145438fd1498Szrj /* ??? We can't handle bitfield precision extracts without 145538fd1498Szrj either using an alternate type for the BIT_FIELD_REF and 145638fd1498Szrj then doing a conversion or possibly adjusting the offset 145738fd1498Szrj according to endianness. */ 145838fd1498Szrj && (! INTEGRAL_TYPE_P (TREE_TYPE (base)) 145938fd1498Szrj || (wi::to_offset (TYPE_SIZE (TREE_TYPE (base))) 146038fd1498Szrj == TYPE_PRECISION (TREE_TYPE (base)))) 146138fd1498Szrj && wi::umod_trunc (wi::to_offset (TYPE_SIZE (TREE_TYPE (base))), 146238fd1498Szrj BITS_PER_UNIT) == 0) 146338fd1498Szrj return NULL_TREE; 146438fd1498Szrj return decl; 146538fd1498Szrj } 146638fd1498Szrj 146738fd1498Szrj return NULL_TREE; 146838fd1498Szrj } 146938fd1498Szrj 147038fd1498Szrj /* For an lvalue tree LHS return true if it cannot be rewritten into SSA form. 147138fd1498Szrj Otherwise return true. */ 147238fd1498Szrj 147338fd1498Szrj static bool 147438fd1498Szrj non_rewritable_lvalue_p (tree lhs) 147538fd1498Szrj { 147638fd1498Szrj /* A plain decl is always rewritable. */ 147738fd1498Szrj if (DECL_P (lhs)) 147838fd1498Szrj return false; 147938fd1498Szrj 148038fd1498Szrj /* We can re-write REALPART_EXPR and IMAGPART_EXPR sets in 148138fd1498Szrj a reasonably efficient manner... */ 148238fd1498Szrj if ((TREE_CODE (lhs) == REALPART_EXPR 148338fd1498Szrj || TREE_CODE (lhs) == IMAGPART_EXPR) 148438fd1498Szrj && DECL_P (TREE_OPERAND (lhs, 0))) 148538fd1498Szrj return false; 148638fd1498Szrj 148738fd1498Szrj /* ??? The following could be relaxed allowing component 148838fd1498Szrj references that do not change the access size. */ 148938fd1498Szrj if (TREE_CODE (lhs) == MEM_REF 149038fd1498Szrj && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR) 149138fd1498Szrj { 149238fd1498Szrj tree decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0); 149338fd1498Szrj 149438fd1498Szrj /* A decl that is wrapped inside a MEM-REF that covers 149538fd1498Szrj it full is also rewritable. */ 149638fd1498Szrj if (integer_zerop (TREE_OPERAND (lhs, 1)) 149738fd1498Szrj && DECL_P (decl) 149838fd1498Szrj && DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (lhs)) 149938fd1498Szrj /* If the dynamic type of the decl has larger precision than 150038fd1498Szrj the decl itself we can't use the decls type for SSA rewriting. */ 150138fd1498Szrj && ((! INTEGRAL_TYPE_P (TREE_TYPE (decl)) 150238fd1498Szrj || compare_tree_int (DECL_SIZE (decl), 150338fd1498Szrj TYPE_PRECISION (TREE_TYPE (decl))) == 0) 150438fd1498Szrj || (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) 150538fd1498Szrj && (TYPE_PRECISION (TREE_TYPE (decl)) 150638fd1498Szrj >= TYPE_PRECISION (TREE_TYPE (lhs))))) 150738fd1498Szrj /* Make sure we are not re-writing non-float copying into float 150838fd1498Szrj copying as that can incur normalization. */ 150938fd1498Szrj && (! FLOAT_TYPE_P (TREE_TYPE (decl)) 151038fd1498Szrj || types_compatible_p (TREE_TYPE (lhs), TREE_TYPE (decl))) 151138fd1498Szrj && (TREE_THIS_VOLATILE (decl) == TREE_THIS_VOLATILE (lhs))) 151238fd1498Szrj return false; 151338fd1498Szrj 151438fd1498Szrj /* A vector-insert using a MEM_REF or ARRAY_REF is rewritable 151538fd1498Szrj using a BIT_INSERT_EXPR. */ 151638fd1498Szrj if (DECL_P (decl) 151738fd1498Szrj && VECTOR_TYPE_P (TREE_TYPE (decl)) 151838fd1498Szrj && TYPE_MODE (TREE_TYPE (decl)) != BLKmode 151938fd1498Szrj && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)), 152038fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))), 0) 152138fd1498Szrj && known_ge (mem_ref_offset (lhs), 0) 152238fd1498Szrj && known_gt (wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))), 152338fd1498Szrj mem_ref_offset (lhs)) 152438fd1498Szrj && multiple_of_p (sizetype, TREE_OPERAND (lhs, 1), 152538fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) 152638fd1498Szrj return false; 152738fd1498Szrj } 152838fd1498Szrj 152938fd1498Szrj /* A vector-insert using a BIT_FIELD_REF is rewritable using 153038fd1498Szrj BIT_INSERT_EXPR. */ 153138fd1498Szrj if (TREE_CODE (lhs) == BIT_FIELD_REF 153238fd1498Szrj && DECL_P (TREE_OPERAND (lhs, 0)) 153338fd1498Szrj && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))) 153438fd1498Szrj && TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode 153538fd1498Szrj && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)), 153638fd1498Szrj TYPE_SIZE_UNIT 153738fd1498Szrj (TREE_TYPE (TREE_TYPE (TREE_OPERAND (lhs, 0)))), 0) 153838fd1498Szrj && (tree_to_uhwi (TREE_OPERAND (lhs, 2)) 153938fd1498Szrj % tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs)))) == 0) 154038fd1498Szrj return false; 154138fd1498Szrj 154238fd1498Szrj return true; 154338fd1498Szrj } 154438fd1498Szrj 154538fd1498Szrj /* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and 154638fd1498Szrj mark the variable VAR for conversion into SSA. Return true when updating 154738fd1498Szrj stmts is required. */ 154838fd1498Szrj 154938fd1498Szrj static void 155038fd1498Szrj maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs, 155138fd1498Szrj bitmap suitable_for_renaming) 155238fd1498Szrj { 155338fd1498Szrj /* Global Variables, result decls cannot be changed. */ 155438fd1498Szrj if (is_global_var (var) 155538fd1498Szrj || TREE_CODE (var) == RESULT_DECL 155638fd1498Szrj || bitmap_bit_p (addresses_taken, DECL_UID (var))) 155738fd1498Szrj return; 155838fd1498Szrj 155938fd1498Szrj if (TREE_ADDRESSABLE (var) 156038fd1498Szrj /* Do not change TREE_ADDRESSABLE if we need to preserve var as 156138fd1498Szrj a non-register. Otherwise we are confused and forget to 156238fd1498Szrj add virtual operands for it. */ 156338fd1498Szrj && (!is_gimple_reg_type (TREE_TYPE (var)) 156438fd1498Szrj || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE 156538fd1498Szrj || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE 156638fd1498Szrj || !bitmap_bit_p (not_reg_needs, DECL_UID (var)))) 156738fd1498Szrj { 156838fd1498Szrj TREE_ADDRESSABLE (var) = 0; 156938fd1498Szrj if (is_gimple_reg (var)) 157038fd1498Szrj bitmap_set_bit (suitable_for_renaming, DECL_UID (var)); 157138fd1498Szrj if (dump_file) 157238fd1498Szrj { 157338fd1498Szrj fprintf (dump_file, "No longer having address taken: "); 157438fd1498Szrj print_generic_expr (dump_file, var); 157538fd1498Szrj fprintf (dump_file, "\n"); 157638fd1498Szrj } 157738fd1498Szrj } 157838fd1498Szrj 157938fd1498Szrj if (!DECL_GIMPLE_REG_P (var) 158038fd1498Szrj && !bitmap_bit_p (not_reg_needs, DECL_UID (var)) 158138fd1498Szrj && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE 158238fd1498Szrj || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE) 158338fd1498Szrj && !TREE_THIS_VOLATILE (var) 158438fd1498Szrj && (!VAR_P (var) || !DECL_HARD_REGISTER (var))) 158538fd1498Szrj { 158638fd1498Szrj DECL_GIMPLE_REG_P (var) = 1; 158738fd1498Szrj bitmap_set_bit (suitable_for_renaming, DECL_UID (var)); 158838fd1498Szrj if (dump_file) 158938fd1498Szrj { 159038fd1498Szrj fprintf (dump_file, "Now a gimple register: "); 159138fd1498Szrj print_generic_expr (dump_file, var); 159238fd1498Szrj fprintf (dump_file, "\n"); 159338fd1498Szrj } 159438fd1498Szrj } 159538fd1498Szrj } 159638fd1498Szrj 159738fd1498Szrj /* Return true when STMT is ASAN mark where second argument is an address 159838fd1498Szrj of a local variable. */ 159938fd1498Szrj 160038fd1498Szrj static bool 160138fd1498Szrj is_asan_mark_p (gimple *stmt) 160238fd1498Szrj { 160338fd1498Szrj if (!gimple_call_internal_p (stmt, IFN_ASAN_MARK)) 160438fd1498Szrj return false; 160538fd1498Szrj 160638fd1498Szrj tree addr = get_base_address (gimple_call_arg (stmt, 1)); 160738fd1498Szrj if (TREE_CODE (addr) == ADDR_EXPR 160838fd1498Szrj && VAR_P (TREE_OPERAND (addr, 0))) 160938fd1498Szrj { 161038fd1498Szrj tree var = TREE_OPERAND (addr, 0); 161138fd1498Szrj if (lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE, 161238fd1498Szrj DECL_ATTRIBUTES (var))) 161338fd1498Szrj return false; 161438fd1498Szrj 161538fd1498Szrj unsigned addressable = TREE_ADDRESSABLE (var); 161638fd1498Szrj TREE_ADDRESSABLE (var) = 0; 161738fd1498Szrj bool r = is_gimple_reg (var); 161838fd1498Szrj TREE_ADDRESSABLE (var) = addressable; 161938fd1498Szrj return r; 162038fd1498Szrj } 162138fd1498Szrj 162238fd1498Szrj return false; 162338fd1498Szrj } 162438fd1498Szrj 162538fd1498Szrj /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables. */ 162638fd1498Szrj 162738fd1498Szrj void 162838fd1498Szrj execute_update_addresses_taken (void) 162938fd1498Szrj { 163038fd1498Szrj basic_block bb; 163138fd1498Szrj auto_bitmap addresses_taken; 163238fd1498Szrj auto_bitmap not_reg_needs; 163338fd1498Szrj auto_bitmap suitable_for_renaming; 163438fd1498Szrj tree var; 163538fd1498Szrj unsigned i; 163638fd1498Szrj 163738fd1498Szrj timevar_push (TV_ADDRESS_TAKEN); 163838fd1498Szrj 163938fd1498Szrj /* Collect into ADDRESSES_TAKEN all variables whose address is taken within 164038fd1498Szrj the function body. */ 164138fd1498Szrj FOR_EACH_BB_FN (bb, cfun) 164238fd1498Szrj { 164338fd1498Szrj for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); 164438fd1498Szrj gsi_next (&gsi)) 164538fd1498Szrj { 164638fd1498Szrj gimple *stmt = gsi_stmt (gsi); 164738fd1498Szrj enum gimple_code code = gimple_code (stmt); 164838fd1498Szrj tree decl; 164938fd1498Szrj 165038fd1498Szrj if (code == GIMPLE_CALL) 165138fd1498Szrj { 165238fd1498Szrj if (optimize_atomic_compare_exchange_p (stmt)) 165338fd1498Szrj { 165438fd1498Szrj /* For __atomic_compare_exchange_N if the second argument 165538fd1498Szrj is &var, don't mark var addressable; 165638fd1498Szrj if it becomes non-addressable, we'll rewrite it into 165738fd1498Szrj ATOMIC_COMPARE_EXCHANGE call. */ 165838fd1498Szrj tree arg = gimple_call_arg (stmt, 1); 165938fd1498Szrj gimple_call_set_arg (stmt, 1, null_pointer_node); 166038fd1498Szrj gimple_ior_addresses_taken (addresses_taken, stmt); 166138fd1498Szrj gimple_call_set_arg (stmt, 1, arg); 166238fd1498Szrj } 166338fd1498Szrj else if (is_asan_mark_p (stmt) 166438fd1498Szrj || gimple_call_internal_p (stmt, IFN_GOMP_SIMT_ENTER)) 166538fd1498Szrj ; 166638fd1498Szrj else 166738fd1498Szrj gimple_ior_addresses_taken (addresses_taken, stmt); 166838fd1498Szrj } 166938fd1498Szrj else 167038fd1498Szrj /* Note all addresses taken by the stmt. */ 167138fd1498Szrj gimple_ior_addresses_taken (addresses_taken, stmt); 167238fd1498Szrj 167338fd1498Szrj /* If we have a call or an assignment, see if the lhs contains 167438fd1498Szrj a local decl that requires not to be a gimple register. */ 167538fd1498Szrj if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) 167638fd1498Szrj { 167738fd1498Szrj tree lhs = gimple_get_lhs (stmt); 167838fd1498Szrj if (lhs 167938fd1498Szrj && TREE_CODE (lhs) != SSA_NAME 168038fd1498Szrj && ((code == GIMPLE_CALL && ! DECL_P (lhs)) 168138fd1498Szrj || non_rewritable_lvalue_p (lhs))) 168238fd1498Szrj { 168338fd1498Szrj decl = get_base_address (lhs); 168438fd1498Szrj if (DECL_P (decl)) 168538fd1498Szrj bitmap_set_bit (not_reg_needs, DECL_UID (decl)); 168638fd1498Szrj } 168738fd1498Szrj } 168838fd1498Szrj 168938fd1498Szrj if (gimple_assign_single_p (stmt)) 169038fd1498Szrj { 169138fd1498Szrj tree rhs = gimple_assign_rhs1 (stmt); 169238fd1498Szrj if ((decl = non_rewritable_mem_ref_base (rhs))) 169338fd1498Szrj bitmap_set_bit (not_reg_needs, DECL_UID (decl)); 169438fd1498Szrj } 169538fd1498Szrj 169638fd1498Szrj else if (code == GIMPLE_CALL) 169738fd1498Szrj { 169838fd1498Szrj for (i = 0; i < gimple_call_num_args (stmt); ++i) 169938fd1498Szrj { 170038fd1498Szrj tree arg = gimple_call_arg (stmt, i); 170138fd1498Szrj if ((decl = non_rewritable_mem_ref_base (arg))) 170238fd1498Szrj bitmap_set_bit (not_reg_needs, DECL_UID (decl)); 170338fd1498Szrj } 170438fd1498Szrj } 170538fd1498Szrj 170638fd1498Szrj else if (code == GIMPLE_ASM) 170738fd1498Szrj { 170838fd1498Szrj gasm *asm_stmt = as_a <gasm *> (stmt); 170938fd1498Szrj for (i = 0; i < gimple_asm_noutputs (asm_stmt); ++i) 171038fd1498Szrj { 171138fd1498Szrj tree link = gimple_asm_output_op (asm_stmt, i); 171238fd1498Szrj tree lhs = TREE_VALUE (link); 171338fd1498Szrj if (TREE_CODE (lhs) != SSA_NAME) 171438fd1498Szrj { 171538fd1498Szrj decl = get_base_address (lhs); 171638fd1498Szrj if (DECL_P (decl) 171738fd1498Szrj && (non_rewritable_lvalue_p (lhs) 171838fd1498Szrj /* We cannot move required conversions from 171938fd1498Szrj the lhs to the rhs in asm statements, so 172038fd1498Szrj require we do not need any. */ 172138fd1498Szrj || !useless_type_conversion_p 172238fd1498Szrj (TREE_TYPE (lhs), TREE_TYPE (decl)))) 172338fd1498Szrj bitmap_set_bit (not_reg_needs, DECL_UID (decl)); 172438fd1498Szrj } 172538fd1498Szrj } 172638fd1498Szrj for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i) 172738fd1498Szrj { 172838fd1498Szrj tree link = gimple_asm_input_op (asm_stmt, i); 172938fd1498Szrj if ((decl = non_rewritable_mem_ref_base (TREE_VALUE (link)))) 173038fd1498Szrj bitmap_set_bit (not_reg_needs, DECL_UID (decl)); 173138fd1498Szrj } 173238fd1498Szrj } 173338fd1498Szrj } 173438fd1498Szrj 173538fd1498Szrj for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); 173638fd1498Szrj gsi_next (&gsi)) 173738fd1498Szrj { 173838fd1498Szrj size_t i; 173938fd1498Szrj gphi *phi = gsi.phi (); 174038fd1498Szrj 174138fd1498Szrj for (i = 0; i < gimple_phi_num_args (phi); i++) 174238fd1498Szrj { 174338fd1498Szrj tree op = PHI_ARG_DEF (phi, i), var; 174438fd1498Szrj if (TREE_CODE (op) == ADDR_EXPR 174538fd1498Szrj && (var = get_base_address (TREE_OPERAND (op, 0))) != NULL 174638fd1498Szrj && DECL_P (var)) 174738fd1498Szrj bitmap_set_bit (addresses_taken, DECL_UID (var)); 174838fd1498Szrj } 174938fd1498Szrj } 175038fd1498Szrj } 175138fd1498Szrj 175238fd1498Szrj /* We cannot iterate over all referenced vars because that can contain 175338fd1498Szrj unused vars from BLOCK trees, which causes code generation differences 175438fd1498Szrj for -g vs. -g0. */ 175538fd1498Szrj for (var = DECL_ARGUMENTS (cfun->decl); var; var = DECL_CHAIN (var)) 175638fd1498Szrj maybe_optimize_var (var, addresses_taken, not_reg_needs, 175738fd1498Szrj suitable_for_renaming); 175838fd1498Szrj 175938fd1498Szrj FOR_EACH_VEC_SAFE_ELT (cfun->local_decls, i, var) 176038fd1498Szrj maybe_optimize_var (var, addresses_taken, not_reg_needs, 176138fd1498Szrj suitable_for_renaming); 176238fd1498Szrj 176338fd1498Szrj /* Operand caches need to be recomputed for operands referencing the updated 176438fd1498Szrj variables and operands need to be rewritten to expose bare symbols. */ 176538fd1498Szrj if (!bitmap_empty_p (suitable_for_renaming)) 176638fd1498Szrj { 176738fd1498Szrj FOR_EACH_BB_FN (bb, cfun) 176838fd1498Szrj for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) 176938fd1498Szrj { 177038fd1498Szrj gimple *stmt = gsi_stmt (gsi); 177138fd1498Szrj 177238fd1498Szrj /* Re-write TARGET_MEM_REFs of symbols we want to 177338fd1498Szrj rewrite into SSA form. */ 177438fd1498Szrj if (gimple_assign_single_p (stmt)) 177538fd1498Szrj { 177638fd1498Szrj tree lhs = gimple_assign_lhs (stmt); 177738fd1498Szrj tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt); 177838fd1498Szrj tree sym; 177938fd1498Szrj 178038fd1498Szrj /* Rewrite LHS IMAG/REALPART_EXPR similar to 178138fd1498Szrj gimplify_modify_expr_complex_part. */ 178238fd1498Szrj if ((TREE_CODE (lhs) == IMAGPART_EXPR 178338fd1498Szrj || TREE_CODE (lhs) == REALPART_EXPR) 178438fd1498Szrj && DECL_P (TREE_OPERAND (lhs, 0)) 178538fd1498Szrj && bitmap_bit_p (suitable_for_renaming, 178638fd1498Szrj DECL_UID (TREE_OPERAND (lhs, 0)))) 178738fd1498Szrj { 178838fd1498Szrj tree other = make_ssa_name (TREE_TYPE (lhs)); 178938fd1498Szrj tree lrhs = build1 (TREE_CODE (lhs) == IMAGPART_EXPR 179038fd1498Szrj ? REALPART_EXPR : IMAGPART_EXPR, 179138fd1498Szrj TREE_TYPE (other), 179238fd1498Szrj TREE_OPERAND (lhs, 0)); 179338fd1498Szrj gimple *load = gimple_build_assign (other, lrhs); 179438fd1498Szrj location_t loc = gimple_location (stmt); 179538fd1498Szrj gimple_set_location (load, loc); 179638fd1498Szrj gimple_set_vuse (load, gimple_vuse (stmt)); 179738fd1498Szrj gsi_insert_before (&gsi, load, GSI_SAME_STMT); 179838fd1498Szrj gimple_assign_set_lhs (stmt, TREE_OPERAND (lhs, 0)); 179938fd1498Szrj gimple_assign_set_rhs_with_ops 180038fd1498Szrj (&gsi, COMPLEX_EXPR, 180138fd1498Szrj TREE_CODE (lhs) == IMAGPART_EXPR 180238fd1498Szrj ? other : gimple_assign_rhs1 (stmt), 180338fd1498Szrj TREE_CODE (lhs) == IMAGPART_EXPR 180438fd1498Szrj ? gimple_assign_rhs1 (stmt) : other, NULL_TREE); 180538fd1498Szrj stmt = gsi_stmt (gsi); 180638fd1498Szrj unlink_stmt_vdef (stmt); 180738fd1498Szrj update_stmt (stmt); 180838fd1498Szrj continue; 180938fd1498Szrj } 181038fd1498Szrj 181138fd1498Szrj /* Rewrite a vector insert via a BIT_FIELD_REF on the LHS 181238fd1498Szrj into a BIT_INSERT_EXPR. */ 181338fd1498Szrj if (TREE_CODE (lhs) == BIT_FIELD_REF 181438fd1498Szrj && DECL_P (TREE_OPERAND (lhs, 0)) 181538fd1498Szrj && bitmap_bit_p (suitable_for_renaming, 181638fd1498Szrj DECL_UID (TREE_OPERAND (lhs, 0))) 181738fd1498Szrj && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (lhs, 0))) 181838fd1498Szrj && TYPE_MODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) != BLKmode 181938fd1498Szrj && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)), 182038fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE 182138fd1498Szrj (TREE_TYPE (TREE_OPERAND (lhs, 0)))), 182238fd1498Szrj 0) 182338fd1498Szrj && (tree_to_uhwi (TREE_OPERAND (lhs, 2)) 182438fd1498Szrj % tree_to_uhwi (TYPE_SIZE (TREE_TYPE (lhs))) == 0)) 182538fd1498Szrj { 182638fd1498Szrj tree var = TREE_OPERAND (lhs, 0); 182738fd1498Szrj tree val = gimple_assign_rhs1 (stmt); 182838fd1498Szrj if (! types_compatible_p (TREE_TYPE (TREE_TYPE (var)), 182938fd1498Szrj TREE_TYPE (val))) 183038fd1498Szrj { 183138fd1498Szrj tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (var))); 183238fd1498Szrj gimple *pun 183338fd1498Szrj = gimple_build_assign (tem, 183438fd1498Szrj build1 (VIEW_CONVERT_EXPR, 183538fd1498Szrj TREE_TYPE (tem), val)); 183638fd1498Szrj gsi_insert_before (&gsi, pun, GSI_SAME_STMT); 183738fd1498Szrj val = tem; 183838fd1498Szrj } 183938fd1498Szrj tree bitpos = TREE_OPERAND (lhs, 2); 184038fd1498Szrj gimple_assign_set_lhs (stmt, var); 184138fd1498Szrj gimple_assign_set_rhs_with_ops 184238fd1498Szrj (&gsi, BIT_INSERT_EXPR, var, val, bitpos); 184338fd1498Szrj stmt = gsi_stmt (gsi); 184438fd1498Szrj unlink_stmt_vdef (stmt); 184538fd1498Szrj update_stmt (stmt); 184638fd1498Szrj continue; 184738fd1498Szrj } 184838fd1498Szrj 184938fd1498Szrj /* Rewrite a vector insert using a MEM_REF on the LHS 185038fd1498Szrj into a BIT_INSERT_EXPR. */ 185138fd1498Szrj if (TREE_CODE (lhs) == MEM_REF 185238fd1498Szrj && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR 185338fd1498Szrj && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0)) 185438fd1498Szrj && DECL_P (sym) 185538fd1498Szrj && bitmap_bit_p (suitable_for_renaming, DECL_UID (sym)) 185638fd1498Szrj && VECTOR_TYPE_P (TREE_TYPE (sym)) 185738fd1498Szrj && TYPE_MODE (TREE_TYPE (sym)) != BLKmode 185838fd1498Szrj && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)), 185938fd1498Szrj TYPE_SIZE_UNIT 186038fd1498Szrj (TREE_TYPE (TREE_TYPE (sym))), 0) 186138fd1498Szrj && tree_fits_uhwi_p (TREE_OPERAND (lhs, 1)) 186238fd1498Szrj && tree_int_cst_lt (TREE_OPERAND (lhs, 1), 186338fd1498Szrj TYPE_SIZE_UNIT (TREE_TYPE (sym))) 186438fd1498Szrj && (tree_to_uhwi (TREE_OPERAND (lhs, 1)) 186538fd1498Szrj % tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0) 186638fd1498Szrj { 186738fd1498Szrj tree val = gimple_assign_rhs1 (stmt); 186838fd1498Szrj if (! types_compatible_p (TREE_TYPE (val), 186938fd1498Szrj TREE_TYPE (TREE_TYPE (sym)))) 187038fd1498Szrj { 187138fd1498Szrj tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (sym))); 187238fd1498Szrj gimple *pun 187338fd1498Szrj = gimple_build_assign (tem, 187438fd1498Szrj build1 (VIEW_CONVERT_EXPR, 187538fd1498Szrj TREE_TYPE (tem), val)); 187638fd1498Szrj gsi_insert_before (&gsi, pun, GSI_SAME_STMT); 187738fd1498Szrj val = tem; 187838fd1498Szrj } 187938fd1498Szrj tree bitpos 188038fd1498Szrj = wide_int_to_tree (bitsizetype, 188138fd1498Szrj mem_ref_offset (lhs) * BITS_PER_UNIT); 188238fd1498Szrj gimple_assign_set_lhs (stmt, sym); 188338fd1498Szrj gimple_assign_set_rhs_with_ops 188438fd1498Szrj (&gsi, BIT_INSERT_EXPR, sym, val, bitpos); 188538fd1498Szrj stmt = gsi_stmt (gsi); 188638fd1498Szrj unlink_stmt_vdef (stmt); 188738fd1498Szrj update_stmt (stmt); 188838fd1498Szrj continue; 188938fd1498Szrj } 189038fd1498Szrj 189138fd1498Szrj /* We shouldn't have any fancy wrapping of 189238fd1498Szrj component-refs on the LHS, but look through 189338fd1498Szrj VIEW_CONVERT_EXPRs as that is easy. */ 189438fd1498Szrj while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR) 189538fd1498Szrj lhs = TREE_OPERAND (lhs, 0); 189638fd1498Szrj if (TREE_CODE (lhs) == MEM_REF 189738fd1498Szrj && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR 189838fd1498Szrj && integer_zerop (TREE_OPERAND (lhs, 1)) 189938fd1498Szrj && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0)) 190038fd1498Szrj && DECL_P (sym) 190138fd1498Szrj && !TREE_ADDRESSABLE (sym) 190238fd1498Szrj && bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))) 190338fd1498Szrj lhs = sym; 190438fd1498Szrj else 190538fd1498Szrj lhs = gimple_assign_lhs (stmt); 190638fd1498Szrj 190738fd1498Szrj /* Rewrite the RHS and make sure the resulting assignment 190838fd1498Szrj is validly typed. */ 190938fd1498Szrj maybe_rewrite_mem_ref_base (rhsp, suitable_for_renaming); 191038fd1498Szrj rhs = gimple_assign_rhs1 (stmt); 191138fd1498Szrj if (gimple_assign_lhs (stmt) != lhs 191238fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (lhs), 191338fd1498Szrj TREE_TYPE (rhs))) 191438fd1498Szrj { 191538fd1498Szrj if (gimple_clobber_p (stmt)) 191638fd1498Szrj { 191738fd1498Szrj rhs = build_constructor (TREE_TYPE (lhs), NULL); 191838fd1498Szrj TREE_THIS_VOLATILE (rhs) = 1; 191938fd1498Szrj } 192038fd1498Szrj else 192138fd1498Szrj rhs = fold_build1 (VIEW_CONVERT_EXPR, 192238fd1498Szrj TREE_TYPE (lhs), rhs); 192338fd1498Szrj } 192438fd1498Szrj if (gimple_assign_lhs (stmt) != lhs) 192538fd1498Szrj gimple_assign_set_lhs (stmt, lhs); 192638fd1498Szrj 192738fd1498Szrj if (gimple_assign_rhs1 (stmt) != rhs) 192838fd1498Szrj { 192938fd1498Szrj gimple_stmt_iterator gsi = gsi_for_stmt (stmt); 193038fd1498Szrj gimple_assign_set_rhs_from_tree (&gsi, rhs); 193138fd1498Szrj } 193238fd1498Szrj } 193338fd1498Szrj 193438fd1498Szrj else if (gimple_code (stmt) == GIMPLE_CALL) 193538fd1498Szrj { 193638fd1498Szrj unsigned i; 193738fd1498Szrj if (optimize_atomic_compare_exchange_p (stmt)) 193838fd1498Szrj { 193938fd1498Szrj tree expected = gimple_call_arg (stmt, 1); 194038fd1498Szrj if (bitmap_bit_p (suitable_for_renaming, 194138fd1498Szrj DECL_UID (TREE_OPERAND (expected, 0)))) 194238fd1498Szrj { 194338fd1498Szrj fold_builtin_atomic_compare_exchange (&gsi); 194438fd1498Szrj continue; 194538fd1498Szrj } 194638fd1498Szrj } 194738fd1498Szrj else if (is_asan_mark_p (stmt)) 194838fd1498Szrj { 194938fd1498Szrj tree var = TREE_OPERAND (gimple_call_arg (stmt, 1), 0); 195038fd1498Szrj if (bitmap_bit_p (suitable_for_renaming, DECL_UID (var))) 195138fd1498Szrj { 195238fd1498Szrj unlink_stmt_vdef (stmt); 195338fd1498Szrj if (asan_mark_p (stmt, ASAN_MARK_POISON)) 195438fd1498Szrj { 195538fd1498Szrj gcall *call 195638fd1498Szrj = gimple_build_call_internal (IFN_ASAN_POISON, 0); 195738fd1498Szrj gimple_call_set_lhs (call, var); 195838fd1498Szrj gsi_replace (&gsi, call, GSI_SAME_STMT); 195938fd1498Szrj } 196038fd1498Szrj else 196138fd1498Szrj { 196238fd1498Szrj /* In ASAN_MARK (UNPOISON, &b, ...) the variable 196338fd1498Szrj is uninitialized. Avoid dependencies on 196438fd1498Szrj previous out of scope value. */ 196538fd1498Szrj tree clobber 196638fd1498Szrj = build_constructor (TREE_TYPE (var), NULL); 196738fd1498Szrj TREE_THIS_VOLATILE (clobber) = 1; 196838fd1498Szrj gimple *g = gimple_build_assign (var, clobber); 196938fd1498Szrj gsi_replace (&gsi, g, GSI_SAME_STMT); 197038fd1498Szrj } 197138fd1498Szrj continue; 197238fd1498Szrj } 197338fd1498Szrj } 197438fd1498Szrj else if (gimple_call_internal_p (stmt, IFN_GOMP_SIMT_ENTER)) 197538fd1498Szrj for (i = 1; i < gimple_call_num_args (stmt); i++) 197638fd1498Szrj { 197738fd1498Szrj tree *argp = gimple_call_arg_ptr (stmt, i); 197838fd1498Szrj if (*argp == null_pointer_node) 197938fd1498Szrj continue; 198038fd1498Szrj gcc_assert (TREE_CODE (*argp) == ADDR_EXPR 198138fd1498Szrj && VAR_P (TREE_OPERAND (*argp, 0))); 198238fd1498Szrj tree var = TREE_OPERAND (*argp, 0); 198338fd1498Szrj if (bitmap_bit_p (suitable_for_renaming, DECL_UID (var))) 198438fd1498Szrj *argp = null_pointer_node; 198538fd1498Szrj } 198638fd1498Szrj for (i = 0; i < gimple_call_num_args (stmt); ++i) 198738fd1498Szrj { 198838fd1498Szrj tree *argp = gimple_call_arg_ptr (stmt, i); 198938fd1498Szrj maybe_rewrite_mem_ref_base (argp, suitable_for_renaming); 199038fd1498Szrj } 199138fd1498Szrj } 199238fd1498Szrj 199338fd1498Szrj else if (gimple_code (stmt) == GIMPLE_ASM) 199438fd1498Szrj { 199538fd1498Szrj gasm *asm_stmt = as_a <gasm *> (stmt); 199638fd1498Szrj unsigned i; 199738fd1498Szrj for (i = 0; i < gimple_asm_noutputs (asm_stmt); ++i) 199838fd1498Szrj { 199938fd1498Szrj tree link = gimple_asm_output_op (asm_stmt, i); 200038fd1498Szrj maybe_rewrite_mem_ref_base (&TREE_VALUE (link), 200138fd1498Szrj suitable_for_renaming); 200238fd1498Szrj } 200338fd1498Szrj for (i = 0; i < gimple_asm_ninputs (asm_stmt); ++i) 200438fd1498Szrj { 200538fd1498Szrj tree link = gimple_asm_input_op (asm_stmt, i); 200638fd1498Szrj maybe_rewrite_mem_ref_base (&TREE_VALUE (link), 200738fd1498Szrj suitable_for_renaming); 200838fd1498Szrj } 200938fd1498Szrj } 201038fd1498Szrj 201138fd1498Szrj else if (gimple_debug_bind_p (stmt) 201238fd1498Szrj && gimple_debug_bind_has_value_p (stmt)) 201338fd1498Szrj { 201438fd1498Szrj tree *valuep = gimple_debug_bind_get_value_ptr (stmt); 201538fd1498Szrj tree decl; 201638fd1498Szrj maybe_rewrite_mem_ref_base (valuep, suitable_for_renaming); 201738fd1498Szrj decl = non_rewritable_mem_ref_base (*valuep); 201838fd1498Szrj if (decl 201938fd1498Szrj && bitmap_bit_p (suitable_for_renaming, DECL_UID (decl))) 202038fd1498Szrj gimple_debug_bind_reset_value (stmt); 202138fd1498Szrj } 202238fd1498Szrj 202338fd1498Szrj if (gimple_references_memory_p (stmt) 202438fd1498Szrj || is_gimple_debug (stmt)) 202538fd1498Szrj update_stmt (stmt); 202638fd1498Szrj 202738fd1498Szrj gsi_next (&gsi); 202838fd1498Szrj } 202938fd1498Szrj 203038fd1498Szrj /* Update SSA form here, we are called as non-pass as well. */ 203138fd1498Szrj if (number_of_loops (cfun) > 1 203238fd1498Szrj && loops_state_satisfies_p (LOOP_CLOSED_SSA)) 203338fd1498Szrj rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); 203438fd1498Szrj else 203538fd1498Szrj update_ssa (TODO_update_ssa); 203638fd1498Szrj } 203738fd1498Szrj 203838fd1498Szrj timevar_pop (TV_ADDRESS_TAKEN); 203938fd1498Szrj } 204038fd1498Szrj 204138fd1498Szrj namespace { 204238fd1498Szrj 204338fd1498Szrj const pass_data pass_data_update_address_taken = 204438fd1498Szrj { 204538fd1498Szrj GIMPLE_PASS, /* type */ 204638fd1498Szrj "addressables", /* name */ 204738fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */ 204838fd1498Szrj TV_ADDRESS_TAKEN, /* tv_id */ 204938fd1498Szrj PROP_ssa, /* properties_required */ 205038fd1498Szrj 0, /* properties_provided */ 205138fd1498Szrj 0, /* properties_destroyed */ 205238fd1498Szrj 0, /* todo_flags_start */ 205338fd1498Szrj TODO_update_address_taken, /* todo_flags_finish */ 205438fd1498Szrj }; 205538fd1498Szrj 205638fd1498Szrj class pass_update_address_taken : public gimple_opt_pass 205738fd1498Szrj { 205838fd1498Szrj public: 205938fd1498Szrj pass_update_address_taken (gcc::context *ctxt) 206038fd1498Szrj : gimple_opt_pass (pass_data_update_address_taken, ctxt) 206138fd1498Szrj {} 206238fd1498Szrj 206338fd1498Szrj /* opt_pass methods: */ 206438fd1498Szrj 206538fd1498Szrj }; // class pass_update_address_taken 206638fd1498Szrj 206738fd1498Szrj } // anon namespace 206838fd1498Szrj 206938fd1498Szrj gimple_opt_pass * 207038fd1498Szrj make_pass_update_address_taken (gcc::context *ctxt) 207138fd1498Szrj { 207238fd1498Szrj return new pass_update_address_taken (ctxt); 207338fd1498Szrj } 2074