!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:
commit
0c24e155b2
342
0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
Normal file
342
0035-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
Normal 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
|
||||||
|
|
||||||
1115
0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch
Normal file
1115
0036-StructReorg-Refactoring-reorder-fields-to-struct-lay.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||||
|
|
||||||
902
0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
Normal file
902
0038-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
Normal 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
|
||||||
|
|
||||||
143
0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch
Normal file
143
0039-Backport-ipa-sra-Fix-thinko-when-overriding-safe_to_.patch
Normal 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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
665
0042-DFE-Fix-bugs.patch
Normal 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
|
||||||
|
|
||||||
165
0043-Backport-Extend-special_memory_constraint.patch
Normal file
165
0043-Backport-Extend-special_memory_constraint.patch
Normal 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
|
||||||
|
|
||||||
73
0044-Backport-ira-Fix-unnecessary-register-spill.patch
Normal file
73
0044-Backport-ira-Fix-unnecessary-register-spill.patch
Normal 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
|
||||||
|
|
||||||
3009
0045-Transposed-SLP-Enable-Transposed-SLP.patch
Normal file
3009
0045-Transposed-SLP-Enable-Transposed-SLP.patch
Normal file
File diff suppressed because it is too large
Load Diff
1982
0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch
Normal file
1982
0046-ArrayWidenCompare-Add-a-new-optimization-for-array-c.patch
Normal file
File diff suppressed because it is too large
Load Diff
32
gcc.spec
32
gcc.spec
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user