From 2ee5c7a8361c8d3fd775df9a4bb5ffcb5568960b Mon Sep 17 00:00:00 2001
From: Doug Evans <dje@gnu.org>
Date: Wed, 25 Jan 1995 04:11:29 +0000
Subject: [PATCH] (movsicc): New named pattern.

(movdicc, movsfcc, movdfcc): Likewise.
(SImode conditional move): New matcher.

From-SVN: r8796
---
 gcc/config/alpha/alpha.md | 184 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 184 insertions(+)

diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 459ca6616070..510ad3fdd5ee 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -1304,6 +1304,24 @@
   "cmple $31,%1,%0"
   [(set_attr "type" "icmp")])
 
+;; This pattern exists so conditional moves of SImode values are handled.
+;; Comparisons are still done in DImode though.
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(if_then_else:DI
+	 (match_operator 2 "signed_comparison_operator"
+			 [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J")
+			  (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")])
+	 (match_operand:SI 1 "reg_or_8bit_operand" "rI,0,rI,0")
+	 (match_operand:SI 5 "reg_or_8bit_operand" "0,rI,0,rI")))]
+  "operands[3] == const0_rtx || operands[4] == const0_rtx"
+  "@
+   cmov%C2 %r3,%1,%0
+   cmov%D2 %r3,%5,%0
+   cmov%c2 %r4,%1,%0
+   cmov%d2 %r4,%5,%0")
+
 (define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
 	(if_then_else:DI
@@ -2204,6 +2222,172 @@
 			 alpha_compare_op0);
 }")
 
+;; These are the main define_expand's used to make conditional moves.
+
+(define_expand "movsicc"
+  [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+   (set (match_operand:SI 0 "register_operand" "")
+	(if_then_else:DI (match_dup 5)
+			 (match_operand:SI 2 "reg_or_8bit_operand" "")
+			 (match_operand:SI 3 "reg_or_8bit_operand" "")))]
+  ""
+  "
+{
+  rtx op0,op1;
+  enum rtx_code code = GET_CODE (operands[1]);
+
+  if (alpha_compare_fp_p)
+    FAIL;
+  switch (code)
+    {
+    case EQ: case NE: case LE: case LT:
+      op0 = alpha_compare_op0;
+      op1 = alpha_compare_op1;
+      break;
+    case GE:
+      code = LE;
+      op0 = force_reg (DImode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    case GT:
+      code = LT;
+      op0 = force_reg (DImode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    default:
+      FAIL;
+    }
+  operands[1] = gen_rtx (code, DImode, op0, op1);
+  operands[4] = gen_reg_rtx (DImode);
+  operands[5] = gen_rtx (NE, VOIDmode, operands[4], CONST0_RTX (DImode));
+}")
+
+(define_expand "movdicc"
+  [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+   (set (match_operand:DI 0 "register_operand" "")
+	(if_then_else:DI (match_dup 5)
+			 (match_operand:DI 2 "reg_or_8bit_operand" "")
+			 (match_operand:DI 3 "reg_or_8bit_operand" "")))]
+  ""
+  "
+{
+  rtx op0,op1;
+  enum rtx_code code = GET_CODE (operands[1]);
+
+  if (alpha_compare_fp_p)
+    FAIL;
+  switch (code)
+    {
+    case EQ: case NE: case LE: case LT:
+      op0 = alpha_compare_op0;
+      op1 = alpha_compare_op1;
+      break;
+    case GE:
+      code = LE;
+      op0 = force_reg (DImode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    case GT:
+      code = LT;
+      op0 = force_reg (DImode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    default:
+      FAIL;
+    }
+  operands[1] = gen_rtx (code, DImode, op0, op1);
+  operands[4] = gen_reg_rtx (DImode);
+  operands[5] = gen_rtx (NE, VOIDmode, operands[4], CONST0_RTX (DImode));
+}")
+
+(define_expand "movsfcc"
+  [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+   (set (match_operand:SF 0 "register_operand" "")
+	(if_then_else:SF (match_dup 5)
+			 (match_operand:SF 2 "reg_or_fp0_operand" "")
+			 (match_operand:SF 3 "reg_or_fp0_operand" "")))]
+  ""
+  "
+{
+  rtx op0,op1;
+  enum rtx_code code = GET_CODE (operands[1]), code2 = NE;
+
+  if (!alpha_compare_fp_p)
+    FAIL;
+  switch (code)
+    {
+    case EQ: case LE: case LT:
+      op0 = alpha_compare_op0;
+      op1 = alpha_compare_op1;
+      break;
+    case NE:
+      /* There isn't a cmptne insn.  */
+      code = code2 = EQ;
+      op0 = alpha_compare_op0;
+      op1 = alpha_compare_op1;
+      break;
+    case GE:
+      code = LE;
+      op0 = force_reg (DFmode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    case GT:
+      code = LT;
+      op0 = force_reg (DFmode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    default:
+      FAIL;
+    }
+  operands[1] = gen_rtx (code, DFmode, op0, op1);
+  operands[4] = gen_reg_rtx (DFmode);
+  operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DFmode));
+}")
+
+(define_expand "movdfcc"
+  [(set (match_dup 4) (match_operand 1 "comparison_operator" ""))
+   (set (match_operand:DF 0 "register_operand" "")
+	(if_then_else:DF (match_dup 5)
+			 (match_operand:DF 2 "reg_or_fp0_operand" "")
+			 (match_operand:DF 3 "reg_or_fp0_operand" "")))]
+  ""
+  "
+{
+  rtx op0,op1;
+  enum rtx_code code = GET_CODE (operands[1]), code2 = NE;
+
+  if (!alpha_compare_fp_p)
+    FAIL;
+  switch (code)
+    {
+    case EQ: case LE: case LT:
+      op0 = alpha_compare_op0;
+      op1 = alpha_compare_op1;
+      break;
+    case NE:
+      /* There isn't a cmptne insn.  */
+      code = code2 = EQ;
+      op0 = alpha_compare_op0;
+      op1 = alpha_compare_op1;
+      break;
+    case GE:
+      code = LE;
+      op0 = force_reg (DFmode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    case GT:
+      code = LT;
+      op0 = force_reg (DFmode, alpha_compare_op1);
+      op1 = alpha_compare_op0;
+      break;
+    default:
+      FAIL;
+    }
+  operands[1] = gen_rtx (code, DFmode, op0, op1);
+  operands[4] = gen_reg_rtx (DFmode);
+  operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DFmode));
+}")
+
 ;; These define_split definitions are used in cases when comparisons have
 ;; not be stated in the correct way and we need to reverse the second
 ;; comparison.  For example, x >= 7 has to be done as x < 6 with the
-- 
GitLab