summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc/config/rs6000/rs6000.md198
1 files changed, 159 insertions, 39 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index ed5ff397e07..276ad8a32e8 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -182,7 +182,7 @@
cmp,
branch,jmpreg,mfjmpr,mtjmpr,trap,isync,sync,load_l,store_c,
cr_logical,delayed_cr,mfcr,mfcrf,mtcr,
- fpcompare,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,
+ fpcompare,fp,fpsimple,dmul,qmul,sdiv,ddiv,ssqrt,dsqrt,
vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto,
veclogical,veccmpfx,vecexts,vecmove,
@@ -323,6 +323,9 @@
; of whole values in GPRs.
(define_mode_iterator GPR [SI (DI "TARGET_POWERPC64")])
+; And again, for patterns that need two (potentially) different integer modes.
+(define_mode_iterator GPR2 [SI (DI "TARGET_POWERPC64")])
+
; Any supported integer mode.
(define_mode_iterator INT [QI HI SI DI TI PTI])
@@ -2429,13 +2432,15 @@
[(set_attr "type" "store")])
(define_insn_and_split "bswaphi2_reg"
- [(set (match_operand:HI 0 "gpc_reg_operand" "=&r")
+ [(set (match_operand:HI 0 "gpc_reg_operand" "=&r,wo")
(bswap:HI
- (match_operand:HI 1 "gpc_reg_operand" "r")))
- (clobber (match_scratch:SI 2 "=&r"))]
+ (match_operand:HI 1 "gpc_reg_operand" "r,wo")))
+ (clobber (match_scratch:SI 2 "=&r,X"))]
""
- "#"
- "reload_completed"
+ "@
+ #
+ xxbrh %x0,%x1"
+ "reload_completed && int_reg_operand (operands[0], HImode)"
[(set (match_dup 3)
(and:SI (lshiftrt:SI (match_dup 4)
(const_int 8))
@@ -2451,18 +2456,20 @@
operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
}
- [(set_attr "length" "12")
- (set_attr "type" "*")])
+ [(set_attr "length" "12,4")
+ (set_attr "type" "*,vecperm")])
;; We are always BITS_BIG_ENDIAN, so the bit positions below in
;; zero_extract insns do not change for -mlittle.
(define_insn_and_split "bswapsi2_reg"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,wo")
(bswap:SI
- (match_operand:SI 1 "gpc_reg_operand" "r")))]
+ (match_operand:SI 1 "gpc_reg_operand" "r,wo")))]
""
- "#"
- "reload_completed"
+ "@
+ #
+ xxbrw %x0,%x1"
+ "reload_completed && int_reg_operand (operands[0], SImode)"
[(set (match_dup 0) ; DABC
(rotate:SI (match_dup 1)
(const_int 24)))
@@ -2478,7 +2485,9 @@
(const_int 255))
(and:SI (match_dup 0)
(const_int -256))))]
- "")
+ ""
+ [(set_attr "length" "12,4")
+ (set_attr "type" "*,vecperm")])
;; On systems with LDBRX/STDBRX generate the loads/stores directly, just like
;; we do for L{H,W}BRX and ST{H,W}BRX above. If not, we have to generate more
@@ -2504,6 +2513,8 @@
emit_insn (gen_bswapdi2_load (dest, src));
else if (MEM_P (dest))
emit_insn (gen_bswapdi2_store (dest, src));
+ else if (TARGET_P9_VECTOR)
+ emit_insn (gen_bswapdi2_xxbrd (dest, src));
else
emit_insn (gen_bswapdi2_reg (dest, src));
DONE;
@@ -2534,12 +2545,19 @@
"stdbrx %1,%y0"
[(set_attr "type" "store")])
+(define_insn "bswapdi2_xxbrd"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=wo")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "wo")))]
+ "TARGET_P9_VECTOR"
+ "xxbrd %x0,%x1"
+ [(set_attr "type" "vecperm")])
+
(define_insn "bswapdi2_reg"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
(clobber (match_scratch:DI 2 "=&r"))
(clobber (match_scratch:DI 3 "=&r"))]
- "TARGET_POWERPC64 && TARGET_LDBRX"
+ "TARGET_POWERPC64 && TARGET_LDBRX && !TARGET_P9_VECTOR"
"#"
[(set_attr "length" "36")])
@@ -2688,7 +2706,7 @@
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
(clobber (match_operand:DI 2 "gpc_reg_operand" ""))
(clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
- "TARGET_POWERPC64 && reload_completed"
+ "TARGET_POWERPC64 && !TARGET_P9_VECTOR && reload_completed"
[(const_int 0)]
"
{
@@ -11780,13 +11798,9 @@
(clobber (match_operand:GPR 0 "gpc_reg_operand"))]
""
{
- /* Use ISEL if the user asked for it. */
- if (TARGET_ISEL)
- rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx);
-
/* Expanding EQ and NE directly to some machine instructions does not help
but does hurt combine. So don't. */
- else if (GET_CODE (operands[1]) == EQ)
+ if (GET_CODE (operands[1]) == EQ)
emit_insn (gen_eq<mode>3 (operands[0], operands[2], operands[3]));
else if (<MODE>mode == Pmode
&& GET_CODE (operands[1]) == NE)
@@ -11798,7 +11812,11 @@
emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx));
}
- /* Expanding the unsigned comparisons however helps a lot: all the neg_ltu
+ /* If ISEL is fast, expand to it. */
+ else if (TARGET_ISEL)
+ rs6000_emit_int_cmove (operands[0], operands[1], const1_rtx, const0_rtx);
+
+ /* Expanding the unsigned comparisons helps a lot: all the neg_ltu
etc. combinations magically work out just right. */
else if (<MODE>mode == Pmode
&& unsigned_comparison_operator (operands[1], VOIDmode))
@@ -12280,18 +12298,102 @@
"")
+(define_code_iterator cmp [eq ne lt ltu gt gtu le leu ge geu])
+(define_code_attr UNS [(eq "CC")
+ (ne "CC")
+ (lt "CC") (ltu "CCUNS")
+ (gt "CC") (gtu "CCUNS")
+ (le "CC") (leu "CCUNS")
+ (ge "CC") (geu "CCUNS")])
+(define_code_attr UNSu_ [(eq "")
+ (ne "")
+ (lt "") (ltu "u_")
+ (gt "") (gtu "u_")
+ (le "") (leu "u_")
+ (ge "") (geu "u_")])
+(define_code_attr UNSIK [(eq "I")
+ (ne "I")
+ (lt "I") (ltu "K")
+ (gt "I") (gtu "K")
+ (le "I") (leu "K")
+ (ge "I") (geu "K")])
+
+(define_insn_and_split "<code><GPR:mode><GPR2:mode>2_isel"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (cmp:GPR (match_operand:GPR2 1 "gpc_reg_operand" "r")
+ (match_operand:GPR2 2 "reg_or_<cmp:UNSu_>short_operand" "r<cmp:UNSIK>")))
+ (clobber (match_scratch:GPR 3 "=r"))
+ (clobber (match_scratch:GPR 4 "=r"))
+ (clobber (match_scratch:<UNS> 5 "=y"))]
+ "TARGET_ISEL
+ && !(<CODE> == EQ && operands[2] == const0_rtx)
+ && !(<CODE> == NE && operands[2] == const0_rtx
+ && <GPR:MODE>mode == Pmode && <GPR2:MODE>mode == Pmode)"
+ "#"
+ "&& 1"
+ [(pc)]
+{
+ if (<CODE> == NE || <CODE> == LE || <CODE> == GE
+ || <CODE> == LEU || <CODE> == GEU)
+ operands[3] = const0_rtx;
+ else
+ {
+ if (GET_CODE (operands[3]) == SCRATCH)
+ operands[3] = gen_reg_rtx (<GPR:MODE>mode);
+ emit_move_insn (operands[3], const0_rtx);
+ }
+
+ if (GET_CODE (operands[4]) == SCRATCH)
+ operands[4] = gen_reg_rtx (<GPR:MODE>mode);
+ emit_move_insn (operands[4], const1_rtx);
+
+ if (GET_CODE (operands[5]) == SCRATCH)
+ operands[5] = gen_reg_rtx (<UNS>mode);
+
+ rtx c1 = gen_rtx_COMPARE (<UNS>mode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (operands[5], c1));
+
+ rtx c2 = gen_rtx_fmt_ee (<CODE>, <GPR:MODE>mode, operands[5], const0_rtx);
+ rtx x = gen_rtx_IF_THEN_ELSE (<GPR:MODE>mode, c2, operands[4], operands[3]);
+ emit_move_insn (operands[0], x);
+
+ DONE;
+}
+ [(set (attr "cost")
+ (if_then_else (match_test "<CODE> == NE || <CODE> == LE || <CODE> == GE
+ || <CODE> == LEU || <CODE> == GEU")
+ (const_string "9")
+ (const_string "10")))])
+
(define_mode_attr scc_eq_op2 [(SI "rKLI")
(DI "rKJI")])
-(define_insn_and_split "eq<mode>3"
+(define_expand "eq<mode>3"
+ [(parallel [
+ (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
+ (clobber (match_scratch:GPR 3 "=r"))
+ (clobber (match_scratch:GPR 4 "=r"))])]
+ ""
+{
+ if (TARGET_ISEL && operands[2] != const0_rtx)
+ {
+ emit_insn (gen_eq<mode><mode>2_isel (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*eq<mode>3"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))
(clobber (match_scratch:GPR 3 "=r"))
(clobber (match_scratch:GPR 4 "=r"))]
- ""
+ "!(TARGET_ISEL && operands[2] != const0_rtx)"
"#"
- ""
+ "&& 1"
[(set (match_dup 4)
(clz:GPR (match_dup 3)))
(set (match_dup 0)
@@ -12311,16 +12413,34 @@
(const_string "8")
(const_string "12")))])
-(define_insn_and_split "ne<mode>3"
+(define_expand "ne<mode>3"
+ [(parallel [
+ (set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (ne:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>")))
+ (clobber (match_scratch:P 3 "=r"))
+ (clobber (match_scratch:P 4 "=r"))
+ (clobber (reg:P CA_REGNO))])]
+ ""
+{
+ if (TARGET_ISEL && operands[2] != const0_rtx)
+ {
+ emit_insn (gen_ne<mode><mode>2_isel (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*ne<mode>3"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(ne:P (match_operand:P 1 "gpc_reg_operand" "r")
(match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>")))
(clobber (match_scratch:P 3 "=r"))
(clobber (match_scratch:P 4 "=r"))
(clobber (reg:P CA_REGNO))]
- "!TARGET_ISEL"
+ "!(TARGET_ISEL && operands[2] != const0_rtx)"
"#"
- ""
+ "&& 1"
[(parallel [(set (match_dup 4)
(plus:P (match_dup 3)
(const_int -1)))
@@ -12573,9 +12693,9 @@
(clobber (match_scratch:SI 3 "=r"))
(clobber (match_scratch:SI 4 "=r"))
(clobber (match_scratch:EXTSI 5 "=r"))]
- ""
+ "!TARGET_ISEL"
"#"
- ""
+ "&& 1"
[(set (match_dup 4)
(clz:SI (match_dup 3)))
(set (match_dup 5)
@@ -14230,7 +14350,7 @@
(match_operand:IEEE128 2 "altivec_register_operand" "v")))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsmulqp %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "div<mode>3"
@@ -14332,7 +14452,7 @@
(match_operand:IEEE128 3 "altivec_register_operand" "0")))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsmaddqp %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "*fms<mode>4_hw"
@@ -14344,7 +14464,7 @@
(match_operand:IEEE128 3 "altivec_register_operand" "0"))))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsmsubqp %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "*nfma<mode>4_hw"
@@ -14356,7 +14476,7 @@
(match_operand:IEEE128 3 "altivec_register_operand" "0"))))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsnmaddqp %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "*nfms<mode>4_hw"
@@ -14369,7 +14489,7 @@
(match_operand:IEEE128 3 "altivec_register_operand" "0")))))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsnmsubqp %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "extend<SFDF:mode><IEEE128:mode>2_hw"
@@ -14644,7 +14764,7 @@
UNSPEC_MUL_ROUND_TO_ODD))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsmulqpo %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "div<mode>3_odd"
@@ -14677,7 +14797,7 @@
UNSPEC_FMA_ROUND_TO_ODD))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsmaddqpo %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "*fms<mode>4_odd"
@@ -14690,7 +14810,7 @@
UNSPEC_FMA_ROUND_TO_ODD))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsmsubqpo %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "*nfma<mode>4_odd"
@@ -14703,7 +14823,7 @@
UNSPEC_FMA_ROUND_TO_ODD)))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsnmaddqpo %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "*nfms<mode>4_odd"
@@ -14717,7 +14837,7 @@
UNSPEC_FMA_ROUND_TO_ODD)))]
"TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
"xsnmsubqpo %0,%1,%2"
- [(set_attr "type" "vecfloat")
+ [(set_attr "type" "qmul")
(set_attr "size" "128")])
(define_insn "trunc<mode>df2_odd"