Projects
Mega:24.03
gcc
_service:tar_scm:0030-Struct-Reorg-Add-unsafe-s...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch of Package gcc
From 82d6166cd29fb1c3474f29b28cb7e5478d3a551a Mon Sep 17 00:00:00 2001 From: liyancheng <412998149@qq.com> Date: Mon, 25 Dec 2023 11:17:04 +0800 Subject: [PATCH] [Struct Reorg] Add unsafe structure pointer compression Unsafe structure pointer compression allows for some dangerous conversions for better performance. Add flag -fipa-struct-reorg=5 to enable unsafe structure pointer compression. --- gcc/common.opt | 6 +- gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 365 ++++++++++++++---- gcc/symbol-summary.h | 22 +- .../gcc.dg/struct/csr_skip_void_struct_name.c | 53 +++ gcc/testsuite/gcc.dg/struct/pc_cast_int.c | 91 +++++ .../gcc.dg/struct/pc_compress_and_decomress.c | 90 +++++ gcc/testsuite/gcc.dg/struct/pc_ptr2void.c | 87 +++++ .../gcc.dg/struct/pc_simple_rewrite_pc.c | 112 ++++++ .../gcc.dg/struct/pc_skip_void_struct_name.c | 53 +++ gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 8 + 10 files changed, 804 insertions(+), 83 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c create mode 100644 gcc/testsuite/gcc.dg/struct/pc_cast_int.c create mode 100644 gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c create mode 100644 gcc/testsuite/gcc.dg/struct/pc_ptr2void.c create mode 100644 gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c create mode 100644 gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c diff --git a/gcc/common.opt b/gcc/common.opt index 56b547506..c7c6bc256 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1993,9 +1993,9 @@ Common Var(flag_ipa_struct_reorg) Init(0) Optimization Perform structure layout optimizations. fipa-struct-reorg= -Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 4) --fipa-struct-reorg=[0,1,2,3,4] adding none, struct-reorg, reorder-fields, -dfe, safe-pointer-compression optimizations. +Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 5) +-fipa-struct-reorg=[0,1,2,3,4,5] adding none, struct-reorg, reorder-fields, +dfe, safe-pointer-compression, unsafe-pointer-compression optimizations. fipa-vrp Common Var(flag_ipa_vrp) Optimization diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc index 5d451c4c8..fa33f2d35 100644 --- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc @@ -293,7 +293,8 @@ enum struct_layout_opt_level COMPLETE_STRUCT_RELAYOUT = 1 << 1, STRUCT_REORDER_FIELDS = 1 << 2, DEAD_FIELD_ELIMINATION = 1 << 3, - POINTER_COMPRESSION_SAFE = 1 << 4 + POINTER_COMPRESSION_SAFE = 1 << 4, + POINTER_COMPRESSION_UNSAFE = 1 << 5 }; /* Defines the target pointer size of compressed pointer, which should be 8, @@ -1267,10 +1268,10 @@ csrtype::init_type_info (void) /* Close enough to pad to improve performance. 33~63 should pad to 64 but 33~48 (first half) are too far away, and - 65~127 should pad to 128 but 65~96 (first half) are too far away. */ + 70~127 should pad to 128 but 65~70 (first half) are too far away. */ if (old_size > 48 && old_size < 64) new_size = 64; - if (old_size > 96 && old_size < 128) + if (old_size > 70 && old_size < 128) new_size = 128; /* For performance reasons, only allow structure size @@ -1423,8 +1424,12 @@ public: bool pc_candidate_tree_p (tree); bool pc_type_conversion_candidate_p (tree); bool pc_direct_rewrite_chance_p (tree, tree &); + bool pc_simplify_chance_for_compress_p (gassign *, tree); + bool compress_candidate_without_check (gimple_stmt_iterator *, tree, tree &); bool compress_candidate_with_check (gimple_stmt_iterator *, tree, tree &); bool compress_candidate (gassign *, gimple_stmt_iterator *, tree, tree &); + bool decompress_candidate_without_check (gimple_stmt_iterator *, + tree, tree, tree &, tree &); bool decompress_candidate_with_check (gimple_stmt_iterator *, tree, tree &); bool decompress_candidate (gimple_stmt_iterator *, tree, tree, tree &, tree &); @@ -1924,7 +1929,6 @@ bool ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *gsi, HOST_WIDE_INT ×) { - bool ret = false; gcc_assert (TREE_CODE (cst) == INTEGER_CST); gimple *stmt = gsi_stmt (*gsi); @@ -1948,27 +1952,95 @@ ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *gsi, { if (gsi_one_before_end_p (*gsi)) return false; - gsi_next (gsi); - gimple *stmt2 = gsi_stmt (*gsi); - - if (gimple_code (stmt2) == GIMPLE_ASSIGN - && gimple_assign_rhs_code (stmt2) == POINTER_PLUS_EXPR) + // Check uses. + imm_use_iterator imm_iter_lhs; + use_operand_p use_p_lhs; + FOR_EACH_IMM_USE_FAST (use_p_lhs, imm_iter_lhs, gimple_assign_lhs (stmt)) { - tree lhs = gimple_assign_lhs (stmt2); - tree rhs1 = gimple_assign_rhs1 (stmt2); - if (types_compatible_p (inner_type (TREE_TYPE (rhs1)), ctype.type) - || types_compatible_p (inner_type (TREE_TYPE (lhs)), ctype.type)) + gimple *stmt2 = USE_STMT (use_p_lhs); + if (gimple_code (stmt2) != GIMPLE_ASSIGN) + continue; + if (gimple_assign_rhs_code (stmt2) == POINTER_PLUS_EXPR) { - tree num = NULL; - if (is_result_of_mult (cst, &num, TYPE_SIZE_UNIT (ctype.type))) + tree lhs = gimple_assign_lhs (stmt2); + tree rhs1 = gimple_assign_rhs1 (stmt2); + if (types_compatible_p (inner_type (TREE_TYPE (rhs1)), ctype.type) + || types_compatible_p (inner_type (TREE_TYPE (lhs)), + ctype.type)) { - times = TREE_INT_CST_LOW (num); - ret = true; + tree num = NULL; + if (is_result_of_mult (cst, &num, + TYPE_SIZE_UNIT (ctype.type))) + { + times = TREE_INT_CST_LOW (num); + return true; + } + } + } + // For pointer compression, handle plus stmt. + else if (gimple_assign_rhs_code (stmt2) == PLUS_EXPR) + { + // Check uses. + imm_use_iterator imm_iter_cast; + use_operand_p use_p_cast; + FOR_EACH_IMM_USE_FAST (use_p_cast, imm_iter_cast, + gimple_assign_lhs (stmt2)) + { + gimple *stmt_cast = USE_STMT (use_p_cast); + if (gimple_code (stmt_cast) != GIMPLE_ASSIGN) + continue; + if (gimple_assign_cast_p (stmt_cast)) + { + tree lhs_type = inner_type (TREE_TYPE ( + gimple_assign_lhs (stmt_cast))); + if (types_compatible_p (lhs_type, ctype.type)) + { + tree num = NULL; + if (is_result_of_mult (cst, &num, + TYPE_SIZE_UNIT (ctype.type))) + { + times = TREE_INT_CST_LOW (num); + return true; + } + } + } } } } - gsi_prev (gsi); - return ret; + } + // For pointer compression, handle div stmt. + if (gimple_assign_rhs_code (stmt) == TRUNC_DIV_EXPR) + { + imm_use_iterator imm_iter; + use_operand_p use_p; + tree lhs = gimple_assign_lhs (stmt); + if (lhs == NULL_TREE) + return false; + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs) + { + gimple *use_stmt = USE_STMT (use_p); + if (is_gimple_debug (use_stmt)) + continue; + if (gimple_code (use_stmt) != GIMPLE_ASSIGN) + continue; + if (gimple_assign_cast_p (use_stmt)) + { + tree lhs_type = inner_type (TREE_TYPE ( + gimple_assign_lhs (use_stmt))); + if (TYPE_UNSIGNED (lhs_type) + && TREE_CODE (lhs_type) == INTEGER_TYPE + && TYPE_PRECISION (lhs_type) == compressed_size) + { + tree num = NULL; + if (is_result_of_mult (cst, &num, + TYPE_SIZE_UNIT (ctype.type))) + { + times = TREE_INT_CST_LOW (num); + return true; + } + } + } + } } return false; } @@ -2967,7 +3039,9 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) e = escape_separate_instance; - if (e != does_not_escape) + if (e != does_not_escape + && (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT + || replace_type_map.get (type->type) == NULL)) type->mark_escape (e, NULL); } @@ -3629,7 +3703,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, if (TREE_CODE (side) == SSA_NAME && VOID_POINTER_P (TREE_TYPE (side))) return; - d->type->mark_escape (escape_cast_another_ptr, stmt); + if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT + || replace_type_map.get (d->type->type) == NULL) + d->type->mark_escape (escape_cast_another_ptr, stmt); return; } @@ -3645,7 +3721,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, } else /* *_1 = &MEM[(void *)&x + 8B]. */ - type->mark_escape (escape_cast_another_ptr, stmt); + if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT + || replace_type_map.get (type->type) == NULL) + type->mark_escape (escape_cast_another_ptr, stmt); } else if (type != d->type) { @@ -4364,7 +4442,9 @@ ipa_struct_reorg::check_definition_assign (srdecl *decl, /* Casts between pointers and integer are escaping. */ if (gimple_assign_cast_p (stmt)) { - type->mark_escape (escape_cast_int, stmt); + if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT + || replace_type_map.get (type->type) == NULL) + type->mark_escape (escape_cast_int, stmt); return; } @@ -4684,7 +4764,9 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, /* Casts between pointers and integer are escaping. */ if (gimple_assign_cast_p (stmt)) { - type->mark_escape (escape_cast_int, stmt); + if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT + || replace_type_map.get (type->type) == NULL) + type->mark_escape (escape_cast_int, stmt); return; } @@ -5364,9 +5446,9 @@ ipa_struct_reorg::prune_escaped_types (void) /* Prune types that escape, all references to those types will have been removed in the above loops. */ - /* The escape type is not deleted in STRUCT_REORDER_FIELDS, - Then the type that contains the escaped type fields - can find complete information. */ + /* The escape type is not deleted in current_layout_opt_level + after STRUCT_REORDER_FIELDS, then the type that contains + the escaped type fields can find complete information. */ if (current_layout_opt_level < STRUCT_REORDER_FIELDS) { for (unsigned i = 0; i < types.length ();) @@ -5842,17 +5924,17 @@ ipa_struct_reorg::compress_ptr_to_offset (tree xhs, srtype *type, tree step2 = gimplify_build2 (gsi, TRUNC_DIV_EXPR, long_unsigned_type_node, step1, TYPE_SIZE_UNIT (type->newtype[0])); - /* Emit gimple _X3 = _X2 + 1. */ - tree step3 = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node, - step2, build_one_cst (long_unsigned_type_node)); + /* Emit _X3 = (compressed_size) _X2. */ + tree pc_type = make_unsigned_type (compressed_size); + tree step3 = gimplify_build1 (gsi, NOP_EXPR, pc_type, step2); - /* Emit _X4 = (compressed_size) _X3. */ - tree step4 = gimplify_build1 (gsi, NOP_EXPR, - make_unsigned_type (compressed_size), step3); + /* Emit gimple _X4 = _X3 + 1. */ + tree step4 = gimplify_build2 (gsi, PLUS_EXPR, pc_type, step3, + build_one_cst (pc_type)); if (dump_file && (dump_flags & TDF_DETAILS)) { - print_generic_expr (dump_file, step3); + print_generic_expr (dump_file, step4); fprintf (dump_file, "\n"); } return step4; @@ -5894,7 +5976,7 @@ ipa_struct_reorg::decompress_offset_to_ptr (tree xhs, srtype *type, if (dump_file && (dump_flags & TDF_DETAILS)) { - print_generic_expr (dump_file, step3); + print_generic_expr (dump_file, step4); fprintf (dump_file, "\n"); } return step4; @@ -5967,7 +6049,10 @@ ipa_struct_reorg::pc_type_conversion_candidate_p (tree xhs) if (TREE_CODE (xhs) == COMPONENT_REF) { - srtype *base_type = find_type (TREE_TYPE (TREE_OPERAND (xhs, 0))); + tree mem = TREE_OPERAND (xhs, 0); + if (TREE_CODE (mem) != MEM_REF) + return false; + srtype *base_type = find_type (TREE_TYPE (mem)); if (base_type != NULL && base_type->has_escaped ()) return pc_candidate_st_type_p (TREE_TYPE (xhs)); @@ -6057,6 +6142,49 @@ ipa_struct_reorg::pc_direct_rewrite_chance_p (tree rhs, tree &new_rhs) return false; } +/* The following cases can simplify the checking of null pointer: + 1. rhs defined from POINTER_PLUS_EXPR. + 2. rhs used as COMPONENT_REF in this basic block. */ + +bool +ipa_struct_reorg::pc_simplify_chance_for_compress_p (gassign *stmt, + tree rhs) +{ + imm_use_iterator imm_iter; + use_operand_p use_p; + gimple *def_stmt = SSA_NAME_DEF_STMT (rhs); + + if (def_stmt && is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR) + return true; + + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, rhs) + { + gimple *use_stmt = USE_STMT (use_p); + if (use_stmt->bb != stmt->bb || !is_gimple_assign (use_stmt)) + continue; + + tree use_rhs = gimple_assign_rhs1 (use_stmt); + if (TREE_CODE (use_rhs) == COMPONENT_REF + && TREE_OPERAND (TREE_OPERAND (use_rhs, 0), 0) == rhs) + return true; + } + return false; +} + +/* Perform compression directly without checking null pointer. */ + +bool +ipa_struct_reorg::compress_candidate_without_check (gimple_stmt_iterator *gsi, + tree rhs, + tree &new_rhs) +{ + srtype *type = get_compression_candidate_type (rhs); + gcc_assert (type != NULL); + new_rhs = compress_ptr_to_offset (new_rhs, type, gsi); + return true; +} + /* Perform pointer compression with check. The conversion will be as shown in the following example: Orig bb: @@ -6157,6 +6285,9 @@ ipa_struct_reorg::compress_candidate (gassign *stmt, gimple_stmt_iterator *gsi, { if (pc_direct_rewrite_chance_p (rhs, new_rhs)) return true; + else if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE + && pc_simplify_chance_for_compress_p (stmt, rhs)) + return compress_candidate_without_check (gsi, rhs, new_rhs); return compress_candidate_with_check (gsi, rhs, new_rhs); } @@ -6219,6 +6350,80 @@ ipa_struct_reorg::create_bb_for_decompress_candidate (basic_block last_bb, return new_bb; } +/* Try decompress candidate without check. */ + +bool +ipa_struct_reorg::decompress_candidate_without_check (gimple_stmt_iterator *gsi, + tree lhs, tree rhs, + tree &new_lhs, + tree &new_rhs) +{ + imm_use_iterator imm_iter; + use_operand_p use_p; + bool processed = false; + + if (!gsi_one_before_end_p (*gsi)) + { + gsi_next (gsi); + gimple *next_stmt = gsi_stmt (*gsi); + if (gimple_code (next_stmt) == GIMPLE_ASSIGN + && gimple_assign_rhs_class (next_stmt) == GIMPLE_SINGLE_RHS) + { + tree next_rhs = gimple_assign_rhs1 (next_stmt); + /* If current lhs is used as rhs in the next stmt: + -> _1 = t->s + tt->s = _1. */ + if (lhs == next_rhs) + { + /* Check whether: + 1. the lhs is only used in the next stmt. + 2. the next lhs is candidate type. */ + if (has_single_use (lhs) + && pc_candidate_tree_p (gimple_assign_lhs (next_stmt))) + { + processed = true; + /* Copy directly without conversion after update type. */ + TREE_TYPE (new_lhs) + = make_unsigned_type (compressed_size); + } + } + /* -> _1 = t->s + _2 = _1->s + In this case, _1 might not be nullptr, so decompress it without + check. */ + else if (TREE_CODE (next_rhs) == COMPONENT_REF) + { + tree use_base = TREE_OPERAND (TREE_OPERAND (next_rhs, 0), 0); + if (use_base == lhs) + { + srtype *type = get_compression_candidate_type (rhs); + gcc_assert (type != NULL); + gsi_prev (gsi); + tree new_ref = NULL_TREE; + if (TREE_CODE (new_rhs) == MEM_REF) + new_ref = new_rhs; + else + { + tree base = TREE_OPERAND (TREE_OPERAND (new_rhs, 0), 0); + tree new_mem_ref = build_simple_mem_ref (base); + new_ref = build3 (COMPONENT_REF, + TREE_TYPE (new_rhs), + new_mem_ref, + TREE_OPERAND (new_rhs, 1), + NULL_TREE); + } + new_rhs = decompress_offset_to_ptr (new_ref, type, gsi); + processed = true; + gsi_next (gsi); + } + } + } + gsi_prev (gsi); + return processed; + } + return false; +} + /* Perform pointer decompression with check. The conversion will be as shown in the following example: Orig bb: @@ -6320,7 +6525,10 @@ ipa_struct_reorg::decompress_candidate (gimple_stmt_iterator *gsi, tree lhs, tree rhs, tree &new_lhs, tree &new_rhs) { - // TODO: simplifiy check and rewrite will be pushed in next PR. + if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE + && decompress_candidate_without_check (gsi, lhs, rhs, new_lhs, new_rhs)) + return true; + return decompress_candidate_with_check (gsi, rhs, new_rhs); } @@ -6341,14 +6549,23 @@ ipa_struct_reorg::try_rewrite_with_pointer_compression (gassign *stmt, if (pc_type_conversion_candidate_p (lhs)) { /* Transfer MEM[(struct *)_1].files = _4; - to MEM[(struct *)_1].files = (struct *)_4; */ - new_rhs = fold_convert (TREE_TYPE (lhs), tmp_rhs); + to _tmp = (struct *)_4; + MEM[(struct *)_1].files = _tmp; */ + tree tmp_reg = create_tmp_reg (TREE_TYPE (lhs)); + tree tmp_rhs_cvt = fold_convert (TREE_TYPE (lhs), tmp_rhs); + gimple *copy_stmt = gimple_build_assign (tmp_reg, tmp_rhs_cvt); + gsi_insert_before (gsi, copy_stmt, GSI_SAME_STMT); + new_rhs = tmp_reg; } else if (pc_type_conversion_candidate_p (rhs)) { /* Transfer _4 = MEM[(struct *)_1].nodes; - to _4 = (new_struct *) MEM[(struct *)_1].nodes; */ - new_rhs = fold_convert (TREE_TYPE (new_lhs), tmp_rhs); + to _tmp = MEM[(struct *)_1].nodes; + _4 = (new_struct *) _tmp; */ + tree tmp_reg = create_tmp_reg (TREE_TYPE (new_lhs)); + gimple *copy_stmt = gimple_build_assign (tmp_reg, tmp_rhs); + gsi_insert_before (gsi, copy_stmt, GSI_SAME_STMT); + new_rhs = fold_convert (TREE_TYPE (new_lhs), tmp_reg); } } else if (l && r) @@ -6544,7 +6761,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) if (dump_file && (dump_flags & TDF_DETAILS)) { - fprintf (dump_file, "\nrewriting stamtenet:\n"); + fprintf (dump_file, "\nrewriting statement:\n"); print_gimple_stmt (dump_file, stmt, 0); } tree newlhs[max_split]; @@ -6809,7 +7026,8 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) old statement is to be removed. */ bool -ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi) +ipa_struct_reorg::rewrite_cond (gcond *stmt, + gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED) { tree_code rhs_code = gimple_cond_code (stmt); @@ -7039,8 +7257,11 @@ ipa_struct_reorg::rewrite_functions (void) if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "\nNo rewrite:\n"); - dump_function_to_file (current_function_decl, dump_file, - dump_flags | TDF_VOPS); + if (current_function_decl) + dump_function_to_file (current_function_decl, dump_file, + dump_flags | TDF_VOPS); + else + fprintf (dump_file, " no declaration\n"); } pop_cfun (); } @@ -7073,11 +7294,13 @@ ipa_struct_reorg::rewrite_functions (void) push_cfun (DECL_STRUCT_FUNCTION (node->decl)); if (dump_file && (dump_flags & TDF_DETAILS)) { - fprintf (dump_file, "==== Before create decls: %dth_%s ====\n\n", + fprintf (dump_file, "==== Before create decls: %dth %s ====\n\n", i, f->node->name ()); if (current_function_decl) dump_function_to_file (current_function_decl, dump_file, dump_flags | TDF_VOPS); + else + fprintf (dump_file, " no declaration\n"); } pop_cfun (); } @@ -7109,10 +7332,13 @@ ipa_struct_reorg::rewrite_functions (void) if (dump_file && (dump_flags & TDF_DETAILS)) { - fprintf (dump_file, "\nBefore rewrite: %dth_%s\n", + fprintf (dump_file, "\nBefore rewrite: %dth %s\n", i, f->node->name ()); - dump_function_to_file (current_function_decl, dump_file, - dump_flags | TDF_VOPS); + if (current_function_decl) + dump_function_to_file (current_function_decl, dump_file, + dump_flags | TDF_VOPS); + else + fprintf (dump_file, " no declaration\n"); fprintf (dump_file, "\n======== Start to rewrite: %dth_%s ========\n", i, f->node->name ()); } @@ -7187,10 +7413,13 @@ ipa_struct_reorg::rewrite_functions (void) if (dump_file) { - fprintf (dump_file, "\nAfter rewrite: %dth_%s\n", + fprintf (dump_file, "\nAfter rewrite: %dth %s\n", i, f->node->name ()); - dump_function_to_file (current_function_decl, dump_file, - dump_flags | TDF_VOPS); + if (current_function_decl) + dump_function_to_file (current_function_decl, dump_file, + dump_flags | TDF_VOPS); + else + fprintf (dump_file, " no declaration\n"); } pop_cfun (); @@ -7309,18 +7538,24 @@ ipa_struct_reorg::check_and_prune_struct_for_pointer_compression (void) " skip compression.\n"); continue; } - if ((current_layout_opt_level & POINTER_COMPRESSION_SAFE) - && !type->has_legal_alloc_num) + if (!type->has_legal_alloc_num) { - if (dump_file) - fprintf (dump_file, " has illegal struct array size," - " skip compression.\n"); - continue; + if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE) + if (dump_file) + fprintf (dump_file, " has unknown alloc size, but" + " in unsafe mode, so"); + else + { + if (dump_file) + fprintf (dump_file, " has illegal struct array size," + " skip compression.\n"); + continue; + } } pc_transform_num++; type->pc_candidate = true; if (dump_file) - fprintf (dump_file, " attemps to do pointer compression.\n"); + fprintf (dump_file, " attempts to do pointer compression.\n"); } if (dump_file) @@ -7342,14 +7577,10 @@ init_pointer_size_for_pointer_compression (void) switch (param_pointer_compression_size) { case 8: - compressed_size = 8; // sizeof (uint8) - break; + // FALLTHRU case 16: - compressed_size = 16; // sizeof (uint16) - break; - case 32: - compressed_size = 32; // sizeof (uint32) - break; + // FALLTHRU + case 32: compressed_size = param_pointer_compression_size; break; default: error ("Invalid pointer compression size, using the following param: " "\"--param compressed-pointer-size=[8,16,32]\""); @@ -7426,6 +7657,8 @@ public: unsigned int level = 0; switch (struct_layout_optimize_level) { + case 5: level |= POINTER_COMPRESSION_UNSAFE; + // FALLTHRU case 4: level |= POINTER_COMPRESSION_SAFE; // FALLTHRU case 3: level |= DEAD_FIELD_ELIMINATION; diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h index 3fe64047c..4f896f4e4 100644 --- a/gcc/symbol-summary.h +++ b/gcc/symbol-summary.h @@ -103,16 +103,15 @@ protected: /* Allocates new data that are stored within map. */ T* allocate_new () { - /* In structure optimizatons, we call new to ensure that - the allocated memory is initialized to 0. */ - if (flag_ipa_struct_reorg) - return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () - : new T (); - /* Call gcc_internal_because we do not want to call finalizer for a type T. We call dtor explicitly. */ - return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () - : m_allocator.allocate () ; + T* allocated = is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () + : m_allocator.allocate (); + /* In structure optimizatons, we call memset to ensure that + the allocated memory is initialized to 0. */ + if (flag_ipa_struct_reorg) + memset (allocated, 0, sizeof (T)); + return allocated; } /* Release an item that is stored within map. */ @@ -121,12 +120,7 @@ protected: if (is_ggc ()) ggc_delete (item); else - { - if (flag_ipa_struct_reorg) - delete item; - else - m_allocator.remove (item); - } + m_allocator.remove (item); } /* Unregister all call-graph hooks. */ diff --git a/gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c b/gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c new file mode 100644 index 000000000..c5e4968d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c @@ -0,0 +1,53 @@ +// Structures without names should not be optimized +/* { dg-do compile } */ +#include <stdlib.h> +#include <math.h> + +typedef struct +{ + int a; + float b; + double s1; + double s2; + double s3; + double s4; + double s5; + double s6; + double s7; + double s8; +} str_t1; + +#define N 1000 + +int num; + +int +main () +{ + int i, r; + + r = rand (); + num = r > N ? N : r; + str_t1 *p1 = calloc (num, sizeof (str_t1)); + + if (p1 == NULL) + return 0; + + for (i = 0; i < num; i++) + p1[i].a = 1; + + for (i = 0; i < num; i++) + p1[i].b = 2; + + for (i = 0; i < num; i++) + if (p1[i].a != 1) + abort (); + + for (i = 0; i < num; i++) + if (fabsf (p1[i].b - 2) > 0.0001) + abort (); + + return 0; +} + +/* { dg-final { scan-ipa-dump "No structures to transform in Complete Structure Relayout." "struct_reorg" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/struct/pc_cast_int.c b/gcc/testsuite/gcc.dg/struct/pc_cast_int.c new file mode 100644 index 000000000..6f67fc556 --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct/pc_cast_int.c @@ -0,0 +1,91 @@ +// Escape cast int for pointer compression +/* { dg-do compile } */ + +#include <stdio.h> +#include <stdlib.h> + +typedef struct node node_t; +typedef struct node *node_p; + +typedef struct arc arc_t; +typedef struct arc *arc_p; + +typedef struct network +{ + arc_p arcs; + arc_p sorted_arcs; + int x; + node_p nodes; + node_p stop_nodes; +} network_t; + +struct node +{ + int64_t potential; + int orientation; + node_p child; + node_p pred; + node_p sibling; + node_p sibling_prev; + arc_p basic_arc; + arc_p firstout; + arc_p firstin; + arc_p arc_tmp; + int64_t flow; + int64_t depth; + int number; + int time; +}; + +struct arc +{ + int id; + int64_t cost; + node_p tail; + node_p head; + short ident; + arc_p nextout; + arc_p nextin; + int64_t flow; + int64_t org_cost; + network_t* net_add; +}; + + +const int MAX = 100; +network_t* net; +node_p node; + +int +main () +{ + net = (network_t*) calloc (1, sizeof(network_t)); + net->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); + net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t)); + net->nodes = (node_p) calloc (MAX, sizeof (node_t)); + net->arcs->id = 100; + + node = net->nodes; + node_p n1 = (node_p) 0x123456; + + for (unsigned i = 0; i < MAX; i++) + { + node->pred = n1; + node = node + 1; + } + + node = net->nodes; + + for (unsigned i = 0; i < MAX; i++) + { + if (node->pred != n1) + { + abort (); + } + node = node + 1; + } + + return 0; +} + +/* { dg-final { scan-ipa-dump "No structures to transform in pointer compression" "struct_reorg" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c b/gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c new file mode 100644 index 000000000..d0b8d1afa --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c @@ -0,0 +1,90 @@ +// Support basic pointer compression and decompression +/* { dg-do compile } */ + +#include <stdio.h> +#include <stdlib.h> + +typedef struct node node_t; +typedef struct node *node_p; + +typedef struct arc arc_t; +typedef struct arc *arc_p; + +typedef struct network +{ + arc_p arcs; + arc_p sorted_arcs; + int x; + node_p nodes; + node_p stop_nodes; +} network_t; + +struct node +{ + int64_t potential; + int orientation; + node_p child; + node_p pred; + node_p sibling; + node_p sibling_prev; + arc_p basic_arc; + arc_p firstout; + arc_p firstin; + arc_p arc_tmp; + int64_t flow; + int64_t depth; + int number; + int time; +}; + +struct arc +{ + int id; + int64_t cost; + node_p tail; + node_p head; + short ident; + arc_p nextout; + arc_p nextin; + int64_t flow; + int64_t org_cost; + network_t* net_add; +}; + + +const int MAX = 100; +network_t* net; +node_p node; + +int +main () +{ + net = (network_t*) calloc (1, sizeof(network_t)); + net->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); + net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t)); + net->nodes = (node_p) calloc (MAX, sizeof (node_t)); + net->arcs->id = 100; + + node = net->nodes; + + for (unsigned i = 0; i < MAX; i++) + { + node->pred = node; + node = node + 1; + } + + node = net->nodes; + + for (unsigned i = 0; i < MAX; i++) + { + if (node->pred != node) + { + abort (); + } + node = node + 1; + } + + return 0; +} + +/* { dg-final { scan-ipa-dump "Number of structures to transform in pointer compression is 1" "struct_reorg" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/struct/pc_ptr2void.c b/gcc/testsuite/gcc.dg/struct/pc_ptr2void.c new file mode 100644 index 000000000..5022c1967 --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct/pc_ptr2void.c @@ -0,0 +1,87 @@ +// Partially support escape_cast_void for pointer compression. +/* { dg-do compile } */ + +#include <stdio.h> +#include <stdlib.h> + +typedef struct node node_t; +typedef struct node *node_p; + +typedef struct arc arc_t; +typedef struct arc *arc_p; + +typedef struct network +{ + arc_p arcs, sorted_arcs; + int x; + node_p nodes, stop_nodes; +} network_t; + +struct node +{ + int64_t potential; + int orientation; + node_p child; + node_p pred; + node_p sibling; + node_p sibling_prev; + arc_p basic_arc; + arc_p firstout; + arc_p firstin; + arc_p arc_tmp; + int64_t flow; + int64_t depth; + int number; + int time; +}; + +struct arc +{ + int id; + int64_t cost; + node_p tail; + node_p head; + short ident; + arc_p nextout; + arc_p nextin; + int64_t flow; + int64_t org_cost; +}; + +const int MAX = 100; +network_t* net = NULL; +int cnt = 0; + +__attribute__((noinline)) int +primal_feasible (network_t *net) +{ + void* stop; + node_t *node; + + node = net->nodes; + stop = (void *)net->stop_nodes; + for( node++; node < (node_t *)stop; node++ ) + { + net->x = 1; + printf( "PRIMAL NETWORK SIMPLEX: "); + } + return 0; +} + +int +main () +{ + net = (network_t*) calloc (1, 20); + net->nodes = calloc (MAX, sizeof (node_t)); + net->stop_nodes = net->nodes + MAX - 1; + cnt = primal_feasible( net ); + + net = (network_t*) calloc (1, 20); + if( !(net->arcs) ) + { + return -1; + } + return cnt; +} + +/* { dg-final { scan-ipa-dump "Number of structures to transform in pointer compression is 1" "struct_reorg" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c b/gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c new file mode 100644 index 000000000..98943c9b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c @@ -0,0 +1,112 @@ +// Check simplify rewrite chance for pointer compression and decompression +/* { dg-do compile } */ + +#include <stdio.h> +#include <stdlib.h> + +typedef struct node node_t; +typedef struct node *node_p; + +typedef struct arc arc_t; +typedef struct arc *arc_p; + +typedef struct network +{ + arc_p arcs; + arc_p sorted_arcs; + int x; + node_p nodes; + node_p stop_nodes; +} network_t; + +struct node +{ + int64_t potential; + int orientation; + node_p child; + node_p pred; + node_p sibling; + node_p sibling_prev; + arc_p basic_arc; + arc_p firstout; + arc_p firstin; + arc_p arc_tmp; + int64_t flow; + int64_t depth; + int number; + int time; +}; + +struct arc +{ + int id; + int64_t cost; + node_p tail; + node_p head; + short ident; + arc_p nextout; + arc_p nextin; + int64_t flow; + int64_t org_cost; + network_t* net_add; +}; + + +const int MAX = 100; +network_t* net; +node_p node; +arc_p arc; + +int +main () +{ + net = (network_t*) calloc (1, sizeof(network_t)); + net->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); + net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t)); + net->nodes = (node_p) calloc (MAX, sizeof (node_t)); + net->arcs->id = 100; + + node = net->nodes; + arc = net->arcs; + + for (unsigned i = 0; i < MAX; i++) + { + arc->head = node; + arc->head->child = node; + node->potential = i + 1; + arc->cost = arc->head->potential; + arc->tail = node->sibling; + if (i % 2) + node->pred = net->nodes + i; + else + node->pred = NULL; + + if (node->pred && node->pred->child != NULL) + node->number = 0; + else + node->number = 1; + + node = node + 1; + arc = arc + 1; + } + + node = net->nodes; + arc = net->arcs; + + for (unsigned i = 0; i < MAX; i++) + { + node_p t = i % 2 ? node : NULL; + int tt = i % 2 ? 0 : 1; + if (arc->head->pred != t || arc->cost == 0 + || arc->tail != node->sibling || node->number != tt) + { + abort (); + } + arc = arc + 1; + node = node + 1; + } + + return 0; +} + +/* { dg-final { scan-ipa-dump "Number of structures to transform in pointer compression is 1" "struct_reorg" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c b/gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c new file mode 100644 index 000000000..a0e191267 --- /dev/null +++ b/gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c @@ -0,0 +1,53 @@ +// Structures without names should not be optimized +/* { dg-do compile } */ +#include <stdlib.h> +#include <math.h> + +typedef struct +{ + int a; + float b; + double s1; + double s2; + double s3; + double s4; + double s5; + double s6; + double s7; + double s8; +} str_t1; + +#define N 1000 + +int num; + +int +main () +{ + int i, r; + + r = rand (); + num = r > N ? N : r; + str_t1 *p1 = calloc (num, sizeof (str_t1)); + + if (p1 == NULL) + return 0; + + for (i = 0; i < num; i++) + p1[i].a = 1; + + for (i = 0; i < num; i++) + p1[i].b = 2; + + for (i = 0; i < num; i++) + if (p1[i].a != 1) + abort (); + + for (i = 0; i < num; i++) + if (fabsf (p1[i].b - 2) > 0.0001) + abort (); + + return 0; +} + +/* { dg-final { scan-ipa-dump "No structures to transform in pointer compression" "struct_reorg" } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp index 278c4e4f5..c40474407 100644 --- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp @@ -47,6 +47,14 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \ "" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program" +# -fipa-struct-reorg=4 +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \ + "" "-fipa-struct-reorg=4 -fdump-ipa-all -flto-partition=one -fwhole-program" + +# -fipa-struct-reorg=5 +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \ + "" "-fipa-struct-reorg=5 -fdump-ipa-all -flto-partition=one -fwhole-program" + # All done. torture-finish dg-finish -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2