[RFC] Run store-merging pass once more before pass fre/pre

Xionghu Luo luoxhu@linux.ibm.com
Tue Feb 18 09:40:00 GMT 2020


Store-merging pass should run twice, the reason is pass fre/pre will do
some kind of optimizations to instructions by:
  1. Converting the load from address to load from function arguments
  (store_merging_30.c:foo1).
  2. Converting the byte access to BIT_FIELD_REF(store_merging_30.c:foo2).
  3. Other bitfield combinations or potential interference optimizations etc.
These optimizations will break the store chain, store-merging pass fails
to catch such kind of pattern so stores are not merged in middle end,
then consecutive stb/sth instructions(should be merged to stw) are emitted
finally.

And why not directly move store-merging pass(numbered 194) just before
fre1(numbered 35) is for case store_merging_14.c, 5 merges are done by
store_merging1, and 4 merges are done fore store_merge2. So, keep the
original store_merge as store_merge2 as store merge may be still available
after other pass optimizations.  Most of the 30 store_merging_N.c test
case dg-final pass name would be updated from store-merging to
store-merging1 once this RFC patch idea got confirmed.
Any comments?  Thanks.

PS:
Before this patch, store_merging_30.c.035t.fre1:

... foo1:
Inserted _13 = (short unsigned int) counters_new_5(D);
Replaced tmp.D.2912.D.2911.D.2910.D.2909.inuse with _13 in all uses of
_1 = tmp.D.2912.D.2911.D.2910.D.2909.inuse;
Removing dead stmt _1 = tmp.D.2912.D.2911.D.2910.D.2909.inuse;
... foo2:
Inserted _17 = BIT_FIELD_REF <_1, 8, 16>;
Replaced tmp.D.2926.D.2925.D.2924.D.2923.objects with _17 in all uses of
_3 = tmp.D.2926.D.2925.D.2924.D.2923.objects;
Removing dead stmt _3 = tmp.D.2926.D.2925.D.2924.D.2923.objects;

foo1 asm:
rldicl 9,4,48,48
sth 4,0(3)
sth 9,2(3)
blr

With this patch(similar for foo2):

stw r4,0(r3)
blr

gcc/ChangeLog

2020-02-18  Xiong Hu Luo  <luoxhu@linux.ibm.com>

	Part of PR middle-end/71509
	gimple-ssa-store-merging.c (clone): New.
	passes.def (pass_store_merging): New.

gcc/testsuite/ChangeLog

2020-02-18  Xiong Hu Luo  <luoxhu@linux.ibm.com>

	Part of PR middle-end/71509
	testsuite/gcc.dg/store_merging_14.c: Update.
	testsuite/gcc.dg/store_merging_30.c: New.
---
 gcc/gimple-ssa-store-merging.c          |  2 +
 gcc/passes.def                          |  1 +
 gcc/testsuite/gcc.dg/store_merging_14.c |  3 +-
 gcc/testsuite/gcc.dg/store_merging_30.c | 86 +++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/store_merging_30.c

diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 8371323ef4a..9a5bd49fc3a 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -2156,6 +2156,8 @@ public:
   {
   }
 
+  opt_pass * clone () { return new pass_store_merging (m_ctxt); }
+
   /* Pass not supported for PDP-endian, nor for insane hosts or
      target character sizes where native_{encode,interpret}_expr
      doesn't work properly.  */
diff --git a/gcc/passes.def b/gcc/passes.def
index 2bf2cb78fc5..e531531cb14 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3.  If not see
 	  /* pass_build_ealias is a dummy pass that ensures that we
 	     execute TODO_rebuild_alias at this point.  */
 	  NEXT_PASS (pass_build_ealias);
+	  NEXT_PASS (pass_store_merging);
 	  NEXT_PASS (pass_fre, true /* may_iterate */);
 	  NEXT_PASS (pass_early_vrp);
 	  NEXT_PASS (pass_merge_phi);
diff --git a/gcc/testsuite/gcc.dg/store_merging_14.c b/gcc/testsuite/gcc.dg/store_merging_14.c
index 9310aaf3489..bd120d18ac6 100644
--- a/gcc/testsuite/gcc.dg/store_merging_14.c
+++ b/gcc/testsuite/gcc.dg/store_merging_14.c
@@ -214,4 +214,5 @@ main ()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "Merging successful" 9 "store-merging" } } */
+/* { dg-final { scan-tree-dump-times "Merging successful" 5 "store-merging1" } } */
+/* { dg-final { scan-tree-dump-times "Merging successful" 4 "store-merging2" } } */
diff --git a/gcc/testsuite/gcc.dg/store_merging_30.c b/gcc/testsuite/gcc.dg/store_merging_30.c
new file mode 100644
index 00000000000..71369c3b196
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/store_merging_30.c
@@ -0,0 +1,86 @@
+/* { dg-do run } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+typedef unsigned int atomic_t;
+
+struct page
+{
+  union
+  {
+    unsigned long counters;
+    struct
+    {
+      union
+      {
+	struct
+	{
+	  unsigned inuse : 16;
+	  unsigned objects : 15;
+	  unsigned frozen : 1;
+	};
+      };
+    };
+  };
+};
+
+struct page2
+{
+  union
+  {
+    unsigned counters;
+    struct
+    {
+      union
+      {
+	struct
+	{
+	  unsigned inuse : 16;
+	  unsigned objects : 8;
+	  unsigned frozen : 8;
+	};
+      };
+    };
+  };
+};
+
+__attribute__((noipa)) void
+foo1 (struct page *page, unsigned long counters_new)
+{
+        struct page tmp;
+        tmp.counters = counters_new;
+        page->inuse   = tmp.inuse;
+        page->objects = tmp.objects;
+        page->frozen  = tmp.frozen;
+}
+
+__attribute__((noipa)) void
+foo2 (struct page2 *page2, unsigned long counters_new)
+{
+        struct page2 tmp;
+        tmp.counters = counters_new;
+        page2->inuse   = tmp.inuse;
+        page2->objects = tmp.objects;
+        page2->frozen  = tmp.frozen;
+}
+
+int main ()
+{
+  struct page page;
+  foo1 (&page, 0x12345678ABCDEFFEUL);
+
+  asm volatile ("" : : : "memory");
+  if (page.frozen != 1 || page.objects != 0x2bcd || page.inuse != 0xeffe)
+    __builtin_abort ();
+
+  struct page2 page2;
+  foo2 (&page2, 0x12345678ABCDEFFEUL);
+
+  asm volatile ("" : : : "memory");
+
+  if (page2.frozen != 0xab || page2.objects != 0xcd || page2.inuse != 0xeffe)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Merging successful" 2 "store-merging1" } } */
-- 
2.21.0.777.g83232e3864



More information about the Gcc-patches mailing list