gcc/0042-DFE-Fix-bugs.patch

666 lines
16 KiB
Diff
Raw Normal View History

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