(movsfcc, movdfcc): New standard patterns.
authorRichard Kenner <kenner@gcc.gnu.org>
Wed, 22 Feb 1995 13:40:06 +0000 (08:40 -0500)
committerRichard Kenner <kenner@gcc.gnu.org>
Wed, 22 Feb 1995 13:40:06 +0000 (08:40 -0500)
(fselsfsf4, fseldfsf4, fseldfdf4, fselsfdf4): Name and create variants of
existing anonymous patterns for movsfcc and movdfcc.

From-SVN: r9031

gcc/config/rs6000/rs6000.md

index 23279e7..47215d2 100644 (file)
   "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)
                         (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))
   "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")))]
   "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"
                         (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))
   "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")])
 \f
 ;; Conversions to and from floating-point.
 (define_expand "floatsidf2"