diff mbox

[RS6000] PR70052, ICE compiling _Decimal128 test case

Message ID 20160324110113.GE31470@bubble.grove.modra.org
State New
Headers show

Commit Message

Alan Modra March 24, 2016, 11:01 a.m. UTC
This fixes the PR70052 ICE by modifying easy_fp_constant to correctly
return false for decimal floating point zero.  0.0D is not an all-zero
bit pattern, at least, not the canonical form.

I've also taken on Mike's suggestion of using a mode dependent
constraint for insns that currently use "j".  Note that
"easy_fp_constant" is already part of "input_operand" so in the usual
case we ought to be prevented from generating 0.0D immediate
constants.  However, in the past I've seen reload do some nasty tricks
when pseudos don't get hard regs, and believe that a pseudo that is
known to be equal to 0.0D may have the constant substituted with only
constraints being checked, not the operand predicates.  So either the
"j" constraint needs fixing to reject decimal float (as I had in my
original patch) or not used with decimal float (Mike's approach).
I left in a small tidy for "j" from my original patch.

Bootstrapped and regression tested powerpc64le-linux.  OK to apply?

gcc/
	PR target/70052
	* config/rs6000/constraints.md (j): Simplify.
	* config/rs6000/predicates.md (easy_fp_constant): Exclude
	decimal float 0.D.
	* config/rs6000/rs6000.md (zero_fp): New mode_attr.  Use in place
	of "j" in all constraints.
	(movtd_64bit_nodm): Delete "j" constraint alternative.
gcc/testsuite/
	* gcc.dg/dfp/pr70052.c: New.

Comments

David Edelsohn March 24, 2016, 4:51 p.m. UTC | #1
On Thu, Mar 24, 2016 at 7:01 AM, Alan Modra <amodra@gmail.com> wrote:
> This fixes the PR70052 ICE by modifying easy_fp_constant to correctly
> return false for decimal floating point zero.  0.0D is not an all-zero
> bit pattern, at least, not the canonical form.
>
> I've also taken on Mike's suggestion of using a mode dependent
> constraint for insns that currently use "j".  Note that
> "easy_fp_constant" is already part of "input_operand" so in the usual
> case we ought to be prevented from generating 0.0D immediate
> constants.  However, in the past I've seen reload do some nasty tricks
> when pseudos don't get hard regs, and believe that a pseudo that is
> known to be equal to 0.0D may have the constant substituted with only
> constraints being checked, not the operand predicates.  So either the
> "j" constraint needs fixing to reject decimal float (as I had in my
> original patch) or not used with decimal float (Mike's approach).
> I left in a small tidy for "j" from my original patch.
>
> Bootstrapped and regression tested powerpc64le-linux.  OK to apply?
>
> gcc/
>         PR target/70052
>         * config/rs6000/constraints.md (j): Simplify.
>         * config/rs6000/predicates.md (easy_fp_constant): Exclude
>         decimal float 0.D.
>         * config/rs6000/rs6000.md (zero_fp): New mode_attr.  Use in place
>         of "j" in all constraints.

The patch did not convert all "j" constraints, so the ChangeLog needs
to be a little clearer to explain which alternatives required the
change.

>         (movtd_64bit_nodm): Delete "j" constraint alternative.
> gcc/testsuite/
>         * gcc.dg/dfp/pr70052.c: New.

Okay with that clarification.

Thanks, David
diff mbox

Patch

diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index 9eca757..ea15764 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -272,4 +272,4 @@  usually better to use @samp{m} or @samp{es} in @code{asm} statements)"
 
 (define_constraint "j"
   "Zero vector constant"
-  (match_test "op == const0_rtx || op == CONST0_RTX (GET_MODE (op))"))
+  (match_test "op == const0_rtx || op == CONST0_RTX (mode)"))
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 072291e..71fac76 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -527,13 +527,14 @@ 
       && mode != DImode)
     return 1;
 
+  /* 0.0D is not all zero bits.  */
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    return 0;
+
   /* The constant 0.0 is easy under VSX.  */
   if (TARGET_VSX && SCALAR_FLOAT_MODE_P (mode) && op == CONST0_RTX (mode))
     return 1;
 
-  if (DECIMAL_FLOAT_MODE_P (mode))
-    return 0;
-
   /* If we are using V.4 style PIC, consider all constants to be hard.  */
   if (flag_pic && DEFAULT_ABI == ABI_V4)
     return 0;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d4678af..d47f93e 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -428,6 +428,16 @@ 
 					(SD "REAL_VALUE_TO_TARGET_DECIMAL32")
 					(DD "REAL_VALUE_TO_TARGET_DECIMAL64")])
 
+; Whether 0.0 has an all-zero bit pattern
+(define_mode_attr zero_fp [(SF "j")
+			   (DF "j")
+			   (TF "j")
+			   (IF "j")
+			   (KF "j")
+			   (SD "wn")
+			   (DD "wn")
+			   (TD "wn")])
+
 ; Definitions for load to 32-bit fpr register
 (define_mode_attr f32_lr  [(SF "f")		  (SD "wz")])
 (define_mode_attr f32_lr2 [(SF "wb")		  (SD "wn")])
@@ -6472,7 +6482,7 @@ 
 
 (define_insn "mov<mode>_hardfloat"
   [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,<f32_vsx>,<f32_vsx>,!r,<f32_lr>,<f32_lr2>,<f32_sm>,<f32_sm2>,<f32_av>,Z,?<f32_dm>,?r,*c*l,!r,*h")
-	(match_operand:FMOVE32 1 "input_operand" "r,m,r,f,<f32_vsx>,j,j,<f32_lm>,<f32_lm2>,<f32_sr>,<f32_sr2>,Z,<f32_av>,r,<f32_dm>,r,h,0"))]
+	(match_operand:FMOVE32 1 "input_operand" "r,m,r,f,<f32_vsx>,<zero_fp>,<zero_fp>,<f32_lm>,<f32_lm2>,<f32_sr>,<f32_sr2>,Z,<f32_av>,r,<f32_dm>,r,h,0"))]
   "(gpc_reg_operand (operands[0], <MODE>mode)
    || gpc_reg_operand (operands[1], <MODE>mode))
    && (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)"
@@ -6612,7 +6622,7 @@ 
 
 (define_insn "*mov<mode>_hardfloat32"
   [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,<f64_av>,Z,<f64_p9>,o,<f64_vsx>,<f64_vsx>,!r,Y,r,!r")
-	(match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,<f64_av>,o,<f64_p9>,<f64_vsx>,j,j,r,Y,r"))]
+	(match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,<f64_av>,o,<f64_p9>,<f64_vsx>,<zero_fp>,<zero_fp>,r,Y,r"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
@@ -6650,7 +6660,7 @@ 
 ; List Y->r and r->Y before r->r for reload.
 (define_insn "*mov<mode>_hardfloat64"
   [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,<f64_p9>,o,<f64_av>,Z,<f64_vsx>,<f64_vsx>,!r,Y,r,!r,*c*l,!r,*h,r,wg,r,<f64_dm>")
-	(match_operand:FMOVE64 1 "input_operand" "d,m,d,o,<f64_p9>,Z,<f64_av>,<f64_vsx>,j,j,r,Y,r,r,h,0,wg,r,<f64_dm>,r"))]
+	(match_operand:FMOVE64 1 "input_operand" "d,m,d,o,<f64_p9>,Z,<f64_av>,<f64_vsx>,<zero_fp>,<zero_fp>,r,Y,r,r,h,0,wg,r,<f64_dm>,r"))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
@@ -6713,7 +6723,7 @@ 
 
 (define_insn_and_split "*mov<mode>_64bit_dm"
   [(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"))]
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,<zero_fp>,r,jY,r,wh,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
    && FLOAT128_2REG_P (<MODE>mode)
    && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
@@ -6726,8 +6736,8 @@ 
   [(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,d,Y,r,r")
-	(match_operand:TD 1 "input_operand" "d,m,d,j,r,jY,r"))]
+  [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
+	(match_operand:TD 1 "input_operand" "d,m,d,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 && !WORDS_BIG_ENDIAN
    && (gpc_reg_operand (operands[0], TDmode)
        || gpc_reg_operand (operands[1], TDmode))"
@@ -6735,11 +6745,11 @@ 
   "&& reload_completed"
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
-  [(set_attr "length" "8,8,8,8,12,12,8")])
+  [(set_attr "length" "8,8,8,12,12,8")])
 
 (define_insn_and_split "*mov<mode>_32bit"
   [(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"))]
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,<zero_fp>,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
    && (FLOAT128_2REG_P (<MODE>mode)
        || int_reg_operand_not_pseudo (operands[0], <MODE>mode)
diff --git a/gcc/testsuite/gcc.dg/dfp/pr70052.c b/gcc/testsuite/gcc.dg/dfp/pr70052.c
new file mode 100644
index 0000000..53eb075
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/pr70052.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+typedef struct
+{
+  _Decimal128 td0;
+  _Decimal128 td1;
+} TDx2_t;
+
+
+TDx2_t
+D256_add_finite (void)
+{
+  _Decimal128 z, zz;
+  TDx2_t result = {0.DL, 0.DL};
+
+  if (zz == 0.DL)
+  {
+    result.td0 = z;
+    return result;
+  }
+
+  return result;
+}