aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2010-06-03 00:06:12 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2010-06-03 00:06:12 +0000
commit92902797041a42ac500f7dc9639df8a680e0b691 (patch)
treed55e7fa0ae623e1c748075d3f81edeb35fb123fb /gcc/config/rs6000/rs6000.md
parent6c07d08b90b124d8d3be8015726caf799e2e2a13 (diff)
downloadgcc-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.md119
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")