Index: struct-reorg.c =================================================================== --- struct-reorg.c (revision 114271) +++ struct-reorg.c (working copy) @@ -1389,6 +1389,7 @@ create_and_assemble_new_types (struct da a tree_list of existing variables, and adds the new variables to the list. */ +#if 0 static tree insert_into_var_list (struct struct_tree_list *new_vars, tree var_list, tree current_var_decl ATTRIBUTE_UNUSED) @@ -1411,13 +1412,12 @@ insert_into_var_list (struct struct_tree return var_list; } +#endif -/* This function takes a list of newly created variables (NEW_VARS) and - a tree_list of existing variables, and adds the new variables to the - list. */ - +/* Given an old variable ORIG_SSA_NAME, this function generates + new variables to replace it accoriding to the set of types decided before. */ static struct struct_tree_list * -make_new_vars_1 (tree orig_decl, struct data_structure *struct_data) +make_new_vars_1 (tree orig_ssa_name, struct data_structure *struct_data) { struct struct_tree_list *new_vars = NULL; struct struct_tree_list *tmp_node; @@ -1425,35 +1425,26 @@ make_new_vars_1 (tree orig_decl, struct struct struct_tree_list *current; bool pointer_type_p = false; bool array_type_p = false; - tree pointer_type; - tree array_type; int i; - + tree orig_decl = SSA_NAME_VAR (orig_ssa_name); + if (POINTER_TYPE_P (TREE_TYPE (orig_decl))) pointer_type_p = true; else if (TREE_CODE (TREE_TYPE (orig_decl)) == ARRAY_TYPE) array_type_p = true; /* For each new type... */ - for (current = new_types, i = 0; current; current = current->next, i++) { tree new_type = current->data; - tree new_decl; - tree id_node; - char *new_name; + tree new_decl = NULL; + char *new_name = NULL; char *old_name; int len; - /* Make a copy of the original variable decl. */ - - new_decl = copy_node (orig_decl); - new_decl->decl.rtl = NULL; - DECL_CONTEXT (new_decl) = DECL_CONTEXT (orig_decl); - + /* IFF the original variable decl has a name, create an appropriate new name for the new decl and attach it to the new decl. */ - if (DECL_NAME (orig_decl) && IDENTIFIER_POINTER (DECL_NAME (orig_decl))) { @@ -1463,7 +1454,8 @@ make_new_vars_1 (tree orig_decl, struct old_name = (char *) IDENTIFIER_POINTER (DECL_NAME (orig_decl)); len = strlen (old_name) + 6; new_name = (char *) xmalloc (len * sizeof (char)); - sprintf (new_name, "%s_%d", old_name, i); + sprintf (new_name, "%s_%d_%d", old_name, + SSA_NAME_VERSION (orig_ssa_name), i); /* Make sure there isn't anything else that already has that name. */ @@ -1476,29 +1468,30 @@ make_new_vars_1 (tree orig_decl, struct sprintf (tmp_name, "%s.%d", new_name, counter++); new_name = tmp_name; - id_node = get_identifier (new_name); - DECL_NAME (new_decl) = id_node; } - else - DECL_NAME (new_decl) = NULL; + + gcc_assert (new_name); /* Create the appropriate type for the new variable decl, and attach it. */ - + if (pointer_type_p) - { - pointer_type = build_pointer_type (new_type); - TREE_TYPE (new_decl) = pointer_type; - } + new_type = build_pointer_type (new_type); else if (array_type_p) - { - array_type = build_array_type (new_type, + new_type = build_array_type (new_type, TYPE_DOMAIN (TREE_TYPE (orig_decl))); - TREE_TYPE (new_decl) = array_type; - } - else - TREE_TYPE (new_decl) = new_type; + new_decl = create_tmp_var (new_type, new_name); + if (referenced_vars) + add_referenced_tmp_var (new_decl); + + /* If original var was readonly, we make new vars also readonly + and gave them default definitions of themselves. */ + + if (TREE_CODE (orig_decl) == VAR_DECL && + TREE_READONLY (orig_decl)) + TREE_READONLY (new_decl) = 1; + /* Stuff the new var decl into a struct_tree_list node, and append it to the front of the list created so far. */ @@ -1567,374 +1560,236 @@ build_new_type (struct struct_tree_list return new_type; } + static void replace_var_types (tree old_record, tree new_record) { - struct cgraph_varpool_node *current_varpool; - struct cgraph_varpool_node *first_new_var = NULL; - struct cgraph_node *c_node; - tree var_decl; - tree var_type; - tree var_list; - tree new_type; + unsigned i; + struct cgraph_node *node; struct struct_tree_list *type_nest; struct struct_tree_list *tmp_node; struct struct_tree_list *donelist = NULL; + tree new_type; - /* Go through global variables... */ + cfun = NULL; + bitmap_obstack_initialize (NULL); - for (current_varpool = cgraph_varpool_nodes_queue; - current_varpool && (current_varpool != first_new_var); - current_varpool = current_varpool->next) - { - var_decl = current_varpool->decl; - if (!var_decl || TREE_CODE (var_decl) != VAR_DECL) - continue; + for (node = cgraph_nodes; node; node = node->next) + if (node->analyzed) + { + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + current_function_decl = node->decl; + if (in_ssa_p) + { + for (i = 1; i < num_ssa_names; i++) + { + tree ssa_name = ssa_name (i) ; + tree ssa_name_type; + + if (debug_mode) + debug_tree (ssa_name); + ssa_name_type = TREE_TYPE (ssa_name); + + type_nest = NULL; + while (POINTER_TYPE_P (ssa_name_type) + || TREE_CODE (ssa_name_type) == ARRAY_TYPE) + { + tmp_node = (struct struct_tree_list *) xmalloc + (sizeof + (struct struct_tree_list)); + tmp_node->data = ssa_name_type; + tmp_node->next = type_nest; + type_nest = tmp_node; + ssa_name_type = TREE_TYPE (ssa_name_type); + } - var_type = TREE_TYPE (var_decl); + if (ssa_name_type && debug_mode) + debug_tree (ssa_name_type); - type_nest = NULL; - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = type_nest; - type_nest = tmp_node; - var_type = TREE_TYPE (var_type); - } + if (similar_struct_decls_p (ssa_name_type, old_record)) + { + if (debug_mode) + fprintf (stderr, "\nssa_name_type is similar to old_record\n"); + new_type = build_new_type (type_nest, new_record); + TREE_TYPE (ssa_name) = new_type; + TREE_TYPE (SSA_NAME_VAR (ssa_name)) = new_type; + + if (ssa_name && debug_mode) + debug_tree (ssa_name); + } + else if (TREE_CODE (ssa_name_type) == RECORD_TYPE) + { + + tmp_node = (struct struct_tree_list *) xmalloc + (sizeof + (struct struct_tree_list)); + tmp_node->data = ssa_name_type; + tmp_node->next = NULL; + replace_old_field_types (tmp_node, new_record, old_record, + &donelist); + } + } + } + /* free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS);*/ + current_function_decl = NULL; + pop_cfun (); + } + bitmap_obstack_release (NULL); +} - if (similar_struct_decls_p (var_type, old_record)) - { - new_type = build_new_type (type_nest, new_record); - TREE_TYPE (var_decl) = new_type; - } - else if (TREE_CODE (var_type) == RECORD_TYPE) - { - - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = NULL; - replace_old_field_types (tmp_node, new_record, old_record, - &donelist); - } - } +static int +find_struct_field (tree field, struct data_structure *struct_data) +{ + int i; - /* For each function in the call graph... */ + gcc_assert (field && struct_data); - for (c_node = cgraph_nodes; c_node; c_node = c_node->next) + for (i = 0; i < struct_data->num_fields; i++) { - struct function *func = DECL_STRUCT_FUNCTION (c_node->decl); + + if (struct_data->fields[i].decl == field) + return i; + } - /* Check the type of the function */ + return -1; +} - var_type = TREE_TYPE (TREE_TYPE (c_node->decl)); +/* This function returns a new variable of type TYPE + found in STRUCT_DATA. If not found, returns null. */ +static tree +find_new_var_of_type (struct struct_tree_list *struct_data, + tree type) +{ + bool found = false; + struct struct_tree_list *cur_var; + tree ret = NULL; - type_nest = NULL; - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = type_nest; - type_nest = tmp_node; - var_type = TREE_TYPE (var_type); - } - - if (similar_struct_decls_p (var_type, old_record)) + for (cur_var = struct_data; cur_var && !found; + cur_var = cur_var->next) + { + if (TREE_TYPE (cur_var->data) == type) { - new_type = build_new_type (type_nest, new_record); - TREE_TYPE (TREE_TYPE (c_node->decl)) = new_type; + found = true; + ret = cur_var->data; } + } - /* Check the return type of the function */ + return ret; +} - if (DECL_RESULT (c_node->decl)) - { - var_type = TREE_TYPE (DECL_RESULT (c_node->decl)); +/* If VAR has initial value, this function copy it + to newly created variables, received in NEW_VARS_LIST. + STRUCT_DATA represent VAR's type; it's needed here + for mapping of old struct type to new types. */ +static void +copy_struct_init (tree var, struct data_structure *struct_data, + struct struct_tree_list *new_vars_list) +{ + unsigned HOST_WIDE_INT ix; + tree field, val; + /* int i; + struct data_field_entry cur_field; */ + struct field_map *new_mapping; + tree new_type; + tree new_var; + tree init = DECL_INITIAL (SSA_NAME_VAR (var)); - type_nest = NULL; - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = type_nest; - type_nest = tmp_node; - var_type = TREE_TYPE (var_type); - } - - if (similar_struct_decls_p (var_type, old_record)) - { - new_type = build_new_type (type_nest, new_record); - TREE_TYPE (DECL_RESULT (c_node->decl)) = new_type; - } - } - - - /* Go through the arguments for each function... */ + gcc_assert (var && new_vars_list && struct_data); - for (var_decl = DECL_ARGUMENTS (c_node->decl); var_decl; - var_decl = TREE_CHAIN (var_decl)) - { - var_type = TREE_TYPE (var_decl); + if (!init) + return; - type_nest = NULL; - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = type_nest; - type_nest = tmp_node; - var_type = TREE_TYPE (var_type); - } + gcc_assert (TREE_CODE (init) == CONSTRUCTOR); - if (similar_struct_decls_p (var_type, old_record)) - { - new_type = build_new_type (type_nest, new_record); - TREE_TYPE (var_decl) = new_type; - } - else if (TREE_CODE (var_type) == RECORD_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = NULL; - replace_old_field_types (tmp_node, new_record, old_record, - &donelist); - } - } + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix, field, val) + { + int index; - if (! func) - continue; + index = find_struct_field (field, struct_data); + + gcc_assert (index != -1); - /* If the function has a body, go through the local variables for - the function... */ + new_mapping = struct_data->fields[index].new_mapping; + + if (new_mapping->contains || new_mapping->containing_type) + fatal_error ("Structure has substructs or superstructs."); - for (var_list = func->unexpanded_var_list; var_list; - var_list = TREE_CHAIN (var_list)) - { - var_decl = TREE_VALUE (var_list); - if (TREE_CODE (var_decl) == VAR_DECL) - { - var_type = TREE_TYPE (var_decl); + new_type = new_mapping->decl; - type_nest = NULL; - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = type_nest; - type_nest = tmp_node; - var_type = TREE_TYPE (var_type); - } + new_var = find_new_var_of_type (new_vars_list, new_type); + + gcc_assert (new_var); - if (similar_struct_decls_p (var_type, old_record)) - { - new_type = build_new_type (type_nest, new_record); - TREE_TYPE (var_decl) = new_type; - } - else if (TREE_CODE (var_type) == RECORD_TYPE) - { - tmp_node = (struct struct_tree_list *) xmalloc - (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = NULL; - replace_old_field_types (tmp_node, new_record, old_record, - &donelist); - } - } + /* in new_var find field equal to field of original var. */ + + if (!DECL_INITIAL (new_var)) + DECL_INITIAL (new_var) = build_constructor_single (new_type, field, val); + else + { + tree new_init = DECL_INITIAL (new_var); + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init), field, val); } } } -/* This function finds every global or local variable or parameter of the - type described in STRUCT_DATA (the struct type we are peeling), and - for each original variable found, creates a set of new variables, one for - each newly peeled struct type. It also puts the newly created variables - into the appropriate list (global variables vs. local variables vs. local - parameters). */ - +/* For each variable of structure type in current function (cfun) + this function generate new variable(s) to replace it. */ static struct new_var_data * -create_new_var_decls (struct data_structure *struct_data) +create_new_vars (struct struct_list *data_struct_list) { - struct struct_tree_list *current; - struct struct_tree_list *new_vars_list; - struct new_var_data *return_list = NULL; + unsigned i; + struct struct_list *cur_struct; struct new_var_data *tmp_node; - struct cgraph_varpool_node *current_varpool; - struct cgraph_varpool_node *first_new_var = NULL; - struct cgraph_node *c_node; - tree var_decl; - tree var_type; - tree var_list; - tree tmp; - struct struct_tree_list *donelist = NULL; - - /* Go through global variables,,, */ - - for (current_varpool = cgraph_varpool_nodes_queue; - current_varpool && (current_varpool != first_new_var); - current_varpool = current_varpool->next_needed) - { - var_decl = current_varpool->decl; - if (!var_decl || TREE_CODE (var_decl) != VAR_DECL) - continue; - - var_type = TREE_TYPE (var_decl); - - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - var_type = TREE_TYPE (var_type); - - if (similar_struct_decls_p (var_type, struct_data->decl)) - { - struct cgraph_varpool_node *new_node; - struct struct_tree_list *current; - - new_vars_list = make_new_vars_1 (var_decl, struct_data); - tmp_node = (struct new_var_data *) xmalloc (sizeof - (struct new_var_data)); - tmp_node->orig_var = var_decl; - tmp_node->new_vars = new_vars_list; - tmp_node->next = NULL; - add_to_vars_list (tmp_node, &return_list); - - /* Add the newly created global variahles (NEW_VARS_LIST) - to the cgraph varpool list at its end. */ - for (current = new_vars_list; current; current = current->next) - { - tree v_decl = current->data; - - new_node = cgraph_varpool_node (v_decl); - notice_global_symbol (v_decl); - cgraph_varpool_mark_needed_node (new_node); - cgraph_varpool_finalize_decl (v_decl); - if (! first_new_var) - first_new_var = new_node; - } - } - else if (TREE_CODE (var_type) == RECORD_TYPE) - { - struct struct_tree_list *tmp_node; - tmp_node = (struct struct_tree_list *) xmalloc (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = NULL; - replace_old_field_types (tmp_node, struct_data->new_types->data, - struct_data->decl, &donelist); - } - } - - /* For each function in the call graph... */ + struct struct_tree_list *new_vars_list = NULL; + struct new_var_data *return_list = NULL; - for (c_node = cgraph_nodes; c_node; c_node = c_node->next) + if (in_ssa_p) { - struct function *func = DECL_STRUCT_FUNCTION (c_node->decl); - - /* Go through the arguments for each function... */ - - for (var_decl = DECL_ARGUMENTS (c_node->decl); var_decl; - var_decl = TREE_CHAIN (var_decl)) + for (i = 1; i < num_ssa_names; i++) { - var_type = TREE_TYPE (var_decl); - - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - var_type = TREE_TYPE (var_type); - - if (similar_struct_decls_p (var_type, struct_data->decl)) - { - new_vars_list = make_new_vars_1 (var_decl, struct_data); - tmp_node = (struct new_var_data *) xmalloc (sizeof - (struct new_var_data)); - tmp_node->orig_var = var_decl; - tmp_node->new_vars = new_vars_list; - tmp_node->next = NULL; - add_to_vars_list (tmp_node, &return_list); - tmp = TREE_CHAIN (var_decl); - for (current = new_vars_list; current; current = current->next) - { - TREE_CHAIN (var_decl) = current->data; - var_decl = current->data; - } - TREE_CHAIN (var_decl) = tmp; - } - else if (TREE_CODE (var_type) == RECORD_TYPE) + tree ssa_name = ssa_name (i) ; + tree ssa_name_type; + + if (debug_mode) + debug_tree (ssa_name); + ssa_name_type = TREE_TYPE (ssa_name); + + while (POINTER_TYPE_P (ssa_name_type) + || TREE_CODE (ssa_name_type) == ARRAY_TYPE) + ssa_name_type = TREE_TYPE (ssa_name_type); + + for (cur_struct = data_struct_list; cur_struct; + cur_struct = cur_struct->next) { - struct struct_tree_list * tmp_node; - tmp_node = (struct struct_tree_list *) xmalloc (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = NULL; - replace_old_field_types (tmp_node, struct_data->new_types->data, - struct_data->decl, &donelist); - } - } - if (! func) - continue; + struct data_structure *struct_data = cur_struct->struct_data; - /* If the function has a body, go through the local variables for - the function... */ + if (similar_struct_decls_p (ssa_name_type, struct_data->decl)) + { + new_vars_list = make_new_vars_1 (ssa_name, struct_data); - for (var_list = func->unexpanded_var_list; var_list; - var_list = TREE_CHAIN (var_list)) - { - var_decl = TREE_VALUE (var_list); - if (TREE_CODE (var_decl) == VAR_DECL) - { - var_type = TREE_TYPE (var_decl); + /* Take care of initialized structs. */ + copy_struct_init (ssa_name, struct_data, new_vars_list); - while (POINTER_TYPE_P (var_type) - || TREE_CODE (var_type) == ARRAY_TYPE) - var_type = TREE_TYPE (var_type); - - if (similar_struct_decls_p (var_type, struct_data->decl)) - { - new_vars_list = make_new_vars_1 (var_decl, struct_data); tmp_node = (struct new_var_data *) xmalloc (sizeof - (struct new_var_data)); - tmp_node->orig_var = var_decl; + (struct new_var_data)); + tmp_node->orig_var = ssa_name; + tmp_node->new_vars = new_vars_list; tmp_node->next = NULL; add_to_vars_list (tmp_node, &return_list); - var_list = insert_into_var_list (new_vars_list, var_list, - var_decl); - } - else if (TREE_CODE (var_type) == RECORD_TYPE) - { - struct struct_tree_list *tmp_node; - tmp_node = (struct struct_tree_list *) xmalloc (sizeof - (struct struct_tree_list)); - tmp_node->data = var_type; - tmp_node->next = NULL; - replace_old_field_types (tmp_node, - struct_data->new_types->data, - struct_data->decl, &donelist); + + break; } } } - } + } + + if (return_list && debug_mode) + print_new_vars (return_list); /* Return a list of all newly created variables. */ - return return_list; } @@ -2919,18 +2781,46 @@ create_new_mallocs (struct struct_list * } /* end function create_new_mallocs */ + +/* This function checks to see if tree LHS is one of the original + variables of listed in NEW_VARS. If such variable is found, this + function returns it. */ + +static struct new_var_data * +search_lhs_for_struct_vars (tree stmt, tree lhs, struct new_var_data *new_vars) +{ + ssa_op_iter iter; + tree op; + struct new_var_data *current; + + FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_VMAYDEF|SSA_OP_VMUSTDEF) + { + if (SSA_NAME_VAR (op) == lhs) + { + for (current = new_vars; current; current = current->next) + { + if (current->orig_var == op) + return current; + } + } + } + + return NULL; +} + /* This function checks to see if tree RHS contains any of the original - variables of the a type listed in DATA_STRUCT_LIST, for which we created - new variables. If so, it returns a list of each such original variable - found. */ + variables listed in NEW_VARS. If so, it returns a list of such + original variable found. */ static struct struct_tree_list * -search_rhs_for_struct_vars (tree rhs, struct struct_list *data_struct_list, - struct new_var_data *new_vars) +search_rhs_for_struct_vars (tree stmt, tree rhs, struct new_var_data *new_vars) { struct struct_tree_list *return_list = NULL; struct struct_tree_list *tmp_node; struct struct_tree_list *tmp_list; + ssa_op_iter iter; + tree op; + switch (TREE_CODE (rhs)) { @@ -2940,21 +2830,29 @@ search_rhs_for_struct_vars (tree rhs, st struct new_var_data *current; bool found = false; - for (current = new_vars; current && !found; current = current->next) - if (rhs == current->orig_var) - found = true; - - if (found) - { - tmp_node = (struct struct_tree_list *) xmalloc (sizeof - (struct struct_tree_list)); - tmp_node->data = rhs; - tmp_node->next = return_list; - return_list = tmp_node; + FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VUSE|SSA_OP_VMAYUSE|SSA_OP_USE) + { + if (SSA_NAME_VAR (op) == rhs) + { + for (current = new_vars; current && !found; current = current->next) + { + if (current->orig_var == op) + { + found = true; + tmp_node = (struct struct_tree_list *) xmalloc (sizeof + (struct struct_tree_list)); + tmp_node->data = current->orig_var; + tmp_node->next = return_list; + return_list = tmp_node; + break; + } + } + } + if (found) + break; } - - break; } + break; case COMPONENT_REF: case INDIRECT_REF: case FIELD_DECL: @@ -2970,14 +2868,13 @@ search_rhs_for_struct_vars (tree rhs, st tree t = TREE_OPERAND (rhs, i); if (t) { - tmp_list = search_rhs_for_struct_vars (t, data_struct_list, - new_vars); + tmp_list = search_rhs_for_struct_vars (stmt, t, new_vars); if (tmp_list) add_to_types_list (tmp_list, &return_list); } } - break; } + break; } return return_list; @@ -3011,8 +2908,80 @@ equivalent_types_p (tree type1, tree typ return ret_value; } +/* Given and OLD_RHS of an OLD_TYPE, find the newly create var + with which we can substitute OLD_RHS. */ + +static struct struct_tree_list * +find_var_of_given_type (tree old_type, tree new_type, + struct new_var_data *new_vars, + tree old_rhs, struct struct_tree_list *rhs_vars) +{ + /* int i; */ + struct new_var_data *current; + /* struct new_var_data *cur_var; */ + struct struct_tree_list *rhs_var; + bool found; + tree tmp_type; + struct struct_tree_list *cur; + + /* + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (old_rhs)); i++) + find_var_of_given_type (old_type, new_type, new_vars, + TREE_OPERAND (old_rhs, i), rhs_vars); + */ + + tmp_type = new_type; + while (POINTER_TYPE_P (tmp_type) + || TREE_CODE (tmp_type) == ARRAY_TYPE) + tmp_type = TREE_TYPE (tmp_type); + + switch (TREE_CODE (old_rhs)) + { + case CONVERT_EXPR: + case NOP_EXPR: + { + if (TREE_TYPE (old_rhs) == old_type) + TREE_TYPE (old_rhs) = new_type; + break; + } + case VAR_DECL: + case PARM_DECL: + { + if (equivalent_types_p (TREE_TYPE (old_rhs), old_type)) + { + found = false; + for (rhs_var = rhs_vars; rhs_var && !found; + rhs_var = rhs_var->next) + { + if (SSA_NAME_VAR (rhs_var->data) == old_rhs) + { + for (current = new_vars; current && !found; + current = current->next) + { + if (current->orig_var == rhs_var->data) + { + for (cur = current->new_vars; cur && !found; cur = cur->next) + { + if (equivalent_types_p (TREE_TYPE (cur->data), new_type) + || similar_struct_decls_p (TREE_TYPE (cur->data), + tmp_type)) + return cur; + } + } + } + } + } + } + break; + } + default: + break; + } + return NULL; +} + /* Given and OLD_RHS of an OLD_TYPE, start with a NEW_RHS that is - a copy of the OLD_RHS, but then find the original var in for which + a copy of the OLD_RHS, but then find the original var for which we created new vars, and which corresponds to the OLD_RHS; replace the old var with the appropriate newly created var (one whose type is NEW_TYPE). Call self recursively on all tree_operands of NEW_RHS, @@ -3022,20 +2991,25 @@ equivalent_types_p (tree type1, tree typ static void find_and_substitute_types_and_vars (tree old_type, tree new_type, struct new_var_data *new_vars, - tree *new_rhs, tree old_rhs) + tree *new_rhs, tree old_rhs, + struct struct_tree_list *rhs_vars) { int i; - struct struct_tree_list *current; - struct new_var_data *cur_var; + struct new_var_data *current; + /* struct new_var_data *cur_var; */ + struct struct_tree_list *rhs_var; bool found; tree tmp_type; + struct struct_tree_list *cur; if (! (*new_rhs)) return; - + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (*new_rhs)); i++) - find_and_substitute_types_and_vars (old_type, new_type, new_vars, - &TREE_OPERAND (*new_rhs, i), old_rhs); + { + find_and_substitute_types_and_vars (old_type, new_type, new_vars, + &TREE_OPERAND (*new_rhs, i), old_rhs, rhs_vars); + } tmp_type = new_type; while (POINTER_TYPE_P (tmp_type) @@ -3057,21 +3031,34 @@ find_and_substitute_types_and_vars (tree if (equivalent_types_p (TREE_TYPE (*new_rhs), old_type)) { found = false; - for (cur_var = new_vars; cur_var && !found; - cur_var = cur_var->next) - if (cur_var->orig_var == *new_rhs - || cur_var->orig_var == old_rhs) - { - for (current = cur_var->new_vars; current && !found; - current = current->next) - if (equivalent_types_p (TREE_TYPE (current->data), new_type) - || similar_struct_decls_p (TREE_TYPE (current->data), - tmp_type)) + for (rhs_var = rhs_vars; rhs_var && !found; + rhs_var = rhs_var->next) + { + if (SSA_NAME_VAR (rhs_var->data) == *new_rhs + || SSA_NAME_VAR (rhs_var->data) == old_rhs) + { + for (current = new_vars; current && !found; + current = current->next) { - *new_rhs = current->data; - found = true; + if (current->orig_var == rhs_var->data) + { + for (cur = current->new_vars; cur && !found; cur = cur->next) + { + if (equivalent_types_p (TREE_TYPE (cur->data), new_type) + || similar_struct_decls_p (TREE_TYPE (cur->data), + tmp_type)) + { + *new_rhs = cur->data; + found = true; + fprintf (stderr, "\nfound:"); + print_generic_stmt (stderr, current->orig_var, 0); + print_generic_stmt (stderr, cur->data, 0); + } + } + } } - } + } + } } break; } @@ -3111,21 +3098,13 @@ recursively_copy_node (tree old_node) variables in the rhs that were of the original struct type. */ static tree -build_new_stmts (tree lhs, struct new_var_data *new_vars, tree stmt, - tree fn_decl, struct struct_list *data_struct_list) +build_new_stmts (tree lhs, struct struct_tree_list *rhs_vars, + struct new_var_data *new_vars, tree stmt) { tree new_stmt_list = NULL_TREE; tree tmp_lhs; struct struct_tree_list *cur_lhs; struct new_var_data *cur_var; - struct function *save_cfun; - tree save_fn_decl; - - save_cfun = cfun; - save_fn_decl = current_function_decl; - - current_function_decl = fn_decl; - cfun = DECL_STRUCT_FUNCTION (fn_decl); if (TREE_CODE (lhs) == COMPONENT_REF) { @@ -3140,10 +3119,8 @@ build_new_stmts (tree lhs, struct new_va else tmp_lhs = lhs; - /* Find the lhs var in the new_vars list */ - - for (cur_var = new_vars; cur_var && cur_var->orig_var != tmp_lhs; - cur_var = cur_var->next); + /* Find the lhs var in the new_vars list. */ + cur_var = search_lhs_for_struct_vars (stmt, tmp_lhs, new_vars); if (!cur_var) { @@ -3154,8 +3131,7 @@ build_new_stmts (tree lhs, struct new_va tree old_var; tree old_rhs = TREE_OPERAND (stmt, 1); - rhs_vars = search_rhs_for_struct_vars (old_rhs, data_struct_list, - new_vars); + rhs_vars = search_rhs_for_struct_vars (stmt, old_rhs, new_vars); if (!rhs_vars) fatal_error ("Can't find correct number of structs in rhs."); @@ -3182,12 +3158,12 @@ build_new_stmts (tree lhs, struct new_va new_lhs = create_tmp_var_raw (new_type, NULL); gimple_add_tmp_var (new_lhs); new_rhs = copy_node (old_rhs); - if (DECL_P (new_rhs)) - new_rhs->decl.rtl = NULL; + if (DECL_P (new_rhs) && HAS_RTL_P (new_rhs)) + SET_DECL_RTL (new_rhs, NULL); find_and_substitute_types_and_vars (old_type, new_type, new_vars, - &new_rhs, old_rhs); - new_stmt = build (MODIFY_EXPR, TREE_TYPE (new_lhs), + &new_rhs, old_rhs, rhs_vars); + new_stmt = build2 (MODIFY_EXPR, TREE_TYPE (new_lhs), new_lhs, new_rhs); if (!new_stmt_list) new_stmt_list = alloc_stmt_list (); @@ -3202,63 +3178,29 @@ build_new_stmts (tree lhs, struct new_va tree new_var_decl = cur_lhs->data; tree new_type = TREE_TYPE (new_var_decl); tree old_type = TREE_TYPE (cur_var->orig_var); - tree old_rhs = TREE_OPERAND (stmt, 1); - tree new_rhs = recursively_copy_node (old_rhs); + tree old_rhs = TREE_OPERAND (stmt, 1); + tree new_rhs = NULL_TREE; tree new_lhs; + struct struct_tree_list *cur_rhs; + new_lhs = new_var_decl; - if (lhs == tmp_lhs) - new_lhs = new_var_decl; - else if (TREE_CODE (lhs) == INDIRECT_REF) - new_lhs = lang_hooks.optimize.build_pointer_ref (cur_lhs->data, ""); - else if (TREE_CODE (lhs) == ARRAY_REF) - { - new_lhs = copy_node (lhs); + cur_rhs = find_var_of_given_type (old_type, new_type, + new_vars, old_rhs, rhs_vars); + gcc_assert (cur_rhs); + + new_rhs = cur_rhs->data; - if (DECL_P (new_lhs)) - new_lhs->decl.rtl = NULL; + new_stmt = build2 (MODIFY_EXPR, TREE_TYPE (new_lhs), + new_lhs, new_rhs); - find_and_substitute_types_and_vars (old_type, new_type, new_vars, - &new_lhs, lhs); - } - else - { - tree field_identifier = TREE_OPERAND (lhs, 1); - - if (TREE_CODE (field_identifier) == INDIRECT_REF) - field_identifier = TREE_OPERAND (field_identifier, 0); - - if (TREE_CODE (field_identifier) != FIELD_DECL) - fatal_error ("Expected FIELD_DECL; found something else."); - - field_identifier = DECL_NAME (field_identifier); + update_stmt (new_stmt); + mark_new_vars_to_rename (new_stmt); - if (lang_hooks.optimize.lookup_field (TREE_TYPE (cur_lhs->data), field_identifier)) - new_lhs = lang_hooks.optimize.build_field_reference (lang_hooks.optimize.build_pointer_ref (cur_lhs->data, - ""), - field_identifier); - else - { - new_lhs = lhs; - } - } - - if (DECL_P (new_rhs)) - new_rhs->decl.rtl = NULL; - - find_and_substitute_types_and_vars (old_type, new_type, new_vars, - &new_rhs, old_rhs); - - new_stmt = build (MODIFY_EXPR, TREE_TYPE (new_lhs), - new_lhs, new_rhs); - if (!new_stmt_list) new_stmt_list = alloc_stmt_list (); - append_to_statement_list (new_stmt, &new_stmt_list); + append_to_statement_list_force (new_stmt, &new_stmt_list); } - cfun = save_cfun; - current_function_decl = save_fn_decl; - return new_stmt_list; } @@ -3457,28 +3399,70 @@ update_struct_offset (struct struct_list current_function_decl = save_fn_decl; } -/* This function takes two lists of type new_var_data, prepends NEW_LIST to - RETURN_LIST, and modifies RETURN_LIST to be the newly combined list. */ +/* This function is helper for update_field_accesses. + Given VAR as it appear in stmt, it looks for new_var_data + correspondent to this VAR's ssa_name as it appear in STMT + virtual operands. It returns found new_var_data, and null otherwise. */ -static void -append_to_var_list (struct new_var_data *new_list, - struct new_var_data **return_list) +static struct new_var_data * +find_orig_variable (tree var, struct new_var_data *new_vars, int arg_position, tree stmt) { - struct new_var_data *current; + ssa_op_iter iter; + tree op; + bool found = false; + tree ssa_name = NULL; + struct new_var_data *cur_var; - if (!new_list) - return; - else if (! *return_list) - *return_list = new_list; - else + if (!stmt || !var) + return NULL; + if (arg_position != 0 && arg_position != 1) + return NULL; + + + if (arg_position == 0) { - for (current = *return_list; current && current->next; - current = current->next); - current->next = new_list; + FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF) + if (SSA_NAME_VAR (op) == var) + { + found = true; + ssa_name = op; + break; + } + + if (found) + for (cur_var = new_vars; cur_var; + cur_var = cur_var->next) + { + if (cur_var->orig_var == ssa_name) + return cur_var; + } + + return NULL; + } + else + { + FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VUSE) + if (SSA_NAME_VAR (op) == var) + { + found = true; + ssa_name = op; + break; + } + + if (found) + for (cur_var = new_vars; cur_var; + cur_var = cur_var->next) + { + if (cur_var->orig_var == ssa_name) + return cur_var; + } + + return NULL; } + } -/* This function goes to every place where a field in the original struct +/* This function goes to every place where a field in the original struct (STRUCT_DATA) is accessed, and updates the field access code to correctly reflect the new struct hierarchy, types, variables, etc. */ @@ -3487,15 +3471,11 @@ update_field_accesses (struct struct_lis struct new_var_data *new_vars) { int i; - struct function *save_cfun; struct struct_list *cur_struct; struct data_field_entry cur_field; struct new_var_data *cur_var; + struct new_var_data *found_var; tree new_stmt_list = NULL_TREE; - tree save_fn_decl; - - save_cfun = cfun; - save_fn_decl = current_function_decl; for (cur_struct = data_struct_list; cur_struct; cur_struct = cur_struct->next) @@ -3517,7 +3497,7 @@ update_field_accesses (struct struct_lis tree arg0; tree arg1; tree old_var; - tree new_access; + tree new_access = NULL_TREE; tree field_identifier; tree outer_tree; bool found = false; @@ -3530,6 +3510,7 @@ update_field_accesses (struct struct_lis tree mem_ref_index = NULL_TREE; tree array_ref_index = NULL_TREE; int arg_position; + struct struct_tree_list *current; new_stmt_list = NULL_TREE; @@ -3539,6 +3520,11 @@ update_field_accesses (struct struct_lis continue; outer_tree = cur_access->stmt; + + /* Skip those accesses that are not in current function. */ + if (cur_access->context != cfun) + continue; + if (TREE_OPERAND (outer_tree, 0) == access) arg_position = 0; else if (TREE_OPERAND (outer_tree, 1) == access) @@ -3590,17 +3576,14 @@ update_field_accesses (struct struct_lis break; } - cfun = cur_access->context; - current_function_decl = cfun->decl; - /* find whose arg1 is field decl for cur_field */ if (TREE_CODE (arg0) == INDIRECT_REF) is_indirect_ref = true; - else if (TREE_CODE (arg0) == MEM_REF) + else if (TREE_CODE (arg0) == TARGET_MEM_REF) { is_mem_ref = true; - mem_ref_index = TREE_OPERAND (arg0, 1); + mem_ref_index = TREE_OPERAND (arg0, 2); } else if (TREE_CODE (arg0) == ARRAY_REF) { @@ -3618,11 +3601,49 @@ update_field_accesses (struct struct_lis old_var = arg0; else old_var = TREE_OPERAND (arg0, 0); + + + found_var = find_orig_variable (old_var, new_vars, arg_position, outer_tree); + if (!found_var) + fatal_error ("Original variable was not found for fields access."); + + for (current = found_var->new_vars; current; + current = current->next) + { + tree var_type = TREE_TYPE (current->data); + + while (POINTER_TYPE_P (var_type)) + var_type = TREE_TYPE (var_type); + + if (TREE_CODE (var_type) == ARRAY_TYPE) + var_type = TREE_TYPE (var_type); + + if (similar_struct_decls_p (var_type, new_mapping->decl)) + { + tree new_var = current->data; + + + if (new_mapping->contains || new_mapping->containing_type) + fatal_error ("Structure has substructs or superstructs."); + + field_identifier = DECL_NAME (arg1); + new_access = lang_hooks.optimize.build_field_reference + (new_var, field_identifier); + + break; + } + } + + TREE_OPERAND (outer_tree, arg_position) = new_access; + update_stmt (outer_tree); + mark_new_vars_to_rename (outer_tree); + continue; + for (cur_var = new_vars; cur_var && !found; cur_var = cur_var->next) { - if (old_var == cur_var->orig_var) + if (old_var == SSA_NAME_VAR (cur_var->orig_var)) { struct struct_tree_list *current; found = true; @@ -3765,25 +3790,20 @@ update_field_accesses (struct struct_lis } } - cfun = save_cfun; - current_function_decl = save_fn_decl; } + static void -collect_struct_use_data (struct struct_list *data_struct_list, +collect_struct_use_data (struct cgraph_node *c_node, struct struct_list *data_struct_list, struct new_var_data *new_vars_list, struct use_struct **uses_list) { - struct cgraph_node *c_node; basic_block this_bb; struct use_struct *last_use = NULL; struct use_struct *first_use_in_fn; struct use_struct *prev_use, *cur_use; - struct function *func; + struct function *func = DECL_STRUCT_FUNCTION (c_node->decl); struct malloc_struct *cur_malloc; - struct function *save_cfun; - tree fn_decl; - tree save_fn_decl; bool function_contains_malloc; block_stmt_iterator bsi; tree cur_stmt; @@ -3792,325 +3812,305 @@ collect_struct_use_data (struct struct_l struct struct_tree_list *tmp_node_1; struct struct_tree_list *prev, *cur; - save_cfun = cfun; - save_fn_decl = current_function_decl; - - for (c_node = cgraph_nodes; c_node; c_node = c_node->next) - { - if (!c_node->next_clone) - { - func = DECL_STRUCT_FUNCTION (c_node->decl); - fn_decl = c_node->decl; - if (func) - { - /* Check to see if we need to do any malloc work in this - function. */ + /* Check to see if we need to do any malloc work in this + function. */ - function_contains_malloc = false; - for (cur_malloc = malloc_data_list; - cur_malloc && !function_contains_malloc; - cur_malloc = cur_malloc->next) - if (cur_malloc->context == fn_decl) - { - function_contains_malloc = true; - visited_nodes = pointer_set_create (); - } + function_contains_malloc = false; + for (cur_malloc = malloc_data_list; + cur_malloc && !function_contains_malloc; + cur_malloc = cur_malloc->next) + if (cur_malloc->context == c_node->decl) + { + function_contains_malloc = true; + visited_nodes = pointer_set_create (); + } - plus_modifies = NULL; - base_modifies = NULL; - first_use_in_fn = NULL; - prev_use = last_use; + plus_modifies = NULL; + base_modifies = NULL; + first_use_in_fn = NULL; + prev_use = last_use; - FOR_EACH_BB_FN (this_bb, func) - { - /* Collect malloc data, if appropriate. */ + FOR_EACH_BB_FN (this_bb, func) + { + /* Collect malloc data, if appropriate. */ - if (function_contains_malloc) - { - c_node->current_basic_block = this_bb; - walk_tree (&this_bb->stmt_list, record_malloc_1, c_node, - visited_nodes); - } + if (function_contains_malloc) + { + /* c_node->current_basic_block = this_bb; */ + walk_tree (&this_bb->stmt_list, record_malloc_1, c_node, + visited_nodes); + } - /* Go through all the statements in the function, looking for - those we might need to modify. */ + /* Go through all the statements in the function, looking for + those we might need to modify. */ - for (bsi = bsi_start (this_bb); !bsi_end_p (bsi); - bsi_next (&bsi)) - { - cur_stmt = bsi_stmt (bsi); - if (TREE_CODE (cur_stmt) == MODIFY_EXPR) - { - struct data_structure *struct_data = NULL; - tree lhs = TREE_OPERAND (cur_stmt, 0); - tree rhs = TREE_OPERAND (cur_stmt, 1); - bool is_part_of_malloc = false; + for (bsi = bsi_start (this_bb); !bsi_end_p (bsi); + bsi_next (&bsi)) + { + cur_stmt = bsi_stmt (bsi); + if (TREE_CODE (cur_stmt) == MODIFY_EXPR) + { + struct data_structure *struct_data = NULL; + tree lhs = TREE_OPERAND (cur_stmt, 0); + tree rhs = TREE_OPERAND (cur_stmt, 1); + bool is_part_of_malloc = false; - /* If stmt is part of a set of malloc statements, - skip it; it will be taken care of when we fix up - the mallocs. */ + /* If stmt is part of a set of malloc statements, + skip it; it will be taken care of when we fix up + the mallocs. */ - if (function_contains_malloc) - for (cur_malloc = malloc_data_list; - cur_malloc && !is_part_of_malloc; - cur_malloc = cur_malloc->next) - if (cur_malloc->context == fn_decl) - { - int idx; - for (idx = 0; idx < cur_malloc->num_calls; - idx++) - { - if (lhs == cur_malloc->malloc_list[idx].size_var - || lhs == cur_malloc->malloc_list[idx].result_var - || lhs == cur_malloc->malloc_list[idx].final_lhs) - is_part_of_malloc = true; - } - } + if (function_contains_malloc) + for (cur_malloc = malloc_data_list; + cur_malloc && !is_part_of_malloc; + cur_malloc = cur_malloc->next) + if (cur_malloc->context == c_node->decl) + { + int idx; + for (idx = 0; idx < cur_malloc->num_calls; + idx++) + { + if (lhs == cur_malloc->malloc_list[idx].size_var + || lhs == cur_malloc->malloc_list[idx].result_var + || lhs == cur_malloc->malloc_list[idx].final_lhs) + is_part_of_malloc = true; + } + } - if (!is_part_of_malloc) - { - tree lhs_type; - int pointer_levels_count = 0; + if (!is_part_of_malloc) + { + tree lhs_type; + int pointer_levels_count = 0; - /* Check to see if lhs is of an interesting - type. */ + /* Check to see if lhs is of an interesting + type. */ - lhs_type = TREE_TYPE (lhs); + lhs_type = TREE_TYPE (lhs); - while (POINTER_TYPE_P (lhs_type)) - { - pointer_levels_count++; - lhs_type = TREE_TYPE (lhs_type); - } + while (POINTER_TYPE_P (lhs_type)) + { + pointer_levels_count++; + lhs_type = TREE_TYPE (lhs_type); + } - if (TREE_CODE (lhs_type) == RECORD_TYPE) - { - struct struct_list *cur_struct; - - for (cur_struct = data_struct_list; - cur_struct && !struct_data; - cur_struct = cur_struct->next) - if (cur_struct->struct_data->decl == lhs_type - && cur_struct->struct_data->struct_clustering - && cur_struct->struct_data->struct_clustering->direct_access) - struct_data = cur_struct->struct_data; + if (TREE_CODE (lhs_type) == RECORD_TYPE) + { + struct struct_list *cur_struct; - } + for (cur_struct = data_struct_list; + cur_struct && !struct_data; + cur_struct = cur_struct->next) + if (cur_struct->struct_data->decl == lhs_type + && cur_struct->struct_data->struct_clustering + && cur_struct->struct_data->struct_clustering->direct_access) + struct_data = cur_struct->struct_data; + } - if (struct_data - && (TREE_CODE (rhs) == VAR_DECL - || TREE_CODE (rhs) == PARM_DECL)) - { - tmp_node_1 = (struct struct_tree_list *) - xmalloc (sizeof (struct struct_tree_list)); - tmp_node_1->data = cur_stmt; - tmp_node_1->next = base_modifies; - base_modifies = tmp_node_1; - } - else if (struct_data - && TREE_CODE (rhs) == PLUS_EXPR) - { - tmp_node_1 = (struct struct_tree_list *) - xmalloc (sizeof (struct struct_tree_list)); - tmp_node_1->data = cur_stmt; - tmp_node_1->next = plus_modifies; - plus_modifies = tmp_node_1; - } + if (struct_data + && (TREE_CODE (rhs) == VAR_DECL + || TREE_CODE (rhs) == PARM_DECL)) + { + tmp_node_1 = (struct struct_tree_list *) + xmalloc (sizeof (struct struct_tree_list)); + tmp_node_1->data = cur_stmt; + tmp_node_1->next = base_modifies; + base_modifies = tmp_node_1; + } + else if (struct_data + && TREE_CODE (rhs) == PLUS_EXPR) + { + tmp_node_1 = (struct struct_tree_list *) + xmalloc (sizeof (struct struct_tree_list)); + tmp_node_1->data = cur_stmt; + tmp_node_1->next = plus_modifies; + plus_modifies = tmp_node_1; + } - if (struct_data - && (TREE_CODE (rhs) == CONVERT_EXPR - || TREE_CODE (rhs) == NOP_EXPR) - && INTEGRAL_TYPE_P (TREE_TYPE - (TREE_OPERAND (rhs, 0)))) - { - /* We've found an offset conversion */ - /* OFFSET == INDEX * ELEMENT_SIZE */ - struct use_struct *offset; + if (struct_data + && (TREE_CODE (rhs) == CONVERT_EXPR + || TREE_CODE (rhs) == NOP_EXPR) + && INTEGRAL_TYPE_P (TREE_TYPE + (TREE_OPERAND (rhs, 0)))) + { + /* We've found an offset conversion */ + /* OFFSET == INDEX * ELEMENT_SIZE */ + struct use_struct *offset; - offset = (struct use_struct *) xmalloc - (sizeof (struct use_struct)); + offset = (struct use_struct *) xmalloc + (sizeof (struct use_struct)); - offset->lhs_use = false; - offset->lhs = lhs; - offset->rhs_vars = NULL; - offset->offset = rhs; - offset->stmt = cur_stmt; - offset->bb = this_bb; - offset->function = fn_decl; - offset->next = NULL; + offset->lhs_use = false; + offset->lhs = lhs; + offset->rhs_vars = NULL; + offset->offset = rhs; + offset->stmt = cur_stmt; + offset->bb = this_bb; + offset->function = c_node->decl; + offset->next = NULL; - if (!last_use) - (*uses_list) = offset; - else - last_use->next = offset; - last_use = offset; + if (!last_use) + (*uses_list) = offset; + else + last_use->next = offset; + last_use = offset; - if (!first_use_in_fn) - first_use_in_fn = offset; - } - else /* if (struct_data) */ - { - struct struct_tree_list *rhs_vars; + if (!first_use_in_fn) + first_use_in_fn = offset; + } + else /* if (struct_data) */ + { + struct struct_tree_list *rhs_vars; - rhs_vars = search_rhs_for_struct_vars (rhs, - data_struct_list, - new_vars_list); + rhs_vars = search_rhs_for_struct_vars (cur_stmt, rhs, + new_vars_list); - if (rhs_vars || struct_data) - { - /* We've found a "use" that needs to be - "updated. */ - - struct use_struct *use; - - use = (struct use_struct *) xmalloc - (sizeof (struct use_struct)); + if (rhs_vars || struct_data) + { + /* We've found a "use" that needs to be + "updated. */ - if (struct_data) - use->lhs_use = true; - else - use->lhs_use = false; - use->lhs = lhs; - use->rhs_vars = rhs_vars; - use->offset = NULL_TREE; - use->stmt = cur_stmt; - use->bb = this_bb; - use->function = fn_decl; - use->next = NULL; + struct use_struct *use; - if (!last_use) - (*uses_list) = use; - else - last_use->next = use; - last_use = use; + use = (struct use_struct *) xmalloc + (sizeof (struct use_struct)); - if (!first_use_in_fn) - first_use_in_fn = use; + if (struct_data) + use->lhs_use = true; + else + use->lhs_use = false; + use->lhs = lhs; + use->rhs_vars = rhs_vars; + use->offset = NULL_TREE; + use->stmt = cur_stmt; + use->bb = this_bb; + use->function = c_node->decl; + use->next = NULL; - } - } - } + if (!last_use) + (*uses_list) = use; + else + last_use->next = use; + last_use = use; + + if (!first_use_in_fn) + first_use_in_fn = use; + } } + } + } + } - } /* FOR_EACH_BB_FN */ + } /* FOR_EACH_BB_FN */ - /* Verify that every "offset" use is really an offset, i.e. actually - gets use in a base-plus-offset calculation. */ - - /* First, go through the plus_modifies stmt list and find the ones - where one argument is a 'base' variable, i.e. the argument is an - lhs in the base_modifies list. Remove other plus_expr stmts from - the list. */ + /* Verify that every "offset" use is really an offset, i.e. actually + gets use in a base-plus-offset calculation. */ + + /* First, go through the plus_modifies stmt list and find the ones + where one argument is a 'base' variable, i.e. the argument is an + lhs in the base_modifies list. Remove other plus_expr stmts from + the list. */ - prev = NULL; - for (cur = plus_modifies; cur; cur = cur->next) - { - struct struct_list *cur_struct; - tree plus_stmt = cur->data; - tree plus_expr = TREE_OPERAND (plus_stmt, 1); - tree arg0 = TREE_OPERAND (plus_expr, 0); - tree arg1 = TREE_OPERAND (plus_expr, 1); - struct struct_tree_list *tmp_ptr; - bool found = false; + prev = NULL; + for (cur = plus_modifies; cur; cur = cur->next) + { + struct struct_list *cur_struct; + tree plus_stmt = cur->data; + tree plus_expr = TREE_OPERAND (plus_stmt, 1); + tree arg0 = TREE_OPERAND (plus_expr, 0); + tree arg1 = TREE_OPERAND (plus_expr, 1); + struct struct_tree_list *tmp_ptr; + bool found = false; - for (tmp_ptr = base_modifies; tmp_ptr && !found; - tmp_ptr = tmp_ptr->next) - if (TREE_OPERAND (tmp_ptr->data, 0) == arg0 - || TREE_OPERAND (tmp_ptr->data, 0) == arg1) - found = 1; + for (tmp_ptr = base_modifies; tmp_ptr && !found; + tmp_ptr = tmp_ptr->next) + if (TREE_OPERAND (tmp_ptr->data, 0) == arg0 + || TREE_OPERAND (tmp_ptr->data, 0) == arg1) + found = 1; - if (!found) - { - tree type0 = TREE_TYPE (arg0); - tree type1 = TREE_TYPE (arg1); - - while (POINTER_TYPE_P (type0) - || TREE_CODE (type0) == ARRAY_TYPE) - type0 = TREE_TYPE (type0); + if (!found) + { + tree type0 = TREE_TYPE (arg0); + tree type1 = TREE_TYPE (arg1); - while (POINTER_TYPE_P (type1) - || TREE_CODE (type1) == ARRAY_TYPE) - type1 = TREE_TYPE (type1); + while (POINTER_TYPE_P (type0) + || TREE_CODE (type0) == ARRAY_TYPE) + type0 = TREE_TYPE (type0); + + while (POINTER_TYPE_P (type1) + || TREE_CODE (type1) == ARRAY_TYPE) + type1 = TREE_TYPE (type1); - if ((TREE_CODE (type0) == RECORD_TYPE) - || (TREE_CODE (type1) == RECORD_TYPE)) - for (cur_struct = data_struct_list; cur_struct && !found; - cur_struct = cur_struct->next) - { - if (similar_struct_decls_p (cur_struct->struct_data->decl, - type0) - || similar_struct_decls_p (cur_struct->struct_data->decl, - type1)) - found = true; - } - } + if ((TREE_CODE (type0) == RECORD_TYPE) + || (TREE_CODE (type1) == RECORD_TYPE)) + for (cur_struct = data_struct_list; cur_struct && !found; + cur_struct = cur_struct->next) + { + if (similar_struct_decls_p (cur_struct->struct_data->decl, + type0) + || similar_struct_decls_p (cur_struct->struct_data->decl, + type1)) + found = true; + } + } - if (!found) - { - if (!prev) - plus_modifies = cur->next; - else - prev->next = cur->next; - } - else - prev = cur; - } + if (!found) + { + if (!prev) + plus_modifies = cur->next; + else + prev->next = cur->next; + } + else + prev = cur; + } - /* Now every statement in the plus_modifies list is a base plus - offset calculation. Next, go through the convert uses found in - the current function, and remove all of the ones where the - 'offset' being converted is not used in a base-plus-offset - calculation. */ + /* Now every statement in the plus_modifies list is a base plus + offset calculation. Next, go through the convert uses found in + the current function, and remove all of the ones where the + 'offset' being converted is not used in a base-plus-offset + calculation. */ - for (cur_use = first_use_in_fn; cur_use; cur_use = cur_use->next) - { - tree convert_stmt = cur_use->stmt; - tree convert_lhs = TREE_OPERAND (convert_stmt, 0); - struct struct_tree_list *tmp_ptr; - bool found = false; + for (cur_use = first_use_in_fn; cur_use; cur_use = cur_use->next) + { + tree convert_stmt = cur_use->stmt; + tree convert_lhs = TREE_OPERAND (convert_stmt, 0); + struct struct_tree_list *tmp_ptr; + bool found = false; - if (!cur_use->offset) - { - prev_use = cur_use; - continue; - } + if (!cur_use->offset) + { + prev_use = cur_use; + continue; + } - for (tmp_ptr = plus_modifies; tmp_ptr && !found; - tmp_ptr = tmp_ptr->next) - if ((TREE_OPERAND (TREE_OPERAND (tmp_ptr->data, 1), 0) - == convert_lhs) - || (TREE_OPERAND (TREE_OPERAND (tmp_ptr->data, 1), 1) - == convert_lhs)) - found = true; + for (tmp_ptr = plus_modifies; tmp_ptr && !found; + tmp_ptr = tmp_ptr->next) + if ((TREE_OPERAND (TREE_OPERAND (tmp_ptr->data, 1), 0) + == convert_lhs) + || (TREE_OPERAND (TREE_OPERAND (tmp_ptr->data, 1), 1) + == convert_lhs)) + found = true; - if (!found) - { - if (!prev_use) - *uses_list = cur_use->next; - else - prev_use->next = cur_use->next; - } - else - prev_use = cur_use; - } - - /* Clean up malloc data collection stuff. */ - - if (function_contains_malloc) - { - pointer_set_destroy (visited_nodes); - visited_nodes = NULL; - } - - } /* if (func) */ + if (!found) + { + if (!prev_use) + *uses_list = cur_use->next; + else + prev_use->next = cur_use->next; } - } /* for (c_node = cgraph_nodes... */ - - cfun = save_cfun; - current_function_decl = save_fn_decl; - + else + prev_use = cur_use; + } + + /* Clean up malloc data collection stuff. */ + + if (function_contains_malloc) + { + pointer_set_destroy (visited_nodes); + visited_nodes = NULL; + } + } /* function update_code_in_functions */ static void @@ -4131,26 +4132,23 @@ update_struct_use_stmts (struct struct_l { tree_stmt_iterator *insertion_point = &(bsi.tsi); if (current->offset) - { - update_struct_offset (data_struct_list, new_vars_list, - current, insertion_point); - } + update_struct_offset (data_struct_list, new_vars_list, + current, insertion_point); else { tree new_stmt_list; - new_stmt_list = build_new_stmts (current->lhs, + new_stmt_list = build_new_stmts (current->lhs, + current->rhs_vars, new_vars_list, - current->stmt, - current->function, - data_struct_list); + current->stmt); if (new_stmt_list) { add_bb_info (current->bb, new_stmt_list); tsi_link_after (insertion_point, new_stmt_list, TSI_CONTINUE_LINKING); - } + } } } } @@ -4557,47 +4562,49 @@ replace_all_types_1 (tree *tp, int *walk for (tsi = tsi_start (*tp); !tsi_end_p (tsi); tsi_next (&tsi)) walk_tree (tsi_stmt_ptr (tsi), replace_all_types_1, data, visited_nodes); - break; - default: - { - struct struct_tree_list *type_nest; - struct struct_tree_list *tmp_node; - tree node_type; - tree new_type; - tree operand; - int i; - - node_type = TREE_TYPE (t); - type_nest = NULL; - while (node_type - && (POINTER_TYPE_P (node_type) - || TREE_CODE (node_type) == ARRAY_TYPE)) - { - tmp_node = (struct struct_tree_list *) xmalloc (sizeof - (struct struct_tree_list)); - tmp_node->data = node_type; - tmp_node->next = type_nest; - type_nest = tmp_node; - node_type = TREE_TYPE (node_type); - } + } + break; + default: + { + + struct struct_tree_list *type_nest; + struct struct_tree_list *tmp_node; + tree node_type; + tree new_type; + tree operand; + int i; - if (similar_struct_decls_p (node_type, struct_data->decl)) - { - new_type = build_new_type (type_nest, struct_data->new_types->data); - TREE_TYPE (t) = new_type; - } + node_type = TREE_TYPE (t); + type_nest = NULL; + while (node_type + && (POINTER_TYPE_P (node_type) + || TREE_CODE (node_type) == ARRAY_TYPE)) + { + tmp_node = (struct struct_tree_list *) xmalloc (sizeof + (struct struct_tree_list)); + tmp_node->data = node_type; + tmp_node->next = type_nest; + type_nest = tmp_node; + node_type = TREE_TYPE (node_type); + } - for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (t)); i++) - { - operand = TREE_OPERAND (t, i); - if (operand) - walk_tree (&operand, replace_all_types_1, data, - visited_nodes); - } - break; - } + if (similar_struct_decls_p (node_type, struct_data->decl)) + { + new_type = build_new_type (type_nest, struct_data->new_types->data); + TREE_TYPE (t) = new_type; + } + + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (t)); i++) + { + operand = TREE_OPERAND (t, i); + if (operand) + walk_tree (&operand, replace_all_types_1, data, + visited_nodes); + } } + break; } + return NULL; } @@ -4634,16 +4641,65 @@ replace_all_types (struct data_structure cfun = save_cfun; } +/* Do transformation for a function represented by NODE. */ +static void +do_reorg_for_func (struct cgraph_node *node, + struct struct_list *data_struct_list) +{ + struct use_struct *uses_list = NULL; + struct new_var_data* new_vars = NULL; + bool debug_uses = false; + + new_vars = create_new_vars (data_struct_list); + + collect_struct_use_data (node, data_struct_list, new_vars, &uses_list); + + create_new_mallocs (data_struct_list, new_vars); + if (debug_uses) + print_use_list (uses_list); + + update_struct_use_stmts (data_struct_list, new_vars, uses_list); + + update_field_accesses (data_struct_list, new_vars); + + update_ssa (TODO_update_ssa); + +} + +/* This function is a helper for do_reorg. It goes over functions in call graph + and performs actual transformation on each one of them. */ +static void +do_reorg1 (struct struct_list *data_struct_list) +{ + struct cgraph_node *node; + + /* Initialize the default bitmap obstack. */ + bitmap_obstack_initialize (NULL); + + for (node = cgraph_nodes; node; node = node->next) + if (node->analyzed && node->decl) + { + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + current_function_decl = node->decl; + do_reorg_for_func (node, data_struct_list); + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + pop_cfun (); + } + + /* FIXME: I am not sure we need it. */ + bitmap_obstack_release (NULL); + cfun = NULL; +} + static void do_reorg (struct struct_list *data_struct_list, bitmap passed_types, - bitmap escaped_types) + bitmap escaped_types, FILE *vcg_dump) { int sub_type_count = 0; struct struct_list *cur_struct; - struct new_var_data *total_new_vars = NULL; - bool debug_vars = false; bool debug_new_types = false; - bool debug_uses = true; + bool new_vars_p = false; /* 1). Create a new struct/record type (or hierarchy of types) @@ -4686,8 +4742,8 @@ do_reorg (struct struct_list *data_struc && (TYPE_NAME (struct_data->decl)) && struct_data->struct_clustering) { - if (bitmap_bit_p (escaped_types, (struct_data->decl)->type.uid) - || bitmap_bit_p (passed_types, (struct_data->decl)->type.uid) + if (bitmap_bit_p (escaped_types, TYPE_UID (struct_data->decl)) + || bitmap_bit_p (passed_types, TYPE_UID (struct_data->decl)) || contains_bit_field_accesses_p (struct_data)) struct_data->reorder_only = true; @@ -4723,22 +4779,30 @@ do_reorg (struct struct_list *data_struc struct_data->new_types->data, struct_data->decl, &donelist); + replace_var_types (struct_data->decl, struct_data->new_types->data); - replace_all_types (struct_data); + replace_all_types (struct_data); } } else if ((struct_data->struct_clustering->sibling || struct_data->struct_clustering->children)) { struct struct_tree_list *donelist = NULL; - struct new_var_data *new_vars; bool recursive_struct = false; if (!struct_data->struct_clustering->children) - struct_data->struct_clustering->direct_access = true; + { + fprintf (vcg_dump, "\nDoing peeling for structure %s.\n", + get_type_name (struct_data->decl)); + struct_data->struct_clustering->direct_access = true; + } + else + fprintf (vcg_dump, "\nDoing spliting for structure %s.\n", + get_type_name (struct_data->decl)); sub_type_count = 0; - + new_vars_p = true; + struct_data->new_types = create_and_assemble_new_types (struct_data, struct_data->struct_clustering, @@ -4757,16 +4821,10 @@ do_reorg (struct struct_list *data_struc else struct_data->new_types = NULL; } - - new_vars = create_new_var_decls (struct_data); - append_to_var_list (new_vars, &total_new_vars); - if (debug_vars) - print_new_vars (new_vars); } else struct_data->new_types = NULL; - - /* if (struct_data->new_types) */ + if (debug_new_types) { fprintf (stdout, @@ -4777,18 +4835,8 @@ do_reorg (struct struct_list *data_struc } } - if (total_new_vars) - { - struct use_struct *uses_list = NULL; - - collect_struct_use_data (data_struct_list, total_new_vars, &uses_list); - create_new_mallocs (data_struct_list, total_new_vars); - if (debug_uses) - print_use_list (uses_list); - update_struct_use_stmts (data_struct_list, total_new_vars, - uses_list); - update_field_accesses (data_struct_list, total_new_vars); - } + if (new_vars_p) + do_reorg1 (data_struct_list); } /* The following aren't imeplemnted yet, so we comment them out