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