From: Jeff Law Date: Wed, 30 Oct 2013 19:21:27 +0000 (-0600) Subject: re PR rtl-optimization/58369 (ICE in subreg_get_info when compiling boost for m68k... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=46088939523a187d0545f8faffdf1e44e75f9948;p=gcc.git re PR rtl-optimization/58369 (ICE in subreg_get_info when compiling boost for m68k-linux) PR rtl-optimization/58369 * reload1.c (compute_reload_subreg_offset): New function. (choose_reload_regs): Use it to pass endian-correct offset to subreg_regno_offset. * PR rtl-optimization/58369 * g++.dg/torture/pr58369.C: New test. From-SVN: r204224 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef40a4372e2..e3d2abda205 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2013-10-18 Mikael Pettersson + + PR rtl-optimization/58369 + * reload1.c (compute_reload_subreg_offset): New function. + (choose_reload_regs): Use it to pass endian-correct + offset to subreg_regno_offset. + 2013-10-30 Tobias Burnus PR other/33426 diff --git a/gcc/reload1.c b/gcc/reload1.c index d56c554b10d..b62b047b070 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -6371,6 +6371,37 @@ replaced_subreg (rtx x) } #endif +/* Compute the offset to pass to subreg_regno_offset, for a pseudo of + mode OUTERMODE that is available in a hard reg of mode INNERMODE. + SUBREG is non-NULL if the pseudo is a subreg whose reg is a pseudo, + otherwise it is NULL. */ + +static int +compute_reload_subreg_offset (enum machine_mode outermode, + rtx subreg, + enum machine_mode innermode) +{ + int outer_offset; + enum machine_mode middlemode; + + if (!subreg) + return subreg_lowpart_offset (outermode, innermode); + + outer_offset = SUBREG_BYTE (subreg); + middlemode = GET_MODE (SUBREG_REG (subreg)); + + /* If SUBREG is paradoxical then return the normal lowpart offset + for OUTERMODE and INNERMODE. Our caller has already checked + that OUTERMODE fits in INNERMODE. */ + if (outer_offset == 0 + && GET_MODE_SIZE (outermode) > GET_MODE_SIZE (middlemode)) + return subreg_lowpart_offset (outermode, innermode); + + /* SUBREG is normal, but may not be lowpart; return OUTER_OFFSET + plus the normal lowpart offset for MIDDLEMODE and INNERMODE. */ + return outer_offset + subreg_lowpart_offset (middlemode, innermode); +} + /* Assign hard reg targets for the pseudo-registers we must reload into hard regs for this insn. Also output the instructions to copy them in and out of the hard regs. @@ -6508,6 +6539,7 @@ choose_reload_regs (struct insn_chain *chain) int byte = 0; int regno = -1; enum machine_mode mode = VOIDmode; + rtx subreg = NULL_RTX; if (rld[r].in == 0) ; @@ -6528,7 +6560,10 @@ choose_reload_regs (struct insn_chain *chain) if (regno < FIRST_PSEUDO_REGISTER) regno = subreg_regno (rld[r].in_reg); else - byte = SUBREG_BYTE (rld[r].in_reg); + { + subreg = rld[r].in_reg; + byte = SUBREG_BYTE (subreg); + } mode = GET_MODE (rld[r].in_reg); } #ifdef AUTO_INC_DEC @@ -6566,6 +6601,9 @@ choose_reload_regs (struct insn_chain *chain) rtx last_reg = reg_last_reload_reg[regno]; i = REGNO (last_reg); + byte = compute_reload_subreg_offset (mode, + subreg, + GET_MODE (last_reg)); i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode); last_class = REGNO_REG_CLASS (i); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fdc9ed0fead..748ab127cba 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-10-30 Mikael Pettersson + + * PR rtl-optimization/58369 + * g++.dg/torture/pr58369.C: New test. + 2013-10-30 Tobias Burnus PR other/33426 diff --git a/gcc/testsuite/g++.dg/torture/pr58369.C b/gcc/testsuite/g++.dg/torture/pr58369.C new file mode 100644 index 00000000000..9284e2ca768 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr58369.C @@ -0,0 +1,109 @@ +// { dg-do compile } +// Reduced from boost-1.54 + +int pow(int, int); +int sqrt(int); + +class PolicyA { }; + +template +int max_value() { return 0x7fffffff; } + +template +int min_value() { return 1; } + +void raise_denorm_error(); + +template +void raise_domain_error(int, int, const T &, const PolicyA &); + +template +int check_overflow(long double p1) { + long double __trans_tmp_2 = __builtin_fabsl(p1); + if (__trans_tmp_2 > max_value()) + return 1; + return 0; +} + +template +int check_underflow(long double p1) { + if (p1 && (double)p1) + return 1; + return 0; +} + +template +int check_denorm(long double p1) { + long double __trans_tmp_3 = __builtin_fabsl(p1); + if (__trans_tmp_3 < min_value() && (double)p1) { + raise_denorm_error(); + return 1; + } + return 0; +} + +template +double checked_narrowing_cast(long double p1) { + if (check_overflow(p1)) + return 0; + if (check_underflow(p1)) + return 0; + if (check_denorm(p1)) + return 0; + return (double)p1; +} + +long double ellint_rf_imp(long double, long double, long double); + +template +T ellint_rj_imp(T p1, T p2, T p3, T p4, Policy &p5) { + T value, tolerance, P, S3; + if (p4) + return 0; + if (p3 || p1) + raise_domain_error(0, 0, 0, p5); + tolerance = pow(0, 0); + if (p4) { + T q = -p4; + { + long double q6 = ellint_rj_imp((long double)p1, (long double)(double)p2, (long double)(double)p3, (long double)(int)0, p5); + value = checked_narrowing_cast(q6); + } + { + long double q7 = ellint_rf_imp((long double)p1, (long double)(double)p2, (long double)(double)p3); + value -= checked_narrowing_cast(q7); + } + value += p1 * p3 + p4 * q; + return value; + } + do { + P = p4 / p1; + if (0 < tolerance) + break; + sqrt(p3); + } while (1); + S3 = P * p2 * 0; + value = S3 / p1; + return value; +} + +template +void ellint_pi_imp4(double, double p3, Policy &p4) { + double x, y, z; + ellint_rj_imp(x, y, z, p3, p4); +} + +template +double ellint_pi_imp5(double, double p3, double p4, Policy &p5) { + double x, y, z, p; + if (p3 > 0) + return 0; + ellint_rj_imp(x, y, z, p, p5); + ellint_pi_imp4((double)0, p4, p5); +} + +void boost_ellint_3f() { + PolicyA p4; + ellint_pi_imp5((double)0, (double)0, (double)0, p4); +} +