!192 [sync] PR-186: [Sync] Sync patch from openeuler/gcc

From: @openeuler-sync-bot 
Reviewed-by: @li-yancheng 
Signed-off-by: @li-yancheng
This commit is contained in:
openeuler-ci-bot 2022-09-15 12:04:01 +00:00 committed by Gitee
commit 0c24e155b2
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 8609 additions and 1 deletions

View File

@ -0,0 +1,342 @@
From cf0f086ec274d794a2a180047123920bf8a5224b Mon Sep 17 00:00:00 2001
From: dingguangya <dingguangya1@huawei.com>
Date: Mon, 17 Jan 2022 21:03:47 +0800
Subject: [PATCH 01/12] [ccmp] Add another optimization opportunity for ccmp
instruction
Add flag -fccmp2.
Enables the use of the ccmp instruction by creating a new conflict
relationship for instances where temporary expressions replacement
cannot be effectively created.
---
gcc/ccmp.c | 33 ++++
gcc/ccmp.h | 1 +
gcc/common.opt | 4 +
gcc/testsuite/gcc.target/aarch64/ccmp_3.c | 15 ++
gcc/tree-ssa-coalesce.c | 197 ++++++++++++++++++++++
5 files changed, 250 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/ccmp_3.c
diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index ca77375a9..8d2d73e52 100644
--- a/gcc/ccmp.c
+++ b/gcc/ccmp.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgexpand.h"
#include "ccmp.h"
#include "predict.h"
+#include "gimple-iterator.h"
/* Check whether T is a simple boolean variable or a SSA name
set by a comparison operator in the same basic block. */
@@ -129,6 +130,38 @@ ccmp_candidate_p (gimple *g)
return false;
}
+/* Check whether bb is a potential conditional compare candidate. */
+bool
+check_ccmp_candidate (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+ gimple *bb_last_stmt, *stmt;
+ tree op0, op1;
+
+ gsi = gsi_last_bb (bb);
+ bb_last_stmt = gsi_stmt (gsi);
+
+ if (bb_last_stmt && gimple_code (bb_last_stmt) == GIMPLE_COND)
+ {
+ op0 = gimple_cond_lhs (bb_last_stmt);
+ op1 = gimple_cond_rhs (bb_last_stmt);
+
+ if (TREE_CODE (op0) == SSA_NAME
+ && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
+ && TREE_CODE (op1) == INTEGER_CST
+ && ((gimple_cond_code (bb_last_stmt) == NE_EXPR)
+ || (gimple_cond_code (bb_last_stmt) == EQ_EXPR)))
+ {
+ stmt = SSA_NAME_DEF_STMT (op0);
+ if (stmt && gimple_code (stmt) == GIMPLE_ASSIGN)
+ {
+ return ccmp_candidate_p (stmt);
+ }
+ }
+ }
+ return false;
+}
+
/* Extract the comparison we want to do from the tree. */
void
get_compare_parts (tree t, int *up, rtx_code *rcode,
diff --git a/gcc/ccmp.h b/gcc/ccmp.h
index 199dd581d..ac862f0f6 100644
--- a/gcc/ccmp.h
+++ b/gcc/ccmp.h
@@ -21,5 +21,6 @@ along with GCC; see the file COPYING3. If not see
#define GCC_CCMP_H
extern rtx expand_ccmp_expr (gimple *, machine_mode);
+extern bool check_ccmp_candidate (basic_block bb);
#endif /* GCC_CCMP_H */
diff --git a/gcc/common.opt b/gcc/common.opt
index 24834cf60..4dd566def 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1942,6 +1942,10 @@ fira-verbose=
Common RejectNegative Joined UInteger Var(flag_ira_verbose) Init(5)
-fira-verbose=<number> Control IRA's level of diagnostic messages.
+fccmp2
+Common Report Var(flag_ccmp2) Init(0) Optimization
+Optimize potential ccmp instruction in complex scenarios.
+
fivopts
Common Report Var(flag_ivopts) Init(1) Optimization
Optimize induction variables on trees.
diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_3.c b/gcc/testsuite/gcc.target/aarch64/ccmp_3.c
new file mode 100644
index 000000000..b509ba810
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ccmp_3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { aarch64*-*-linux* } } } */
+/* { dg-options "-O -fdump-rtl-expand-details -fccmp2" } */
+
+int func (int a, int b, int c)
+{
+ while(1)
+ {
+ if(a-- == 0 || b >= c)
+ {
+ return 1;
+ }
+ }
+}
+
+/* { dg-final { scan-assembler-times "\tccmp\t" 1} } */
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index 0b0b1b18d..e0120a4a4 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -38,6 +38,9 @@ along with GCC; see the file COPYING3. If not see
#include "explow.h"
#include "tree-dfa.h"
#include "stor-layout.h"
+#include "ccmp.h"
+#include "target.h"
+#include "tree-outof-ssa.h"
/* This set of routines implements a coalesce_list. This is an object which
is used to track pairs of ssa_names which are desirable to coalesce
@@ -854,6 +857,198 @@ live_track_clear_base_vars (live_track *ptr)
bitmap_clear (&ptr->live_base_var);
}
+/* Return true if gimple is a copy assignment. */
+
+static inline bool
+gimple_is_assign_copy_p (gimple *gs)
+{
+ return (is_gimple_assign (gs) && gimple_assign_copy_p (gs)
+ && TREE_CODE (gimple_assign_lhs (gs)) == SSA_NAME
+ && TREE_CODE (gimple_assign_rhs1 (gs)) == SSA_NAME);
+}
+
+#define MAX_CCMP_CONFLICT_NUM 5
+
+/* Clear high-cost conflict graphs. */
+
+static void
+remove_high_cost_graph_for_ccmp (ssa_conflicts *conflict_graph)
+{
+ unsigned x = 0;
+ int add_conflict_num = 0;
+ bitmap b;
+ FOR_EACH_VEC_ELT (conflict_graph->conflicts, x, b)
+ {
+ if (b)
+ {
+ add_conflict_num++;
+ }
+ }
+ if (add_conflict_num >= MAX_CCMP_CONFLICT_NUM)
+ {
+ conflict_graph->conflicts.release ();
+ }
+}
+
+/* Adding a new conflict graph to the original graph. */
+
+static void
+process_add_graph (live_track *live, basic_block bb,
+ ssa_conflicts *conflict_graph)
+{
+ tree use, def;
+ ssa_op_iter iter;
+ gimple *first_visit_stmt = NULL;
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ if (gimple_visited_p (gsi_stmt (gsi)))
+ {
+ first_visit_stmt = gsi_stmt (gsi);
+ break;
+ }
+ }
+ if (!first_visit_stmt)
+ return;
+
+ for (gimple_stmt_iterator gsi = gsi_last_bb (bb);
+ gsi_stmt (gsi) != first_visit_stmt; gsi_prev (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (gimple_visited_p (gsi_stmt (gsi)) && is_gimple_debug (stmt))
+ {
+ continue;
+ }
+ if (gimple_is_assign_copy_p (stmt))
+ {
+ live_track_clear_var (live, gimple_assign_rhs1 (stmt));
+ }
+ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
+ {
+ live_track_process_def (live, def, conflict_graph);
+ }
+ FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
+ {
+ live_track_process_use (live, use);
+ }
+ }
+}
+
+/* Build a conflict graph based on ccmp candidate. */
+
+static void
+add_ccmp_conflict_graph (ssa_conflicts *conflict_graph,
+ tree_live_info_p liveinfo, var_map map, basic_block bb)
+{
+ live_track *live;
+ tree use, def;
+ ssa_op_iter iter;
+ live = new_live_track (map);
+ live_track_init (live, live_on_exit (liveinfo, bb));
+
+ gimple *last_stmt = gsi_stmt (gsi_last_bb (bb));
+ gcc_assert (gimple_cond_lhs (last_stmt));
+
+ auto_vec<tree> stack;
+ stack.safe_push (gimple_cond_lhs (last_stmt));
+ while (!stack.is_empty ())
+ {
+ tree op = stack.pop ();
+ gimple *op_stmt = SSA_NAME_DEF_STMT (op);
+ if (!op_stmt || gimple_bb (op_stmt) != bb
+ || !is_gimple_assign (op_stmt)
+ || !ssa_is_replaceable_p (op_stmt))
+ {
+ continue;
+ }
+ if (gimple_is_assign_copy_p (op_stmt))
+ {
+ live_track_clear_var (live, gimple_assign_rhs1 (op_stmt));
+ }
+ gimple_set_visited (op_stmt, true);
+ FOR_EACH_SSA_TREE_OPERAND (def, op_stmt, iter, SSA_OP_DEF)
+ {
+ live_track_process_def (live, def, conflict_graph);
+ }
+ FOR_EACH_SSA_TREE_OPERAND (use, op_stmt, iter, SSA_OP_USE)
+ {
+ stack.safe_push (use);
+ live_track_process_use (live, use);
+ }
+ }
+
+ process_add_graph (live, bb, conflict_graph);
+ delete_live_track (live);
+ remove_high_cost_graph_for_ccmp (conflict_graph);
+}
+
+/* Determine whether the ccmp conflict graph can be added.
+ i.e,
+
+ ;; basic block 3, loop depth 1
+ ;; pred: 2
+ ;; 3
+ # ivtmp.5_10 = PHI <ivtmp.5_12 (2), ivtmp.5_11 (3)>
+ _7 = b_4 (D) >= c_5 (D);
+ _8 = ivtmp.5_10 == 0;
+ _9 = _7 | _8;
+ ivtmp.5_11 = ivtmp.5_10 - 1;
+ if (_9 != 0)
+ goto <bb 4>; [10.70%]
+ else
+ goto <bb 3>; [89.30%]
+
+ In the above loop, the expression will be replaced:
+
+ _7 replaced by b_4 (D) >= c_5 (D)
+ _8 replaced by ivtmp.5_10 == 0
+
+ If the current case want use the ccmp instruction, then
+
+ _9 can replaced by _7 | _8
+
+ So this requires that ivtmp.5_11 and ivtmp.5_10 be divided into different
+ partitions.
+
+ Now this function can achieve this ability. */
+
+static void
+determine_add_ccmp_conflict_graph (basic_block bb, tree_live_info_p liveinfo,
+ var_map map, ssa_conflicts *graph)
+{
+ if (!flag_ccmp2 || !targetm.gen_ccmp_first || !check_ccmp_candidate (bb))
+ return;
+ for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi);
+ gsi_next (&bsi))
+ {
+ gimple_set_visited (gsi_stmt (bsi), false);
+ }
+ ssa_conflicts *ccmp_conflict_graph;
+ ccmp_conflict_graph = ssa_conflicts_new (num_var_partitions (map));
+ add_ccmp_conflict_graph (ccmp_conflict_graph, liveinfo, map, bb);
+ unsigned x;
+ bitmap b;
+ if (ccmp_conflict_graph)
+ {
+ FOR_EACH_VEC_ELT (ccmp_conflict_graph->conflicts, x, b)
+ {
+ if (!b)
+ continue;
+ unsigned y = bitmap_first_set_bit (b);
+ if (!graph->conflicts[x] || !bitmap_bit_p (graph->conflicts[x], y))
+ {
+ ssa_conflicts_add (graph, x, y);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "potential ccmp: add additional "
+ "conflict-ssa : bb[%d] %d:%d\n",
+ bb->index, x, y);
+ }
+ }
+ }
+ }
+ ssa_conflicts_delete (ccmp_conflict_graph);
+}
/* Build a conflict graph based on LIVEINFO. Any partitions which are in the
partition view of the var_map liveinfo is based on get entries in the
@@ -938,6 +1133,8 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
live_track_process_use (live, var);
}
+ determine_add_ccmp_conflict_graph (bb, liveinfo, map, graph);
+
/* If result of a PHI is unused, looping over the statements will not
record any conflicts since the def was never live. Since the PHI node
is going to be translated out of SSA form, it will insert a copy.
--
2.27.0.windows.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
From 897d637aec3b077eb9ef95b2f4a5f7656e36ebd6 Mon Sep 17 00:00:00 2001
From: benniaobufeijiushiji <linda7@huawei.com>
Date: Wed, 15 Jun 2022 11:33:03 +0800
Subject: [PATCH 03/12] [Backport] loop-invariant: Don't move cold bb
instructions to preheader in RTL
Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=dc1969dab392661cdac1170bbb8c9f83f388580d
When inner loop is unlikely to execute, loop invariant motion would move
cold instrcutions to a hotter loop. This patch adds profile count checking
to fix the problem.
---
gcc/loop-invariant.c | 17 ++++++++++++++---
gcc/testsuite/gcc.dg/loop-invariant-2.c | 20 ++++++++++++++++++++
2 files changed, 34 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/loop-invariant-2.c
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 37ae6549e..24b9bcb11 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -1184,9 +1184,21 @@ find_invariants_insn (rtx_insn *insn, bool always_reached, bool always_executed)
call. */
static void
-find_invariants_bb (basic_block bb, bool always_reached, bool always_executed)
+find_invariants_bb (class loop *loop, basic_block bb, bool always_reached,
+ bool always_executed)
{
rtx_insn *insn;
+ basic_block preheader = loop_preheader_edge (loop)->src;
+
+ /* Don't move insn of cold BB out of loop to preheader to reduce calculations
+ and register live range in hot loop with cold BB. */
+ if (!always_executed && preheader->count > bb->count)
+ {
+ if (dump_file)
+ fprintf (dump_file, "Don't move invariant from bb: %d out of loop %d\n",
+ bb->index, loop->num);
+ return;
+ }
FOR_BB_INSNS (bb, insn)
{
@@ -1215,8 +1227,7 @@ find_invariants_body (class loop *loop, basic_block *body,
unsigned i;
for (i = 0; i < loop->num_nodes; i++)
- find_invariants_bb (body[i],
- bitmap_bit_p (always_reached, i),
+ find_invariants_bb (loop, body[i], bitmap_bit_p (always_reached, i),
bitmap_bit_p (always_executed, i));
}
diff --git a/gcc/testsuite/gcc.dg/loop-invariant-2.c b/gcc/testsuite/gcc.dg/loop-invariant-2.c
new file mode 100644
index 000000000..df3d84585
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/loop-invariant-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-loop2_invariant" } */
+
+volatile int x;
+void
+bar (int, char *, char *);
+void
+foo (int *a, int n, int k)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ if (__builtin_expect (x, 0))
+ bar (k / 5, "one", "two");
+ a[i] = k;
+ }
+}
+
+/* { dg-final { scan-rtl-dump "Don't move invariant from bb: .*out of loop" "loop2_invariant" } } */
--
2.27.0.windows.1

View File

@ -0,0 +1,902 @@
From edd4200e2b3e94d5c124900657b91c22dfe9c557 Mon Sep 17 00:00:00 2001
From: Mingchuan Wu <wumingchuan1992@foxmail.com>
Date: Wed, 15 Jun 2022 16:00:25 +0800
Subject: [PATCH 04/12] [DFE] Add Dead Field Elimination in Struct-Reorg.
We can transform gimple to eliminate fields that are never read
and remove their redundant stmts.
Also we adapted the partial escape_cast_another_ptr for struct relayout.
Add flag -fipa-struct-reorg=3 to enable dead field elimination.
---
gcc/common.opt | 4 +-
gcc/ipa-struct-reorg/ipa-struct-reorg.c | 209 ++++++++++++++++--
gcc/ipa-struct-reorg/ipa-struct-reorg.h | 9 +-
gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c | 86 +++++++
.../gcc.dg/struct/dfe_ele_minus_verify.c | 60 +++++
.../gcc.dg/struct/dfe_mem_ref_offset.c | 58 +++++
.../struct/dfe_mul_layer_ptr_record_bug.c | 30 +++
gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c | 71 ++++++
.../gcc.dg/struct/dfe_ptr_negate_expr.c | 55 +++++
gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c | 55 +++++
gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 21 +-
11 files changed, 639 insertions(+), 19 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c
diff --git a/gcc/common.opt b/gcc/common.opt
index 7fc075d35..b5ea3c7a1 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1884,8 +1884,8 @@ 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, 2)
--fipa-struct-reorg=[0,1,2] adding none, struct-reorg, reorder-fields optimizations.
+Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 3)
+-fipa-struct-reorg=[0,1,2,3] adding none, struct-reorg, reorder-fields, dfe 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 9214ee74a..2fa560239 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "gimple-pretty-print.h"
#include "gimple-iterator.h"
+#include "gimple-walk.h"
#include "cfg.h"
#include "ssa.h"
#include "tree-dfa.h"
@@ -238,11 +239,44 @@ enum srmode
STRUCT_LAYOUT_OPTIMIZE
};
+/* Enum the struct layout optimize level,
+ which should be the same as the option -fstruct-reorg=. */
+
+enum struct_layout_opt_level
+{
+ NONE = 0,
+ STRUCT_REORG,
+ STRUCT_REORDER_FIELDS,
+ DEAD_FIELD_ELIMINATION
+};
+
static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
bool isptrptr (tree type);
srmode current_mode;
+hash_map<tree, tree> replace_type_map;
+
+/* Return true if one of these types is created by struct-reorg. */
+
+static bool
+is_replace_type (tree type1, tree type2)
+{
+ if (replace_type_map.is_empty ())
+ return false;
+ if (type1 == NULL_TREE || type2 == NULL_TREE)
+ return false;
+ tree *type_value = replace_type_map.get (type1);
+ if (type_value)
+ if (types_compatible_p (*type_value, type2))
+ return true;
+ type_value = replace_type_map.get (type2);
+ if (type_value)
+ if (types_compatible_p (*type_value, type1))
+ return true;
+ return false;
+}
+
} // anon namespace
namespace struct_reorg {
@@ -318,12 +352,13 @@ srfunction::simple_dump (FILE *file)
/* Constructor of FIELD. */
srfield::srfield (tree field, srtype *base)
- : offset(int_byte_position (field)),
+ : offset (int_byte_position (field)),
fieldtype (TREE_TYPE (field)),
fielddecl (field),
- base(base),
- type(NULL),
- clusternum(0)
+ base (base),
+ type (NULL),
+ clusternum (0),
+ field_access (EMPTY_FIELD)
{
for(int i = 0;i < max_split; i++)
newfield[i] = NULL_TREE;
@@ -362,6 +397,25 @@ srtype::srtype (tree type)
}
}
+/* Check it if all fields in the RECORD_TYPE are referenced. */
+
+bool
+srtype::has_dead_field (void)
+{
+ bool may_dfe = false;
+ srfield *this_field;
+ unsigned i;
+ FOR_EACH_VEC_ELT (fields, i, this_field)
+ {
+ if (!(this_field->field_access & READ_FIELD))
+ {
+ may_dfe = true;
+ break;
+ }
+ }
+ return may_dfe;
+}
+
/* Mark the type as escaping type E at statement STMT. */
void
@@ -833,6 +887,10 @@ srtype::create_new_type (void)
for (unsigned i = 0; i < fields.length (); i++)
{
srfield *f = fields[i];
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && !(f->field_access & READ_FIELD))
+ continue;
f->create_new_fields (newtype, newfields, newlast);
}
@@ -854,6 +912,16 @@ srtype::create_new_type (void)
warn_padded = save_warn_padded;
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && replace_type_map.get (this->newtype[0]) == NULL)
+ replace_type_map.put (this->newtype[0], this->type);
+ if (dump_file)
+ {
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && has_dead_field ())
+ fprintf (dump_file, "Dead field elimination.\n");
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Created %d types:\n", maxclusters);
@@ -1128,12 +1196,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~96 (first half) are too far away. */
+ 65~127 should pad to 128 but 65~80 (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 > 80 && old_size < 128)
{
new_size = 128;
}
@@ -1272,6 +1340,7 @@ public:
bool has_rewritten_type (srfunction*);
void maybe_mark_or_record_other_side (tree side, tree other, gimple *stmt);
unsigned execute_struct_relayout (void);
+ bool remove_dead_field_stmt (tree lhs);
};
struct ipa_struct_relayout
@@ -3206,6 +3275,90 @@ ipa_struct_reorg::find_vars (gimple *stmt)
}
}
+/* Update field_access in srfield. */
+
+static void
+update_field_access (tree record, tree field, unsigned access, void *data)
+{
+ srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (record);
+ if (this_srtype == NULL)
+ return;
+ srfield *this_srfield = this_srtype->find_field (int_byte_position (field));
+ if (this_srfield == NULL)
+ return;
+
+ this_srfield->field_access |= access;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "record field access %d:", access);
+ print_generic_expr (dump_file, record);
+ fprintf (dump_file, " field:");
+ print_generic_expr (dump_file, field);
+ fprintf (dump_file, "\n");
+ }
+ return;
+}
+
+/* A callback for walk_stmt_load_store_ops to visit store. */
+
+static bool
+find_field_p_store (gimple *, tree node, tree op, void *data)
+{
+ if (TREE_CODE (op) != COMPONENT_REF)
+ return false;
+ tree node_type = TREE_TYPE (node);
+ if (!handled_type (node_type))
+ return false;
+
+ update_field_access (node_type, TREE_OPERAND (op, 1), WRITE_FIELD, data);
+
+ return false;
+}
+
+/* A callback for walk_stmt_load_store_ops to visit load. */
+
+static bool
+find_field_p_load (gimple *, tree node, tree op, void *data)
+{
+ if (TREE_CODE (op) != COMPONENT_REF)
+ return false;
+ tree node_type = TREE_TYPE (node);
+ if (!handled_type (node_type))
+ return false;
+
+ update_field_access (node_type, TREE_OPERAND (op, 1), READ_FIELD, data);
+
+ return false;
+}
+
+/* Determine whether the stmt should be deleted. */
+
+bool
+ipa_struct_reorg::remove_dead_field_stmt (tree lhs)
+{
+ tree base = NULL_TREE;
+ bool indirect = false;
+ srtype *t = NULL;
+ srfield *f = NULL;
+ bool realpart = false;
+ bool imagpart = false;
+ bool address = false;
+ bool escape_from_base = false;
+ if (!get_type_field (lhs, base, indirect, t, f, realpart, imagpart,
+ address, escape_from_base))
+ return false;
+ if (t ==NULL)
+ return false;
+ if (t->newtype[0] == t->type)
+ return false;
+ if (f == NULL)
+ return false;
+ if (f->newfield[0] == NULL
+ && (f->field_access & WRITE_FIELD))
+ return true;
+ return false;
+}
+
/* Maybe record access of statement for further analaysis. */
void
@@ -3227,6 +3380,13 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt)
default:
break;
}
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION)
+ {
+ /* Look for loads and stores. */
+ walk_stmt_load_store_ops (stmt, this, find_field_p_load,
+ find_field_p_store);
+ }
}
/* Calculate the multiplier. */
@@ -3543,8 +3703,11 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, gimple
}
else if (type != d->type)
{
- type->mark_escape (escape_cast_another_ptr, stmt);
- d->type->mark_escape (escape_cast_another_ptr, stmt);
+ if (!is_replace_type (d->type->type, type->type))
+ {
+ type->mark_escape (escape_cast_another_ptr, stmt);
+ d->type->mark_escape (escape_cast_another_ptr, stmt);
+ }
}
/* x_1 = y.x_nodes; void *x;
Directly mark the structure pointer type assigned
@@ -4131,8 +4294,9 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
}
/* If we have a non void* or a decl (which is hard to track),
then mark the type as escaping. */
- if (!VOID_POINTER_P (TREE_TYPE (newdecl))
- || DECL_P (newdecl))
+ if (replace_type_map.get (type->type) == NULL
+ && (!VOID_POINTER_P (TREE_TYPE (newdecl))
+ || DECL_P (newdecl)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -4142,7 +4306,7 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
print_generic_expr (dump_file, TREE_TYPE (newdecl));
fprintf (dump_file, "\n");
}
- type->mark_escape (escape_cast_another_ptr, stmt);
+ type->mark_escape (escape_cast_another_ptr, stmt);
return;
}
/* At this point there should only be unkown void* ssa names. */
@@ -4465,11 +4629,13 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
return;
}
+ if (!is_replace_type (t1->type, type->type))
+ {
+ if (t1)
+ t1->mark_escape (escape_cast_another_ptr, stmt);
- if (t1)
- t1->mark_escape (escape_cast_another_ptr, stmt);
-
- type->mark_escape (escape_cast_another_ptr, stmt);
+ type->mark_escape (escape_cast_another_ptr, stmt);
+ }
}
@@ -5722,6 +5888,19 @@ bool
ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
{
bool remove = false;
+
+ if (current_mode == STRUCT_LAYOUT_OPTIMIZE
+ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION
+ && remove_dead_field_stmt (gimple_assign_lhs (stmt)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n rewriting statement (remove): \n");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+ return true;
+ }
+
if (gimple_clobber_p (stmt))
{
tree lhs = gimple_assign_lhs (stmt);
diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
index 54b0dc655..936c0fa6f 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
@@ -142,6 +142,7 @@ public:
bool create_new_type (void);
void analyze (void);
+ bool has_dead_field (void);
void mark_escape (escape_type, gimple *stmt);
bool has_escaped (void)
{
@@ -163,6 +164,12 @@ public:
}
};
+/* Bitflags used for determining if a field
+ is never accessed, read or written. */
+const unsigned EMPTY_FIELD = 0x0u;
+const unsigned READ_FIELD = 0x01u;
+const unsigned WRITE_FIELD = 0x02u;
+
struct srfield
{
unsigned HOST_WIDE_INT offset;
@@ -174,7 +181,7 @@ struct srfield
unsigned clusternum;
tree newfield[max_split];
-
+ unsigned field_access; /* FIELD_DECL -> bitflag (use for dfe). */
// Constructors
srfield (tree field, srtype *base);
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
new file mode 100644
index 000000000..4261d2352
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c
@@ -0,0 +1,86 @@
+/* { 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;
+
+/* let it escape_array, "Type is used in an array [not handled yet]". */
+network_t* net[2];
+arc_p stop_arcs = NULL;
+
+int
+main ()
+{
+ net[0] = (network_t*) calloc (1, sizeof(network_t));
+ net[0]->arcs = (arc_p) calloc (MAX, sizeof (arc_t));
+ stop_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
+
+ net[0]->arcs->id = 100;
+
+ for (unsigned i = 0; i < 3; i++)
+ {
+ net[0]->arcs->id = net[0]->arcs->id + 2;
+ stop_arcs->cost = net[0]->arcs->id / 2;
+ stop_arcs->net_add = net[0];
+ printf("stop_arcs->cost = %ld\n", stop_arcs->cost);
+ net[0]->arcs++;
+ stop_arcs++;
+ }
+
+ if( net[1] != 0 && stop_arcs != 0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c
new file mode 100644
index 000000000..42d38c63a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c
@@ -0,0 +1,60 @@
+// verify newarc[cmp-1].flow
+/* { 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;
+
+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;
+arc_p ap = NULL;
+
+int
+main ()
+{
+ ap = (arc_p) calloc(MAX, sizeof(arc_t));
+ printf("%d\n", ap[0].id);
+ for (int i = 1; i < MAX; i++)
+ {
+ ap[i-1].id = 500;
+ }
+ printf("%d\n", ap[0].id);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c
new file mode 100644
index 000000000..53583fe82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c
@@ -0,0 +1,58 @@
+/* Supports the MEM_REF offset.
+ _1 = MEM[(struct arc *)ap_4 + 72B].flow;
+ Old rewrite_1 = ap.reorder.0_8->flow;
+ New rewrite_1 = MEM[(struct arc.reorder.0 *)ap.reorder.0_8 + 64B].flow. */
+/* { 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;
+
+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;
+};
+
+int
+main ()
+{
+ const int MAX = 100;
+ /* A similar scenario can be reproduced only by using local variables. */
+ arc_p ap = NULL;
+ ap = (arc_p) calloc(MAX, sizeof(arc_t));
+ printf("%d\n", ap[1].flow);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c
new file mode 100644
index 000000000..fd675ec2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct T_HASH_ENTRY
+{
+ unsigned int hash;
+ unsigned int klen;
+ char *key;
+} iHashEntry;
+
+typedef struct T_HASH
+{
+ unsigned int size;
+ unsigned int fill;
+ unsigned int keys;
+
+ iHashEntry **array;
+} uHash;
+
+uHash *retval;
+
+int
+main() {
+ retval->array = (iHashEntry **)calloc(sizeof(iHashEntry *), retval->size);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c
new file mode 100644
index 000000000..600e7908b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c
@@ -0,0 +1,71 @@
+// support POINTER_DIFF_EXPR & NOP_EXPR to avoid
+// escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt"
+/* { 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;
+};
+
+int
+main ()
+{
+ arc_t *old_arcs;
+ node_t *node;
+ node_t *stop;
+ size_t off;
+ network_t* net;
+
+ for( ; node->number < stop->number; node++ )
+ {
+ off = node->basic_arc - old_arcs;
+ node->basic_arc = (arc_t *)(net->arcs + off);
+ }
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 3 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c
new file mode 100644
index 000000000..f411364a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c
@@ -0,0 +1,55 @@
+// support NEGATE_EXPR rewriting
+/* { 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;
+
+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;
+};
+
+int
+main ()
+{
+ int64_t susp = 0;
+ const int MAX = 100;
+ arc_p ap = (arc_p) calloc(MAX, sizeof(arc_t));
+ ap -= susp;
+ printf("%d\n", ap[1].flow);
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c
new file mode 100644
index 000000000..a4e723763
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c
@@ -0,0 +1,55 @@
+// release escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]";
+/* { 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;
+
+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;
+arc_t **ap = NULL;
+
+int
+main ()
+{
+ ap = (arc_t**) malloc(MAX * sizeof(arc_t*));
+ (*ap)[0].id = 300;
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
index 67b3ac2d5..ac5585813 100644
--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
@@ -64,8 +64,27 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout
"" "-fipa-struct-reorg=1 -fdump-ipa-all -flto-partition=one -fwhole-program"
# -fipa-struct-reorg=2
-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_prof_*.c]] \
"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_ratio_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_prof_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/struct_reorg*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sr_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/complete_struct_relayout.c]] \
+ "" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
+
+# -fipa-struct-reorg=3
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \
+ "" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
+
# All done.
torture-finish
dg-finish
--
2.27.0.windows.1

View File

@ -0,0 +1,143 @@
From d8753de2129d230afc9a887d5804747c69824a68 Mon Sep 17 00:00:00 2001
From: zhaowenyu <804544223@qq.com>
Date: Mon, 20 Jun 2022 11:24:45 +0800
Subject: [PATCH 05/12] [Backport] ipa-sra: Fix thinko when overriding
safe_to_import_accesses (PR 101066)
Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=5aa28c8cf15cd254cc5a3a12278133b93b8b017f
ipa-sra: Fix thinko when overriding safe_to_import_accesses (PR 101066)
The "new" IPA-SRA has a more difficult job than the previous
not-truly-IPA version when identifying situations in which a parameter
passed by reference can be passed into a third function and only thee
converted to one passed by value (and possibly "split" at the same
time).
In order to allow this, two conditions must be fulfilled. First the
call to the third function must happen before any modifications of
memory, because it could change the value passed by reference.
Second, in order to make sure we do not introduce new (invalid)
dereferences, the call must postdominate the entry BB.
The second condition is actually not necessary if the caller function
is also certain to dereference the pointer but the first one must
still hold. Unfortunately, the code making this overriding decision
also happen to trigger when the first condition is not fulfilled.
This is fixed in the following patch.
gcc/ChangeLog:
2021-06-16 Martin Jambor <mjambor@suse.cz>
(cherry picked from commit 763121ccd908f52bc666f277ea2cf42110b3aad9)
---
gcc/ipa-sra.c | 15 +++++++++++++--
gcc/testsuite/gcc.dg/ipa/pr101066.c | 20 ++++++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/ipa/pr101066.c
diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c
index b706fceff..1cb30afc3 100644
--- a/gcc/ipa-sra.c
+++ b/gcc/ipa-sra.c
@@ -340,7 +340,7 @@ class isra_call_summary
public:
isra_call_summary ()
: m_arg_flow (), m_return_ignored (false), m_return_returned (false),
- m_bit_aligned_arg (false)
+ m_bit_aligned_arg (false), m_before_any_store (false)
{}
void init_inputs (unsigned arg_count);
@@ -359,6 +359,10 @@ public:
/* Set when any of the call arguments are not byte-aligned. */
unsigned m_bit_aligned_arg : 1;
+
+ /* Set to true if the call happend before any (other) store to memory in the
+ caller. */
+ unsigned m_before_any_store : 1;
};
/* Class to manage function summaries. */
@@ -472,6 +476,8 @@ isra_call_summary::dump (FILE *f)
fprintf (f, " return value ignored\n");
if (m_return_returned)
fprintf (f, " return value used only to compute caller return value\n");
+ if (m_before_any_store)
+ fprintf (f, " happens before any store to memory\n");
for (unsigned i = 0; i < m_arg_flow.length (); i++)
{
fprintf (f, " Parameter %u:\n", i);
@@ -516,6 +522,7 @@ ipa_sra_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
new_sum->m_return_ignored = old_sum->m_return_ignored;
new_sum->m_return_returned = old_sum->m_return_returned;
new_sum->m_bit_aligned_arg = old_sum->m_bit_aligned_arg;
+ new_sum->m_before_any_store = old_sum->m_before_any_store;
}
@@ -2355,6 +2362,7 @@ process_scan_results (cgraph_node *node, struct function *fun,
unsigned count = gimple_call_num_args (call_stmt);
isra_call_summary *csum = call_sums->get_create (cs);
csum->init_inputs (count);
+ csum->m_before_any_store = uses_memory_as_obtained;
for (unsigned argidx = 0; argidx < count; argidx++)
{
if (!csum->m_arg_flow[argidx].pointer_pass_through)
@@ -2601,6 +2609,7 @@ isra_write_edge_summary (output_block *ob, cgraph_edge *e)
bp_pack_value (&bp, csum->m_return_ignored, 1);
bp_pack_value (&bp, csum->m_return_returned, 1);
bp_pack_value (&bp, csum->m_bit_aligned_arg, 1);
+ bp_pack_value (&bp, csum->m_before_any_store, 1);
streamer_write_bitpack (&bp);
}
@@ -2719,6 +2728,7 @@ isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs)
csum->m_return_ignored = bp_unpack_value (&bp, 1);
csum->m_return_returned = bp_unpack_value (&bp, 1);
csum->m_bit_aligned_arg = bp_unpack_value (&bp, 1);
+ csum->m_before_any_store = bp_unpack_value (&bp, 1);
}
/* Read intraprocedural analysis information about NODE and all of its outgoing
@@ -3475,7 +3485,8 @@ param_splitting_across_edge (cgraph_edge *cs)
}
else if (!ipf->safe_to_import_accesses)
{
- if (!all_callee_accesses_present_p (param_desc, arg_desc))
+ if (!csum->m_before_any_store
+ || !all_callee_accesses_present_p (param_desc, arg_desc))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " %u->%u: cannot import accesses.\n",
diff --git a/gcc/testsuite/gcc.dg/ipa/pr101066.c b/gcc/testsuite/gcc.dg/ipa/pr101066.c
new file mode 100644
index 000000000..1ceb6e431
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr101066.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-Os -fno-ipa-cp -fno-inline" } */
+
+int a = 1, c, d, e;
+int *b = &a;
+static int g(int *h) {
+ c = *h;
+ return d;
+}
+static void f(int *h) {
+ e = *h;
+ *b = 0;
+ g(h);
+}
+int main() {
+ f(b);
+ if (c)
+ __builtin_abort();
+ return 0;
+}
--
2.27.0.windows.1

View File

@ -0,0 +1,59 @@
From ea059ab02ac79eba1c05d6e05cbb2590c47d7c1f Mon Sep 17 00:00:00 2001
From: zhaowenyu <804544223@qq.com>
Date: Thu, 23 Jun 2022 10:16:08 +0800
Subject: [PATCH 06/12] [Backport] ifcvt: Allow constants for
noce_convert_multiple.
Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=9b8eaa282250ad260e01d164093b597579db00d9
This lifts the restriction of not allowing constants for noce_convert_multiple.
The code later checks if a valid sequence is produced anyway.
gcc/ChangeLog:
* ifcvt.cc (noce_convert_multiple_sets): Allow constants.
(bb_ok_for_noce_convert_multiple_sets): Likewise.
---
gcc/ifcvt.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 977dd1bd4..2452f231c 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -3252,7 +3252,9 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
we'll end up trying to emit r4:HI = cond ? (r1:SI) : (r3:HI).
Wrap the two cmove operands into subregs if appropriate to prevent
that. */
- if (GET_MODE (new_val) != GET_MODE (temp))
+
+ if (!CONSTANT_P (new_val)
+ && GET_MODE (new_val) != GET_MODE (temp))
{
machine_mode src_mode = GET_MODE (new_val);
machine_mode dst_mode = GET_MODE (temp);
@@ -3263,7 +3265,8 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
}
new_val = lowpart_subreg (dst_mode, new_val, src_mode);
}
- if (GET_MODE (old_val) != GET_MODE (temp))
+ if (!CONSTANT_P (old_val)
+ && GET_MODE (old_val) != GET_MODE (temp))
{
machine_mode src_mode = GET_MODE (old_val);
machine_mode dst_mode = GET_MODE (temp);
@@ -3392,9 +3395,9 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb)
if (!REG_P (dest))
return false;
- if (!(REG_P (src)
- || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
- && subreg_lowpart_p (src))))
+ if (!((REG_P (src) || CONSTANT_P (src))
+ || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
+ && subreg_lowpart_p (src))))
return false;
/* Destination must be appropriate for a conditional write. */
--
2.27.0.windows.1

View File

@ -0,0 +1,40 @@
From beeb0fb50c7e40ee3d79044abc6408f760d6584a Mon Sep 17 00:00:00 2001
From: zhaowenyu <804544223@qq.com>
Date: Thu, 23 Jun 2022 10:40:46 +0800
Subject: [PATCH 07/12] [Backport] Register --sysroot in the driver switches
table
Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=48e2d9b7b88dabed336cd098cd212d0e53c5125f
This change adjusts the processing of --sysroot to save the option in the internal "switches"
array, which lets self-specs test for it and provide a default value possibly dependent on
environment variables, as in
--with-specs=%{!-sysroot*:--sysroot=%:getenv("WIND_BASE" /target)}
2021-12-20 Olivier Hainque <hainque@adacore.com>
gcc/
* gcc.c (driver_handle_option): do_save --sysroot.
---
gcc/gcc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/gcc/gcc.c b/gcc/gcc.c
index b55075b14..655beffcc 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -4190,7 +4190,9 @@ driver_handle_option (struct gcc_options *opts,
case OPT__sysroot_:
target_system_root = arg;
target_system_root_changed = 1;
- do_save = false;
+ /* Saving this option is useful to let self-specs decide to
+ provide a default one. */
+ do_save = true;
break;
case OPT_time_:
--
2.27.0.windows.1

665
0042-DFE-Fix-bugs.patch Normal file
View File

@ -0,0 +1,665 @@
From f8308a2b440efe124cd6ff59924f135e85e53888 Mon Sep 17 00:00:00 2001
From: Mingchuan Wu <wumingchuan1992@foxmail.com>
Date: Sat, 18 Jun 2022 17:51:04 +0800
Subject: [PATCH 08/12] [DFE] Fix bugs
Fix bugs:
1. Fixed a bug in check replace type.
2. Use new to update field access for ref.
3. We now replace the dead fields in stmt by creating a new ssa.
4. The replaced type is no longer optimized in NORMAL mode.
Also we added 5 dejaGNU test cases.
---
gcc/ipa-struct-reorg/ipa-struct-reorg.c | 77 ++++++---
gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c | 56 ++++++
gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c | 162 ++++++++++++++++++
gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c | 126 ++++++++++++++
.../gcc.dg/struct/dfe_extr_tcp_usrreq.c | 58 +++++++
.../gcc.dg/struct/dfe_extr_ui_main.c | 61 +++++++
6 files changed, 516 insertions(+), 24 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c
create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c
diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.c b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
index 2fa560239..00dc4bf1d 100644
--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.c
+++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.c
@@ -252,6 +252,7 @@ enum struct_layout_opt_level
static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
bool isptrptr (tree type);
+void get_base (tree &base, tree expr);
srmode current_mode;
@@ -631,7 +632,15 @@ srtype::analyze (void)
into 2 different structures. In future we intend to add profile
info and/or static heuristics to differentiate splitting process. */
if (fields.length () == 2)
- fields[1]->clusternum = 1;
+ {
+ for (hash_map<tree, tree>::iterator it = replace_type_map.begin ();
+ it != replace_type_map.end (); ++it)
+ {
+ if (types_compatible_p ((*it).second, this->type))
+ return;
+ }
+ fields[1]->clusternum = 1;
+ }
/* Otherwise we do nothing. */
if (fields.length () >= 3)
@@ -3278,12 +3287,33 @@ ipa_struct_reorg::find_vars (gimple *stmt)
/* Update field_access in srfield. */
static void
-update_field_access (tree record, tree field, unsigned access, void *data)
+update_field_access (tree node, tree op, unsigned access, void *data)
{
- srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (record);
+ HOST_WIDE_INT offset = 0;
+ switch (TREE_CODE (op))
+ {
+ case COMPONENT_REF:
+ {
+ offset = int_byte_position (TREE_OPERAND (op, 1));
+ break;
+ }
+ case MEM_REF:
+ {
+ offset = tree_to_uhwi (TREE_OPERAND (op, 1));
+ break;
+ }
+ default:
+ return;
+ }
+ tree base = node;
+ get_base (base, node);
+ srdecl *this_srdecl = ((ipa_struct_reorg *)data)->find_decl (base);
+ if (this_srdecl == NULL)
+ return;
+ srtype *this_srtype = this_srdecl->type;
if (this_srtype == NULL)
return;
- srfield *this_srfield = this_srtype->find_field (int_byte_position (field));
+ srfield *this_srfield = this_srtype->find_field (offset);
if (this_srfield == NULL)
return;
@@ -3291,9 +3321,9 @@ update_field_access (tree record, tree field, unsigned access, void *data)
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "record field access %d:", access);
- print_generic_expr (dump_file, record);
+ print_generic_expr (dump_file, this_srtype->type);
fprintf (dump_file, " field:");
- print_generic_expr (dump_file, field);
+ print_generic_expr (dump_file, this_srfield->fielddecl);
fprintf (dump_file, "\n");
}
return;
@@ -3302,15 +3332,10 @@ update_field_access (tree record, tree field, unsigned access, void *data)
/* A callback for walk_stmt_load_store_ops to visit store. */
static bool
-find_field_p_store (gimple *, tree node, tree op, void *data)
+find_field_p_store (gimple *stmt ATTRIBUTE_UNUSED,
+ tree node, tree op, void *data)
{
- if (TREE_CODE (op) != COMPONENT_REF)
- return false;
- tree node_type = TREE_TYPE (node);
- if (!handled_type (node_type))
- return false;
-
- update_field_access (node_type, TREE_OPERAND (op, 1), WRITE_FIELD, data);
+ update_field_access (node, op, WRITE_FIELD, data);
return false;
}
@@ -3318,15 +3343,10 @@ find_field_p_store (gimple *, tree node, tree op, void *data)
/* A callback for walk_stmt_load_store_ops to visit load. */
static bool
-find_field_p_load (gimple *, tree node, tree op, void *data)
+find_field_p_load (gimple *stmt ATTRIBUTE_UNUSED,
+ tree node, tree op, void *data)
{
- if (TREE_CODE (op) != COMPONENT_REF)
- return false;
- tree node_type = TREE_TYPE (node);
- if (!handled_type (node_type))
- return false;
-
- update_field_access (node_type, TREE_OPERAND (op, 1), READ_FIELD, data);
+ update_field_access (node, op, READ_FIELD, data);
return false;
}
@@ -4629,7 +4649,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, vec<
return;
}
- if (!is_replace_type (t1->type, type->type))
+ if (!is_replace_type (inner_type (t), type->type))
{
if (t1)
t1->mark_escape (escape_cast_another_ptr, stmt);
@@ -5898,7 +5918,16 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
fprintf (dump_file, "\n rewriting statement (remove): \n");
print_gimple_stmt (dump_file, stmt, 0);
}
- return true;
+ /* Replace the dead field in stmt by creating a dummy ssa. */
+ tree dummy_ssa = make_ssa_name (TREE_TYPE (gimple_assign_lhs (stmt)));
+ gimple_assign_set_lhs (stmt, dummy_ssa);
+ update_stmt (stmt);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "To: \n");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+ return false;
}
if (gimple_clobber_p (stmt))
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c
new file mode 100644
index 000000000..13a226ee8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c
@@ -0,0 +1,56 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_4__ TYPE_2__;
+typedef struct TYPE_3__ TYPE_1__;
+
+typedef int uint8_t;
+typedef int uint16_t;
+
+struct TYPE_4__
+{
+ size_t cpu_id;
+};
+
+struct TYPE_3__
+{
+ int cpuc_dtrace_flags;
+};
+
+TYPE_2__ *CPU;
+volatile int CPU_DTRACE_FAULT;
+TYPE_1__ *cpu_core;
+scalar_t__ dtrace_load8 (uintptr_t);
+
+__attribute__((used)) static int
+dtrace_bcmp (const void *s1, const void *s2, size_t len)
+{
+ volatile uint16_t *flags;
+ flags = (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
+ if (s1 == s2)
+ return (0);
+ if (s1 == NULL || s2 == NULL)
+ return (1);
+ if (s1 != s2 && len != 0)
+ {
+ const uint8_t *ps1 = s1;
+ const uint8_t *ps2 = s2;
+ do
+ {
+ if (dtrace_load8 ((uintptr_t)ps1++) != *ps2++)
+ return (1);
+ }
+ while (--len != 0 && !(*flags & CPU_DTRACE_FAULT));
+ }
+ return (0);
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c
new file mode 100644
index 000000000..1fff2cb9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c
@@ -0,0 +1,162 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+struct mrb_context
+{
+ size_t stack;
+ size_t stbase;
+ size_t stend;
+ size_t eidx;
+ int *ci;
+ int *cibase;
+ int status;
+};
+
+struct RObject
+{
+ int dummy;
+};
+
+struct RHash
+{
+ int dummy;
+};
+
+struct RFiber
+{
+ struct mrb_context *cxt;
+};
+
+struct RClass
+{
+ int dummy;
+};
+
+struct RBasic
+{
+ int tt;
+};
+
+struct RArray
+{
+ int dummy;
+};
+
+typedef int mrb_state;
+typedef int mrb_gc;
+typedef int mrb_callinfo;
+size_t ARY_LEN (struct RArray *);
+size_t MRB_ENV_STACK_LEN (struct RBasic *);
+int MRB_FIBER_TERMINATED;
+
+#define MRB_TT_ARRAY 140
+#define MRB_TT_CLASS 139
+#define MRB_TT_DATA 138
+#define MRB_TT_ENV 137
+#define MRB_TT_EXCEPTION 136
+#define MRB_TT_FIBER 135
+#define MRB_TT_HASH 134
+#define MRB_TT_ICLASS 133
+#define MRB_TT_MODULE 132
+#define MRB_TT_OBJECT 131
+#define MRB_TT_PROC 130
+#define MRB_TT_RANGE 129
+#define MRB_TT_SCLASS 128
+
+size_t ci_nregs (int *);
+int gc_mark_children (int *, int *, struct RBasic *);
+size_t mrb_gc_mark_hash_size (int *, struct RHash *);
+size_t mrb_gc_mark_iv_size (int *, struct RObject *);
+size_t mrb_gc_mark_mt_size (int *, struct RClass *);
+
+__attribute__((used)) static size_t
+gc_gray_mark (mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
+{
+ size_t children = 0;
+ gc_mark_children (mrb, gc, obj);
+ switch (obj->tt)
+ {
+ case MRB_TT_ICLASS:
+ children++;
+ break;
+
+ case MRB_TT_CLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_MODULE:
+ {
+ struct RClass *c = (struct RClass *)obj;
+ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj);
+ children += mrb_gc_mark_mt_size (mrb, c);
+ children ++;
+ }
+ break;
+
+ case MRB_TT_OBJECT:
+ case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
+ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj);
+ break;
+
+ case MRB_TT_ENV:
+ children += MRB_ENV_STACK_LEN (obj);
+ break;
+
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber *)obj)->cxt;
+ size_t i;
+ mrb_callinfo *ci;
+ if (!c || c->status == MRB_FIBER_TERMINATED)
+ break;
+
+ i = c->stack - c->stbase;
+ if (c->ci)
+ {
+ i += ci_nregs (c->ci);
+ }
+ if (c->stbase + i > c->stend)
+ i = c->stend - c->stbase;
+
+ children += i;
+ children += c->eidx;
+ if (c->cibase)
+ {
+ for (i = 0, ci = c->cibase; ci <= c->ci; i++, ci++)
+ ;
+ }
+ children += i;
+ }
+ break;
+
+ case MRB_TT_ARRAY:
+ {
+ struct RArray *a = (struct RArray *)obj;
+ children += ARY_LEN (a);
+ }
+ break;
+
+ case MRB_TT_HASH:
+ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj);
+ children += mrb_gc_mark_hash_size (mrb, (struct RHash *)obj);
+ break;
+
+ case MRB_TT_PROC:
+ case MRB_TT_RANGE:
+ children += 2;
+ break;
+ default:
+ break;
+ }
+
+ return children;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c
new file mode 100644
index 000000000..0f577667c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c
@@ -0,0 +1,126 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_6__ TYPE_3__;
+typedef struct TYPE_5__ TYPE_2__;
+typedef struct TYPE_4__ TYPE_1__;
+
+struct io_accel2_cmd
+{
+ int dummy;
+};
+
+struct hpsa_tmf_struct
+{
+ int it_nexus;
+};
+
+struct hpsa_scsi_dev_t
+{
+ int nphysical_disks;
+ int ioaccel_handle;
+ struct hpsa_scsi_dev_t **phys_disk;
+};
+
+struct ctlr_info
+{
+ TYPE_3__ *pdev;
+ struct io_accel2_cmd *ioaccel2_cmd_pool;
+};
+struct TYPE_4__
+{
+ int LunAddrBytes;
+};
+
+struct TYPE_5__
+{
+ TYPE_1__ LUN;
+};
+
+struct CommandList
+{
+ size_t cmdindex;
+ int cmd_type;
+ struct hpsa_scsi_dev_t *phys_disk;
+ TYPE_2__ Header;
+};
+
+struct TYPE_6__
+{
+ int dev;
+};
+
+int BUG ();
+#define CMD_IOACCEL1 132
+#define CMD_IOACCEL2 131
+#define CMD_IOCTL_PEND 130
+#define CMD_SCSI 129
+#define IOACCEL2_TMF 128
+int dev_err (int *, char *, int);
+scalar_t__ hpsa_is_cmd_idle (struct CommandList *);
+int le32_to_cpu (int);
+int test_memcmp (unsigned char *, int *, int);
+
+__attribute__((used)) static bool
+hpsa_cmd_dev_match (struct ctlr_info *h, struct CommandList *c,
+ struct hpsa_scsi_dev_t *dev, unsigned char *scsi3addr)
+{
+ int i;
+ bool match = false;
+ struct io_accel2_cmd * c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
+ struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *)c2;
+
+ if (hpsa_is_cmd_idle (c))
+ return false;
+
+ switch (c->cmd_type)
+ {
+ case CMD_SCSI:
+ case CMD_IOCTL_PEND:
+ match = !test_memcmp (scsi3addr, &c->Header.LUN.LunAddrBytes,
+ sizeof (c->Header.LUN.LunAddrBytes));
+ break;
+
+ case CMD_IOACCEL1:
+ case CMD_IOACCEL2:
+ if (c->phys_disk == dev)
+ {
+ match = true;
+ }
+ else
+ {
+ for (i = 0; i < dev->nphysical_disks && !match; i++)
+ {
+ match = dev->phys_disk[i] == c->phys_disk;
+ }
+ }
+ break;
+
+ case IOACCEL2_TMF:
+ for (i = 0; i < dev->nphysical_disks && !match; i++)
+ {
+ match = dev->phys_disk[i]->ioaccel_handle ==
+ le32_to_cpu (ac->it_nexus);
+ }
+ break;
+
+ case 0:
+ match = false;
+ break;
+ default:
+ dev_err (&h->pdev->dev, "unexpected cmd_type: %d\n", c->cmd_type);
+ BUG ();
+ }
+
+ return match;
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c
new file mode 100644
index 000000000..5570c762e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c
@@ -0,0 +1,58 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+struct tcpcb
+{
+ int t_state;
+};
+
+struct socket
+{
+ int dummy;
+};
+
+struct proc
+{
+ int dummy;
+};
+
+struct inpcb
+{
+ scalar_t__ inp_lport;
+};
+
+int COMMON_END (int);
+int COMMON_START ();
+int PRU_LISTEN;
+int TCPS_LISTEN;
+int in_pcbbind (struct inpcb *, int *, struct proc *);
+struct inpcb* sotoinpcb (struct socket *);
+
+__attribute__((used)) static void
+tcp_usr_listen (struct socket *so, struct proc *p)
+{
+ int error = 0;
+ struct inpcb *inp = sotoinpcb (so);
+ struct tcpcb *tp;
+
+ COMMON_START ();
+ if (inp->inp_lport == 0)
+ {
+ error = in_pcbbind (inp, NULL, p);
+ }
+ if (error == 0)
+ {
+ tp->t_state = TCPS_LISTEN;
+ }
+ COMMON_END (PRU_LISTEN);
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "struct_layout" } } */
diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c
new file mode 100644
index 000000000..50ab9cc24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c
@@ -0,0 +1,61 @@
+/* { dg-do compile} */
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long scalar_t__;
+typedef int bool;
+#define false 0
+#define true 1
+
+typedef struct TYPE_4__ TYPE_2__;
+typedef struct TYPE_3__ TYPE_1__;
+
+struct TYPE_4__
+{
+ size_t modCount;
+ TYPE_1__ *modList;
+};
+
+struct TYPE_3__
+{
+ void *modDescr;
+ void *modName;
+};
+
+size_t MAX_MODS;
+void *String_Alloc (char *);
+int test_strlen (char *);
+int trap_FD_GetFileList (char *, char *, char *, int);
+TYPE_2__ uiInfo;
+
+__attribute__((used)) static void
+UI_LoadMods ()
+{
+ int numdirs;
+ char dirlist[2048];
+ char *dirptr;
+ char *descptr;
+ int i;
+ int dirlen;
+
+ uiInfo.modCount = 0;
+ numdirs = trap_FD_GetFileList ("$modelist", "", dirlist, sizeof (dirlist));
+ dirptr = dirlist;
+ for (i = 0; i < numdirs; i++)
+ {
+ dirlen = test_strlen (dirptr) + 1;
+ descptr = dirptr + dirlen;
+ uiInfo.modList[uiInfo.modCount].modName = String_Alloc (dirptr);
+ uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc (descptr);
+ dirptr += dirlen + test_strlen (descptr) + 1;
+ uiInfo.modCount++;
+ if (uiInfo.modCount >= MAX_MODS)
+ {
+ break;
+ }
+ }
+}
+
+/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "struct_layout" } } */
--
2.27.0.windows.1

View File

@ -0,0 +1,165 @@
From b4770dd95fa342671d53c9de2077d77ee07b68dd Mon Sep 17 00:00:00 2001
From: zhaowenyu <804544223@qq.com>
Date: Sat, 25 Jun 2022 00:41:50 +0800
Subject: [PATCH 09/12] [Backport] Extend special_memory_constraint.
Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=4de7b010038933dd6ca96bf186ca49f243d0def6
For operand with special_memory_constraint, there could be a wrapper for memory_operand.
Extract mem for operand for conditional judgement like MEM_P, also for record_address_regs.
---
gcc/ira-costs.c | 12 +++++++-----
gcc/ira.c | 2 +-
gcc/lra-constraints.c | 28 +++++++++++++++++++++++-----
gcc/recog.c | 7 +++++--
gcc/rtl.h | 1 +
5 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index 6891156b5..aeda6588b 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -781,7 +781,8 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
case CT_SPECIAL_MEMORY:
insn_allows_mem[i] = allows_mem[i] = 1;
- if (MEM_P (op) && constraint_satisfied_p (op, cn))
+ if (MEM_P (extract_mem_from_operand (op))
+ && constraint_satisfied_p (op, cn))
win = 1;
break;
@@ -1397,15 +1398,16 @@ record_operand_costs (rtx_insn *insn, enum reg_class *pref)
commutative. */
for (i = 0; i < recog_data.n_operands; i++)
{
+ rtx op_mem = extract_mem_from_operand (recog_data.operand[i]);
memcpy (op_costs[i], init_cost, struct_costs_size);
if (GET_CODE (recog_data.operand[i]) == SUBREG)
recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
- if (MEM_P (recog_data.operand[i]))
- record_address_regs (GET_MODE (recog_data.operand[i]),
- MEM_ADDR_SPACE (recog_data.operand[i]),
- XEXP (recog_data.operand[i], 0),
+ if (MEM_P (op_mem))
+ record_address_regs (GET_MODE (op_mem),
+ MEM_ADDR_SPACE (op_mem),
+ XEXP (op_mem, 0),
0, MEM, SCRATCH, frequency * 2);
else if (constraints[i][0] == 'p'
|| (insn_extra_address_constraint
diff --git a/gcc/ira.c b/gcc/ira.c
index 681ec2f46..c13650229 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1868,7 +1868,7 @@ ira_setup_alts (rtx_insn *insn)
case CT_MEMORY:
case CT_SPECIAL_MEMORY:
- if (MEM_P (op))
+ if (MEM_P (extract_mem_from_operand (op)))
goto op_success;
win_p = true;
break;
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 7cc479b30..df75c7b94 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -409,14 +409,34 @@ valid_address_p (rtx op, struct address_info *ad,
return valid_address_p (ad->mode, *ad->outer, ad->as);
}
+/* For special_memory_operand, it could be false for MEM_P (op),
+ i.e. bcst_mem_operand in i386 backend.
+ Extract and return real memory operand or op. */
+rtx
+extract_mem_from_operand (rtx op)
+{
+ for (rtx x = op;; x = XEXP (x, 0))
+ {
+ if (MEM_P (x))
+ return x;
+ if (GET_RTX_LENGTH (GET_CODE (x)) != 1
+ || GET_RTX_FORMAT (GET_CODE (x))[0] != 'e')
+ break;
+ }
+ return op;
+}
+
/* Return true if the eliminated form of memory reference OP satisfies
extra (special) memory constraint CONSTRAINT. */
static bool
satisfies_memory_constraint_p (rtx op, enum constraint_num constraint)
{
struct address_info ad;
+ rtx mem = extract_mem_from_operand (op);
+ if (!MEM_P (mem))
+ return false;
- decompose_mem_address (&ad, op);
+ decompose_mem_address (&ad, mem);
address_eliminator eliminator (&ad);
return constraint_satisfied_p (op, constraint);
}
@@ -2344,8 +2364,7 @@ process_alt_operands (int only_alternative)
break;
case CT_MEMORY:
- if (MEM_P (op)
- && satisfies_memory_constraint_p (op, cn))
+ if (satisfies_memory_constraint_p (op, cn))
win = true;
else if (spilled_pseudo_p (op))
win = true;
@@ -2386,8 +2405,7 @@ process_alt_operands (int only_alternative)
break;
case CT_SPECIAL_MEMORY:
- if (MEM_P (op)
- && satisfies_memory_constraint_p (op, cn))
+ if (satisfies_memory_constraint_p (op, cn))
win = true;
else if (spilled_pseudo_p (op))
win = true;
diff --git a/gcc/recog.c b/gcc/recog.c
index 2720aaaac..8674054b9 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1798,7 +1798,8 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
case CT_MEMORY:
case CT_SPECIAL_MEMORY:
/* Every memory operand can be reloaded to fit. */
- result = result || memory_operand (op, VOIDmode);
+ result = result || memory_operand (extract_mem_from_operand (op),
+ VOIDmode);
break;
case CT_ADDRESS:
@@ -2584,7 +2585,9 @@ constrain_operands (int strict, alternative_mask alternatives)
/* A unary operator may be accepted by the predicate, but it
is irrelevant for matching constraints. */
- if (UNARY_P (op))
+ /* For special_memory_operand, there could be a memory operand inside,
+ and it would cause a mismatch for constraint_satisfied_p. */
+ if (UNARY_P (op) && op == extract_mem_from_operand (op))
op = XEXP (op, 0);
if (GET_CODE (op) == SUBREG)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index b29afca8d..35fb6ba73 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -4323,6 +4323,7 @@ extern rtx gen_hard_reg_clobber (machine_mode, unsigned int);
extern rtx get_reg_known_value (unsigned int);
extern bool get_reg_known_equiv_p (unsigned int);
extern rtx get_reg_base_value (unsigned int);
+extern rtx extract_mem_from_operand (rtx);
#ifdef STACK_REGS
extern int stack_regs_mentioned (const_rtx insn);
--
2.27.0.windows.1

View File

@ -0,0 +1,73 @@
From 95d8a6545bef39f5deff376c60c38e4e3c13c8f5 Mon Sep 17 00:00:00 2001
From: zhaowenyu <804544223@qq.com>
Date: Sat, 25 Jun 2022 00:45:24 +0800
Subject: [PATCH 10/12] [Backport] ira: Fix unnecessary register spill
Reference: https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=edf95e51e53697f3050f076675c26a4cece17741
The variables first_moveable_pseudo and last_moveable_pseudo aren't reset after compiling a function,
which means they leak into the first scheduler pass of the following function. In some cases, this
can cause an extra spill during register location of the second function.
---
gcc/ira.c | 2 ++
gcc/testsuite/gcc.target/aarch64/nospill.c | 35 ++++++++++++++++++++++
2 files changed, 37 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/nospill.c
diff --git a/gcc/ira.c b/gcc/ira.c
index 681ec2f46..77e4bb988 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -5130,6 +5130,8 @@ move_unallocated_pseudos (void)
INSN_UID (newinsn), i);
SET_REG_N_REFS (i, 0);
}
+
+ first_moveable_pseudo = last_moveable_pseudo = 0;
}
/* If the backend knows where to allocate pseudos for hard
diff --git a/gcc/testsuite/gcc.target/aarch64/nospill.c b/gcc/testsuite/gcc.target/aarch64/nospill.c
new file mode 100644
index 000000000..968a4267e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/nospill.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+/* The pseudo for P is marked as moveable in the IRA pass. */
+float
+func_0 (float a, float b, float c)
+{
+ float p = c / a;
+
+ if (b > 1)
+ {
+ b /= p;
+ if (c > 2)
+ a /= 3;
+ }
+
+ return b / c * a;
+}
+
+/* If first_moveable_pseudo and last_moveable_pseudo are not reset correctly,
+ they will carry over and spill the pseudo for Q. */
+float
+func_1 (float a, float b, float c)
+{
+ float q = a + b;
+
+ c *= a / (b + b);
+ if (a > 0)
+ c *= q;
+
+ return a * b * c;
+}
+
+/* We have plenty of spare registers, so check nothing has been spilled. */
+/* { dg-final { scan-assembler-not "\tstr\t" } } */
--
2.27.0.windows.1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -61,7 +61,7 @@
Summary: Various compilers (C, C++, Objective-C, ...) Summary: Various compilers (C, C++, Objective-C, ...)
Name: gcc Name: gcc
Version: %{gcc_version} Version: %{gcc_version}
Release: 12 Release: 13
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD
URL: https://gcc.gnu.org URL: https://gcc.gnu.org
@ -150,6 +150,18 @@ Patch31: 0031-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
Patch32: 0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch Patch32: 0032-Autoprefetch-Prune-invaild-loops-containing-edges-wh.patch
Patch33: 0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch Patch33: 0033-AutoFdo-Fix-memory-leaks-in-autofdo-and-autoprefetch.patch
Patch34: 0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch Patch34: 0034-Backport-sanitizer-Fix-asan-against-glibc-2.34-PR100.patch
Patch35: 0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
Patch36: 0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch
Patch37: 0037-Backport-loop-invariant-Don-t-move-cold-bb-instructi.patch
Patch38: 0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
Patch39: 0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch
Patch40: 0040-Backport-ifcvt-Allow-constants-for-noce_convert_mult.patch
Patch41: 0041-Backport-Register-sysroot-in-the-driver-switches-tab.patch
Patch42: 0042-DFE-Fix-bugs.patch
Patch43: 0043-Backport-Extend-special_memory_constraint.patch
Patch44: 0044-Backport-ira-Fix-unnecessary-register-spill.patch
Patch45: 0045-Transposed-SLP-Enable-Transposed-SLP.patch
Patch46: 0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch
%global gcc_target_platform %{_arch}-linux-gnu %global gcc_target_platform %{_arch}-linux-gnu
@ -640,6 +652,18 @@ not stable, so plugins must be rebuilt any time GCC is updated.
%patch32 -p1 %patch32 -p1
%patch33 -p1 %patch33 -p1
%patch34 -p1 %patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%build %build
@ -2660,6 +2684,12 @@ end
%doc rpm.doc/changelogs/libcc1/ChangeLog* %doc rpm.doc/changelogs/libcc1/ChangeLog*
%changelog %changelog
* Mon Aug 8 2022 benniaobufeijiushiji <linda7@huawei.com> - 10.3.1-13
- Type:Sync
- ID:NA
- SUG:NA
- DESC:Sync patch from openeuler/gcc
* Fri Jul 08 2022 zhaomengmeng <zhaomengmeng@kylinos.cn> - 10.3.1-12 * Fri Jul 08 2022 zhaomengmeng <zhaomengmeng@kylinos.cn> - 10.3.1-12
- Type:SPEC - Type:SPEC
- ID:NA - ID:NA