bool may_propagate_copy (tree dest, tree orig) { tree type_d = TREE_TYPE (dest); tree type_o = TREE_TYPE (orig); /* If ORIG flows in from an abnormal edge, it cannot be propagated. */ if (TREE_CODE (orig) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig) /* If it is the default definition and an automatic variable then we can though and it is important that we do to avoid uninitialized regular copies. */ && !(SSA_NAME_IS_DEFAULT_DEF (orig) && (SSA_NAME_VAR (orig) == NULL_TREE || TREE_CODE (SSA_NAME_VAR (orig)) == VAR_DECL))) return false; /* If DEST is an SSA_NAME that flows from an abnormal edge, then it cannot be replaced. */ if (TREE_CODE (dest) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest)) return false; /* Do not copy between types for which we *do* need a conversion. */ if (!useless_type_conversion_p (type_d, type_o)) return false; /* Generally propagating virtual operands is not ok as that may create overlapping life-ranges. */ if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest)) return false; /* Anything else is OK. */ return true; }
static inline void unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr) { /* Note that the code for EXPR has already been unpacked to create EXPR in streamer_alloc_tree. */ if (!TYPE_P (expr)) { TREE_SIDE_EFFECTS (expr) = (unsigned) bp_unpack_value (bp, 1); TREE_CONSTANT (expr) = (unsigned) bp_unpack_value (bp, 1); TREE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1); /* TREE_PUBLIC is used on types to indicate that the type has a TYPE_CACHED_VALUES vector. This is not streamed out, so we skip it here. */ TREE_PUBLIC (expr) = (unsigned) bp_unpack_value (bp, 1); } else bp_unpack_value (bp, 4); TREE_ADDRESSABLE (expr) = (unsigned) bp_unpack_value (bp, 1); TREE_THIS_VOLATILE (expr) = (unsigned) bp_unpack_value (bp, 1); if (DECL_P (expr)) DECL_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1); else if (TYPE_P (expr)) TYPE_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1); else bp_unpack_value (bp, 1); TREE_ASM_WRITTEN (expr) = (unsigned) bp_unpack_value (bp, 1); if (TYPE_P (expr)) TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1); else TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1); TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1); TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1); if (TREE_CODE (expr) != TREE_BINFO) TREE_PRIVATE (expr) = (unsigned) bp_unpack_value (bp, 1); else bp_unpack_value (bp, 1); TREE_PROTECTED (expr) = (unsigned) bp_unpack_value (bp, 1); TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1); if (TYPE_P (expr)) { if (AGGREGATE_TYPE_P (expr)) TYPE_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1); else TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_ADDR_SPACE (expr) = (unsigned) bp_unpack_value (bp, 8); } else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF) { REF_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1); bp_unpack_value (bp, 8); } else if (TREE_CODE (expr) == SSA_NAME) { SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1); bp_unpack_value (bp, 8); } else bp_unpack_value (bp, 9); }
tree make_ssa_name_fn (struct function *fn, tree var, gimple stmt) { tree t; use_operand_p imm; gcc_assert (TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == RESULT_DECL || (TYPE_P (var) && is_gimple_reg_type (var))); /* If our free list has an element, then use it. */ if (!vec_safe_is_empty (FREE_SSANAMES (fn))) { t = FREE_SSANAMES (fn)->pop (); if (GATHER_STATISTICS) ssa_name_nodes_reused++; /* The node was cleared out when we put it on the free list, so there is no need to do so again here. */ gcc_assert (ssa_name (SSA_NAME_VERSION (t)) == NULL); (*SSANAMES (fn))[SSA_NAME_VERSION (t)] = t; } else { t = make_node (SSA_NAME); SSA_NAME_VERSION (t) = SSANAMES (fn)->length (); vec_safe_push (SSANAMES (fn), t); if (GATHER_STATISTICS) ssa_name_nodes_created++; } if (TYPE_P (var)) { TREE_TYPE (t) = var; SET_SSA_NAME_VAR_OR_IDENTIFIER (t, NULL_TREE); } else { TREE_TYPE (t) = TREE_TYPE (var); SET_SSA_NAME_VAR_OR_IDENTIFIER (t, var); } SSA_NAME_DEF_STMT (t) = stmt; if (POINTER_TYPE_P (TREE_TYPE (t))) SSA_NAME_PTR_INFO (t) = NULL; else SSA_NAME_RANGE_INFO (t) = NULL; SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IS_DEFAULT_DEF (t) = 0; imm = &(SSA_NAME_IMM_USE_NODE (t)); imm->use = NULL; imm->prev = imm; imm->next = imm; imm->loc.ssa_name = t; return t; }
tree make_ssa_name (tree var, tree stmt) { tree t; use_operand_p imm; gcc_assert (DECL_P (var) || TREE_CODE (var) == INDIRECT_REF); gcc_assert (!stmt || EXPR_P (stmt) || GIMPLE_STMT_P (stmt) || TREE_CODE (stmt) == PHI_NODE); /* If our free list has an element, then use it. */ if (FREE_SSANAMES (cfun)) { t = FREE_SSANAMES (cfun); FREE_SSANAMES (cfun) = TREE_CHAIN (FREE_SSANAMES (cfun)); #ifdef GATHER_STATISTICS ssa_name_nodes_reused++; #endif /* The node was cleared out when we put it on the free list, so there is no need to do so again here. */ gcc_assert (ssa_name (SSA_NAME_VERSION (t)) == NULL); VEC_replace (tree, SSANAMES (cfun), SSA_NAME_VERSION (t), t); } else { t = make_node (SSA_NAME); SSA_NAME_VERSION (t) = num_ssa_names; VEC_safe_push (tree, gc, SSANAMES (cfun), t); #ifdef GATHER_STATISTICS ssa_name_nodes_created++; #endif } TREE_TYPE (t) = TREE_TYPE (var); SSA_NAME_VAR (t) = var; SSA_NAME_DEF_STMT (t) = stmt; SSA_NAME_PTR_INFO (t) = NULL; SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IS_DEFAULT_DEF (t) = 0; imm = &(SSA_NAME_IMM_USE_NODE (t)); imm->use = NULL; imm->prev = imm; imm->next = imm; imm->stmt = t; return t; }
static void pack_ts_base_value_fields (struct bitpack_d *bp, tree expr) { bp_pack_value (bp, TREE_CODE (expr), 16); if (!TYPE_P (expr)) { bp_pack_value (bp, TREE_SIDE_EFFECTS (expr), 1); bp_pack_value (bp, TREE_CONSTANT (expr), 1); bp_pack_value (bp, TREE_READONLY (expr), 1); /* TREE_PUBLIC is used on types to indicate that the type has a TYPE_CACHED_VALUES vector. This is not streamed out, so we skip it here. */ bp_pack_value (bp, TREE_PUBLIC (expr), 1); } else bp_pack_value (bp, 0, 4); bp_pack_value (bp, TREE_ADDRESSABLE (expr), 1); bp_pack_value (bp, TREE_THIS_VOLATILE (expr), 1); if (DECL_P (expr)) bp_pack_value (bp, DECL_UNSIGNED (expr), 1); else if (TYPE_P (expr)) bp_pack_value (bp, TYPE_UNSIGNED (expr), 1); else bp_pack_value (bp, 0, 1); /* We write debug info two times, do not confuse the second one. The only relevant TREE_ASM_WRITTEN use is on SSA names. */ bp_pack_value (bp, (TREE_CODE (expr) != SSA_NAME ? 0 : TREE_ASM_WRITTEN (expr)), 1); if (TYPE_P (expr)) bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1); else bp_pack_value (bp, TREE_NO_WARNING (expr), 1); bp_pack_value (bp, TREE_NOTHROW (expr), 1); bp_pack_value (bp, TREE_STATIC (expr), 1); if (TREE_CODE (expr) != TREE_BINFO) bp_pack_value (bp, TREE_PRIVATE (expr), 1); bp_pack_value (bp, TREE_PROTECTED (expr), 1); bp_pack_value (bp, TREE_DEPRECATED (expr), 1); if (TYPE_P (expr)) { bp_pack_value (bp, TYPE_SATURATING (expr), 1); bp_pack_value (bp, TYPE_ADDR_SPACE (expr), 8); } else if (TREE_CODE (expr) == SSA_NAME) bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1); else bp_pack_value (bp, 0, 1); }
tree make_ssa_name_fn (struct function *fn, tree var, gimple stmt) { tree t; use_operand_p imm; gcc_assert (DECL_P (var)); /* If our free list has an element, then use it. */ if (FREE_SSANAMES (fn)) { t = FREE_SSANAMES (fn); FREE_SSANAMES (fn) = TREE_CHAIN (FREE_SSANAMES (fn)); #ifdef GATHER_STATISTICS ssa_name_nodes_reused++; #endif /* The node was cleared out when we put it on the free list, so there is no need to do so again here. */ gcc_assert (ssa_name (SSA_NAME_VERSION (t)) == NULL); VEC_replace (tree, SSANAMES (fn), SSA_NAME_VERSION (t), t); } else { t = make_node (SSA_NAME); SSA_NAME_VERSION (t) = VEC_length (tree, SSANAMES (fn)); VEC_safe_push (tree, gc, SSANAMES (fn), t); #ifdef GATHER_STATISTICS ssa_name_nodes_created++; #endif } TREE_TYPE (t) = TREE_TYPE (var); SSA_NAME_VAR (t) = var; SSA_NAME_DEF_STMT (t) = stmt; SSA_NAME_PTR_INFO (t) = NULL; SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IS_DEFAULT_DEF (t) = 0; imm = &(SSA_NAME_IMM_USE_NODE (t)); imm->use = NULL; imm->prev = imm; imm->next = imm; imm->loc.ssa_name = t; return t; }
/* This function calls the main recursion function (expand) that duplicates the stmts. Before that it checks the intentional_overflow attribute, * it decides whether the duplication is necessary or not. After expand() it changes the orig node to the duplicated node * in the original stmt (first stmt) and it inserts the overflow check for the arg of the callee or for the return value. */ static struct interesting_stmts *search_interesting_stmt(struct interesting_stmts *head, gimple first_stmt, tree orig_node, unsigned int num) { enum tree_code orig_code; gcc_assert(orig_node != NULL_TREE); if (is_gimple_constant(orig_node)) return head; orig_code = TREE_CODE(orig_node); gcc_assert(orig_code != FIELD_DECL && orig_code != FUNCTION_DECL); gcc_assert(!skip_types(orig_node)); if (check_intentional_asm(first_stmt, num) != MARK_NO) return head; if (SSA_NAME_IS_DEFAULT_DEF(orig_node)) return head; if (skip_asm_cast(orig_node)) return head; return create_interesting_stmts(head, orig_node, first_stmt, num); }
void release_ssa_name (tree var) { if (!var) return; /* Never release the default definition for a symbol. It's a special SSA name that should always exist once it's created. */ if (SSA_NAME_IS_DEFAULT_DEF (var)) return; /* If VAR has been registered for SSA updating, don't remove it. After update_ssa has run, the name will be released. */ if (name_registered_for_update_p (var)) { release_ssa_name_after_update_ssa (var); return; } /* release_ssa_name can be called multiple times on a single SSA_NAME. However, it should only end up on our free list one time. We keep a status bit in the SSA_NAME node itself to indicate it has been put on the free list. Note that once on the freelist you can not reference the SSA_NAME's defining statement. */ if (! SSA_NAME_IN_FREE_LIST (var)) { tree saved_ssa_name_var = SSA_NAME_VAR (var); int saved_ssa_name_version = SSA_NAME_VERSION (var); use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var)); if (MAY_HAVE_DEBUG_STMTS) insert_debug_temp_for_var_def (NULL, var); #ifdef ENABLE_CHECKING verify_imm_links (stderr, var); #endif while (imm->next != imm) delink_imm_use (imm->next); (*SSANAMES (cfun))[SSA_NAME_VERSION (var)] = NULL_TREE; memset (var, 0, tree_size (var)); imm->prev = imm; imm->next = imm; imm->loc.ssa_name = var; /* First put back the right tree node so that the tree checking macros do not complain. */ TREE_SET_CODE (var, SSA_NAME); /* Restore the version number. */ SSA_NAME_VERSION (var) = saved_ssa_name_version; /* Hopefully this can go away once we have the new incremental SSA updating code installed. */ SET_SSA_NAME_VAR_OR_IDENTIFIER (var, saved_ssa_name_var); /* Note this SSA_NAME is now in the first list. */ SSA_NAME_IN_FREE_LIST (var) = 1; /* And finally put it on the free list. */ vec_safe_push (FREE_SSANAMES (cfun), var); } }