Hi!

When ICF encounteres a GIMPLE_PREDICT (as in the testcase) or GIMPLE_NOP,
it stops looking at further statements in the bb (assumes they must be the
same), which is of course wrong.

I'm attaching 3 versions of the patch, the first one I've
bootstrapped/regtested on x86_64-linux and i686-linux, the second one
will handle GIMPLE_PREDICT just as (fixed) GIMPLE_NOP handling, as Honza is
saying that at this point GIMPLE_PREDICT can be ignored (but we e.g. risk
when using the same function for something different that we'll not handle
GIMPLE_PREDICT right), the third one is the most minimal one (but I'm afraid
the lack of GIMPLE_EH_DISPATCH region checking might cause wrong-code).

Ok for trunk (which version) and 5.1 (which version)?

        Jakub
2015-04-15  Jakub Jelinek  <ja...@redhat.com>

        PR ipa/65765
        * ipa-icf-gimple.c (func_checker::compare_bb): For GIMPLE_NOP,
        use break instead of return true.  For GIMPLE_PREDICT, compare
        predictor and outcome, and break instead of return true if it is
        the same.  For GIMPLE_EH_DISPATCH, compare dispatch region.

        * g++.dg/ipa/pr65765.C: New test.

--- gcc/ipa-icf-gimple.c.jj     2015-04-12 21:29:24.000000000 +0200
+++ gcc/ipa-icf-gimple.c        2015-04-15 09:08:19.637659016 +0200
@@ -706,7 +706,11 @@ func_checker::compare_bb (sem_bb *bb1, s
            return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
          break;
        case GIMPLE_DEBUG:
+         break;
        case GIMPLE_EH_DISPATCH:
+         if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
+             != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
+           return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
          break;
        case GIMPLE_RESX:
          if (!compare_gimple_resx (as_a <gresx *> (s1),
@@ -733,8 +737,12 @@ func_checker::compare_bb (sem_bb *bb1, s
            return return_different_stmts (s1, s2, "GIMPLE_ASM");
          break;
        case GIMPLE_PREDICT:
+         if (gimple_predict_predictor (s1) != gimple_predict_predictor (s2)
+             || gimple_predict_outcome (s1) != gimple_predict_outcome (s2))
+           return return_different_stmts (s1, s2, "GIMPLE_PREDICT");
+         break;
        case GIMPLE_NOP:
-         return true;
+         break;
        default:
          return return_false_with_msg ("Unknown GIMPLE code reached");
        }
--- gcc/testsuite/g++.dg/ipa/pr65765.C.jj       2015-04-15 09:14:03.329930193 
+0200
+++ gcc/testsuite/g++.dg/ipa/pr65765.C  2015-04-15 09:13:41.000000000 +0200
@@ -0,0 +1,45 @@
+// PR ipa/65765
+// { dg-do run }
+// { dg-options "-O2" }
+
+int a, b, c, d, e;
+unsigned char h[] = { 1, 1 };
+
+__attribute__ ((cold)) int ModRM_Mode () { return a; }
+
+int
+ModRM_RM (int p1)
+{
+  return p1;
+}
+
+__attribute__ ((cold)) static bool ModRM_hasSIB (unsigned char p1)
+{
+  return ModRM_Mode () != 1 && ModRM_RM (p1);
+}
+
+__attribute__ ((cold)) static bool ModRM_hasRIP (unsigned char p1)
+{
+  return ModRM_Mode () && ModRM_RM (p1);
+}
+
+unsigned char *
+DisassembleHeapAccess (unsigned char *p1)
+{
+  b = *p1++;
+  if (ModRM_hasSIB (b))
+    c = *p1++;
+  int f = c, g = 0;
+  d = ModRM_hasRIP (g);
+  e = f == 0;
+  if (e)
+    p1 += sizeof 0;
+  return p1;
+}
+
+int
+main ()
+{
+  if (DisassembleHeapAccess (h) != h + 2)
+    __builtin_abort ();
+}
2015-04-15  Jakub Jelinek  <ja...@redhat.com>

        PR ipa/65765
        * ipa-icf-gimple.c (func_checker::compare_bb): For GIMPLE_NOP
        and GIMPLE_PREDICT use break instead of return true. For
        GIMPLE_EH_DISPATCH, compare dispatch region.

        * g++.dg/ipa/pr65765.C: New test.

--- gcc/ipa-icf-gimple.c.jj     2015-04-12 21:29:24.000000000 +0200
+++ gcc/ipa-icf-gimple.c        2015-04-15 09:08:19.637659016 +0200
@@ -706,7 +706,11 @@ func_checker::compare_bb (sem_bb *bb1, s
            return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
          break;
        case GIMPLE_DEBUG:
+         break;
        case GIMPLE_EH_DISPATCH:
+         if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
+             != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
+           return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
          break;
        case GIMPLE_RESX:
          if (!compare_gimple_resx (as_a <gresx *> (s1),
@@ -734,7 +738,7 @@ func_checker::compare_bb (sem_bb *bb1, s
          break;
        case GIMPLE_PREDICT:
        case GIMPLE_NOP:
-         return true;
+         break;
        default:
          return return_false_with_msg ("Unknown GIMPLE code reached");
        }
--- gcc/testsuite/g++.dg/ipa/pr65765.C.jj       2015-04-15 09:14:03.329930193 
+0200
+++ gcc/testsuite/g++.dg/ipa/pr65765.C  2015-04-15 09:13:41.000000000 +0200
@@ -0,0 +1,45 @@
+// PR ipa/65765
+// { dg-do run }
+// { dg-options "-O2" }
+
+int a, b, c, d, e;
+unsigned char h[] = { 1, 1 };
+
+__attribute__ ((cold)) int ModRM_Mode () { return a; }
+
+int
+ModRM_RM (int p1)
+{
+  return p1;
+}
+
+__attribute__ ((cold)) static bool ModRM_hasSIB (unsigned char p1)
+{
+  return ModRM_Mode () != 1 && ModRM_RM (p1);
+}
+
+__attribute__ ((cold)) static bool ModRM_hasRIP (unsigned char p1)
+{
+  return ModRM_Mode () && ModRM_RM (p1);
+}
+
+unsigned char *
+DisassembleHeapAccess (unsigned char *p1)
+{
+  b = *p1++;
+  if (ModRM_hasSIB (b))
+    c = *p1++;
+  int f = c, g = 0;
+  d = ModRM_hasRIP (g);
+  e = f == 0;
+  if (e)
+    p1 += sizeof 0;
+  return p1;
+}
+
+int
+main ()
+{
+  if (DisassembleHeapAccess (h) != h + 2)
+    __builtin_abort ();
+}
2015-04-15  Jakub Jelinek  <ja...@redhat.com>

        PR ipa/65765
        * ipa-icf-gimple.c (func_checker::compare_bb): For GIMPLE_NOP
        and GIMPLE_PREDICT use break instead of return true.

        * g++.dg/ipa/pr65765.C: New test.

--- gcc/ipa-icf-gimple.c.jj     2015-04-12 21:29:24.000000000 +0200
+++ gcc/ipa-icf-gimple.c        2015-04-15 09:08:19.637659016 +0200
@@ -734,7 +734,7 @@ func_checker::compare_bb (sem_bb *bb1, s
          break;
        case GIMPLE_PREDICT:
        case GIMPLE_NOP:
-         return true;
+         break;
        default:
          return return_false_with_msg ("Unknown GIMPLE code reached");
        }
--- gcc/testsuite/g++.dg/ipa/pr65765.C.jj       2015-04-15 09:14:03.329930193 
+0200
+++ gcc/testsuite/g++.dg/ipa/pr65765.C  2015-04-15 09:13:41.000000000 +0200
@@ -0,0 +1,45 @@
+// PR ipa/65765
+// { dg-do run }
+// { dg-options "-O2" }
+
+int a, b, c, d, e;
+unsigned char h[] = { 1, 1 };
+
+__attribute__ ((cold)) int ModRM_Mode () { return a; }
+
+int
+ModRM_RM (int p1)
+{
+  return p1;
+}
+
+__attribute__ ((cold)) static bool ModRM_hasSIB (unsigned char p1)
+{
+  return ModRM_Mode () != 1 && ModRM_RM (p1);
+}
+
+__attribute__ ((cold)) static bool ModRM_hasRIP (unsigned char p1)
+{
+  return ModRM_Mode () && ModRM_RM (p1);
+}
+
+unsigned char *
+DisassembleHeapAccess (unsigned char *p1)
+{
+  b = *p1++;
+  if (ModRM_hasSIB (b))
+    c = *p1++;
+  int f = c, g = 0;
+  d = ModRM_hasRIP (g);
+  e = f == 0;
+  if (e)
+    p1 += sizeof 0;
+  return p1;
+}
+
+int
+main ()
+{
+  if (DisassembleHeapAccess (h) != h + 2)
+    __builtin_abort ();
+}

Reply via email to