re PR bootstrap/64050 (r218009 causes LTO/PGO bootstrap failure: ICE: in inline_small...
authorMartin Liska <mliska@suse.cz>
Tue, 25 Nov 2014 15:16:27 +0000 (16:16 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Tue, 25 Nov 2014 15:16:27 +0000 (15:16 +0000)
2014-11-25  Martin Liska  <mliska@suse.cz>

PR bootstrap/64050
PR ipa/64060
* sreal.c (sreal::operator+): Addition fixed.
(sreal::signedless_plus): Negative numbers are
handled correctly.
(sreal::operator-): Subtraction is fixed.
(sreal::signedless_minus): Negative numbers are
handled correctly.
* sreal.h (sreal::operator<): Equal negative numbers
are compared correctly.
(sreal::shift): New checking asserts are introduced.
Operation is fixed.
* gcc.dg/plugin/plugin.exp: New plugin.
* gcc.dg/plugin/sreal-test-1.c: New test.
* gcc.dg/plugin/sreal_plugin.c: New test.

From-SVN: r218048

gcc/ChangeLog
gcc/sreal.c
gcc/sreal.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/plugin/plugin.exp
gcc/testsuite/gcc.dg/plugin/sreal-test-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/plugin/sreal_plugin.c [new file with mode: 0644]

index 6c90015565a406cc7570464b22197ebe1086a49a..e6052320a10aa610731aa2754770177409c5cdb2 100644 (file)
@@ -1,3 +1,18 @@
+2014-11-25  Martin Liska  <mliska@suse.cz>
+
+       PR bootstrap/64050
+       PR ipa/64060
+       * sreal.c (sreal::operator+): Addition fixed.
+       (sreal::signedless_plus): Negative numbers are
+       handled correctly.
+       (sreal::operator-): Subtraction is fixed.
+       (sreal::signedless_minus): Negative numbers are
+       handled correctly.
+       * sreal.h (sreal::operator<): Equal negative numbers
+       are compared correctly.
+       (sreal::shift): New checking asserts are introduced.
+       Operation is fixed.
+
 2014-11-25  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/61927
index 0337f9e540c694ac255d90ad2049261318be563b..2b5e3ae82be06cd54fc14ca9ccf0bb6d8120e351 100644 (file)
@@ -182,9 +182,9 @@ sreal::operator+ (const sreal &other) const
     {
       sreal tmp = -(*b_p);
       if (*a_p < tmp)
-       return signedless_minus (tmp, *a_p, false);
+       return signedless_minus (tmp, *a_p, true);
       else
-       return signedless_minus (*a_p, tmp, true);
+       return signedless_minus (*a_p, tmp, false);
     }
 
   gcc_checking_assert (a_p->m_negative == b_p->m_negative);
@@ -203,7 +203,7 @@ sreal::signedless_plus (const sreal &a, const sreal &b, bool negative)
   const sreal *a_p = &a;
   const sreal *b_p = &b;
 
-  if (*a_p < *b_p)
+  if (a_p->m_exp < b_p->m_exp)
     std::swap (a_p, b_p);
 
   dexp = a_p->m_exp - b_p->m_exp;
@@ -211,6 +211,7 @@ sreal::signedless_plus (const sreal &a, const sreal &b, bool negative)
   if (dexp > SREAL_BITS)
     {
       r.m_sig = a_p->m_sig;
+      r.m_negative = negative;
       return r;
     }
 
@@ -248,11 +249,11 @@ sreal::operator- (const sreal &other) const
   /* We want to substract a smaller number from bigger
     for nonegative numbers.  */
   if (!m_negative && *this < other)
-    return -signedless_minus (other, *this, true);
+    return signedless_minus (other, *this, true);
 
   /* Example: -2 - (-3) => 3 - 2 */
   if (m_negative && *this > other)
-    return signedless_minus (-other, -(*this), true);
+    return signedless_minus (-other, -(*this), false);
 
   sreal r = signedless_minus (*this, other, m_negative);
 
@@ -274,6 +275,7 @@ sreal::signedless_minus (const sreal &a, const sreal &b, bool negative)
   if (dexp > SREAL_BITS)
     {
       r.m_sig = a_p->m_sig;
+      r.m_negative = negative;
       return r;
     }
   if (dexp == 0)
index 1362bf66866af2083148f29dce4dfb3190269988..3938c6ef12a98ce9ad4e7bf8d54c666ccb4b4d14 100644 (file)
@@ -60,6 +60,11 @@ public:
 
   bool operator< (const sreal &other) const
   {
+    /* We negate result in case of negative numbers and
+       it would return true for equal negative numbers.  */
+    if (*this == other)
+      return false;
+
     if (m_negative != other.m_negative)
       return m_negative > other.m_negative;
 
@@ -86,10 +91,19 @@ public:
     return tmp;
   }
 
-  sreal shift (int sig) const
+  sreal shift (int s) const
   {
+    gcc_checking_assert (s <= SREAL_BITS);
+    gcc_checking_assert (s >= -SREAL_BITS);
+
+    /* Exponent should never be so large because shift_right is used only by
+     sreal_add and sreal_sub ant thus the number cannot be shifted out from
+     exponent range.  */
+    gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
+    gcc_checking_assert (m_exp + s >= -SREAL_MAX_EXP);
+
     sreal tmp = *this;
-    tmp.m_sig += sig;
+    tmp.m_exp += s;
 
     return tmp;
   }
index 7b9b365c5a13b061c91ac63b25fc5e438adedf87..9dc2269427a385b86dde295b149d4fe91f2fed23 100644 (file)
@@ -1,3 +1,11 @@
+2014-11-25  Martin Liska  <mliska@suse.cz>
+
+       PR bootstrap/64050
+       PR ipa/64060
+       * gcc.dg/plugin/plugin.exp: New plugin.
+       * gcc.dg/plugin/sreal-test-1.c: New test.
+       * gcc.dg/plugin/sreal_plugin.c: New test.
+
 2014-11-25  Matthew Fortune  <matthew.fortune@imgtec.com>
 
        * gcc.target/mips/mips.exp: Add support for -msoft-float and
index e4b5f5473ada45891d4f994257707bebe595b784..c12b3dac4e3d166f6bd5898c608c0fb3a300917d 100644 (file)
@@ -59,6 +59,7 @@ set plugin_test_list [list \
     { selfassign.c self-assign-test-1.c self-assign-test-2.c } \
     { ggcplug.c ggcplug-test-1.c } \
     { one_time_plugin.c one_time-test-1.c } \
+    { sreal_plugin.c sreal-test-1.c } \
     { start_unit_plugin.c start_unit-test-1.c } \
     { finish_unit_plugin.c finish_unit-test-1.c } \
 ]
diff --git a/gcc/testsuite/gcc.dg/plugin/sreal-test-1.c b/gcc/testsuite/gcc.dg/plugin/sreal-test-1.c
new file mode 100644 (file)
index 0000000..1bce2cc
--- /dev/null
@@ -0,0 +1,8 @@
+/* Test that pass is inserted and invoked once. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+int main (int argc, char **argv)
+{
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/sreal_plugin.c b/gcc/testsuite/gcc.dg/plugin/sreal_plugin.c
new file mode 100644 (file)
index 0000000..f113816
--- /dev/null
@@ -0,0 +1,170 @@
+/* Plugin that process internal tests for sreal.  */
+#include "config.h"
+#include "gcc-plugin.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tm.h"
+#include "toplev.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "context.h"
+#include "sreal.h"
+
+int plugin_is_GPL_compatible;
+
+namespace {
+
+static void assert (bool c)
+{
+  if (!c)
+    abort ();
+}
+
+const pass_data pass_data_sreal_pass =
+{
+  GIMPLE_PASS, /* type */
+  "sreal", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  PROP_gimple_any, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0, /* todo_flags_finish */
+};
+
+class sreal_pass : public gimple_opt_pass
+{
+public:
+  sreal_pass(gcc::context *ctxt)
+    : gimple_opt_pass(pass_data_sreal_pass, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *);
+  virtual unsigned int execute (function *);
+
+private:
+  void check_sreal ();
+
+  static void verify_aritmetics (int a, int b);
+  static void verify_shifting (int a);
+}; // class one_pass
+
+} // anon namespace
+
+void
+sreal_pass::verify_aritmetics (int a, int b)
+{
+  assert (a == -(-(sreal (a))).to_int ());
+  assert ((a < b) == (sreal (a) < sreal (b)));
+  assert ((a <= b) == (sreal (a) <= sreal (b)));
+  assert ((a == b) == (sreal (a) == sreal (b)));
+  assert ((a != b) == (sreal (a) != sreal (b)));
+  assert ((a > b) == (sreal (a) > sreal (b)));
+  assert ((a >= b) == (sreal (a) >= sreal (b)));
+  assert ((a + b) == (sreal (a) + sreal (b)).to_int ());
+  assert ((a - b) == (sreal (a) - sreal (b)).to_int ());
+  assert ((b + a) == (sreal (b) + sreal (a)).to_int ());
+  assert ((b - a) == (sreal (b) - sreal (a)).to_int ());
+}
+
+void
+sreal_pass::verify_shifting (int a)
+{
+  sreal v = a;
+
+  for (unsigned i = 0; i < 16; i++)
+    assert ((a << i) == (v << i).to_int());
+
+  a = a << 16;
+  v = v << 16;
+
+  for (unsigned i = 0; i < 16; i++)
+    assert ((a >> i) == (v >> i).to_int());
+}
+
+void
+sreal_pass::check_sreal ()
+{
+  sreal minimum = INT_MIN;
+  sreal maximum = INT_MAX;
+  sreal seven = 7;
+  sreal minus_two = -2;
+  sreal minus_nine = -9;
+
+  assert (minimum.to_int () == INT_MIN);
+  assert (maximum.to_int () == INT_MAX);
+
+  assert (!(minus_two < minus_two));
+  assert (!(seven < seven));
+  assert (seven > minus_two);
+  assert (minus_two < seven);
+  assert (minus_two != seven);
+  assert (minus_two == minus_two);
+  assert (seven == seven);
+
+  assert (seven == ((seven << 10) >> 10));
+
+  assert ((seven + minus_two) == 5);
+  assert ((seven + minus_nine) == -2);
+
+  for (int a = -100; a < 100; a++)
+    for (int b = -100; b < 100; b++)
+      {
+        verify_aritmetics (a, b);
+        verify_aritmetics (INT_MIN + 100, b);
+        verify_aritmetics (INT_MAX - 100, b);
+      }
+
+  srand (123456);
+
+  for (int i = 0; i < 1000 * 1000; i++)
+    {
+      verify_aritmetics (rand () % 10, rand () % 1000000);
+      verify_aritmetics (rand () % 100, rand () % 10000);
+    }
+
+  for (int a = -100; a < 100; a++)
+    verify_shifting (a);
+}
+
+bool sreal_pass::gate (function *)
+{
+  return true;
+}
+
+unsigned int
+sreal_pass::execute (function *)
+{
+  check_sreal ();
+
+  return 0;
+}
+
+int plugin_init (struct plugin_name_args *plugin_info,
+                 struct plugin_gcc_version *version)
+{
+  struct register_pass_info p;
+
+  p.pass = new sreal_pass (g);
+  p.reference_pass_name = "cfg";
+  p.ref_pass_instance_number = 1;
+  p.pos_op = PASS_POS_INSERT_AFTER;
+
+  register_callback ("sreal", PLUGIN_PASS_MANAGER_SETUP, NULL, &p);
+
+  return 0;
+}