diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 198 |
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" |