This patch is the second part to allow TFmode to be IBM extended double or IEEE 128-bit floating point depending on switches.
I have built the compiler with this patch and the previous subpatches (1-12). I have bootstrapped the compiler with all 16 subpatches installed, and there were no regressions. Is it ok to install in the trunk? 2015-10-22 Michael Meissner <meiss...@linux.vnet.ibm.com> * config/rs6000/rs6000.md (FP iterator): Allow TFmode to be IEEE 128-bit floating point. (extenddftf2): Rework 128-bit floating point conversions to properly handle -mabi=ieeelongdouble. Merge IFmode, TFmode, and KFmode expanders into one function. (extenddf<mode>2): Likewise. (extenddftf2_fprs): Likewise. (extenddf<mode>2_fprs): Likewise. (extenddftf2_vsx): Likewise. (extenddf<mode>2_vsx): Likewise. (extendsftf2): Likewise. (extendsf<mode>2): Likewise. (trunctfdf2): Likewise. (trunc<mode>df2): Likewise. (trunctfdf2_internal1): Likewise. (trunc<mode>df2_internal1): Likewise. (trunctfdf2_internal2): Likewise. (trunc<mode>df2_internal2): Likewise. (trunctfsf2): Likewise. (trunc<mode>sf2): Likewise. (trunctfsf2_fprs): Likewise. (trunc<mode>sf2_fprs): Likewise. (floatsit2f): Likewise. (floatsi<mode>2): Likewise. (fix_trunc_helper): Likewise. (fix_trunc_helper<mode>): Likewise. (fix_trunctfsi2): Likewise. (fix_trunc<mode>si2): Likewise. (fix_trunctfsi2_fprs): Likewise. (fix_trunc<mode>si2_fprs): Likewise. (fix_trunctfsi2_internal): Likewise. (fix_trunc<mode>si2_internal): Likewise. (fix_trunctfdi2): Likewise. (fix_trunc<mode>di2): Likewise. (fixuns_trunctf<mode>2): Likewise. (fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise. (floatditf2): Likewise. (floatdi<mode>2): Likewise. (floatuns<mode>tf2): Likewise. (floatuns<SDI:mode><IEEE128:mode>): Likewise. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 229198) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -347,8 +347,7 @@ (define_mode_iterator FP [ && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_E500_SINGLE)") (DF "TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)") - (TF "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT + (TF "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128") (IF "TARGET_FLOAT128") @@ -6463,34 +6462,51 @@ (define_insn_and_split "*mov<mode>_softf { rs6000_split_multireg_move (operands[0], operands[1]); DONE; } [(set_attr "length" "20,20,16")]) -(define_expand "extenddftf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (float_extend:TF (match_operand:DF 1 "gpc_reg_operand" "")))] +(define_expand "extenddf<mode>2" + [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") + (float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand" "")))] "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_IEEEQUAD) + if (FLOAT128_IEEE_P (<MODE>mode)) rs6000_expand_float128_convert (operands[0], operands[1], false); else if (TARGET_E500_DOUBLE) - emit_insn (gen_spe_extenddftf2 (operands[0], operands[1])); + { + gcc_assert (<MODE>mode == TFmode); + emit_insn (gen_spe_extenddftf2 (operands[0], operands[1])); + } else if (TARGET_VSX) - emit_insn (gen_extenddftf2_vsx (operands[0], operands[1])); - else + { + if (<MODE>mode == TFmode) + emit_insn (gen_extenddftf2_vsx (operands[0], operands[1])); + else if (<MODE>mode == IFmode) + emit_insn (gen_extenddfif2_vsx (operands[0], operands[1])); + else + gcc_unreachable (); + } + else { rtx zero = gen_reg_rtx (DFmode); rs6000_emit_move (zero, CONST0_RTX (DFmode), DFmode); - emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero)); + + if (<MODE>mode == TFmode) + emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero)); + else if (<MODE>mode == IFmode) + emit_insn (gen_extenddfif2_fprs (operands[0], operands[1], zero)); + else + gcc_unreachable (); } DONE; }) ;; Allow memory operands for the source to be created by the combiner. -(define_insn_and_split "extenddftf2_fprs" - [(set (match_operand:TF 0 "gpc_reg_operand" "=d,d,&d") - (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "d,m,d"))) +(define_insn_and_split "extenddf<mode>2_fprs" + [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d,&d") + (float_extend:IBM128 + (match_operand:DF 1 "nonimmediate_operand" "d,m,d"))) (use (match_operand:DF 2 "nonimmediate_operand" "m,m,d"))] "!TARGET_VSX && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD" + && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)" "#" "&& reload_completed" [(set (match_dup 3) (match_dup 1)) @@ -6499,14 +6515,15 @@ (define_insn_and_split "extenddftf2_fprs const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0; const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode); - operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word); - operands[4] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word); + operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word); + operands[4] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word); }) -(define_insn_and_split "extenddftf2_vsx" - [(set (match_operand:TF 0 "gpc_reg_operand" "=d,d") - (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "ws,m")))] - "TARGET_LONG_DOUBLE_128 && TARGET_VSX && !TARGET_IEEEQUAD" +(define_insn_and_split "extenddf<mode>2_vsx" + [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d") + (float_extend:IBM128 + (match_operand:DF 1 "nonimmediate_operand" "ws,m")))] + "TARGET_LONG_DOUBLE_128 && TARGET_VSX && FLOAT128_IBM_P (<MODE>mode)" "#" "&& reload_completed" [(set (match_dup 2) (match_dup 1)) @@ -6515,47 +6532,48 @@ (define_insn_and_split "extenddftf2_vsx" const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0; const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode); - operands[2] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word); - operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word); + operands[2] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word); + operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word); operands[4] = CONST0_RTX (DFmode); }) -(define_expand "extendsftf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))] +(define_expand "extendsf<mode>2" + [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") + (float_extend:FLOAT128 (match_operand:SF 1 "gpc_reg_operand" "")))] "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_IEEEQUAD) + if (FLOAT128_IEEE_P (<MODE>mode)) rs6000_expand_float128_convert (operands[0], operands[1], false); else { rtx tmp = gen_reg_rtx (DFmode); emit_insn (gen_extendsfdf2 (tmp, operands[1])); - emit_insn (gen_extenddftf2 (operands[0], tmp)); + emit_insn (gen_extenddf<mode>2 (operands[0], tmp)); } DONE; }) -(define_expand "trunctfdf2" +(define_expand "trunc<mode>df2" [(set (match_operand:DF 0 "gpc_reg_operand" "") - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))] + (float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_IEEEQUAD) + if (FLOAT128_IEEE_P (<MODE>mode)) { rs6000_expand_float128_convert (operands[0], operands[1], false); DONE; } }) -(define_insn_and_split "trunctfdf2_internal1" +(define_insn_and_split "trunc<mode>df2_internal1" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d") - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,d")))] - "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT + (float_truncate:DF + (match_operand:IBM128 1 "gpc_reg_operand" "0,d")))] + "FLOAT128_IBM_P (<MODE>mode) && !TARGET_XL_COMPAT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" "@ # @@ -6568,39 +6586,44 @@ (define_insn_and_split "trunctfdf2_inter } [(set_attr "type" "fp")]) -(define_insn "trunctfdf2_internal2" +(define_insn "trunc<mode>df2_internal2" [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "d")))] - "!TARGET_IEEEQUAD && TARGET_XL_COMPAT - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && TARGET_LONG_DOUBLE_128" + (float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "d")))] + "FLOAT128_IBM_P (<MODE>mode) && TARGET_XL_COMPAT && TARGET_HARD_FLOAT + && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128" "fadd %0,%1,%L1" [(set_attr "type" "fp") (set_attr "fp_type" "fp_addsub_d")]) -(define_expand "trunctfsf2" +(define_expand "trunc<mode>sf2" [(set (match_operand:SF 0 "gpc_reg_operand" "") - (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))] + (float_truncate:SF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_IEEEQUAD) + if (FLOAT128_IEEE_P (<MODE>mode)) rs6000_expand_float128_convert (operands[0], operands[1], false); else if (TARGET_E500_DOUBLE) - emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1])); - else + { + gcc_assert (<MODE>mode == TFmode); + emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1])); + } + else if (<MODE>mode == TFmode) emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1])); + else if (<MODE>mode == IFmode) + emit_insn (gen_truncifsf2_fprs (operands[0], operands[1])); + else + gcc_unreachable (); DONE; }) -(define_insn_and_split "trunctfsf2_fprs" +(define_insn_and_split "trunc<mode>sf2_fprs" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "d"))) + (float_truncate:SF (match_operand:IBM128 1 "gpc_reg_operand" "d"))) (clobber (match_scratch:DF 2 "=d"))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT - && TARGET_LONG_DOUBLE_128" + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT + && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)" "#" "&& reload_completed" [(set (match_dup 2) @@ -6609,56 +6632,69 @@ (define_insn_and_split "trunctfsf2_fprs" (float_truncate:SF (match_dup 2)))] "") -(define_expand "floatsitf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (float:TF (match_operand:SI 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT +(define_expand "floatsi<mode>2" + [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") + (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand" "")))] + "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - rtx tmp = gen_reg_rtx (DFmode); - expand_float (tmp, operands[1], false); - emit_insn (gen_extenddftf2 (operands[0], tmp)); + if (FLOAT128_IEEE_P (<MODE>mode)) + rs6000_expand_float128_convert (operands[0], operands[1], false); + else + { + rtx tmp = gen_reg_rtx (DFmode); + expand_float (tmp, operands[1], false); + if (<MODE>mode == TFmode) + emit_insn (gen_extenddftf2 (operands[0], tmp)); + else if (<MODE>mode == IFmode) + emit_insn (gen_extenddfif2 (operands[0], tmp)); + else + gcc_unreachable (); + } DONE; }) ; fadd, but rounding towards zero. ; This is probably not the optimal code sequence. -(define_insn "fix_trunc_helper" +(define_insn "fix_trunc_helper<mode>" [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "d")] + (unspec:DF [(match_operand:IBM128 1 "gpc_reg_operand" "d")] UNSPEC_FIX_TRUNC_TF)) (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && FLOAT128_IBM_P (<MODE>mode)" "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2" [(set_attr "type" "fp") (set_attr "length" "20")]) -(define_expand "fix_trunctfsi2" +(define_expand "fix_trunc<mode>si2" [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))] + (fix:SI (match_operand:FLOAT128 1 "gpc_reg_operand" "")))] "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_IEEEQUAD) + if (FLOAT128_IEEE_P (<MODE>mode)) rs6000_expand_float128_convert (operands[0], operands[1], false); - else if (TARGET_E500_DOUBLE) + else if (TARGET_E500_DOUBLE && <MODE>mode == TFmode) emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1])); - else + else if (<MODE>mode == TFmode) emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1])); + else if (<MODE>mode == IFmode) + emit_insn (gen_fix_truncifsi2_fprs (operands[0], operands[1])); + else + gcc_unreachable (); DONE; }) -(define_expand "fix_trunctfsi2_fprs" +(define_expand "fix_trunc<mode>si2_fprs" [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:TF 1 "gpc_reg_operand" ""))) + (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" ""))) (clobber (match_dup 2)) (clobber (match_dup 3)) (clobber (match_dup 4)) (clobber (match_dup 5))])] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" { operands[2] = gen_reg_rtx (DFmode); operands[3] = gen_reg_rtx (DFmode); @@ -6666,21 +6702,21 @@ (define_expand "fix_trunctfsi2_fprs" operands[5] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode)); }) -(define_insn_and_split "*fix_trunctfsi2_internal" +(define_insn_and_split "*fix_trunc<mode>si2_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:TF 1 "gpc_reg_operand" "d"))) + (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "d"))) (clobber (match_operand:DF 2 "gpc_reg_operand" "=d")) (clobber (match_operand:DF 3 "gpc_reg_operand" "=&d")) (clobber (match_operand:DI 4 "gpc_reg_operand" "=d")) (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" "#" "" [(pc)] { rtx lowword; - emit_insn (gen_fix_trunc_helper (operands[2], operands[1], operands[3])); + emit_insn (gen_fix_trunc_helper<mode> (operands[2], operands[1], + operands[3])); gcc_assert (MEM_P (operands[5])); lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0); @@ -6691,37 +6727,37 @@ (define_insn_and_split "*fix_trunctfsi2_ DONE; }) -(define_expand "fix_trunctfdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (match_operand:TF 1 "gpc_reg_operand" "")))] - "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +(define_expand "fix_trunc<mode>di2" + [(set (match_operand:DI 0 "gpc_reg_operand" "") + (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" { rs6000_expand_float128_convert (operands[0], operands[1], false); DONE; }) -(define_expand "fixuns_trunctf<mode>2" - [(set (match_operand:SDI 0 "nonimmediate_operand" "") - (unsigned_fix:SDI (match_operand:TF 1 "gpc_reg_operand" "")))] - "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +(define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2" + [(set (match_operand:SDI 0 "gpc_reg_operand" "") + (unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" { rs6000_expand_float128_convert (operands[0], operands[1], true); DONE; }) -(define_expand "floatditf2" - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (float:TF (match_operand:DI 1 "gpc_reg_operand" "")))] - "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +(define_expand "floatdi<mode>2" + [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") + (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" { rs6000_expand_float128_convert (operands[0], operands[1], false); DONE; }) -(define_expand "floatuns<mode>tf2" - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (unsigned_float:TF (match_operand:SDI 1 "gpc_reg_operand" "")))] - "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +(define_expand "floatuns<SDI:mode><IEEE128:mode>2" + [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") + (unsigned_float:IEEE128 (match_operand:SDI 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" { rs6000_expand_float128_convert (operands[0], operands[1], true); DONE;