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; }
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; }
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); } }
DEBUG_FUNCTION bool verify_imm_links (FILE *f, tree var) { use_operand_p ptr, prev, list; int count; gcc_assert (TREE_CODE (var) == SSA_NAME); list = &(SSA_NAME_IMM_USE_NODE (var)); gcc_assert (list->use == NULL); if (list->prev == NULL) { gcc_assert (list->next == NULL); return false; } prev = list; count = 0; for (ptr = list->next; ptr != list; ) { if (prev != ptr->prev) goto error; if (ptr->use == NULL) goto error; /* 2 roots, or SAFE guard node. */ else if (*(ptr->use) != var) goto error; prev = ptr; ptr = ptr->next; /* Avoid infinite loops. 50,000,000 uses probably indicates a problem. */ if (count++ > 50000000) goto error; } /* Verify list in the other direction. */ prev = list; for (ptr = list->prev; ptr != list; ) { if (prev != ptr->next) goto error; prev = ptr; ptr = ptr->prev; if (count-- < 0) goto error; } if (count != 0) goto error; return false; error: if (ptr->loc.stmt && gimple_modified_p (ptr->loc.stmt)) { fprintf (f, " STMT MODIFIED. - <%p> ", (void *)ptr->loc.stmt); print_gimple_stmt (f, ptr->loc.stmt, 0, TDF_SLIM); } fprintf (f, " IMM ERROR : (use_p : tree - %p:%p)", (void *)ptr, (void *)ptr->use); print_generic_expr (f, USE_FROM_PTR (ptr), TDF_SLIM); fprintf(f, "\n"); return true; }