From 7dc6940ba0f463137ff6cf98032d1e98edecde54 Mon Sep 17 00:00:00 2001 From: liyancheng <412998149@qq.com> Date: Fri, 25 Nov 2022 19:36:59 +0800 Subject: [PATCH 32/35] [Struct Reorg] Add Unsafe Structure Pointer Compression Unsafe structure pointer compression allows some danger conversions to achieve faster performance. Add flag -fipa-struct-reorg=5 to enable unsafe structure pointer compression. --- gcc/common.opt | 6 +- gcc/ipa-struct-reorg/ipa-struct-reorg.c | 309 +++++++++++++++--- .../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 + 9 files changed, 757 insertions(+), 52 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 c9b099817..384595f16 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1889,9 +1889,9 @@ Common Report 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-extend-auto-profile Common Report Var(flag_ipa_extend_auto_profile) diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c index 3550411dc..ee4893dfb 100644 --- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c +++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c @@ -264,7 +264,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, @@ -1266,12 +1267,12 @@ 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~80 (first half) are too far away. */ + 65~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 > 80 && old_size < 128) + if (old_size > 70 && old_size < 128) { new_size = 128; } @@ -1421,8 +1422,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 &); @@ -1996,27 +2001,95 @@ ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *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 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)) + { + 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. + else if (gimple_assign_rhs_code (stmt2) == PLUS_EXPR) { - tree num = NULL; - if (is_result_of_mult (cst, &num, TYPE_SIZE_UNIT (ctype.type))) + // 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)) { - times = TREE_INT_CST_LOW (num); - ret = true; + 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; + } + } + } + } + } + } + } + // For pointer compression. + 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; + } } } } - gsi_prev (gsi); - return ret; } return false; } @@ -3110,7 +3183,9 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) 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); } @@ -3793,7 +3868,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple 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; } @@ -3810,7 +3887,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple 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) @@ -4550,7 +4629,9 @@ ipa_struct_reorg::check_definition_assign (srdecl *decl, vec &worklist) /* 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; } @@ -4897,7 +4978,9 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, vec &worklist) /* 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; } @@ -5566,9 +5649,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_LAYOUT_OPTIMIZE, - 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 ();) @@ -6052,17 +6135,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; @@ -6104,7 +6187,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; @@ -6267,6 +6350,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: @@ -6368,6 +6494,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); } @@ -6430,6 +6559,79 @@ 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_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: @@ -6532,7 +6734,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); } @@ -7551,18 +7756,26 @@ 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) @@ -7584,14 +7797,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 pointer-compression-size=[8,16,32]\""); @@ -7672,6 +7881,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/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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 +#include + +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 2eebef768..d7367ed96 100644 --- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp @@ -85,6 +85,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.27.0.windows.1