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.

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;
+}

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to