From 8301b194d24cb01e54f36822740ed5b835358fd1 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 25 Nov 2014 16:16:27 +0100 Subject: [PATCH] re PR bootstrap/64050 (r218009 causes LTO/PGO bootstrap failure: ICE: in inline_small_functions, at ipa-inline.c:1709) 2014-11-25 Martin Liska 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 | 15 ++ gcc/sreal.c | 12 +- gcc/sreal.h | 18 ++- gcc/testsuite/ChangeLog | 8 + gcc/testsuite/gcc.dg/plugin/plugin.exp | 1 + gcc/testsuite/gcc.dg/plugin/sreal-test-1.c | 8 + gcc/testsuite/gcc.dg/plugin/sreal_plugin.c | 170 +++++++++++++++++++++ 7 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/plugin/sreal-test-1.c create mode 100644 gcc/testsuite/gcc.dg/plugin/sreal_plugin.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6c90015565a..e6052320a10 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2014-11-25 Martin Liska + + 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 PR tree-optimization/61927 diff --git a/gcc/sreal.c b/gcc/sreal.c index 0337f9e540c..2b5e3ae82be 100644 --- a/gcc/sreal.c +++ b/gcc/sreal.c @@ -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) diff --git a/gcc/sreal.h b/gcc/sreal.h index 1362bf66866..3938c6ef12a 100644 --- a/gcc/sreal.h +++ b/gcc/sreal.h @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7b9b365c5a1..9dc2269427a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2014-11-25 Martin Liska + + 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 * gcc.target/mips/mips.exp: Add support for -msoft-float and diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp index e4b5f5473ad..c12b3dac4e3 100644 --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp @@ -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 index 00000000000..1bce2cc0a35 --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/sreal-test-1.c @@ -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 index 00000000000..f1138163c5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/plugin/sreal_plugin.c @@ -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; +}