diff options
author | Michael Meissner <meissner@linux.vnet.ibm.com> | 2010-06-03 00:06:12 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2010-06-03 00:06:12 +0000 |
commit | 92902797041a42ac500f7dc9639df8a680e0b691 (patch) | |
tree | d55e7fa0ae623e1c748075d3f81edeb35fb123fb /gcc/config/rs6000/rs6000.md | |
parent | 6c07d08b90b124d8d3be8015726caf799e2e2a13 (diff) | |
download | gcc-92902797041a42ac500f7dc9639df8a680e0b691.zip gcc-92902797041a42ac500f7dc9639df8a680e0b691.tar.gz gcc-92902797041a42ac500f7dc9639df8a680e0b691.tar.bz2 |
PR target/44218, improve -mrecip on powerpc
From-SVN: r160199
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 119 |
1 files changed, 71 insertions, 48 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index bcb66ec..8f7093a 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -220,6 +220,9 @@ ; These modes do not fit in integer registers in 32-bit mode. (define_mode_iterator DIFD [DI DF DD]) +;; Iterator for reciprocal estimate instructions +(define_mode_iterator RECIPF [SF DF V4SF V2DF]) + ; Various instructions that come in SI and DI forms. ; A generic w/d attribute, for things like cmpw/cmpd. (define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")]) @@ -240,6 +243,11 @@ (define_mode_attr mptrsize [(SI "si") (DI "di")]) +(define_mode_attr rreg [(SF "f") + (DF "Ws") + (V4SF "Wf") + (V2DF "Wd")]) + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -5563,6 +5571,45 @@ [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") (set_attr "length" "4,4,8,8")]) +;; Builtins to replace a division to generate FRE reciprocal estimate +;; instructions and the necessary fixup instructions +(define_expand "recip<mode>3" + [(match_operand:RECIPF 0 "gpc_reg_operand" "") + (match_operand:RECIPF 1 "gpc_reg_operand" "") + (match_operand:RECIPF 2 "gpc_reg_operand" "")] + "RS6000_RECIP_HAVE_RE_P (<MODE>mode)" +{ + rs6000_emit_swdiv (operands[0], operands[1], operands[2], false); + DONE; +}) + +;; Split to create division from FRE/FRES/etc. and fixup instead of the normal +;; hardware division. This is only done before register allocation and with +;; -ffast-math. This must appear before the divsf3/divdf3 insns. +(define_split + [(set (match_operand:RECIPF 0 "gpc_reg_operand" "") + (div:RECIPF (match_operand 1 "gpc_reg_operand" "") + (match_operand 2 "gpc_reg_operand" "")))] + "RS6000_RECIP_AUTO_RE_P (<MODE>mode) + && can_create_pseudo_p () && optimize_insn_for_speed_p () + && flag_finite_math_only && !flag_trapping_math && flag_reciprocal_math" + [(const_int 0)] +{ + rs6000_emit_swdiv (operands[0], operands[1], operands[2], true); + DONE; +}) + +;; Builtins to replace 1/sqrt(x) with instructions using RSQRTE and the +;; appropriate fixup. +(define_expand "rsqrt<mode>2" + [(match_operand:RECIPF 0 "gpc_reg_operand" "") + (match_operand:RECIPF 1 "gpc_reg_operand" "")] + "RS6000_RECIP_HAVE_RSQRT_P (<MODE>mode)" +{ + rs6000_emit_swrsqrt (operands[0], operands[1]); + DONE; +}) + (define_split [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") (compare:CC (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") @@ -5766,22 +5813,10 @@ "{fd|fdiv} %0,%1,%2" [(set_attr "type" "ddiv")]) -(define_expand "recipsf3" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f") - (match_operand:SF 2 "gpc_reg_operand" "f")] - UNSPEC_FRES))] - "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT && !optimize_size - && flag_finite_math_only && !flag_trapping_math" -{ - rs6000_emit_swdivsf (operands[0], operands[1], operands[2]); - DONE; -}) - (define_insn "fres" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))] - "TARGET_PPC_GFXOPT && flag_finite_math_only" + "TARGET_FRES" "fres %0,%1" [(set_attr "type" "fp")]) @@ -5931,23 +5966,12 @@ "fsqrt %0,%1" [(set_attr "type" "dsqrt")]) -(define_expand "rsqrtsf2" +(define_insn "*rsqrtsf_internal1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_RSQRT))] - "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT && !optimize_size - && flag_finite_math_only && !flag_trapping_math" -{ - rs6000_emit_swrsqrtsf (operands[0], operands[1]); - DONE; -}) - -(define_insn "*rsqrt_internal1" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] - UNSPEC_RSQRT))] - "TARGET_HARD_FLOAT && TARGET_PPC_GFXOPT" - "frsqrte %0,%1" + "TARGET_FRSQRTES" + "frsqrtes %0,%1" [(set_attr "type" "fp")]) (define_expand "copysignsf3" @@ -5960,9 +5984,18 @@ (match_dup 5)) (match_dup 3) (match_dup 4)))] - "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT - && !HONOR_NANS (SFmode) && !HONOR_SIGNED_ZEROS (SFmode)" + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT + && ((TARGET_PPC_GFXOPT + && !HONOR_NANS (SFmode) + && !HONOR_SIGNED_ZEROS (SFmode)) + || VECTOR_UNIT_VSX_P (DFmode))" { + if (VECTOR_UNIT_VSX_P (DFmode)) + { + emit_insn (gen_vsx_copysignsf3 (operands[0], operands[1], operands[2], + CONST0_RTX (SFmode))); + DONE; + } operands[3] = gen_reg_rtx (SFmode); operands[4] = gen_reg_rtx (SFmode); operands[5] = CONST0_RTX (SFmode); @@ -6222,31 +6255,21 @@ "{fd|fdiv} %0,%1,%2" [(set_attr "type" "ddiv")]) -(define_expand "recipdf3" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d") - (match_operand:DF 2 "gpc_reg_operand" "d")] - UNSPEC_FRES))] - "TARGET_RECIP && TARGET_HARD_FLOAT && TARGET_POPCNTB && !optimize_size - && flag_finite_math_only && !flag_trapping_math" -{ - rs6000_emit_swdivdf (operands[0], operands[1], operands[2]); - DONE; -}) - -(define_expand "fred" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRES))] - "(TARGET_POPCNTB || VECTOR_UNIT_VSX_P (DFmode)) && flag_finite_math_only" - "") - (define_insn "*fred_fpr" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))] - "TARGET_POPCNTB && flag_finite_math_only && !VECTOR_UNIT_VSX_P (DFmode)" + "TARGET_FRE && !VECTOR_UNIT_VSX_P (DFmode)" "fre %0,%1" [(set_attr "type" "fp")]) +(define_insn "*rsqrtdf_internal1" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] + UNSPEC_RSQRT))] + "TARGET_FRSQRTE && !VECTOR_UNIT_VSX_P (DFmode)" + "frsqrte %0,%1" + [(set_attr "type" "fp")]) + (define_insn "*fmadddf4_fpr" [(set (match_operand:DF 0 "gpc_reg_operand" "=d") (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%d") |