On 5/24/19 11:37 AM, Richard Biener wrote:
> On Fri, May 24, 2019 at 10:08 AM Jakub Jelinek <ja...@redhat.com> wrote:
>>
>> On Fri, May 24, 2019 at 09:48:03AM +0200, Martin Liška wrote:
>>> gcc/ChangeLog:
>>>
>>> 2019-05-23  Martin Liska  <mli...@suse.cz>
>>>
>>>       PR ipa/90555
>>>       * ipa-icf-gimple.c (func_checker::compare_loops): New function.
>>>       * ipa-icf-gimple.h (func_checker::compare_loops): Likewise.
>>>       * ipa-icf.c (sem_function::equals_private): Use compare_loops.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 2019-05-23  Martin Liska  <mli...@suse.cz>
>>>
>>>       PR ipa/90555
>>>       * gcc.dg/ipa/pr90555.c: New test.
>>
>>> @@ -605,6 +606,45 @@ func_checker::compare_variable_decl (tree t1, tree t2)
>>>    return return_with_debug (ret);
>>>  }
>>>
>>> +/* Compare significant loop information.  */
>>> +bool
>>> +func_checker::compare_loops (void)
>>> +{
>>> +  struct loop *loop;
>>> +
>>> +  auto_vec <struct loop *> loops1;
>>> +  auto_vec <struct loop *> loops2;
>>> +
>>> +  FOR_EACH_LOOP_FN (DECL_STRUCT_FUNCTION (m_source_func_decl), loop, 0)
>>> +    loops1.safe_push (loop);
>>> +
>>> +  FOR_EACH_LOOP_FN (DECL_STRUCT_FUNCTION (m_target_func_decl), loop, 0)
>>> +    loops2.safe_push (loop);
>>> +
>>> +  gcc_assert (loops1.length () == loops2.length ());
>>> +
>>> +  for (unsigned i = 0; i < loops1.length (); i++)
>>
>> I wonder how likely/unlikely it is that the loops will be ordered the same
>> by the iterators.  If they are the same always, then perhaps it would be
>> better to avoid the temporary vectors, and just do one FOR_EACH_LOOP_FN
>> with another manual loop_iterator use in sync with that.
>> If it isn't guaranteed they are ordered the same, then I think we need to
>> match the loops by the corresponding loop header and perhaps also verify
>> loop latch and other basic blocks in the loop?
> 
> In fact I wouldn't even compare loops this way but compare loop
> paris when I run across two equal basic-blocks that are loop
> headers (bb->loop_father == bb->loop_father->header).

That's definitely nicer.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

> 
>>> +    {
>>> +      struct loop *l1 = loops1[i];
>>> +      struct loop *l2 = loops2[i];
>>> +      if (l1->simdlen != l2->simdlen)
>>> +     return return_false_with_msg ("simdlen");
>>> +      if (l1->safelen != l2->safelen)
>>> +     return return_false_with_msg ("safelen");
>>> +      if (l1->can_be_parallel != l2->can_be_parallel)
>>> +     return return_false_with_msg ("can_be_parallel");
>>> +      if (l1->dont_vectorize != l2->dont_vectorize)
>>> +     return return_false_with_msg ("dont_vectorize");
>>> +      if (l1->force_vectorize != l2->force_vectorize)
>>> +     return return_false_with_msg ("force_vectorize");
>>> +      if (l1->unroll != l2->unroll)
>>> +     return return_false_with_msg ("unroll");
>>> +      if (!compare_variable_decl (l1->simduid, l2->simduid))
>>> +     return return_false_with_msg ("simduid");
>>
>> The above looks reasonable if we are guaranteed we are talking about a loop
>> corresponding between the two functions.
>>
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/ipa/pr90555.c
>>> @@ -0,0 +1,67 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-fopenmp-simd -O2 -mavx512f -fdump-ipa-icf" } */
>>> +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
>>
>> Please don't use two dg-do compile directives, drop the first line,
>> move the third line to first one.
>>
>>         Jakub

>From 306cab10e8ef918b25321132aa75d9400f7de247 Mon Sep 17 00:00:00 2001
From: Martin Liska <mli...@suse.cz>
Date: Thu, 23 May 2019 12:47:11 +0200
Subject: [PATCH] Handle loop fields in IPA ICF (PR ipa/90555).

gcc/ChangeLog:

2019-05-23  Martin Liska  <mli...@suse.cz>

	PR ipa/90555
	* ipa-icf-gimple.c (func_checker::compare_loops): New function.
	* ipa-icf-gimple.h (func_checker::compare_loops): Likewise.
	(func_checker::compare_bb): Call compare_loops.

gcc/testsuite/ChangeLog:

2019-05-23  Martin Liska  <mli...@suse.cz>

	PR ipa/90555
	* gcc.dg/ipa/pr90555.c: New test.
---
 gcc/ipa-icf-gimple.c               | 31 ++++++++++++++
 gcc/ipa-icf-gimple.h               |  3 ++
 gcc/testsuite/gcc.dg/ipa/pr90555.c | 67 ++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/pr90555.c

diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c
index 25284936bc3..92b1813ec6c 100644
--- a/gcc/ipa-icf-gimple.c
+++ b/gcc/ipa-icf-gimple.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-utils.h"
 #include "tree-eh.h"
 #include "builtins.h"
+#include "cfgloop.h"
 
 #include "ipa-icf-gimple.h"
 
@@ -605,6 +606,33 @@ func_checker::compare_variable_decl (tree t1, tree t2)
   return return_with_debug (ret);
 }
 
+/* Compare loop information for basic blocks BB1 and BB2.  */
+
+bool
+func_checker::compare_loops (basic_block bb1, basic_block bb2)
+{
+  if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
+    return return_false ();
+
+  struct loop *l1 = bb1->loop_father;
+  struct loop *l2 = bb2->loop_father;
+  if (l1->simdlen != l2->simdlen)
+    return return_false_with_msg ("simdlen");
+  if (l1->safelen != l2->safelen)
+    return return_false_with_msg ("safelen");
+  if (l1->can_be_parallel != l2->can_be_parallel)
+    return return_false_with_msg ("can_be_parallel");
+  if (l1->dont_vectorize != l2->dont_vectorize)
+    return return_false_with_msg ("dont_vectorize");
+  if (l1->force_vectorize != l2->force_vectorize)
+    return return_false_with_msg ("force_vectorize");
+  if (l1->unroll != l2->unroll)
+    return return_false_with_msg ("unroll");
+  if (!compare_variable_decl (l1->simduid, l2->simduid))
+    return return_false_with_msg ("simduid");
+
+  return true;
+}
 
 /* Function visits all gimple labels and creates corresponding
    mapping between basic blocks and labels.  */
@@ -727,6 +755,9 @@ func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
   if (!gsi_end_p (gsi2))
     return return_false ();
 
+  if (!compare_loops (bb1->bb, bb2->bb))
+    return return_false ();
+
   return true;
 }
 
diff --git a/gcc/ipa-icf-gimple.h b/gcc/ipa-icf-gimple.h
index 0035db32e66..51aadced9ea 100644
--- a/gcc/ipa-icf-gimple.h
+++ b/gcc/ipa-icf-gimple.h
@@ -226,6 +226,9 @@ public:
   /* Verifies that trees T1 and T2 do correspond.  */
   bool compare_variable_decl (tree t1, tree t2);
 
+  /* Compare loop information for basic blocks BB1 and BB2.  */
+  bool compare_loops (basic_block bb1, basic_block bb2);
+
   /* Return true if types are compatible for polymorphic call analysis.
      COMPARE_PTR indicates if polymorphic type comparsion should be
      done for pointers, too.  */
diff --git a/gcc/testsuite/gcc.dg/ipa/pr90555.c b/gcc/testsuite/gcc.dg/ipa/pr90555.c
new file mode 100644
index 00000000000..a9c751cd63c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr90555.c
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -O2 -mavx512f -fdump-ipa-icf" } */
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+#define N 1024
+int a[N];
+
+void
+test_simdlen1 (void)
+{
+  int i;
+  #pragma omp simd simdlen (4)
+  for (i = 0; i < N; ++i)
+    a[i] = a[i] + 1;
+}
+
+void
+test_simdlen2 (void)
+{
+  int i;
+  #pragma omp simd simdlen (8)
+  for (i = 0; i < N; ++i)
+    a[i] = a[i] + 1;
+}
+
+void
+test_safelen1 (void)
+{
+  int i;
+  #pragma omp simd safelen (4)
+  for (i = 0; i < N; ++i)
+    a[i] = a[i] + 1;
+}
+
+void
+test_safelen2 (void)
+{
+  int i;
+  #pragma omp simd safelen (8)
+  for (i = 0; i < N; ++i)
+    a[i] = a[i] + 1;
+}
+
+int d[1024];
+
+int
+test_simduid1 (int j, int b)
+{
+  int l, c = 0;
+#pragma omp simd reduction(+: c)
+  for (l = 0; l < b; ++l)
+    c += d[j + l];
+  return c;
+}
+
+int
+test_simduid2 (int j, int b)
+{
+  int l, c2 = 0;
+#pragma omp simd reduction(+: c2)
+  for (l = 0; l < b; ++l)
+    c2 += d[j + l];
+  return c2;
+}
+
+/* { dg-final { scan-ipa-dump "Semantic equality hit:test_simduid1->test_simduid2" "icf"  } } */
+/* { dg-final { scan-ipa-dump "Equal symbols: 1" "icf"  } } */
-- 
2.21.0

Reply via email to