@@ -1,3 +1,10 @@
+2013-10-18 Mikael Pettersson <mikpelinux@gmail.com>
+
+ 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 <burnus@net-b.de>
PR other/33426
@@ -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);
@@ -1,3 +1,8 @@
+2013-10-30 Mikael Pettersson <mikpe@it.uu.se>
+
+ * PR rtl-optimization/58369
+ * g++.dg/torture/pr58369.C: New test.
+
2013-10-30 Tobias Burnus <burnus@net-b.de>
PR other/33426
new file mode 100644
@@ -0,0 +1,109 @@
+// { dg-do compile }
+// Reduced from boost-1.54
+
+int pow(int, int);
+int sqrt(int);
+
+class PolicyA { };
+
+template <class>
+int max_value() { return 0x7fffffff; }
+
+template <class>
+int min_value() { return 1; }
+
+void raise_denorm_error();
+
+template <class T>
+void raise_domain_error(int, int, const T &, const PolicyA &);
+
+template <class>
+int check_overflow(long double p1) {
+ long double __trans_tmp_2 = __builtin_fabsl(p1);
+ if (__trans_tmp_2 > max_value<int>())
+ return 1;
+ return 0;
+}
+
+template <class>
+int check_underflow(long double p1) {
+ if (p1 && (double)p1)
+ return 1;
+ return 0;
+}
+
+template <class>
+int check_denorm(long double p1) {
+ long double __trans_tmp_3 = __builtin_fabsl(p1);
+ if (__trans_tmp_3 < min_value<int>() && (double)p1) {
+ raise_denorm_error();
+ return 1;
+ }
+ return 0;
+}
+
+template <class, class>
+double checked_narrowing_cast(long double p1) {
+ if (check_overflow<int>(p1))
+ return 0;
+ if (check_underflow<int>(p1))
+ return 0;
+ if (check_denorm<int>(p1))
+ return 0;
+ return (double)p1;
+}
+
+long double ellint_rf_imp(long double, long double, long double);
+
+template <typename T, typename Policy>
+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<T, int>(q6);
+ }
+ {
+ long double q7 = ellint_rf_imp((long double)p1, (long double)(double)p2, (long double)(double)p3);
+ value -= checked_narrowing_cast<T, const int>(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 <typename Policy>
+void ellint_pi_imp4(double, double p3, Policy &p4) {
+ double x, y, z;
+ ellint_rj_imp(x, y, z, p3, p4);
+}
+
+template <typename Policy>
+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);
+}
+