diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1995-02-22 08:40:06 -0500 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1995-02-22 08:40:06 -0500 |
commit | 94d7001a79071c2e528c38e9a6e4b6b5b12c4beb (patch) | |
tree | bc1e37dcc03e5e8b9ff77e837a65199b8399510e /gcc | |
parent | cb64953075c20b6e004949206c3d7cdd6795d773 (diff) | |
download | gcc-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.md | 172 |
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" |