aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
authorMichael Meissner <meissner@linux.vnet.ibm.com>2010-07-28 19:58:38 +0000
committerMichael Meissner <meissner@gcc.gnu.org>2010-07-28 19:58:38 +0000
commit8119a6a61b9fd03e677ccdf43d0176eacd5cd3c2 (patch)
treef20e85f45b3293dc8a8643993ad10e771bc57f52 /gcc/config/rs6000/rs6000.md
parent18081149255f8a116512c3e28bf3469ed66d496e (diff)
downloadgcc-8119a6a61b9fd03e677ccdf43d0176eacd5cd3c2.zip
gcc-8119a6a61b9fd03e677ccdf43d0176eacd5cd3c2.tar.gz
gcc-8119a6a61b9fd03e677ccdf43d0176eacd5cd3c2.tar.bz2
Add power6 copysign/parity support
From-SVN: r162656
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc/config/rs6000/rs6000.md110
1 files changed, 53 insertions, 57 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 21287c9..0ef7e98 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -103,6 +103,8 @@
(UNSPEC_TOCREL 49)
(UNSPEC_MACHOPIC_OFFSET 50)
(UNSPEC_BPERM 51)
+ (UNSPEC_COPYSIGN 52)
+ (UNSPEC_PARITY 53)
])
;;
@@ -222,9 +224,12 @@
; but on e500v2, the gpr are 64 bit registers
(define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD])
-;; Iterator for reciprocal estimate instructions
+; Iterator for reciprocal estimate instructions
(define_mode_iterator RECIPF [SF DF V4SF V2DF])
+; Iterator for just SF/DF
+(define_mode_iterator SFDF [SF DF])
+
; 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")])
@@ -250,6 +255,11 @@
(V4SF "Wf")
(V2DF "Wd")])
+(define_mode_attr rreg2 [(SF "f")
+ (DF "d")])
+
+(define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT")
+ (DF "TARGET_DOUBLE_FLOAT")])
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
@@ -2272,17 +2282,11 @@
"TARGET_POPCNTB"
"popcntb %0,%1")
-(define_insn "popcntwsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (popcount:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_insn "popcntd<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
"TARGET_POPCNTD"
- "popcntw %0,%1")
-
-(define_insn "popcntddi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (popcount:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
- "TARGET_POPCNTD && TARGET_POWERPC64"
- "popcntd %0,%1")
+ "popcnt<wd> %0,%1")
(define_expand "popcount<mode>2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
@@ -2293,6 +2297,12 @@
DONE;
})
+(define_insn "parity<mode>2_cmpb"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")] UNSPEC_PARITY))]
+ "TARGET_CMPB && TARGET_POPCNTB"
+ "prty<wd> %0,%1")
+
(define_expand "parity<mode>2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(parity:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
@@ -5976,60 +5986,46 @@
"frsqrtes %0,%1"
[(set_attr "type" "fp")])
-(define_expand "copysignsf3"
+(define_expand "copysign<mode>3"
[(set (match_dup 3)
- (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))
+ (abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))
(set (match_dup 4)
- (neg:SF (abs:SF (match_dup 1))))
- (set (match_operand:SF 0 "gpc_reg_operand" "")
- (if_then_else:SF (ge (match_operand:SF 2 "gpc_reg_operand" "")
- (match_dup 5))
+ (neg:SFDF (abs:SFDF (match_dup 1))))
+ (set (match_operand:SFDF 0 "gpc_reg_operand" "")
+ (if_then_else:SFDF (ge (match_operand:SFDF 2 "gpc_reg_operand" "")
+ (match_dup 5))
(match_dup 3)
(match_dup 4)))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT
+ "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_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);
- })
+ && !HONOR_NANS (<MODE>mode)
+ && !HONOR_SIGNED_ZEROS (<MODE>mode))
+ || TARGET_CMPB
+ || VECTOR_UNIT_VSX_P (<MODE>mode))"
+{
+ if (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))
+ {
+ emit_insn (gen_copysign<mode>3_fcpsgn (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
-(define_expand "copysigndf3"
- [(set (match_dup 3)
- (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))
- (set (match_dup 4)
- (neg:DF (abs:DF (match_dup 1))))
- (set (match_operand:DF 0 "gpc_reg_operand" "")
- (if_then_else:DF (ge (match_operand:DF 2 "gpc_reg_operand" "")
- (match_dup 5))
- (match_dup 3)
- (match_dup 4)))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
- && ((TARGET_PPC_GFXOPT
- && !HONOR_NANS (DFmode)
- && !HONOR_SIGNED_ZEROS (DFmode))
- || VECTOR_UNIT_VSX_P (DFmode))"
- {
- if (VECTOR_UNIT_VSX_P (DFmode))
- {
- emit_insn (gen_vsx_copysigndf3 (operands[0], operands[1],
- operands[2], CONST0_RTX (DFmode)));
- DONE;
- }
- operands[3] = gen_reg_rtx (DFmode);
- operands[4] = gen_reg_rtx (DFmode);
- operands[5] = CONST0_RTX (DFmode);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+ operands[4] = gen_reg_rtx (<MODE>mode);
+ operands[5] = CONST0_RTX (<MODE>mode);
})
+;; Use an unspec rather providing an if-then-else in RTL, to prevent the
+;; compiler from optimizing -0.0
+(define_insn "copysign<mode>3_fcpsgn"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<rreg2>")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_COPYSIGN))]
+ "TARGET_CMPB && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "fcpsgn %0,%2,%1"
+ [(set_attr "type" "fp")])
+
;; For MIN, MAX, and conditional move, we use DEFINE_EXPAND's that involve a
;; fsel instruction and some auxiliary computations. Then we just have a
;; single DEFINE_INSN for fsel and the define_splits to make them if made by