aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1995-02-22 08:40:06 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1995-02-22 08:40:06 -0500
commit94d7001a79071c2e528c38e9a6e4b6b5b12c4beb (patch)
treebc1e37dcc03e5e8b9ff77e837a65199b8399510e /gcc
parentcb64953075c20b6e004949206c3d7cdd6795d773 (diff)
downloadgcc-94d7001a79071c2e528c38e9a6e4b6b5b12c4beb.zip
gcc-94d7001a79071c2e528c38e9a6e4b6b5b12c4beb.tar.gz
gcc-94d7001a79071c2e528c38e9a6e4b6b5b12c4beb.tar.bz2
(movsfcc, movdfcc): New standard patterns.
(fselsfsf4, fseldfsf4, fseldfdf4, fselsfdf4): Name and create variants of existing anonymous patterns for movsfcc and movdfcc. From-SVN: r9031
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.md172
1 files changed, 164 insertions, 8 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 23279e7..47215d2 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -2732,9 +2732,9 @@
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
-;; For SMIN, SMAX, UMIN, and UMAX, 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
+;; 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
;; combine.
(define_expand "maxsf3"
[(set (match_dup 3)
@@ -2792,7 +2792,76 @@
(match_dup 2)))]
"")
-(define_insn ""
+(define_expand "movsfcc"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (if_then_else:SF (match_operand 1 "comparison_operator" "")
+ (match_operand:SF 2 "gpc_reg_operand" "f")
+ (match_operand:SF 3 "gpc_reg_operand" "f")))]
+ "TARGET_PPC_GFXOPT"
+ "
+{
+ rtx temp, op0, op1;
+ enum rtx_code code = GET_CODE (operands[1]);
+ if (! rs6000_compare_fp_p)
+ FAIL;
+ switch (code)
+ {
+ case GE: case EQ: case NE:
+ op0 = rs6000_compare_op0;
+ op1 = rs6000_compare_op1;
+ break;
+ case GT:
+ op0 = rs6000_compare_op1;
+ op1 = rs6000_compare_op0;
+ temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
+ break;
+ case LE:
+ op0 = rs6000_compare_op1;
+ op1 = rs6000_compare_op0;
+ break;
+ case LT:
+ op0 = rs6000_compare_op0;
+ op1 = rs6000_compare_op1;
+ temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
+ break;
+ default:
+ FAIL;
+ }
+ if (GET_MODE (rs6000_compare_op0) == DFmode)
+ {
+ temp = gen_reg_rtx (DFmode);
+ emit_insn (gen_subdf3 (temp, op0, op1));
+ emit_insn (gen_fseldfsf4 (operands[0], temp, operands[2], operands[3]));
+ if (code == EQ)
+ {
+ emit_insn (gen_negdf2 (temp, temp));
+ emit_insn (gen_fseldfsf4 (operands[0], temp, operands[0], operands[3]));
+ }
+ if (code == NE)
+ {
+ emit_insn (gen_negdf2 (temp, temp));
+ emit_insn (gen_fseldfsf4 (operands[0], temp, operands[3], operands[0]));
+ }
+ }
+ else
+ {
+ temp = gen_reg_rtx (SFmode);
+ emit_insn (gen_subsf3 (temp, op0, op1));
+ emit_insn (gen_fselsfsf4 (operands[0], temp, operands[2], operands[3]));
+ if (code == EQ)
+ {
+ emit_insn (gen_negsf2 (temp, temp));
+ emit_insn (gen_fselsfsf4 (operands[0], temp, operands[0], operands[3]));
+ }
+ if (code == NE)
+ {
+ emit_insn (gen_negsf2 (temp, temp));
+ emit_insn (gen_fselsfsf4 (operands[0], temp, operands[3], operands[0]));
+ }
+ }
+ DONE;
+}")
+(define_insn "fselsfsf4"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(if_then_else:SF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
(const_int 0))
@@ -2802,6 +2871,15 @@
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
+(define_insn "fseldfsf4"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (if_then_else:SF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
+ (const_int 0))
+ (match_operand:SF 2 "gpc_reg_operand" "f")
+ (match_operand:SF 3 "gpc_reg_operand" "f")))]
+ "TARGET_PPC_GFXOPT"
+ "fsel %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
@@ -2898,9 +2976,9 @@
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
-;; For SMIN, SMAX, UMIN, and UMAX, 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
+;; 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
;; combine.
(define_expand "maxdf3"
@@ -2959,7 +3037,76 @@
(match_dup 2)))]
"")
-(define_insn ""
+(define_expand "movdfcc"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (if_then_else:DF (match_operand 1 "comparison_operator" "")
+ (match_operand:DF 2 "gpc_reg_operand" "f")
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+ "TARGET_PPC_GFXOPT"
+ "
+{
+ rtx temp, op0, op1;
+ enum rtx_code code = GET_CODE (operands[1]);
+ if (! rs6000_compare_fp_p)
+ FAIL;
+ switch (code)
+ {
+ case GE: case EQ: case NE:
+ op0 = rs6000_compare_op0;
+ op1 = rs6000_compare_op1;
+ break;
+ case GT:
+ op0 = rs6000_compare_op1;
+ op1 = rs6000_compare_op0;
+ temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
+ break;
+ case LE:
+ op0 = rs6000_compare_op1;
+ op1 = rs6000_compare_op0;
+ break;
+ case LT:
+ op0 = rs6000_compare_op0;
+ op1 = rs6000_compare_op1;
+ temp = operands[2]; operands[2] = operands[3]; operands[3] = temp;
+ break;
+ default:
+ FAIL;
+ }
+ if (GET_MODE (rs6000_compare_op0) == DFmode)
+ {
+ temp = gen_reg_rtx (DFmode);
+ emit_insn (gen_subdf3 (temp, op0, op1));
+ emit_insn (gen_fseldfdf4 (operands[0], temp, operands[2], operands[3]));
+ if (code == EQ)
+ {
+ emit_insn (gen_negdf2 (temp, temp));
+ emit_insn (gen_fseldfdf4 (operands[0], temp, operands[0], operands[3]));
+ }
+ if (code == NE)
+ {
+ emit_insn (gen_negdf2 (temp, temp));
+ emit_insn (gen_fseldfdf4 (operands[0], temp, operands[3], operands[0]));
+ }
+ }
+ else
+ {
+ temp = gen_reg_rtx (SFmode);
+ emit_insn (gen_subsf3 (temp, op0, op1));
+ emit_insn (gen_fselsfdf4 (operands[0], temp, operands[2], operands[3]));
+ if (code == EQ)
+ {
+ emit_insn (gen_negsf2 (temp, temp));
+ emit_insn (gen_fselsfdf4 (operands[0], temp, operands[0], operands[3]));
+ }
+ if (code == NE)
+ {
+ emit_insn (gen_negsf2 (temp, temp));
+ emit_insn (gen_fselsfdf4 (operands[0], temp, operands[3], operands[0]));
+ }
+ }
+ DONE;
+}")
+(define_insn "fseldfdf4"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(if_then_else:DF (ge (match_operand:DF 1 "gpc_reg_operand" "f")
(const_int 0))
@@ -2968,6 +3115,15 @@
"TARGET_PPC_GFXOPT"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
+(define_insn "fselsfdf4"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (if_then_else:DF (ge (match_operand:SF 1 "gpc_reg_operand" "f")
+ (const_int 0))
+ (match_operand:DF 2 "gpc_reg_operand" "f")
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+ "TARGET_PPC_GFXOPT"
+ "fsel %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
;; Conversions to and from floating-point.
(define_expand "floatsidf2"