diff mbox series

[cris-decc0,6/14] cris: Introduce CC_NZVCmode and CC_NZmode.

Message ID 202002120657.01C6v6UL026643@ignucius.se.axis.com
State New
Headers show
Series None | expand

Commit Message

Hans-Peter Nilsson Feb. 12, 2020, 6:57 a.m. UTC
Prepare for cmpelim pass to eliminate redundant compare insns.
* config/cris/cris-modes.def: New file.
* config/cris/cris-protos.h (cris_select_cc_mode): Declare.
(cris_notice_update_cc): Remove left-over declaration.
* config/cris/cris.c (TARGET_CC_MODES_COMPATIBLE): Define.
(cris_select_cc_mode, cris_cc_modes_compatible): New functions.
* config/cris/cris.h (SELECT_CC_MODE): Define.
* config/cris/cris.md (NZSET, NZUSE, NZVCSET, NZVCUSE): New
mode_iterators.
(cond): New code_iterator.
(nzcond): Replacement for incorrect ncond.  All callers changed.
(nzvccond): Replacement for ocond.  All callers changed.
(rnzcond): Replacement for rcond.  All callers changed.
(xCC): New code_attr.
(cmp_op1c, cmp_op0c): Renumber from cmp_op1c and cmp_op2c.  All
users changed.
("*cmpdi<NZVCSET:mode>"): Rename from "*cmpdi".  Replace
CCmode with iteration over NZVCSET.
("*cmp_ext<BW:mode><NZVCSET:mode>"): Similarly; rename from
"*cmp_ext<mode>".
("*cmpsi<NZVCSET:mode>"): Similarly, from "*cmpsi".
("*cmp<BW:mode><NZVCSET:mode>"): Similarly from "*cmp<mode>".
("*btst<mode>"): Similarly, from "*btst".
("*cbranch<mode><code>4"): Rename from "*cbranch<mode>4",
iterating over cond instead of matching the comparison with
ordered_comparison_operator.
("*cbranch<mode>4_btstq<CC>"): Correct label operand number.
("b<zcond:code><mode>"): Rename from "b<ncond:code>", iterating
over NZUSE.
("b<nzvccond:code><mode>"): Similarly from "b<ocond:code>", over
NZVCUSE.  Remove FIXME.
("*b<nzcond:code>_reversed<mode>"): Similarly from
"*b<ncond:code>_reversed", over NZUSE.
("*b<nzvccond:code>_reversed<mode>"): Similarly from
"*b<ocond:code>_reversed", over NZVCUSE.  Remove FIXME.
("b<rnzcond:code><mode>"): Similarly from "b<rcond:code>",
over NZUSE.  Reinstate "b<oCC>" vs. "b<CC>" mnemonic choice,
depending on CC_NZmode vs. CCmode.  Remove FIXME.
("*b<rnzcond:code>_reversed<mode>"): Similarly from
"*b<rcond:code>_reversed", over NZUSE.
("*cstore<mode><code>4"): Rename from "*cstore<mode>4",
iterating over cond instead of matching the comparison with
ordered_comparison_operator.
("*s<nzcond:code><mode>"): Rename from "*s<ncond:code>",
iterating over NZUSE.
("*s<rnzcond:code><mode>"): Similar from "*s<rcond:code>", over
NZUSE.  Reinstate "b<oCC>" vs. "b<CC>" mnemonic choice,
depending on CC_NZmode vs. CCmode.
("*s<nzvccond:code><mode>"): Simlar from "*s<ocond:code>", over
NZVCUSE.  Remove FIXME.

This is just the framework bits of splitting CCmode into classes
where the cc-setter can merge mode (CCmode), classes where the
cc-setter must set V and C "usefully" (as well as N and Z flags)
and classes where the cc-setter is something like an arithmetic
instruction, where N and Z are valid but C and V reflect the
operation rather than a compare of the result with zero.  This
should yield identical or near-identical code.

The old split of conditions into the ncond and ocond sets took
into account the transformations done by final.c:alter_cond from
cc_status.flags & CC_NO_OVERFLOW, and wasn't a reflection of the
hardware description of the conditions (i.e. whether V mattered
or not).
---
 gcc/config/cris/cris-modes.def |  54 +++++++++++++
 gcc/config/cris/cris-protos.h  |   2 +-
 gcc/config/cris/cris.c         |  71 ++++++++++++++++
 gcc/config/cris/cris.h         |   4 +-
 gcc/config/cris/cris.md        | 178 +++++++++++++++++++++++++----------------
 5 files changed, 237 insertions(+), 72 deletions(-)
 create mode 100644 gcc/config/cris/cris-modes.def
diff mbox series

Patch

diff --git a/gcc/config/cris/cris-modes.def b/gcc/config/cris/cris-modes.def
new file mode 100644
index 000000000..b0e426159
--- /dev/null
+++ b/gcc/config/cris/cris-modes.def
@@ -0,0 +1,54 @@ 
+/* Definitions of target machine for GNU compiler, for CRIS.
+   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* Node: Condition Code */
+
+/* The mode used for condition-codes depends on both the way the
+   condition-codes are generated (the CC-setter, typically the compare
+   instruction), and used (the CC-user, typically a branch).  For CRIS, we
+   have ordinary compares and incidental condition-code settings from
+   preceding instructions, setting a subset of N, Z, V and C to usable
+   values, from the perspective of comparing the result against zero
+   (fpcraz).  The two subsets meaningful to gcc are all of N, Z, V, C
+   versus just N, Z; some CC-users care only about N and/or Z and some
+   that care about at least one of those flags together with V and/or C.
+   (FIXME: the result of testing a single bit using the btst instruction
+   should be described as a separate mode.)
+
+   The plain "CC_MODE (CC)" (which is always present in gcc), is used to
+   reflect the "unoptimized" state, where the CC-setter is a compare
+   against zero and the CC-user is any branch or s<condition> instruction,
+   before reload.  After reload, a need for C or V is reflected as
+   CC_NZVCmode in both setters and users, and others remain CCmode, until
+   or if optimization of CC-setter and CC-users, when CCmode setters can
+   be changed or replaced by either CC_NZmode or CC_NZVCmode.  To wit, all
+   users that require CC_NZVCmode must match only that mode at any time.
+   All other users must match all CCmodes.  All setters that set only
+   CC_NZmode must set only that mode.  All other setters must match
+   setting all CCmodes.  */
+
+/* Z and N flags only.  For a condition-code setter: only the Z and N
+   flags are set to usable values, fpcraz.  For a condition-code user: the
+   operation using the condition codes only care about the Z and N flags.  */
+CC_MODE (CC_NZ);
+
+/* Z and N *and* V and C flags.  For a condition-code setter: all flags
+   are set to usable values, fpcraz.  For a condition-code user: at least
+   one of V and C are used and possibly N and Z too.  */
+CC_MODE (CC_NZVC);
diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
index 4d8e76f6e..2db1ea1b8 100644
--- a/gcc/config/cris/cris-protos.h
+++ b/gcc/config/cris/cris-protos.h
@@ -23,7 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 extern bool cris_simple_epilogue (void);
 #ifdef RTX_CODE
 extern const char *cris_op_str (rtx);
-extern void cris_notice_update_cc (rtx, rtx_insn *);
+extern machine_mode cris_select_cc_mode (enum rtx_code, rtx, rtx);
 extern bool cris_reload_address_legitimized (rtx, machine_mode, int, int, int);
 extern int cris_side_effect_mode_ok (enum rtx_code, rtx *, int, int,
                                      int, int, int);
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index eecda8384..04c80c314 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -133,6 +133,7 @@  static reg_class_t cris_preferred_reload_class (rtx, reg_class_t);
 
 static int cris_register_move_cost (machine_mode, reg_class_t, reg_class_t);
 static int cris_memory_move_cost (machine_mode, reg_class_t, bool);
+static machine_mode cris_cc_modes_compatible (machine_mode, machine_mode);
 static bool cris_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 static int cris_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool cris_pass_by_reference (cumulative_args_t,
@@ -226,6 +227,9 @@  int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
    nothing.  Beware of changes to its usage; it may make sense to enable
    "later".  */
 
+#undef TARGET_CC_MODES_COMPATIBLE
+#define TARGET_CC_MODES_COMPATIBLE cris_cc_modes_compatible
+
 #undef TARGET_FLAGS_REGNUM
 #define TARGET_FLAGS_REGNUM CRIS_CC0_REGNUM
 
@@ -1509,6 +1513,73 @@  cris_memory_move_cost (machine_mode mode,
     return 6;
 }
 
+/* Worker function for SELECT_CC_MODE.  */
+
+machine_mode
+cris_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+{
+  /* We have different sets of patterns before and after
+     reload_completed, and everything before reload_completed is CCmode.
+     At the time of this writing, this function isn't called before that
+     time, so let's just gcc_assert on that assumption rather than doing
+     "if (!reload_completed) return CCmode;".  */
+  gcc_assert (reload_completed);
+
+  /* For float mode or comparisons with something other than 0, we
+     always go with CCmode.  */
+  if (GET_MODE_CLASS (GET_MODE (x)) != MODE_INT || y != const0_rtx)
+    return CCmode;
+
+  /* If we have a comparison that doesn't have to look at V or C, check
+     operand x; if it looks like a binary operator, return CC_NZmode,
+     else CCmode, so we only use CC_NZmode for the cases where we don't
+     actually have both V and C valid.  */
+  if (op == EQ || op ==  NE || op ==  GTU || op ==  LEU
+      || op ==  LT || op ==  GE)
+    {
+      enum rtx_code e = GET_CODE (x);
+
+    /* Mentioning the rtx_code here is required but not sufficient: the
+       insn also needs to be decorated with <setnz> (and the
+       anonymization prefix <anz> for a named pattern).  */
+      return e == PLUS || e == MINUS || e == MULT || e == NOT
+	? CC_NZmode : CCmode;
+    }
+
+  /* We should only get here for comparison operators.  */
+  gcc_assert (op ==  GEU || op ==  LTU || op ==  GT || op ==  LE);
+
+  return CC_NZVCmode;
+}
+
+/* Worker function for TARGET_CC_MODES_COMPATIBLE.
+   We start with CCmode for most comparisons, which merges and yields to
+   CC_NZmode or CC_NZVCmode.  The exceptions have CC_NZVCmode and can't do with
+   another mode.  */
+
+static machine_mode
+cris_cc_modes_compatible (machine_mode m1, machine_mode m2)
+{
+  if (m1 == CC_NZVCmode)
+    {
+      if (m2 == CC_NZVCmode || m2 == CCmode)
+	return CC_NZVCmode;
+      return VOIDmode;
+    }
+
+  if (m2 == CC_NZVCmode)
+    {
+      if (m1 == CC_NZVCmode || m1 == CCmode)
+	return CC_NZVCmode;
+      return VOIDmode;
+    }
+
+  if (m1 != m2)
+    return CC_NZmode;
+
+  return m1;
+}
+
 /* Return != 0 if the return sequence for the current function is short,
    like "ret" or "jump [sp+]".  Prior to reloading, we can't tell if
    registers must be saved, so return 0 then.  */
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index bc07dd541..2a938fe20 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -699,7 +699,9 @@  struct cum_args {int regs;};
 /* Node: Condition Code */
 
 /* FIXME: Maybe define TARGET_CANONICALIZE_COMPARISON later, when
-   playing with optimizations.  Definitely define SELECT_CC_MODE.  */
+   playing with optimizations.  */
+
+#define SELECT_CC_MODE(op, x, y) cris_select_cc_mode(op, x, y)
 
 #define REVERSIBLE_CC_MODE(MODE) true
 
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index bf2cf9663..362d63f6d 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -179,16 +179,51 @@  (define_code_iterator shiftrt [ashiftrt lshiftrt])
 (define_code_attr shlr [(ashiftrt "ashr") (lshiftrt "lshr") (ashift "ashl")])
 (define_code_attr slr [(ashiftrt "asr") (lshiftrt "lsr") (ashift "lsl")])
 
+;; Compares, branches, cbranch, cstore.  Conditions gt and le are CC_NZVC.
+;; Others start out as CCmode and can degenerate to CC_NZmode.
+;; Incidental setters are either CC_NZVCmode or CC_NZmode.  See also
+;; cris-modes.def.
+(define_mode_iterator NZSET [CC_NZ])
+(define_mode_iterator NZUSE [CC CC_NZ CC_NZVC])
+(define_mode_iterator NZVCSET [CC CC_NZVC CC_NZ])
+(define_mode_iterator NZVCUSE [CC_NZVC])
+
+;; All conditions.
+(define_code_iterator cond [eq ne gtu ltu geu leu gt le lt ge])
+
+;; Just equal and not equal.
 (define_code_iterator zcond [eq ne])
-(define_code_iterator ncond [eq ne gtu ltu geu leu])
-(define_code_iterator ocond [gt le])
-(define_code_iterator rcond [lt ge])
+
+;; Conditions that look only at Z and/or N (or can do with that).
+(define_code_iterator nzcond [eq ne gtu leu lt ge])
+
+;; The complement of nzcond within cond; conditions that look (also) on V
+;; or C.
+(define_code_iterator nzvccond [geu ltu gt le])
+
+;; Within nzcond, those that give different opcodes when operands are
+;; reversed or that can ignore V or C.  Also, the complement of zcond
+;; within nzcond.
+(define_code_iterator rnzcond [gtu leu lt ge])
+
+;; CRIS condition mnemonic.
 (define_code_attr CC [(eq "eq") (ne "ne") (gt "gt") (gtu "hi") (lt "lt")
 		      (ltu "lo") (ge "ge") (geu "hs") (le "le") (leu "ls")])
+
+;; CRIS reverse condition mnemonic.
 (define_code_attr rCC [(eq "ne") (ne "eq") (gt "le") (gtu "ls") (lt "ge")
 		       (ltu "hs") (ge "lt") (geu "lo") (le "gt") (leu "hi")])
-(define_code_attr oCC [(lt "mi") (ge "pl")])
-(define_code_attr roCC [(lt "pl") (ge "mi")])
+
+;; Mnemomic for the CRIS condition when V or C can be ignored.
+(define_code_attr oCC [(lt "mi") (ge "pl") (gtu "eq") (ltu "ne")])
+
+;; Reverse of oCC.
+(define_code_attr roCC [(lt "pl") (ge "mi") (gtu "eq") (ltu "ne")])
+
+;; Required unoptimized CCmode, different for nzcond and nzvccond.
+(define_code_attr xCC [(eq "CC") (ne "CC") (gtu "CC") (ltu "CC_NZVC")
+		       (geu "CC_NZVC") (leu "CC") (lt "CC") (ge "CC")
+		       (gt "CC_NZVC") (le "CC_NZVC")])
 
 ;; Operand and operator predicates.
 
@@ -209,9 +244,9 @@  (define_code_attr roCC [(lt "pl") (ge "mi")])
 ;; (It shouldn't be; it should be done as part of register allocation.)
 (define_mode_attr sCC_destc
  [(DI "r, r,r,r,r,r,r") (SI "r,r, r,  r,r,r") (HI "r, r,  r,r") (QI "r, r,  r,r")])
-(define_mode_attr cmp_op1c
+(define_mode_attr cmp_op0c
  [(DI "rm,r,r,r,r,r,r") (SI "r,r, rQ>,r,r,m") (HI "r, rQ>,r,m") (QI "r, rQ>,r,m")])
-(define_mode_attr cmp_op2c
+(define_mode_attr cmp_op1c
  [(DI "M,Kc,I,P,n,r,o") (SI "I,rQ>,M, P,g,M") (HI "rQ>,M, g,M") (QI "rQ>,M, g,M")])
 
 ;; We could optimize the sizes of the immediate operands for various
@@ -219,10 +254,11 @@  (define_mode_attr cmp_op2c
 ;; DImode for anything else but a structure/block-mode.  Just do the
 ;; obvious stuff for the straight-forward constraint letters.
 
-(define_insn "*cmpdi"
-  [(set (reg:CC CRIS_CC0_REGNUM)
-	(compare:CC (match_operand:DI_ 0 "nonimmediate_operand" "<cmp_op1c>")
-		    (match_operand:DI_ 1 "general_operand" "<cmp_op2c>")))]
+(define_insn "*cmpdi<NZVCSET:mode>"
+  [(set (reg:NZVCSET CRIS_CC0_REGNUM)
+	(compare:NZVCSET
+	 (match_operand:DI_ 0 "nonimmediate_operand" "<cmp_op0c>")
+	 (match_operand:DI_ 1 "general_operand" "<cmp_op1c>")))]
   "reload_completed"
   "@
    test.d %M0\;ax\;test.d %H0
@@ -252,9 +288,9 @@  (define_insn "*cmpdi"
 ;; constants, but sometimes gcc will find its way to use it for other
 ;; (memory) operands.  Avoid side-effect patterns, though (see above).
 
-(define_insn "*cmp_ext<mode>"
-  [(set (reg:CC CRIS_CC0_REGNUM)
-	(compare:CC
+(define_insn "*cmp_ext<BW:mode><NZVCSET:mode>"
+  [(set (reg:NZVCSET CRIS_CC0_REGNUM)
+	(compare:NZVCSET
 	 (match_operand:SI 0 "register_operand" "r,r")
 	 (match_operator:SI 2 "cris_extend_operator"
 			 [(match_operand:BW 1 "memory_operand" "Q>,m")])))]
@@ -265,11 +301,11 @@  (define_insn "*cmp_ext<mode>"
 ;; The "normal" compare patterns, from SI on.  Special-cases with zero
 ;; are covered above.
 
-(define_insn "*cmpsi"
-  [(set (reg:CC CRIS_CC0_REGNUM)
-	(compare:CC
-	 (match_operand:SI_ 0 "nonimmediate_operand" "<cmp_op1c>")
-	 (match_operand:SI_ 1 "general_operand" "<cmp_op2c>")))]
+(define_insn "*cmpsi<NZVCSET:mode>"
+  [(set (reg:NZVCSET CRIS_CC0_REGNUM)
+	(compare:NZVCSET
+	 (match_operand:SI_ 0 "nonimmediate_operand" "<cmp_op0c>")
+	 (match_operand:SI_ 1 "general_operand" "<cmp_op1c>")))]
   "reload_completed"
   "@
    cmpq %1,%0
@@ -280,10 +316,11 @@  (define_insn "*cmpsi"
    test.d %0"
   [(set_attr "slottable" "yes,yes,yes,no,no,no")])
 
-(define_insn "*cmp<mode>"
-  [(set (reg:CC CRIS_CC0_REGNUM)
-	(compare:CC (match_operand:BW 0 "nonimmediate_operand" "<cmp_op1c>")
-		    (match_operand:BW 1 "general_operand" "<cmp_op2c>")))]
+(define_insn "*cmp<BW:mode><NZVCSET:mode>"
+  [(set (reg:NZVCSET CRIS_CC0_REGNUM)
+	(compare:NZVCSET
+	 (match_operand:BW 0 "nonimmediate_operand" "<cmp_op0c>")
+	 (match_operand:BW 1 "general_operand" "<cmp_op1c>")))]
   "reload_completed"
   "@
    cmp<m> %1,%0
@@ -299,9 +336,9 @@  (define_insn "*cmp<mode>"
 
 ;; SImode.  This mode is the only one needed, since gcc automatically
 ;; extends subregs for lower-size modes.  FIXME: Add testcase.
-(define_insn "*btst"
-  [(set (reg:CC CRIS_CC0_REGNUM)
-	(compare:CC
+(define_insn "*btst<mode>"
+  [(set (reg:NZVCSET CRIS_CC0_REGNUM)
+	(compare:NZVCSET
 	 (zero_extract:SI
 	  (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp")
 	  (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n")
@@ -1978,22 +2015,23 @@  (define_expand "cbranch<mode>4"
   ""
   "cris_reduce_compare (&operands[0], &operands[1], &operands[2]);")
 
-(define_insn_and_split "*cbranch<mode>4"
+(define_insn_and_split "*cbranch<mode><code>4"
   [(set (pc)
 	(if_then_else
-	 (match_operator 0 "ordered_comparison_operator"
-	  [(match_operand:BWDD 1 "nonimmediate_operand" "<cmp_op1c>")
-	   (match_operand:BWDD 2 "general_operand" "<cmp_op2c>")])
-	 (label_ref (match_operand 3 ""))
+	 (cond
+	  (match_operand:BWDD 0 "nonimmediate_operand" "<cmp_op0c>")
+	  (match_operand:BWDD 1 "general_operand" "<cmp_op1c>"))
+	 (label_ref (match_operand 2 ""))
 	 (pc)))
    (clobber (reg:CC CRIS_CC0_REGNUM))]
   ""
   "#"
   "&& reload_completed"
-  [(set (reg:CC CRIS_CC0_REGNUM) (compare:CC (match_dup 1) (match_dup 2)))
+  [(set (reg:<xCC> CRIS_CC0_REGNUM)
+	(compare:<xCC> (match_dup 0) (match_dup 1)))
    (set (pc)
-	(if_then_else (match_op_dup 0 [(reg:CC CRIS_CC0_REGNUM) (const_int 0)])
-		      (label_ref (match_dup 3))
+	(if_then_else (cond (reg:<xCC> CRIS_CC0_REGNUM) (const_int 0))
+		      (label_ref (match_dup 2))
 		      (pc)))]
   "")
 
@@ -2019,7 +2057,7 @@  (define_insn_and_split "*cbranch<mode>4_btstq<CC>"
 	 (const_int 0)))
    (set (pc)
 	(if_then_else (zcond (reg:CC CRIS_CC0_REGNUM) (const_int 0))
-		      (label_ref (match_dup 3))
+		      (label_ref (match_dup 2))
 		      (pc)))]
   "")
 
@@ -2028,9 +2066,9 @@  (define_insn_and_split "*cbranch<mode>4_btstq<CC>"
 ;; e.g. m68k, so we have to check if overflow bit is set on all "signed"
 ;; conditions.
 
-(define_insn "b<ncond:code>"
+(define_insn "b<zcond:code><mode>"
   [(set (pc)
-	(if_then_else (ncond (reg:CC CRIS_CC0_REGNUM)
+	(if_then_else (zcond (reg:NZUSE CRIS_CC0_REGNUM)
 			     (const_int 0))
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
@@ -2038,33 +2076,33 @@  (define_insn "b<ncond:code>"
   "b<CC> %l0%#"
   [(set_attr "slottable" "has_slot")])
 
-(define_insn "b<ocond:code>"
+(define_insn "b<nzvccond:code><mode>"
   [(set (pc)
-	(if_then_else (ocond (reg:CC CRIS_CC0_REGNUM)
+	(if_then_else (nzvccond (reg:NZVCUSE CRIS_CC0_REGNUM)
 			     (const_int 0))
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "reload_completed"
-  ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW.
   "b<CC> %l0%#"
   [(set_attr "slottable" "has_slot")])
 
-(define_insn "b<rcond:code>"
+(define_insn "b<rnzcond:code><mode>"
   [(set (pc)
-	(if_then_else (rcond (reg:CC CRIS_CC0_REGNUM)
+	(if_then_else (rnzcond (reg:NZUSE CRIS_CC0_REGNUM)
 			     (const_int 0))
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
   "reload_completed"
-  ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW.
-  "b<CC> %l0%#"
+{
+  return <MODE>mode == CC_NZmode ? "b<oCC> %l0%#": "b<CC> %l0%#";
+}
   [(set_attr "slottable" "has_slot")])
 
 ;; Reversed anonymous patterns to the ones above, as mandated.
 
-(define_insn "*b<ncond:code>_reversed"
+(define_insn "*b<nzcond:code>_reversed<mode>"
   [(set (pc)
-	(if_then_else (ncond (reg:CC CRIS_CC0_REGNUM)
+	(if_then_else (nzcond (reg:NZUSE CRIS_CC0_REGNUM)
 			     (const_int 0))
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))]
@@ -2072,26 +2110,26 @@  (define_insn "*b<ncond:code>_reversed"
   "b<rCC> %l0%#"
   [(set_attr "slottable" "has_slot")])
 
-(define_insn "*b<ocond:code>_reversed"
+(define_insn "*b<nzvccond:code>_reversed<mode>"
   [(set (pc)
-	(if_then_else (ocond (reg:CC CRIS_CC0_REGNUM)
+	(if_then_else (nzvccond (reg:NZVCUSE CRIS_CC0_REGNUM)
 			     (const_int 0))
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))]
   "reload_completed"
-  ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW.
   "b<rCC> %l0%#"
   [(set_attr "slottable" "has_slot")])
 
-(define_insn "*b<rcond:code>_reversed"
+(define_insn "*b<rnzcond:code>_reversed<mode>"
   [(set (pc)
-	(if_then_else (rcond (reg:CC CRIS_CC0_REGNUM)
+	(if_then_else (rnzcond (reg:NZUSE CRIS_CC0_REGNUM)
 			     (const_int 0))
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))]
   "reload_completed"
-  ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW.
-  "b<rCC> %l0%#"
+{
+  return <MODE>mode == CC_NZmode ? "b<roCC> %l0%#" : "b<rCC> %l0%#";
+}
   [(set_attr "slottable" "has_slot")])
 
 ;; Set on condition: sCC.
@@ -2106,46 +2144,46 @@  (define_expand "cstore<mode>4"
   ""
   "cris_reduce_compare (&operands[1], &operands[2], &operands[3]);")
 
-(define_insn_and_split "*cstore<mode>4"
+(define_insn_and_split "*cstore<mode><code>4"
   [(set (match_operand:SI 0 "register_operand" "=<sCC_destc>")
-	(match_operator:SI 1 "ordered_comparison_operator"
-	 [(match_operand:BWDD 2 "nonimmediate_operand" "<cmp_op1c>")
-	  (match_operand:BWDD 3 "general_operand" "<cmp_op2c>")]))
+	(cond:SI
+	 (match_operand:BWDD 1 "nonimmediate_operand" "<cmp_op0c>")
+	 (match_operand:BWDD 2 "general_operand" "<cmp_op1c>")))
    (clobber (reg:CC CRIS_CC0_REGNUM))]
   ""
   "#"
   "&& reload_completed"
-  [(set (reg:CC CRIS_CC0_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
-   (set (match_operand:SI 0 "register_operand")
-	(match_operator:SI 1 "ordered_comparison_operator"
-	 [(reg:CC CRIS_CC0_REGNUM) (const_int 0)]))]
+  [(set (reg:<xCC> CRIS_CC0_REGNUM)
+	(compare:<xCC> (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+	(cond:SI (reg:<xCC> CRIS_CC0_REGNUM) (const_int 0)))]
   "")
 
 ;; Like bCC, we have to check the overflow bit for
 ;; signed conditions.
 
-(define_insn "*s<ncond:code>"
+(define_insn "*s<nzcond:code><mode>"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(ncond:SI (reg:CC CRIS_CC0_REGNUM) (const_int 0)))]
+	(nzcond:SI (reg:NZUSE CRIS_CC0_REGNUM) (const_int 0)))]
   "reload_completed"
   "s<CC> %0"
   [(set_attr "slottable" "yes")
    (set_attr "cc" "none")])
 
-(define_insn "*s<rcond:code>"
+(define_insn "*s<rnzcond:code><mode>"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(rcond:SI (reg:CC CRIS_CC0_REGNUM) (const_int 0)))]
+	(rnzcond:SI (reg:NZUSE CRIS_CC0_REGNUM) (const_int 0)))]
   "reload_completed"
-  ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW.
-  "s<CC> %0"
+{
+  return <MODE>mode == CC_NZmode ? "s<oCC> %0" : "s<CC> %0";
+}
   [(set_attr "slottable" "yes")
    (set_attr "cc" "none")])
 
-(define_insn "*s<ocond:code>"
+(define_insn "*s<nzvccond:code><mode>"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(ocond:SI (reg:CC CRIS_CC0_REGNUM) (const_int 0)))]
+	(nzvccond:SI (reg:NZVCUSE CRIS_CC0_REGNUM) (const_int 0)))]
   "reload_completed"
-  ;; FIXME: optimize out the compare and handle CC_NO_OVERFLOW.
   "s<CC> %0"
   [(set_attr "slottable" "yes")
    (set_attr "cc" "none")])