1 Star 0 Fork 128

cenhuilin/gcc

forked from src-openEuler/gcc 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch 34.76 KB
一键复制 编辑 原始数据 按行查看 历史
赵震宇 提交于 2024-04-01 17:15 . [Sync] Sync patch from openeuler/gcc
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
From 82d6166cd29fb1c3474f29b28cb7e5478d3a551a Mon Sep 17 00:00:00 2001
From: liyancheng <[email protected]>
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 &times)
{
- 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
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/cenhuilin/gcc.git
[email protected]:cenhuilin/gcc.git
cenhuilin
gcc
gcc
master

搜索帮助