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.md581
1 files changed, 520 insertions, 61 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index cc6478ec847..64de3dc5337 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -138,7 +138,7 @@
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in rs6000.h.
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,cell"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell"
(const (symbol_ref "rs6000_cpu_attr")))
@@ -218,6 +218,19 @@
; DImode bits
(define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
+;; ISEL/ISEL64 target selection
+(define_mode_attr sel [(SI "") (DI "64")])
+
+;; Suffix for reload patterns
+(define_mode_attr ptrsize [(SI "32bit")
+ (DI "64bit")])
+
+(define_mode_attr tptrsize [(SI "TARGET_32BIT")
+ (DI "TARGET_64BIT")])
+
+(define_mode_attr mptrsize [(SI "si")
+ (DI "di")])
+
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
@@ -520,7 +533,7 @@
"@
{andil.|andi.} %2,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -546,7 +559,7 @@
"@
{andil.|andi.} %0,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -687,7 +700,7 @@
"@
{andil.|andi.} %2,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -713,7 +726,7 @@
"@
{andil.|andi.} %0,%1,0xff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -856,7 +869,7 @@
"@
{andil.|andi.} %2,%1,0xffff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -882,7 +895,7 @@
"@
{andil.|andi.} %0,%1,0xffff
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -1670,7 +1683,7 @@
"@
nor. %2,%1,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -1696,7 +1709,7 @@
"@
nor. %0,%1,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -2221,10 +2234,22 @@
"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")))]
+ "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")
+
(define_expand "popcount<mode>2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "")
(popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))]
- "TARGET_POPCNTB"
+ "TARGET_POPCNTB || TARGET_POPCNTD"
{
rs6000_emit_popcount (operands[0], operands[1]);
DONE;
@@ -2239,15 +2264,102 @@
DONE;
})
-(define_insn "bswapsi2"
+;; Since the hardware zeros the upper part of the register, save generating the
+;; AND immediate if we are converting to unsigned
+(define_insn "*bswaphi2_extenddi"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (zero_extend:DI
+ (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
+ "TARGET_POWERPC64"
+ "lhbrx %0,%y1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")])
+
+(define_insn "*bswaphi2_extendsi"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (zero_extend:SI
+ (bswap:HI (match_operand:HI 1 "memory_operand" "Z"))))]
+ "TARGET_POWERPC"
+ "lhbrx %0,%y1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")])
+
+(define_expand "bswaphi2"
+ [(parallel [(set (match_operand:HI 0 "reg_or_mem_operand" "")
+ (bswap:HI
+ (match_operand:HI 1 "reg_or_mem_operand" "")))
+ (clobber (match_scratch:SI 2 ""))])]
+ ""
+{
+ if (!REG_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (HImode, operands[1]);
+})
+
+(define_insn "bswaphi2_internal"
+ [(set (match_operand:HI 0 "reg_or_mem_operand" "=r,Z,&r")
+ (bswap:HI
+ (match_operand:HI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:SI 2 "=X,X,&r"))]
+ "TARGET_POWERPC"
+ "@
+ lhbrx %0,%y1
+ sthbrx %1,%y0
+ #"
+ [(set_attr "length" "4,4,12")
+ (set_attr "type" "load,store,*")])
+
+(define_split
+ [(set (match_operand:HI 0 "gpc_reg_operand" "")
+ (bswap:HI (match_operand:HI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+ "TARGET_POWERPC && reload_completed"
+ [(set (match_dup 3)
+ (zero_extract:SI (match_dup 4)
+ (const_int 8)
+ (const_int 16)))
+ (set (match_dup 2)
+ (and:SI (ashift:SI (match_dup 4)
+ (const_int 8))
+ (const_int 65280))) ;; 0xff00
+ (set (match_dup 3)
+ (ior:SI (match_dup 3)
+ (match_dup 2)))]
+ "
+{
+ operands[3] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
+ operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
+}")
+
+(define_insn "*bswapsi2_extenddi"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (zero_extend:DI
+ (bswap:SI (match_operand:SI 1 "memory_operand" "Z"))))]
+ "TARGET_POWERPC64"
+ "lwbrx %0,%y1"
+ [(set_attr "length" "4")
+ (set_attr "type" "load")])
+
+(define_expand "bswapsi2"
+ [(set (match_operand:SI 0 "reg_or_mem_operand" "")
+ (bswap:SI
+ (match_operand:SI 1 "reg_or_mem_operand" "")))]
+ ""
+{
+ if (!REG_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (SImode, operands[1]);
+})
+
+(define_insn "*bswapsi2_internal"
[(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Z,&r")
- (bswap:SI (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
+ (bswap:SI
+ (match_operand:SI 1 "reg_or_mem_operand" "Z,r,r")))]
""
"@
{lbrx|lwbrx} %0,%y1
{stbrx|stwbrx} %1,%y0
#"
- [(set_attr "length" "4,4,12")])
+ [(set_attr "length" "4,4,12")
+ (set_attr "type" "load,store,*")])
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
@@ -2266,6 +2378,294 @@
(const_int 16)))]
"")
+(define_expand "bswapdi2"
+ [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "")
+ (bswap:DI
+ (match_operand:DI 1 "reg_or_mem_operand" "")))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))])]
+ ""
+{
+ if (!REG_P (operands[0]) && !REG_P (operands[1]))
+ operands[1] = force_reg (DImode, operands[1]);
+
+ if (TARGET_32BIT)
+ {
+ /* 32-bit needs fewer scratch registers. */
+ emit_insn (gen_bswapdi2_32bit (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+;; Power7/cell has ldbrx/stdbrx, so use it directly
+(define_insn "*bswapdi2_ldbrx"
+ [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+ (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:DI 2 "=X,X,&r"))
+ (clobber (match_scratch:DI 3 "=X,X,&r"))
+ (clobber (match_scratch:DI 4 "=X,X,&r"))]
+ "TARGET_POWERPC64 && TARGET_LDBRX
+ && (REG_P (operands[0]) || REG_P (operands[1]))"
+ "@
+ ldbrx %0,%y1
+ stdbrx %1,%y0
+ #"
+ [(set_attr "length" "4,4,36")
+ (set_attr "type" "load,store,*")])
+
+;; Non-power7/cell, fall back to use lwbrx/stwbrx
+(define_insn "*bswapdi2_64bit"
+ [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+ (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:DI 2 "=&b,&b,&r"))
+ (clobber (match_scratch:DI 3 "=&b,&r,&r"))
+ (clobber (match_scratch:DI 4 "=&b,X,&r"))]
+ "TARGET_POWERPC64 && !TARGET_LDBRX
+ && (REG_P (operands[0]) || REG_P (operands[1]))"
+ "#"
+ [(set_attr "length" "16,12,36")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" ""))
+ (clobber (match_operand:DI 4 "gpc_reg_operand" ""))]
+ "TARGET_POWERPC64 && !TARGET_LDBRX && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+ rtx op4 = operands[4];
+ rtx op3_32 = simplify_gen_subreg (SImode, op3, DImode, 4);
+ rtx op4_32 = simplify_gen_subreg (SImode, op4, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (src, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_adddi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr1 = XEXP (addr1, 1);
+ }
+ else
+ emit_move_insn (op2, GEN_INT (4));
+
+ addr2 = gen_rtx_PLUS (DImode, op2, addr1);
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (src, SImode, addr1);
+ word_low = change_address (src, SImode, addr2);
+ }
+ else
+ {
+ word_high = change_address (src, SImode, addr2);
+ word_low = change_address (src, SImode, addr1);
+ }
+
+ emit_insn (gen_bswapsi2 (op3_32, word_low));
+ emit_insn (gen_bswapsi2 (op4_32, word_high));
+ emit_insn (gen_ashldi3 (dest, op3, GEN_INT (32)));
+ emit_insn (gen_iordi3 (dest, dest, op4));
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
+ (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" ""))
+ (clobber (match_operand:DI 4 "" ""))]
+ "TARGET_POWERPC64 && reload_completed && !TARGET_LDBRX"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+ rtx src_si = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (dest, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_adddi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr1 = XEXP (addr1, 1);
+ }
+ else
+ emit_move_insn (op2, GEN_INT (4));
+
+ addr2 = gen_rtx_PLUS (DImode, op2, addr1);
+
+ emit_insn (gen_lshrdi3 (op3, src, GEN_INT (32)));
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (dest, SImode, addr1);
+ word_low = change_address (dest, SImode, addr2);
+ emit_insn (gen_bswapsi2 (word_high, src_si));
+ emit_insn (gen_bswapsi2 (word_low, op3_si));
+ }
+ else
+ {
+ word_high = change_address (dest, SImode, addr2);
+ word_low = change_address (dest, SImode, addr1);
+ emit_insn (gen_bswapsi2 (word_low, src_si));
+ emit_insn (gen_bswapsi2 (word_high, op3_si));
+ }
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (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" ""))
+ (clobber (match_operand:DI 4 "" ""))]
+ "TARGET_POWERPC64 && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+ rtx dest_si = simplify_gen_subreg (SImode, dest, DImode, 4);
+ rtx src_si = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx op2_si = simplify_gen_subreg (SImode, op2, DImode, 4);
+ rtx op3_si = simplify_gen_subreg (SImode, op3, DImode, 4);
+
+ emit_insn (gen_lshrdi3 (op2, src, GEN_INT (32)));
+ emit_insn (gen_bswapsi2 (dest_si, src_si));
+ emit_insn (gen_bswapsi2 (op3_si, op2_si));
+ emit_insn (gen_ashldi3 (dest, dest, GEN_INT (32)));
+ emit_insn (gen_iordi3 (dest, dest, op3));
+}")
+
+(define_insn "bswapdi2_32bit"
+ [(set (match_operand:DI 0 "reg_or_mem_operand" "=&r,Z,??&r")
+ (bswap:DI (match_operand:DI 1 "reg_or_mem_operand" "Z,r,r")))
+ (clobber (match_scratch:SI 2 "=&b,&b,X"))]
+ "TARGET_32BIT && (REG_P (operands[0]) || REG_P (operands[1]))"
+ "#"
+ [(set_attr "length" "16,12,36")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "")))
+ (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+ "TARGET_32BIT && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx dest_hi = simplify_gen_subreg (SImode, dest, DImode, 0);
+ rtx dest_lo = simplify_gen_subreg (SImode, dest, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (src, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_adddi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr1 = XEXP (addr1, 1);
+ }
+ else
+ emit_move_insn (op2, GEN_INT (4));
+
+ addr2 = gen_rtx_PLUS (DImode, op2, addr1);
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (src, SImode, addr1);
+ word_low = change_address (src, SImode, addr2);
+ }
+ else
+ {
+ word_high = change_address (src, SImode, addr2);
+ word_low = change_address (src, SImode, addr1);
+ }
+
+ emit_insn (gen_bswapsi2 (dest_hi, word_low));
+ emit_insn (gen_bswapsi2 (dest_lo, word_high));
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "indexed_or_indirect_operand" "")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:SI 2 "gpc_reg_operand" ""))]
+ "TARGET_32BIT && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx op2 = operands[2];
+ rtx src_high = simplify_gen_subreg (SImode, src, DImode, 0);
+ rtx src_low = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx addr1;
+ rtx addr2;
+ rtx word_high;
+ rtx word_low;
+
+ addr1 = XEXP (dest, 0);
+ if (GET_CODE (addr1) == PLUS)
+ {
+ emit_insn (gen_addsi3 (op2, XEXP (addr1, 0), GEN_INT (4)));
+ addr1 = XEXP (addr1, 1);
+ }
+ else
+ emit_move_insn (op2, GEN_INT (4));
+
+ addr2 = gen_rtx_PLUS (SImode, op2, addr1);
+
+ if (BYTES_BIG_ENDIAN)
+ {
+ word_high = change_address (dest, SImode, addr1);
+ word_low = change_address (dest, SImode, addr2);
+ }
+ else
+ {
+ word_high = change_address (dest, SImode, addr2);
+ word_low = change_address (dest, SImode, addr1);
+ }
+
+ emit_insn (gen_bswapsi2 (word_high, src_low));
+ emit_insn (gen_bswapsi2 (word_low, src_high));
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+ (clobber (match_operand:SI 2 "" ""))]
+ "TARGET_32BIT && reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx src_high = simplify_gen_subreg (SImode, src, DImode, 0);
+ rtx src_low = simplify_gen_subreg (SImode, src, DImode, 4);
+ rtx dest_high = simplify_gen_subreg (SImode, dest, DImode, 0);
+ rtx dest_low = simplify_gen_subreg (SImode, dest, DImode, 4);
+
+ emit_insn (gen_bswapsi2 (dest_high, src_low));
+ emit_insn (gen_bswapsi2 (dest_low, src_high));
+}")
+
(define_expand "mulsi3"
[(use (match_operand:SI 0 "gpc_reg_operand" ""))
(use (match_operand:SI 1 "gpc_reg_operand" ""))
@@ -2852,7 +3252,7 @@
{rlinm|rlwinm} %0,%1,0,%m2,%M2
{andil.|andi.} %0,%1,%b2
{andiu.|andis.} %0,%1,%u2"
- [(set_attr "type" "*,*,compare,compare")])
+ [(set_attr "type" "*,*,fast_compare,fast_compare")])
(define_insn "andsi3_nomc"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
@@ -2895,7 +3295,8 @@
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
+ compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal3_mc"
@@ -2915,7 +3316,8 @@
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
+ compare,compare,compare")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split
@@ -2974,7 +3376,8 @@
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\
+ compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")])
(define_insn "*andsi3_internal5_mc"
@@ -2996,7 +3399,8 @@
#
#
#"
- [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
+ compare,compare,compare")
(set_attr "length" "8,4,4,4,8,8,8,8")])
(define_split
@@ -3127,7 +3531,7 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -3156,7 +3560,7 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -3281,7 +3685,7 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -3310,7 +3714,7 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -5303,7 +5707,7 @@
"fres %0,%1"
[(set_attr "type" "fp")])
-(define_insn ""
+(define_insn "*fmaddsf4_powerpc"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5314,7 +5718,7 @@
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fmaddsf4_power"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5323,7 +5727,7 @@
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fmsubsf4_powerpc"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5334,7 +5738,7 @@
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fmsubsf4_power"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5343,7 +5747,7 @@
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmaddsf4_powerpc_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5354,7 +5758,7 @@
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmaddsf4_powerpc_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5365,7 +5769,7 @@
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmaddsf4_power_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5374,7 +5778,7 @@
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmaddsf4_power_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5384,7 +5788,7 @@
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmsubsf4_powerpc_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5395,7 +5799,7 @@
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmsubsf4_powerpc_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
@@ -5406,7 +5810,7 @@
[(set_attr "type" "fp")
(set_attr "fp_type" "fp_maddsub_s")])
-(define_insn ""
+(define_insn "*fnmsubsf4_power_1"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
@@ -5415,7 +5819,7 @@
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
-(define_insn ""
+(define_insn "*fnmsubsf4_power_2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
@@ -5542,12 +5946,12 @@
DONE;
}")
-(define_expand "movsicc"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "gpc_reg_operand" "")
- (match_operand:SI 3 "gpc_reg_operand" "")))]
- "TARGET_ISEL"
+(define_expand "mov<mode>cc"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (if_then_else:GPR (match_operand 1 "comparison_operator" "")
+ (match_operand:GPR 2 "gpc_reg_operand" "")
+ (match_operand:GPR 3 "gpc_reg_operand" "")))]
+ "TARGET_ISEL<sel>"
"
{
if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
@@ -5564,28 +5968,28 @@
;; leave out the mode in operand 4 and use one pattern, but reload can
;; change the mode underneath our feet and then gets confused trying
;; to reload the value.
-(define_insn "isel_signed"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (if_then_else:SI
+(define_insn "isel_signed_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (if_then_else:GPR
(match_operator 1 "comparison_operator"
[(match_operand:CC 4 "cc_reg_operand" "y")
(const_int 0)])
- (match_operand:SI 2 "gpc_reg_operand" "b")
- (match_operand:SI 3 "gpc_reg_operand" "b")))]
- "TARGET_ISEL"
+ (match_operand:GPR 2 "gpc_reg_operand" "b")
+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL<sel>"
"*
{ return output_isel (operands); }"
[(set_attr "length" "4")])
-(define_insn "isel_unsigned"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (if_then_else:SI
+(define_insn "isel_unsigned_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (if_then_else:GPR
(match_operator 1 "comparison_operator"
[(match_operand:CCUNS 4 "cc_reg_operand" "y")
(const_int 0)])
- (match_operand:SI 2 "gpc_reg_operand" "b")
- (match_operand:SI 3 "gpc_reg_operand" "b")))]
- "TARGET_ISEL"
+ (match_operand:GPR 2 "gpc_reg_operand" "b")
+ (match_operand:GPR 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL<sel>"
"*
{ return output_isel (operands); }"
[(set_attr "length" "4")])
@@ -5898,6 +6302,12 @@
"TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
"")
+(define_expand "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "")
+
; For each of these conversions, there is a define_expand, a define_insn
; with a '#' template, and a define_split (with C code). The idea is
; to allow constant folding with the template of the define_insn,
@@ -7609,7 +8019,7 @@
andi. %0,%1,%b2
andis. %0,%1,%u2
#"
- [(set_attr "type" "*,*,*,compare,compare,*")
+ [(set_attr "type" "*,*,*,fast_compare,fast_compare,*")
(set_attr "length" "4,4,4,4,4,8")])
(define_insn "anddi3_nomc"
@@ -7667,7 +8077,9 @@
#
#
#"
- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
+ fast_compare,compare,compare,compare,compare,compare,\
+ compare,compare")
(set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
@@ -7718,7 +8130,9 @@
#
#
#"
- [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+ [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\
+ fast_compare,compare,compare,compare,compare,compare,\
+ compare,compare")
(set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
@@ -7858,7 +8272,7 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -7887,7 +8301,7 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -7958,7 +8372,7 @@
"@
%q4. %3,%2,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -7987,7 +8401,7 @@
"@
%q4. %0,%2,%1
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -8024,7 +8438,7 @@
"@
%q4. %3,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -8053,7 +8467,7 @@
"@
%q4. %0,%1,%2
#"
- [(set_attr "type" "compare")
+ [(set_attr "type" "fast_compare,compare")
(set_attr "length" "4,8")])
(define_split
@@ -8070,6 +8484,51 @@
(compare:CC (match_dup 0)
(const_int 0)))]
"")
+
+(define_expand "smindi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+ DONE;
+}")
+
+(define_expand "smaxdi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+ DONE;
+}")
+
+(define_expand "umindi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]);
+ DONE;
+}")
+
+(define_expand "umaxdi3"
+ [(match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "gpc_reg_operand" "")]
+ "TARGET_ISEL64"
+ "
+{
+ rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]);
+ DONE;
+}")
+
;; Now define ways of moving data around.