diff mbox

, PR 69667, Fix PowerPC long double failure with -mlra

Message ID 20160204203918.GA2201@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Feb. 4, 2016, 8:39 p.m. UTC
This patch fixes a bug where LRA would abort when compiling a C++ program with
-mlra.  I tracked this down to using the "ws" constraint for TFmode, TDmode,
and IFmode, but those types are limited to just the traditional floating point
registers (ws on power8 targets all of the VSX registers).

With this patch, it eliminates the last use of the "wm" constraint.  However,
since it is a documented constraint, I am not proposing to delete the
constraint.

I built a bootstrapped compiler on little endian power8, there were no
regression errors.  Is it ok to check in this patch?

[gcc]
2016-02-04  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/69667
	* config/rs6000/rs6000.md (mov<mode>_64bit_dm): Use 'd' constraint
	instead of 'ws', and 'wh' instead of 'wm' since TFmode/IFmode are
	not allowed into the traditional Altivec registers.
	(movtd_64bit_nodm): Likewise.
	(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.

[gcc/testsuite]
2016-02-04  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/69667
	* g++.dg/pr69667.C: New file.

Comments

David Edelsohn Feb. 4, 2016, 8:49 p.m. UTC | #1
On Thu, Feb 4, 2016 at 3:39 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch fixes a bug where LRA would abort when compiling a C++ program with
> -mlra.  I tracked this down to using the "ws" constraint for TFmode, TDmode,
> and IFmode, but those types are limited to just the traditional floating point
> registers (ws on power8 targets all of the VSX registers).
>
> With this patch, it eliminates the last use of the "wm" constraint.  However,
> since it is a documented constraint, I am not proposing to delete the
> constraint.
>
> I built a bootstrapped compiler on little endian power8, there were no
> regression errors.  Is it ok to check in this patch?
>
> [gcc]
> 2016-02-04  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         PR target/69667
>         * config/rs6000/rs6000.md (mov<mode>_64bit_dm): Use 'd' constraint
>         instead of 'ws', and 'wh' instead of 'wm' since TFmode/IFmode are
>         not allowed into the traditional Altivec registers.
>         (movtd_64bit_nodm): Likewise.
>         (mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
>
> [gcc/testsuite]
> 2016-02-04  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         PR target/69667
>         * g++.dg/pr69667.C: New file.

Okay.

Thanks, David
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 233145)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -6738,8 +6738,8 @@  (define_expand "mov<mode>"
 ;; problematical.  Don't allow direct move for this case.
 
 (define_insn_and_split "*mov<mode>_64bit_dm"
-  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
-	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r,r,wh")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wh,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
    && FLOAT128_2REG_P (<MODE>mode)
    && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
@@ -6752,7 +6752,7 @@  (define_insn_and_split "*mov<mode>_64bit
   [(set_attr "length" "8,8,8,8,12,12,8,8,8")])
 
 (define_insn_and_split "*movtd_64bit_nodm"
-  [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
+  [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r")
 	(match_operand:TD 1 "input_operand" "d,m,d,j,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 && !WORDS_BIG_ENDIAN
    && (gpc_reg_operand (operands[0], TDmode)
@@ -6764,7 +6764,7 @@  (define_insn_and_split "*movtd_64bit_nod
   [(set_attr "length" "8,8,8,8,12,12,8")])
 
 (define_insn_and_split "*mov<mode>_32bit"
-  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r")
 	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
    && (FLOAT128_2REG_P (<MODE>mode)
Index: gcc/testsuite/g++.dg/pr69667.C
===================================================================
--- gcc/testsuite/g++.dg/pr69667.C	(revision 0)
+++ gcc/testsuite/g++.dg/pr69667.C	(revision 0)
@@ -0,0 +1,105 @@ 
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-mcpu=power8 -w -std=c++14 -mlra" } */
+
+/* target/69667, compiler got
+   internal compiler error: Max. number of generated reload insns per insn is achieved (90)  */
+
+struct A {
+  typedef int evaluation_error_type;
+};
+template <class T, class> T get_epsilon();
+template <class E> __attribute__((__noreturn__)) void throw_exception(E);
+template <class Formatter, class Group> char do_format(Formatter, Group &);
+int raise_error_e, non_central_beta_p_k;
+template <class, class T> void raise_error(T &p1) {
+  char msg = do_format(msg, p1);
+  throw_exception(raise_error_e);
+}
+char raise_evaluation_error_function;
+template <class T1, class T2, class Policy>
+T1 gamma_p_derivative(T1, T2, Policy);
+template <class T, class Policy> T ibeta_imp(Policy, bool, T *);
+template <class> struct B {};
+template <class Dist, class RealType> B<Dist> complement(Dist, RealType);
+template <class, class> class C;
+template <class T, class Policy> struct D {
+  D(C<T, Policy> p1, T, bool) : dist(p1) {}
+  void operator()(T p1) { comp ? cdf(complement(dist, p1)) : T(); }
+  C<T, Policy> dist;
+  bool comp;
+};
+template <class, class = A> class C {
+public:
+  C(int, int, int);
+};
+template <class RealType, class Policy> void quantile(Policy p1, RealType) {
+  nc_beta_quantile(p1, false);
+}
+double quantile_sanity_check___trans_tmp_1, quantile_sanity_check___trans_tmp_3,
+    quantile_sanity_check___trans_tmp_5, quantile_sanity_check___trans_tmp_7;
+void Trans_NS_detail_raise_evaluation_error(char *, char *, long double &p3,
+                                            int) {
+  raise_error<int>(p3);
+}
+template <class T, class Policy>
+void raise_evaluation_error(char *, T &p2, Policy) {
+  Trans_NS_detail_raise_evaluation_error(
+      &raise_evaluation_error_function, "", p2,
+      typename Policy::evaluation_error_type());
+}
+template <class T, class Policy>
+T non_central_beta_p(T p1, T p2, T p3, Policy p4, T p5 = 0) {
+  T y, errtol = get_epsilon<T, Policy>(), l2,
+       pois = gamma_p_derivative(T(), l2, p4), xterm, last_term = 0;
+  if (pois)
+    return p5;
+  T beta = y ? ibeta_imp(p4, false, &xterm) : ibeta_imp(p4, true, &xterm);
+  xterm = y - 1;
+  T sum = p5;
+  if (beta && xterm)
+    return p5;
+  for (; non_central_beta_p_k;) {
+    sum += beta;
+    if (errtol && last_term || beta)
+      break;
+    xterm *=
+        p1 + non_central_beta_p_k - 1 / p3 * p1 + p2 + non_central_beta_p_k - 2;
+    last_term = beta;
+  }
+  raise_evaluation_error("", sum, p4);
+}
+template <class RealType, class Policy>
+RealType non_central_beta_cdf(RealType, bool, Policy) {
+  RealType b, a, x;
+  non_central_beta_p(a, b, x, A());
+}
+template <class F, class T, class Tol, class Policy>
+int bracket_and_solve_root_01(F p1, T, bool, Tol, unsigned, Policy) {
+  T guess;
+  p1(guess);
+}
+template <class RealType, class Policy>
+void nc_beta_quantile(C<RealType, Policy>, bool p2) {
+  RealType p;
+  typedef RealType value_type;
+  D<value_type, Policy> f(C<value_type, Policy>(0, 0, 0), p, p2);
+  void tol();
+  long max_iter =
+      bracket_and_solve_root_01(f, value_type(), true, tol, max_iter, Policy());
+}
+template <class RealType, class Policy> RealType cdf(B<C<RealType, Policy>>) {
+  RealType l = non_central_beta_cdf(l, true, Policy());
+}
+template <typename T> void quantile_sanity_check(T) {
+  quantile(C<long double>(quantile_sanity_check___trans_tmp_1,
+                          quantile_sanity_check___trans_tmp_3,
+                          quantile_sanity_check___trans_tmp_5),
+           quantile_sanity_check___trans_tmp_7);
+}
+void test_accuracy() {
+  int ncbeta;
+  quantile_sanity_check(ncbeta);
+}