diff mbox

Commit: V850: Fix floating point comparisons, branches and conditional stores

Message ID 87ehhubdqy.fsf@redhat.com
State New
Headers show

Commit Message

Nick Clifton Jan. 9, 2013, 3:03 p.m. UTC
Hi Guys,

  I am checking in the patch below to fix the V850's floating point
  comparison patterns, which was inverted in many places.  The also
  includes a contribution from Nguyen Duy Dat at Renesas which adds
  floating point conditional store patterns and floating point
  conditional branch patterns.

  Tested with no regressions on a v850e2v3-elf toolchain.

Cheers
  Nick

gcc/ChangeLog
2013-01-09  Nguyen Duy Dat
	    Nick Clifton  <nickc@redhat.com>

	* config/v850/v850.md (cbranchsf4): New pattern.
	(cstoresf4): New pattern.
	(cbranchdf4): New pattern.
	(cstoredf4): New pattern.
	(movsicc): Disallow floating point comparisons.
	(cmpsf_le_insn): Fix order of operators.
	(cmpsf_lt_insn): Likewise.
	(cmpsf_eq_insn): Likewise.
	(cmpdf_le_insn): Likewise.
	(cmpdf_lt_insn): Likewise.
	(cmpdf_eq_insn): Likewise.
	(cmpsf_ge_insn): Use LE comparison.
	(cmpdf_ge_insn): Likewise.
	(cmpsf_gt_insn): Use LT comparison.
	(cmpdf_gt_insn): Likewise.
	(cmpsf_ne_insn): Delete pattern.
	(cmpdf_ne_insn): Delete pattern.
	* config/v850/v850.c (v850_gen_float_compare): Use
	gen_cmpdf_eq_insn for NE comparison.
	(v850_float_z_comparison_operator)
	(v850_float_nz_comparison_operator): Move from here ...
	* config/v850/predicates.md: ... to here.  Move GT and GE
	comparisons into v850_float_z_comparison_operator.
	* config/v850/v850-protos.h (v850_float_z_comparison_operator):
	Delete prototype.
	(v850_float_nz_comparison_operator): Likewise.
diff mbox

Patch

Index: gcc/config/v850/predicates.md
===================================================================
--- gcc/config/v850/predicates.md	(revision 195050)
+++ gcc/config/v850/predicates.md	(working copy)
@@ -497,3 +497,68 @@ 
 
   return op == CONST0_RTX(mode);
 })
+
+;; Return true if the floating point comparison operation
+;; given produces a canonical answer.
+(define_predicate "v850_float_z_comparison_operator"
+  (match_code "lt,le,eq,gt,ge")
+{
+  enum rtx_code code = GET_CODE (op);
+
+  if (GET_RTX_CLASS (code) != RTX_COMPARE
+      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
+    return 0;
+
+  if (mode != GET_MODE (op) && mode != VOIDmode)
+    return 0;
+
+  if ((GET_CODE (XEXP (op, 0)) != REG
+       || REGNO (XEXP (op, 0)) != CC_REGNUM)
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_LTmode)
+    return code == LT;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_LEmode)
+    return code == LE;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_EQmode)
+    return code == EQ;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_GTmode)
+    return code == GT;
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_GEmode)
+    return code == GE;
+
+  /* Note we do not accept CC_FPU_NEmode here.  See
+     v850_float_nz_comparison for the reason why.  */
+  return 0;
+})
+
+;; Return true if the floating point comparison operation
+;; given produces an inverted answer.
+(define_predicate "v850_float_nz_comparison_operator"
+  (match_code "ne")
+{
+  enum rtx_code code = GET_CODE (op);
+
+  /* The V850E2V3 does not have a floating point NZ comparison operator.
+     Instead it is implemented as an EQ comparison and this function ensures
+     that the branch_nz_normal and set_nz_insn patterns are used to examine
+     (and invert) the result of the floating point comparison.  */
+
+  if (GET_RTX_CLASS (code) != RTX_COMPARE
+      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
+    return 0;
+
+  if (mode != GET_MODE (op) && mode != VOIDmode)
+    return 0;
+
+  if ((GET_CODE (XEXP (op, 0)) != REG
+       || REGNO (XEXP (op, 0)) != CC_REGNUM)
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode)
+    return code == NE;
+
+  return 0;
+})
Index: gcc/config/v850/v850-protos.h
===================================================================
--- gcc/config/v850/v850-protos.h	(revision 195050)
+++ gcc/config/v850/v850-protos.h	(working copy)
@@ -40,8 +40,6 @@ 
 extern char * construct_dispose_instruction (rtx);
 extern char * construct_prepare_instruction (rtx);
 extern int    ep_memory_operand             (rtx, enum machine_mode, int);
-extern int    v850_float_z_comparison_operator (rtx, enum machine_mode);
-extern int    v850_float_nz_comparison_operator (rtx, enum machine_mode);
 extern rtx    v850_gen_compare              (enum rtx_code, enum machine_mode,
 					     rtx, rtx);
 extern enum machine_mode  v850_gen_float_compare (enum rtx_code,
Index: gcc/config/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c	(revision 195050)
+++ gcc/config/v850/v850.c	(working copy)
@@ -898,61 +898,6 @@ 
   return "";
 }
 
-/* Generate comparison code.  */
-int
-v850_float_z_comparison_operator (rtx op, enum machine_mode mode)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  if (GET_RTX_CLASS (code) != RTX_COMPARE
-      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
-    return 0;
-
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  if ((GET_CODE (XEXP (op, 0)) != REG
-       || REGNO (XEXP (op, 0)) != CC_REGNUM)
-      || XEXP (op, 1) != const0_rtx)
-    return 0;
-
-  if (GET_MODE (XEXP (op, 0)) == CC_FPU_LTmode)
-    return code == LT;
-  if (GET_MODE (XEXP (op, 0)) == CC_FPU_LEmode)
-    return code == LE;
-  if (GET_MODE (XEXP (op, 0)) == CC_FPU_EQmode)
-    return code == EQ;
-
-  return 0;
-}
-
-int
-v850_float_nz_comparison_operator (rtx op, enum machine_mode mode)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  if (GET_RTX_CLASS (code) != RTX_COMPARE
-      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE)
-    return 0;
-
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  if ((GET_CODE (XEXP (op, 0)) != REG
-       || REGNO (XEXP (op, 0)) != CC_REGNUM)
-      || XEXP (op, 1) != const0_rtx)
-    return 0;
-
-  if (GET_MODE (XEXP (op, 0)) == CC_FPU_GTmode)
-    return code == GT;
-  if (GET_MODE (XEXP (op, 0)) == CC_FPU_GEmode)
-    return code == GE;
-  if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode)
-    return code == NE;
-
-  return code == GT || code == GE || code == NE;
-}
-
 enum machine_mode
 v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED)
 {
@@ -998,17 +943,18 @@ 
 	case GT:
 	  emit_insn (gen_cmpdf_gt_insn (op0, op1));
 	  break;
+	case NE:
+	  /* Note: There is no NE comparison operator. So we
+	     perform an EQ comparison and invert the branch.
+	     See v850_float_nz_comparison for how this is done.  */
 	case EQ:
 	  emit_insn (gen_cmpdf_eq_insn (op0, op1));
 	  break;
-	case NE:
-	  emit_insn (gen_cmpdf_ne_insn (op0, op1));
-	  break;
 	default:
-	  abort ();
+	  gcc_unreachable ();
 	}
     }
-  else if (GET_MODE(v850_compare_op0) == SFmode)
+  else if (GET_MODE (v850_compare_op0) == SFmode)
     {
       switch (cond)
 	{
@@ -1024,20 +970,19 @@ 
 	case GT:
 	  emit_insn (gen_cmpsf_gt_insn(op0, op1));
 	  break;
+	case NE:
+	  /* Note: There is no NE comparison operator. So we
+	     perform an EQ comparison and invert the branch.
+	     See v850_float_nz_comparison for how this is done.  */
 	case EQ:
 	  emit_insn (gen_cmpsf_eq_insn(op0, op1));
 	  break;
-	case NE:
-	  emit_insn (gen_cmpsf_ne_insn(op0, op1));
-	  break;
 	default:
-	  abort ();
+	  gcc_unreachable ();
 	}
     }
   else
-    {
-      abort ();
-    }
+    gcc_unreachable ();
 
   return v850_select_cc_mode (cond, op0, op1);
 }
Index: gcc/config/v850/v850.md
===================================================================
--- gcc/config/v850/v850.md	(revision 195050)
+++ gcc/config/v850/v850.md	(working copy)
@@ -405,6 +405,114 @@ 
   [(set_attr "length" "2,2")
    (set_attr "cc" "compare")])
 
+(define_expand "cbranchsf4"
+  [(set (pc)
+       (if_then_else (match_operator     0 "ordered_comparison_operator"
+                      [(match_operand:SF 1 "register_operand")
+                       (match_operand:SF 2 "register_operand")])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))
+  (clobber (cc0))]
+  "TARGET_V850E2V3"
+{
+  v850_compare_op0 = operands[1];
+  v850_compare_op1 = operands[2];
+
+  enum rtx_code cond = GET_CODE(operands[0]);
+  enum machine_mode mode;
+  rtx fcc_reg;
+  rtx cc_reg;
+  rtx tmp;
+
+  if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
+    FAIL;
+
+  mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1);
+  fcc_reg = gen_rtx_REG (mode, FCC_REGNUM);
+  cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+  emit_insn(gen_rtx_SET (mode, cc_reg, fcc_reg));
+  tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
+  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+                              gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx);
+  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+  DONE;
+})
+
+(define_insn "cstoresf4"
+  [(set (match_operand:SI   0 "register_operand" "=r")
+        (match_operator:SI  1 "ordered_comparison_operator"
+         [(match_operand:SF 2 "register_operand" "r")
+          (match_operand:SF 3 "register_operand" "r")]))]
+  "TARGET_V850E2V3"
+{
+  if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
+    return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf nz, %0";
+  if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE)
+    return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf z, %0";
+  if (GET_CODE (operands[1]) == EQ)
+    return "cmpf.s eq, %z2, %z3 ; trfsr ; setf z, %0";
+  if (GET_CODE (operands[1]) == NE)
+    return "cmpf.s neq, %z2, %z3 ; trfsr ; setf nz, %0";
+  gcc_unreachable ();
+}
+  [(set_attr "length" "12")
+   (set_attr "type" "fpu")]
+)
+
+(define_expand "cbranchdf4"
+  [(set (pc)
+       (if_then_else (match_operator     0 "ordered_comparison_operator"
+                      [(match_operand:DF 1 "even_reg_operand")
+                       (match_operand:DF 2 "even_reg_operand")])
+                     (label_ref (match_operand 3 ""))
+                     (pc)))
+  (clobber (cc0))]
+  "TARGET_V850E2V3"
+{
+  v850_compare_op0 = operands[1];
+  v850_compare_op1 = operands[2];
+
+  enum rtx_code cond = GET_CODE(operands[0]);
+  enum machine_mode mode;
+  rtx fcc_reg;
+  rtx cc_reg;
+  rtx tmp;
+
+  if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
+    FAIL;
+
+  mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1);
+  fcc_reg = gen_rtx_REG (mode, FCC_REGNUM);
+  cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+  emit_insn(gen_rtx_SET (mode, cc_reg, fcc_reg));
+  tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
+  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+                              gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx);
+  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
+  DONE;
+})
+
+(define_insn "cstoredf4"
+  [(set (match_operand:SI   0 "register_operand" "=r")
+        (match_operator:SI  1 "ordered_comparison_operator"
+         [(match_operand:DF 2 "even_reg_operand"  "r")
+          (match_operand:DF 3 "even_reg_operand" "r")]))]
+  "TARGET_V850E2V3"
+{
+  if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
+    return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf nz, %0";
+  if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE)
+    return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf z, %0";
+  if (GET_CODE (operands[1]) == EQ)
+    return "cmpf.d eq, %z2, %z3 ; trfsr ; setf z ,%0";
+  if (GET_CODE (operands[1]) == NE)
+    return "cmpf.d neq, %z2, %z3 ; trfsr ; setf nz, %0";
+  gcc_unreachable ();
+}
+  [(set_attr "length" "12")
+   (set_attr "type" "fpu")]
+)
+
 (define_expand "cmpsf"
   [(set (reg:CC CC_REGNUM)
 	(compare (match_operand:SF 0 "register_operand" "r")
@@ -940,6 +1048,11 @@ 
 	 (match_operand:SI 3 "reg_or_const_operand" "rI")))]
   "(TARGET_V850E || TARGET_V850E2_ALL)"
   {
+    /* Make sure that we have an integer comparison...  */
+    if (GET_MODE (XEXP (operands[1], 0)) != CCmode
+        && GET_MODE (XEXP (operands[1], 0)) != SImode)
+      FAIL;
+
     if ((GET_CODE (operands[2]) == CONST_INT
 	&& GET_CODE (operands[3]) == CONST_INT))
       {
@@ -2210,7 +2323,7 @@ 
         (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.s le,%z1,%z0"
+  "cmpf.s le, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2220,7 +2333,7 @@ 
         (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.s lt,%z1,%z0"
+  "cmpf.s lt, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2230,7 +2343,7 @@ 
         (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.s ge,%z1,%z0"
+  "cmpf.s le, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2240,7 +2353,7 @@ 
         (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.s gt,%z1,%z0"
+  "cmpf.s lt, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2250,21 +2363,11 @@ 
         (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.s eq,%z1,%z0"
+  "cmpf.s eq, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
 
-(define_insn "cmpsf_ne_insn"
-  [(set (reg:CC_FPU_NE FCC_REGNUM)
-        (compare:CC_FPU_NE (match_operand:SF 0 "register_operand" "r")
-			   (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
-  "cmpf.s neq,%z1,%z0"
-  [(set_attr "length" "4")
-   (set_attr "cc" "none_0hit")
-   (set_attr "type" "fpu")])
-
 ; DF
 
 (define_insn "cmpdf_le_insn"
@@ -2272,7 +2375,7 @@ 
         (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.d le,%z1,%z0"
+  "cmpf.d le, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2282,7 +2385,7 @@ 
         (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.d lt,%z1,%z0"
+  "cmpf.d lt, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2292,7 +2395,7 @@ 
         (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.d ge,%z1,%z0"
+  "cmpf.d le, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2300,9 +2403,9 @@ 
 (define_insn "cmpdf_gt_insn"
   [(set (reg:CC_FPU_GT FCC_REGNUM)
         (compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r")
-		      (match_operand:DF 1 "even_reg_operand" "r")))]
+		           (match_operand:DF 1 "even_reg_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.d gt,%z1,%z0"
+  "cmpf.d lt, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
@@ -2312,22 +2415,11 @@ 
         (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
   "TARGET_USE_FPU"
-  "cmpf.d eq,%z1,%z0"
+  "cmpf.d eq, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
    (set_attr "type" "fpu")])
 
-(define_insn "cmpdf_ne_insn"
-  [(set (reg:CC_FPU_NE FCC_REGNUM)
-        (compare:CC_FPU_NE (match_operand:DF 0 "even_reg_operand" "r")
-			   (match_operand:DF 1 "even_reg_operand" "r")))]
-  "TARGET_USE_FPU"
-  "cmpf.d neq,%z1,%z0"
-  [(set_attr "length" "4")
-   (set_attr "cc" "none_0hit")
-   (set_attr "type" "fpu")])
-
-
 ;;
 ;; Transfer a v850e2v3 fcc to the Z bit of CC0 (this is necessary to do a
 ;; conditional branch based on a floating-point compare)