diff mbox series

[committed,2/3] Converting the v850 port away from cc0 -- basic support for new scheme

Message ID 90e9cdf4-9ddd-a3fd-6d5d-75bec16b9ab5@redhat.com
State New
Headers show
Series [committed,1/3] Converting the v850 port away from cc0 -- removing most of cc0 handling | expand

Commit Message

Jeff Law June 27, 2018, 6:32 p.m. UTC
This is the bulk of the changes.  With this change in installed the v850
port should be using the new mechanism for condition code handling
consistently, though without optimizing well.

This is a fairly large change which hits a great many patterns.

It's largely what one would expect.  THe comparison/branch are kept
together as a unit prior to reload, but split post-reload.  Similarly
for things like conditional moves and tst insns.  Clobbers get added to
several patterns that were missing them.

One of the interesting v8 tidbits is that it was already using the new
style for its floating point comparisons & branches.  We actually get to
simplify that a bit because we no longer need special branching patterns
(FP comparison initially are stored in FCC, then get copied into the Z
bit of CC_REG, then we use standard bz/bnz insns).

This commit should work independently of #3 as #3 strictly adds flags
setting variants of arithmetic, logicals and other patterns.  But I
haven't tested that extensively.

Jeff
* config/v850/v850-protos.h (notice_update_cc): Remove.
	* config/v850/v850.c (v850_compare_op0, v850_compare_op1): Remove.
	(v850_print_operand): Handle 'D' and "d".
	(v850_select_cc_mode): Remove ATTRIBUTE_UNUSED for last argument.
	Add handling of arithmetic/logical operations compared against zero.
	(v850_gen_float_compare): Remove ATTRIBUTE_UNUSED for last argument.
	Do not look at v850_compare_op, instead get mode from last argument.
	(v850_gen_compare): Remove
	(increment_stack): Use addsi3_clobber_flags to avoid splitting failure
	after reload for prologue insns.
	(expand_prologue): Account for CLOBBER of CC_REGNUM in various
	patterns.
	(construct_save_jarl): Likewise.
	(TARGET_FLAGS_REGNUM): Define.
	* config/v850/v850.h (v850_compare_op0, v850_compare_op1): Remove.
	(NOTICE_UPDATE_CC): Remove.
	* config/v850/v850.md (v850_tst1): Use (reg:CCZ CC_REGNUM) rather
	than cc0.  Conditionalize on reload_completed.
	(cmpsi_insn, setfcc_insn): Likewise.
	(tst1 splitter): Turn into define_and_split which sets the flags
	after reload.
	(cstoresi4, cbranchsf4, cbranchdf4, cbranchsi4_insn): Likewise.
	(cbranchsi4, branch_normal, branch_invert): Do not expose cc0 here.
	(cstoresf4, cstoredf4): Clobber the flags.
	(cmpsi, cmpsf, cmpdf): Remove expanders.
	(setf_insn): Remove pattern.
	(addsi3): Turn into define_and_split which clobbers the flags after
	reload and a suitable pattern (addsi3_clobber_flags) for use after
	reload.
	(subsi3, negsi2, andsi3, iorsi3, xorsi3, one_cmplsi2) Likewise.
	(ashlsi3, ashlsi3_v850e2, lshrsi3, lsh4si3_v850e2): Likewise.
	(ashrsi3, ashrsi3_v850e2): Likewise.
	(bins): Clobber the flags.
	(movsicc_normal_cc, movsicc_normal, movsicc_tst1): Likewise.
	(movsicc_tst1_revesed, sasf, swap and rotate patterns): Likewise.
	(fix_loop_counter, call_internal_short, call_internal_long): Likewise.
	(call_value_internal_short, call_value_internal_long): Likewise.
	(callt_save_interrupt, callt_return_interrupt): Likewise.
	(save_interrupt, return_interrupt): Likewise.
	(callt_save_all_interrupt, save_all_interrupt): Likewise.
	(_save_all_interrupt, callt_restore_all_interrupt): Likewise.
	(restore_all_interrupt, _restore_all_interrupt): Likewise.
	(All FP comparisons): Only allow after reload has completed.
	(trfsr): Likewise.
	(divh, divhu): Tweak output template.
	(branch_z_normal, branch_z_invert): Remove
	(branch_nz_normal, branch_nz_invert): Likewise.
	(extendhisi_insn, extendqisi_insn): Do not clobber flags.

Comments

Eric Botcazou June 28, 2018, 11:20 a.m. UTC | #1
> This is the bulk of the changes.  With this change in installed the v850
> port should be using the new mechanism for condition code handling
> consistently, though without optimizing well.

Nice work!  You need to update the v850 entry in:
  https://gcc.gnu.org/backends.html

> One of the interesting v8 tidbits is that it was already using the new
> style for its floating point comparisons & branches.  We actually get to
> simplify that a bit because we no longer need special branching patterns
> (FP comparison initially are stored in FCC, then get copied into the Z
> bit of CC_REG, then we use standard bz/bnz insns).

Does this mean that the 'F' in the above document is also obsolete?
Jeff Law June 28, 2018, 2:02 p.m. UTC | #2
On 06/28/2018 05:20 AM, Eric Botcazou wrote:
>> This is the bulk of the changes.  With this change in installed the v850
>> port should be using the new mechanism for condition code handling
>> consistently, though without optimizing well.
> 
> Nice work!  You need to update the v850 entry in:
>   https://gcc.gnu.org/backends.html
It's on  my list :-)


> 
>> One of the interesting v8 tidbits is that it was already using the new
>> style for its floating point comparisons & branches.  We actually get to
>> simplify that a bit because we no longer need special branching patterns
>> (FP comparison initially are stored in FCC, then get copied into the Z
>> bit of CC_REG, then we use standard bz/bnz insns).
> 
> Does this mean that the 'F' in the above document is also obsolete?
Yea, not sure how we got into the inconsistent state, but modern
versions of the v850 have a FP unit or at least it's an option.

jeff
diff mbox series

Patch

diff --git a/gcc/config/v850/v850-protos.h b/gcc/config/v850/v850-protos.h
index e8ff280..ca99703 100644
--- a/gcc/config/v850/v850-protos.h
+++ b/gcc/config/v850/v850-protos.h
@@ -32,7 +32,6 @@  extern void   v850_init_expanders           (void);
 #ifdef RTX_CODE
 extern rtx    v850_return_addr              (int);
 extern const char *output_move_single       (rtx *);
-extern void   notice_update_cc              (rtx, rtx_insn *);
 extern char * construct_save_jarl           (rtx);
 extern char * construct_restore_jr          (rtx);
 #ifdef HAVE_MACHINE_MODES
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index e184718..cb2debf 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -68,8 +68,6 @@  data_area_stack_element * data_area_stack = NULL;
    function is an interrupt handler.  */
 static int v850_interrupt_cache_p = FALSE;
 
-rtx v850_compare_op0, v850_compare_op1;
-
 /* Whether current function is an interrupt handler.  */
 static int v850_interrupt_p = FALSE;
 
@@ -418,7 +416,9 @@  v850_print_operand (FILE * file, rtx x, int code)
     case 'b':
     case 'B':
     case 'C':
-      switch ((code == 'B' || code == 'C')
+    case 'd':
+    case 'D':
+      switch ((code == 'B' || code == 'C' || code == 'D')
 	      ? reverse_condition (GET_CODE (x)) : GET_CODE (x))
 	{
 	  case NE:
@@ -434,7 +434,10 @@  v850_print_operand (FILE * file, rtx x, int code)
 	      fprintf (file, "e");
 	    break;
 	  case GE:
-	    fprintf (file, "ge");
+	    if (code == 'D' || code == 'd')
+	      fprintf (file, "p");
+	    else
+	      fprintf (file, "ge");
 	    break;
 	  case GT:
 	    fprintf (file, "gt");
@@ -443,7 +446,10 @@  v850_print_operand (FILE * file, rtx x, int code)
 	    fprintf (file, "le");
 	    break;
 	  case LT:
-	    fprintf (file, "lt");
+	    if (code == 'D' || code == 'd')
+	      fprintf (file, "n");
+	    else
+	      fprintf (file, "lt");
 	    break;
 	  case GEU:
 	    fprintf (file, "nl");
@@ -905,7 +911,7 @@  output_move_single (rtx * operands)
 }
 
 machine_mode
-v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED)
+v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1)
 {
   if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
     {
@@ -927,11 +933,20 @@  v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED)
 	  gcc_unreachable ();
 	}
     }
+
+  if (op1 == const0_rtx
+      && (cond == EQ || cond == NE || cond == LT || cond == GE)
+      && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
+	  || GET_CODE (op0) == NEG || GET_CODE (op0) == AND
+	  || GET_CODE (op0) == IOR || GET_CODE (op0) == XOR
+	  || GET_CODE (op0) == NOT || GET_CODE (op0) == ASHIFT))
+    return CCNZmode;
+
   return CCmode;
 }
 
 machine_mode
-v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, rtx op0, rtx op1)
+v850_gen_float_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1)
 {
   if (GET_MODE (op0) == DFmode)
     {
@@ -960,7 +975,7 @@  v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED,
 	  gcc_unreachable ();
 	}
     }
-  else if (GET_MODE (v850_compare_op0) == SFmode)
+  else if (mode == SFmode)
     {
       switch (cond)
 	{
@@ -993,25 +1008,6 @@  v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED,
   return v850_select_cc_mode (cond, op0, op1);
 }
 
-rtx
-v850_gen_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1)
-{
-  if (GET_MODE_CLASS(GET_MODE (op0)) != MODE_FLOAT)
-    {
-      emit_insn (gen_cmpsi_insn (op0, op1));
-      return gen_rtx_fmt_ee (cond, mode, gen_rtx_REG(CCmode, CC_REGNUM), const0_rtx);
-    }
-  else
-    {
-      rtx cc_reg;
-      mode = v850_gen_float_compare (cond, mode, op0, op1);
-      cc_reg = gen_rtx_REG (mode, CC_REGNUM);
-      emit_insn (gen_rtx_SET (cc_reg, gen_rtx_REG (mode, FCC_REGNUM)));
-
-      return gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx);
-    }
-}
-
 /* Return maximum offset supported for a short EP memory reference of mode
    MODE and signedness UNSIGNEDP.  */
 
@@ -1635,7 +1631,7 @@  increment_stack (signed int amount, bool in_prologue)
       inc = reg;
     }
 
-  inc = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, inc));
+  inc = emit_insn (gen_addsi3_clobber_flags (stack_pointer_rtx, stack_pointer_rtx, inc));
   if (in_prologue)
     F (inc);
 }
@@ -1712,7 +1708,7 @@  expand_prologue (void)
 
 	  save_all = gen_rtx_PARALLEL
 	    (VOIDmode,
-	     rtvec_alloc (num_save + 1
+	     rtvec_alloc (num_save + 2
 			  + (TARGET_DISABLE_CALLT ? (TARGET_LONG_CALLS ? 2 : 1) : 0)));
 
 	  XVECEXP (save_all, 0, 0)
@@ -1731,13 +1727,16 @@  expand_prologue (void)
 			       save_regs[i]);
 	    }
 
+	  XVECEXP (save_all, 0, num_save + 1)
+	    = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, CC_REGNUM));
+
 	  if (TARGET_DISABLE_CALLT)
 	    {
-	      XVECEXP (save_all, 0, num_save + 1)
+	      XVECEXP (save_all, 0, num_save + 2)
 		= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10));
 
 	      if (TARGET_LONG_CALLS)
-		XVECEXP (save_all, 0, num_save + 2)
+		XVECEXP (save_all, 0, num_save + 3)
 		  = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
 	    }
 
@@ -2330,7 +2329,7 @@  construct_save_jarl (rtx op)
   stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1));
 
   /* Each push will put 4 bytes from the stack....  */
-  stack_bytes += (count - (TARGET_LONG_CALLS ? 3 : 2)) * 4;
+  stack_bytes += (count - (TARGET_LONG_CALLS ? 4 : 3)) * 4;
 
   /* Make sure that the amount we are popping either 0 or 16 bytes.  */
   if (stack_bytes != 0)
@@ -2341,7 +2340,7 @@  construct_save_jarl (rtx op)
 
   /* Now compute the bit mask of registers to push.  */
   mask = 0;
-  for (i = 1; i < count - (TARGET_LONG_CALLS ? 2 : 1); i++)
+  for (i = 1; i < count - (TARGET_LONG_CALLS ? 3 : 2); i++)
     {
       rtx vector_element = XVECEXP (op, 0, i);
       
@@ -3325,6 +3324,9 @@  v850_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 #undef  TARGET_MODES_TIEABLE_P
 #define TARGET_MODES_TIEABLE_P v850_modes_tieable_p
 
+#undef TARGET_FLAGS_REGNUM
+#define TARGET_FLAGS_REGNUM 32
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-v850.h"
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
index 96bddc2..04d226a 100644
--- a/gcc/config/v850/v850.h
+++ b/gcc/config/v850/v850.h
@@ -26,9 +26,6 @@ 
 #ifndef GCC_V850_H
 #define GCC_V850_H
 
-extern GTY(()) rtx v850_compare_op0;
-extern GTY(()) rtx v850_compare_op1;
-
 #undef LIB_SPEC
 #define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -lgcc --end-group}}"
 
@@ -567,8 +564,6 @@  struct cum_arg { int nbytes; };
 
 #define SELECT_CC_MODE(OP, X, Y)       v850_select_cc_mode (OP, X, Y)
 
-#define NOTICE_UPDATE_CC(EXP, INSN)
-
 /* Nonzero if access to memory by bytes or half words is no faster
    than accessing full words.  */
 #define SLOW_BYTE_ACCESS 1
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md
index 0fad9ea..3cfec74 100644
--- a/gcc/config/v850/v850.md
+++ b/gcc/config/v850/v850.md
@@ -28,6 +28,42 @@ 
 ;;
 ;; One day we'll probably need to handle calls to targets more than 4M
 ;; away.
+;;
+
+;; Condition codes
+;;
+;; Data movement (load, store, register copy) does not modify condition
+;; codes.  But there is no way to add two registers together without
+;; modifying the condition codes.
+;;
+;; So we do not expose the condition codes until after reload.  The
+;; general approach is to have a define_insn_and_split for the basic
+;; operation with no condition codes in the pattern (to give the
+;; optimizers maximal freedom).  The splitter adds a clobber of the
+;; condition codes after reload.  There is a distinct pattern which
+;; sets the condition codes.
+;;
+;; As noted, data movement does not affect condition codes.
+;;
+;; Arithmetic generally set the codes in the expected ways, with mul
+;; instructions being a notable outlier.  div instructions generally
+;; do the right thing, except when the output registers are the same
+;; when the flags do not get set.  We just assume they're clobbered
+;; for div instructions to avoid MD bloat with marginal benefit
+;;
+;; The bit manipulation instructions (clr1, not1, set1) set condition
+;; codes, but not in a useful way (they're set to the prior status of
+;; the bit).  So we just model those as clobbers.  tst1 does set the
+;; condition codes in a useful way.  We could perhaps do better with
+;; these by noting they only modify the Z flag, it doesn't seem worth
+;; the effort.
+;;
+;; Byte swaps seem to change the condition codes, but I haven't tried
+;; to describe how.
+;;
+;; I have no documentation on the rotate instructions.  They likely
+;; set the condition codes, but I've left them as clobbers for now.
+
 
 ;; The size of instructions in bytes.
 
@@ -352,110 +388,90 @@ 
 ;; ----------------------------------------------------------------------
 
 (define_insn "*v850_tst1"
-  [(set (cc0)
+  [(set (reg:CCZ CC_REGNUM)
 	(compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
                                   (const_int 1)
                                   (match_operand:QI 1 "const_int_operand" "n"))
 		 (const_int 0)))]
-  ""
+  "reload_completed"
   "tst1 %1,%0"
   [(set_attr "length" "4")])
 
 ;; This replaces ld.b;sar;andi with tst1;setf nz.
+;; Should there be variants for HI or SI modes?
 
-(define_split
+(define_insn_and_split ""
   [(set (match_operand:SI 0 "register_operand" "")
 	(compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "")
 				  (const_int 1)
 				  (match_operand 2 "const_int_operand" ""))
 		 (const_int 0)))]
   ""
-  [(set (cc0) (compare (zero_extract:SI (match_dup 1)
-				        (const_int 1)
-				        (match_dup 2))
-		       (const_int 0)))
-   (set (match_dup 0) (ne:SI (cc0) (const_int 0)))])
+  "#"
+  "reload_completed"
+  [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_dup 1)
+						      (const_int 1)
+						      (match_dup 2))
+				     (const_int 0)))
+   (set (match_dup 0) (ne:SI (reg:CCZ CC_REGNUM) (const_int 0)))])
 
 (define_expand "cbranchsi4"
-  [(set (cc0)
-	(compare (match_operand:SI 1 "register_operand" "")
-		 (match_operand:SI 2 "reg_or_int5_operand" "")))
-   (set (pc)
+  [(set (pc)
 	(if_then_else
-	      (match_operator 0 "ordered_comparison_operator" [(cc0)
-							       (const_int 0)])
+	      (match_operator 0 "comparison_operator"
+	        [(match_operand:SI 1 "register_operand")
+		 (match_operand:SI 2 "reg_or_int5_operand")])
               (label_ref (match_operand 3 "" ""))
               (pc)))]
  "")
 
-(define_expand "cstoresi4"
-  [(set (cc0)
-	(compare (match_operand:SI 2 "register_operand" "")
-		 (match_operand:SI 3 "reg_or_int5_operand" "")))
-   (set (match_operand:SI 0 "register_operand")
-        (match_operator:SI 1 "ordered_comparison_operator" [(cc0)
-							    (const_int 0)]))]
-  "")
-
-(define_expand "cmpsi"
-  [(set (cc0)
-	(compare (match_operand:SI 0 "register_operand" "r,r")
-		 (match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
-   ""
-  {
-    v850_compare_op0 = operands[0];
-    v850_compare_op1 = operands[1];
-    DONE;
-  })
-
 (define_insn "cmpsi_insn"
-  [(set (cc0)
+  [(set (reg:CC CC_REGNUM)
 	(compare (match_operand:SI 0 "register_operand" "r,r")
 		 (match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
-  ""
-  "@
-  cmp %1,%0
-  cmp %1,%0"
+  "reload_completed"
+  "cmp %1,%0"
   [(set_attr "length" "2,2")])
 
-(define_expand "cbranchsf4"
+(define_insn_and_split "cbranchsf4"
   [(set (pc)
        (if_then_else (match_operator     0 "ordered_comparison_operator"
-                      [(match_operand:SF 1 "register_operand")
-                       (match_operand:SF 2 "register_operand")])
+                      [(match_operand:SF 1 "register_operand" "r")
+                       (match_operand:SF 2 "register_operand" "r")])
                      (label_ref (match_operand 3 ""))
-                     (pc)))
-  (clobber (cc0))]
+                     (pc)))]
   "TARGET_USE_FPU"
-{
-  enum rtx_code cond = GET_CODE (operands[0]);
-  machine_mode mode;
-  rtx fcc_reg;
-  rtx cc_reg;
-  rtx tmp;
-
-  v850_compare_op0 = operands[1];
-  v850_compare_op1 = operands[2];
-
-  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 (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 (pc_rtx, tmp));
-  DONE;
-})
+  "#"
+  "reload_completed"
+  [(set (match_dup 4) (match_dup 5))
+   (set (pc)
+        (if_then_else (match_dup 6)
+                      (label_ref (match_dup 3))
+                      (pc)))]
+  "{
+     /* This will generate the comparison insn at the start of
+	the sequence and get us the right mode to use for our
+	condition code registers.  */
+     enum machine_mode mode
+       = v850_gen_float_compare (GET_CODE (operands[0]),
+				 GET_MODE (operands[1]),
+				 operands[1], operands[2]);
+     /* We want operands referring to CC_REGNUM and FCC_REGNUM
+	in mode MODE.  */
+     operands[4] = gen_rtx_REG (mode, CC_REGNUM);
+     operands[5] = gen_rtx_REG (mode, FCC_REGNUM);
+     if (mode == CC_FPU_NEmode)
+       operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx);
+     else
+       operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx);
+}")
 
 (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")]))]
+          (match_operand:SF 3 "register_operand" "r")]))
+  (clobber (reg:CC CC_REGNUM))]
   "TARGET_USE_FPU"
 {
   if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
@@ -471,44 +487,47 @@ 
   [(set_attr "length" "12")
    (set_attr "type" "fpu")])
 
-(define_expand "cbranchdf4"
+(define_insn_and_split "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")])
+                      [(match_operand:DF 1 "even_reg_operand" "r")
+                       (match_operand:DF 2 "even_reg_operand" "r")])
                      (label_ref (match_operand 3 ""))
-                     (pc)))
-  (clobber (cc0))]
+                     (pc)))]
   "TARGET_USE_FPU"
-{
-  enum rtx_code cond = GET_CODE (operands[0]);
-  machine_mode mode;
-  rtx fcc_reg;
-  rtx cc_reg;
-  rtx tmp;
-
-    v850_compare_op0 = operands[1];
-    v850_compare_op1 = operands[2];
-
-  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 (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 (pc_rtx, tmp));
-  DONE;
-})
+  "#"
+  "reload_completed"
+;; How to get the mode here?
+  [(set (match_dup 4) (match_dup 5))
+   (set (pc)
+        (if_then_else (match_dup 6)
+                      (label_ref (match_dup 3))
+                      (pc)))]
+  "{
+     /* This will generate the comparison insn at the start of
+	the sequence and get us the right mode to use for our
+	condition code registers.  */
+     enum machine_mode mode
+       = v850_gen_float_compare (GET_CODE (operands[0]),
+				 GET_MODE (operands[1]),
+				 operands[1], operands[2]);
+     PUT_MODE (operands[0], mode);
+     /* We want operands referring to CC_REGNUM and FCC_REGNUM
+	in mode MODE.  */
+     operands[4] = gen_rtx_REG (mode, CC_REGNUM);
+     operands[5] = gen_rtx_REG (mode, FCC_REGNUM);
+     if (mode == CC_FPU_NEmode)
+       operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx);
+     else
+       operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx);
+}")
 
 (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")]))]
+          (match_operand:DF 3 "even_reg_operand" "r")]))
+  (clobber (reg:CC CC_REGNUM))]
   "TARGET_USE_FPU"
 {
   if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
@@ -524,38 +543,25 @@ 
   [(set_attr "length" "12")
    (set_attr "type" "fpu")])
 
-(define_expand "cmpsf"
-  [(set (reg:CC CC_REGNUM)
-	(compare (match_operand:SF 0 "register_operand" "r")
-		 (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
-  {
-    v850_compare_op0 = operands[0];
-    v850_compare_op1 = operands[1];
-    DONE;
-  })
-
-(define_expand "cmpdf"
-  [(set (reg:CC CC_REGNUM)
-	(compare (match_operand:DF 0 "even_reg_operand" "r")
-		 (match_operand:DF 1 "even_reg_operand" "r")))]
-  "TARGET_USE_FPU"
-  {
-    v850_compare_op0 = operands[0];
-    v850_compare_op1 = operands[1];
-    DONE;
-  })
-
 ;; ----------------------------------------------------------------------
 ;; ADD INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_insn "addsi3"
+(define_insn_and_split "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+	(plus:SI (match_operand:SI 1 "register_operand" "%0,r,r")
+		 (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "addsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(plus:SI (match_operand:SI 1 "register_operand" "%0,r,r")
 		 (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))
    (clobber (reg:CC CC_REGNUM))]
-
   ""
   "@
    add %2,%0
@@ -566,8 +572,17 @@ 
 ;; ----------------------------------------------------------------------
 ;; SUBTRACT INSTRUCTIONS
 ;; ----------------------------------------------------------------------
+(define_insn_and_split "subsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_operand:SI 1 "register_operand" "0,r")
+		  (match_operand:SI 2 "register_operand" "r,0")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
 
-(define_insn "subsi3"
+(define_insn "subsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
 	(minus:SI (match_operand:SI 1 "register_operand" "0,r")
 		  (match_operand:SI 2 "register_operand" "r,0")))
@@ -578,7 +593,16 @@ 
   subr %1,%0"
   [(set_attr "length" "2,2")])
 
-(define_insn "negsi2"
+(define_insn_and_split "negsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(neg:SI (match_operand:SI 1 "register_operand" "0")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "negsi2_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(neg:SI (match_operand:SI 1 "register_operand" "0")))
    (clobber (reg:CC CC_REGNUM))]
@@ -703,7 +727,7 @@ 
 		(match_dup 2)))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850E_UP"
-  "sxh %0\n\tdivh %2,%0,%3"
+  "sxh %0\\n\\tdivh %2,%0,%3"
   [(set_attr "length" "6")
    (set_attr "type" "div")])
 
@@ -719,7 +743,7 @@ 
 		 (match_dup 2)))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850E_UP"
-  "zxh %0\n\tdivhu %2,%0,%3"
+  "zxh %0\\n\\ndivhu %2,%0,%3"
   [(set_attr "length" "6")
    (set_attr "type" "div")])
 
@@ -785,12 +809,22 @@ 
   [(set_attr "length" "4")
    (set_attr "type" "bit1")])
 
-(define_insn "andsi3"
+(define_insn_and_split "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+		(match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "andsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
 		(match_operand:SI 2 "nonmemory_operand" "r,I,M")))
    (clobber (reg:CC CC_REGNUM))]
-  ""
+  "reload_completed"
   "@
   and %2,%0
   and %.,%0
@@ -860,7 +894,17 @@ 
   [(set_attr "length" "4")
    (set_attr "type" "bit1")])
 
-(define_insn "iorsi3"
+(define_insn_and_split "iorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+		(match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "iorsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
 		(match_operand:SI 2 "nonmemory_operand" "r,I,M")))
@@ -935,7 +979,17 @@ 
   [(set_attr "length" "4")
    (set_attr "type" "bit1")])
 
-(define_insn "xorsi3"
+(define_insn_and_split "xorsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+		(match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "xorsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
 		(match_operand:SI 2 "nonmemory_operand" "r,I,M")))
@@ -946,12 +1000,23 @@ 
   xor %.,%0
   xori %2,%1,%0"
   [(set_attr "length" "2,2,4")])
+
 
 ;; ----------------------------------------------------------------------
 ;; NOT INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
-(define_insn "one_cmplsi2"
+(define_insn_and_split "one_cmplsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(not:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (not:SI (match_dup 1)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+
+(define_insn "one_cmplsi2_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(not:SI (match_operand:SI 1 "register_operand" "r")))
    (clobber (reg:CC CC_REGNUM))]
@@ -977,7 +1042,8 @@ 
   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
 			 (match_operand:SI 1 "immediate_operand" "n")
 			 (match_operand:SI 2 "immediate_operand" "n"))
-	(match_operand:SI 3 "register_operand" "r"))]
+	(match_operand:SI 3 "register_operand" "r"))
+   (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850E3V5_UP"
   "bins %3, %2, %1, %0"
   [(set_attr "length" "4")])
@@ -986,20 +1052,46 @@ 
 ;; Scc INSTRUCTIONS
 ;; -----------------------------------------------------------------
 
-(define_insn "*setcc"
+(define_insn_and_split "*cbranchsi4_insn"
+  [(set (pc)
+	(if_then_else (match_operator 0 "comparison_operator"
+			[(match_operand:SI 1 "register_operand" "r")
+			 (match_operand:SI 2 "reg_or_int5_operand" "rJ")])
+		      (label_ref (match_operand 3 "" ""))
+		      (pc)))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (reg:CC CC_REGNUM)
+	(compare:CC (match_dup 1) (match_dup 2)))
+   (set (pc)
+	(if_then_else (match_op_dup 0
+			[(reg:CC CC_REGNUM) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))]
+  "")
+
+
+(define_insn_and_split "cstoresi4"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (match_operator:SI 1 "comparison_operator"
-	 [(cc0) (const_int 0)]))]
+	 [(match_operand:SI 2 "register_operand" "r")
+	  (match_operand:SI 3 "reg_or_int5_operand" "rJ")]))]
   ""
-  "setf %c1,%0"
-  [(set_attr "length" "4")])
+  "#"
+  "reload_completed"
+  [(set (reg:CC CC_REGNUM)
+	(compare:CC (match_dup 2) (match_dup 3)))
+   (set (match_dup 0) (match_op_dup 1 
+			[(reg:CC CC_REGNUM) (const_int 0)]))]
+  "")
 
-(define_insn "setf_insn"
+(define_insn "*setcc_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
-	(match_operator:SI 1 "comparison_operator"
-                          [(reg:CC CC_REGNUM) (const_int 0)]))]
-  ""
-  "setf %b1,%0"
+        (match_operator:SI 1 "comparison_operator"
+	 [(reg:CC CC_REGNUM) (const_int 0)]))]
+  "reload_completed"
+  "setf %c1,%0"
   [(set_attr "length" "4")])
 
 (define_insn "set_z_insn"
@@ -1065,12 +1157,6 @@ 
       }
   })
 
-;; ??? Clobbering the condition codes is overkill.
-
-;; ??? We sometimes emit an unnecessary compare instruction because the
-;; condition codes may have already been set by an earlier instruction,
-;; but we have no code here to avoid the compare if it is unnecessary.
-
 (define_insn "movsicc_normal_cc"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (if_then_else:SI
@@ -1078,7 +1164,7 @@ 
                          [(reg:CC CC_REGNUM) (const_int 0)])
          (match_operand:SI 2 "reg_or_int5_operand" "rJ")
          (match_operand:SI 3 "reg_or_0_operand" "rI")))]
-  "(TARGET_V850E_UP)"
+  "reload_completed && (TARGET_V850E_UP)"
   "cmov %c1,%2,%z3,%0";
   [(set_attr "length" "6")])
 
@@ -1089,11 +1175,11 @@ 
                          [(reg:CC CC_REGNUM) (const_int 0)])
          (match_operand:SI 2 "reg_or_0_operand" "rI")
          (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
-  "(TARGET_V850E_UP)"
+  "reload_completed && (TARGET_V850E_UP)"
   "cmov %C1,%3,%z2,%0"
   [(set_attr "length" "6")])
 
-(define_insn "*movsicc_normal"
+(define_insn_and_split "*movsicc_normal"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(if_then_else:SI
 	 (match_operator 1 "comparison_operator"
@@ -1102,21 +1188,35 @@ 
 	 (match_operand:SI 2 "reg_or_int5_operand" "rJ")
 	 (match_operand:SI 3 "reg_or_0_operand" "rI")))]
   "(TARGET_V850E_UP)"
-  "cmp %5,%4 ; cmov %c1,%2,%z3,%0"
-  [(set_attr "length" "6")])
+  "#"
+  "reload_completed"
+  [(set (reg:CC CC_REGNUM)
+	(compare:CC (match_dup 4) (match_dup 5)))
+   (set (match_dup 0)
+	(if_then_else:SI (match_op_dup 1
+			   [(reg:CC CC_REGNUM) (const_int 0)])
+			 (match_dup 2) (match_dup 3)))])
 
-(define_insn "*movsicc_reversed"
+
+(define_insn_and_split "*movsicc_reversed"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(if_then_else:SI
 	 (match_operator 1 "comparison_operator"
 			 [(match_operand:SI 4 "register_operand" "r")
 			  (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
-	 (match_operand:SI 2 "reg_or_0_operand" "rI")
-	 (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
+	 (match_operand:SI 2 "reg_or_int5_operand" "rI")
+	 (match_operand:SI 3 "reg_or_0_operand" "rJ")))]
   "(TARGET_V850E_UP)"
-  "cmp %5,%4 ; cmov %C1,%3,%z2,%0"
-  [(set_attr "length" "6")])
+  "#"
+  "reload_completed"
+  [(set (reg:CC CC_REGNUM)
+	(compare:CC (match_dup 4) (match_dup 5)))
+   (set (match_dup 0)
+	(if_then_else:SI (match_op_dup 1
+			   [(reg:CC CC_REGNUM) (const_int 0)])
+			 (match_dup 2) (match_dup 3)))])
 
+;; We could expose the setting of the condition codes here.
 (define_insn "*movsicc_tst1"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(if_then_else:SI
@@ -1127,11 +1227,13 @@ 
 			   (match_operand 3 "const_int_operand" "n"))
 			  (const_int 0)])
 	 (match_operand:SI 4 "reg_or_int5_operand" "rJ")
-	 (match_operand:SI 5 "reg_or_0_operand" "rI")))]
+	 (match_operand:SI 5 "reg_or_0_operand" "rI")))
+  (clobber (reg:CC CC_REGNUM))]
   "(TARGET_V850E_UP)"
   "tst1 %3,%2 ; cmov %c1,%4,%z5,%0"
   [(set_attr "length" "8")])
 
+;; We could expose the setting of the condition codes here.
 (define_insn "*movsicc_tst1_reversed"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(if_then_else:SI
@@ -1142,7 +1244,8 @@ 
 			   (match_operand 3 "const_int_operand" "n"))
 			  (const_int 0)])
 	 (match_operand:SI 4 "reg_or_0_operand" "rI")
-	 (match_operand:SI 5 "reg_or_int5_operand" "rJ")))]
+	 (match_operand:SI 5 "reg_or_int5_operand" "rJ")))
+   (clobber (reg:CC CC_REGNUM))]
   "(TARGET_V850E_UP)"
   "tst1 %3,%2 ; cmov %C1,%5,%z4,%0"
   [(set_attr "length" "8")])
@@ -1152,6 +1255,9 @@ 
 ;; second pattern by subsequent combining.  As above, we must include the
 ;; comparison to avoid input reloads in an insn using cc0.
 
+;; We could expose the setting of the condition codes here.
+;; However, I haven't seen this pattern used, so I'm not going
+;; to bother.
 (define_insn "*sasf"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(ior:SI
@@ -1235,7 +1341,8 @@ 
        [(ashift:SI (match_operand:SI 1 "register_operand" "r")
 		   (match_operand:SI 2 "const_int_operand" "n"))
 	(lshiftrt:SI (match_dup 1)
-	(match_operand:SI 3 "const_int_operand" "n"))]))]
+	(match_operand:SI 3 "const_int_operand" "n"))]))
+   (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
   "rotl %2, %1, %0"
   [(set_attr "length" "4")])
@@ -1246,7 +1353,8 @@ 
        [(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
 		     (match_operand:SI 3 "const_int_operand" "n"))
 	(ashift:SI (match_dup 1)
-		   (match_operand:SI 2 "const_int_operand" "n"))]))]
+		   (match_operand:SI 2 "const_int_operand" "n"))]))
+   (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
   "rotl %2, %1, %0"
   [(set_attr "length" "4")])
@@ -1287,9 +1395,11 @@ 
   }
 )
 
+;; Note the embedded arithmetic.  That affects the condition codes!
 (define_insn "fix_loop_counter"
   [(unspec:SI [(match_operand:SI          0 "register_operand" "+r,!m")
-	       (clobber (match_scratch:SI 1                    "=X,r"))] UNSPEC_LOOP)]
+	       (clobber (match_scratch:SI 1                    "=X,r"))] UNSPEC_LOOP)
+   (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850E3V5_UP && TARGET_LOOP"
   {
     switch (which_alternative)
@@ -1349,68 +1459,52 @@ 
 
 ;; Conditional jump instructions
 
-(define_insn "*branch_normal"
+(define_insn_and_split "*cbranchsi4_insn"
   [(set (pc)
-	(if_then_else (match_operator 1 "comparison_operator"
-				      [(cc0) (const_int 0)])
-		      (label_ref (match_operand 0 "" ""))
+	(if_then_else (match_operator 0 "comparison_operator"
+			[(match_operand:SI 1 "register_operand" "r")
+			 (match_operand:SI 2 "reg_or_int5_operand" "rJ")])
+		      (label_ref (match_operand 3 "" ""))
 		      (pc)))]
   ""
-{
-  if (get_attr_length (insn) == 2)
-    return "b%b1 %l0";
-  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
-    return "b%b1 %l0";
-  return "b%B1 .+6 ; jr %l0";
-}
- [(set (attr "length")
-    (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-		      (const_int 256))
-		  (const_int 2)
-		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-		      (const_int 65536))
-		      (const_int 4)
-		      (const_int 6))))])
+  "#"
+  "reload_completed"
+  [(set (reg:CC CC_REGNUM)
+	(compare:CC (match_dup 1) (match_dup 2)))
+   (set (pc)
+	(if_then_else (match_op_dup 0
+			[(reg:CC CC_REGNUM) (const_int 0)])
+		      (label_ref (match_dup 3))
+		      (pc)))]
+  "")
 
-(define_insn "*branch_invert"
+(define_insn "*branch_normal"
   [(set (pc)
 	(if_then_else (match_operator 1 "comparison_operator"
-				      [(cc0) (const_int 0)])
-		      (pc)
-		      (label_ref (match_operand 0 "" ""))))]
-  ""
-{
-  if (get_attr_length (insn) == 2)
-    return "b%B1 %l0";
-
-  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
-    return "b%B1 %l0";
-    
-  return "b%b1 .+6 ; jr %l0";
-}
- [(set (attr "length")
-    (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-		      (const_int 256))
-		  (const_int 2)
-		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-		      (const_int 65536))
-		      (const_int 4)
-		      (const_int 6))))])
-
-(define_insn "branch_z_normal"	
-  [(set (pc)
-	(if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
+				      [(reg CC_REGNUM) (const_int 0)])
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
-  "TARGET_V850E2V3_UP"
+  "reload_completed"
 {
+  bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode;
   if (get_attr_length (insn) == 2)
-    return "bz %l0";
-
+    {
+      if (nzmode)
+	return "b%d1 %l0";
+      else
+	return "b%b1 %l0";
+    }
   if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
-    return "bz %l0";
-
-  return "bnz 1f ; jr %l0 ; 1:";
+    {
+      if (nzmode)
+	return "b%d1 %l0";
+      else
+	return "b%b1 %l0";
+    }
+  if (nzmode)
+    return "b%D1 .+6 ; jr %l0";
+  else
+    return "b%B1 .+6 ; jr %l0";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
@@ -1421,68 +1515,36 @@ 
 		      (const_int 4)
 		      (const_int 6))))])
 
-(define_insn "*branch_z_invert"
+(define_insn "*branch_invert"
   [(set (pc)
-	(if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
+	(if_then_else (match_operator 1 "comparison_operator"
+				      [(reg CC_REGNUM) (const_int 0)])
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))]
-  "TARGET_V850E2V3_UP"
+  "reload_completed"
 {
-  if (get_attr_length (insn) == 2)
-    return "bnz %l0";
-
-  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
-    return "bnz %l0";
-
-  return "bz 1f ; jr %l0 ; 1:";
-}
- [(set (attr "length")
-    (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-			   (const_int 256))
-		  (const_int 2)
-		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-		      (const_int 65536))
-		      (const_int 4)
-		      (const_int 6))))])
+  bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode;
 
-(define_insn "branch_nz_normal"
-  [(set (pc)
-	(if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  "TARGET_V850E2V3_UP"
-{
   if (get_attr_length (insn) == 2)
-    return "bnz %l0";
-
-  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
-    return "bnz %l0";
-
-  return "bz 1f ; jr %l0 ; 1:";
-}
-[(set (attr "length")
-    (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-			   (const_int 256))
-		  (const_int 2)
-		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
-		      (const_int 65536))
-		      (const_int 4)
-		      (const_int 6))))])
-
-(define_insn "*branch_nz_invert"
-  [(set (pc)
-	(if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
-		      (pc)
-		      (label_ref (match_operand 0 "" ""))))]
-  "TARGET_V850E2V3_UP"
-{
-  if (get_attr_length (insn) == 2)
-    return "bz %l0";
+    {
+      if (nzmode)
+	return "b%D1 %l0";
+      else
+	return "b%B1 %l0";
+    }
 
   if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
-    return "bz %l0";
+    {
+      if (nzmode)
+	return "b%D1 %l0";
+      else
+	return "b%B1 %l0";
+    }
 
-  return "bnz 1f ; jr %l0 ; 1:";
+  if (nzmode)
+    return "b%d1 .+6 ; jr %l0";
+  else
+    return "b%b1 .+6 ; jr %l0";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
@@ -1602,6 +1664,7 @@ 
 (define_insn "call_internal_short"
   [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
 	 (match_operand:SI 1 "general_operand" "g,g"))
+   (clobber (reg:CC CC_REGNUM))
    (clobber (reg:SI 31))]
   "! TARGET_LONG_CALLS"
   {
@@ -1620,6 +1683,7 @@ 
 (define_insn "call_internal_long"
   [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
 	 (match_operand:SI 1 "general_operand" "g,g"))
+   (clobber (reg:CC CC_REGNUM))
    (clobber (reg:SI 31))]
   "TARGET_LONG_CALLS"
 {
@@ -1668,6 +1732,7 @@ 
   [(set (match_operand 0 "" "=r,r")
 	(call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
 	      (match_operand:SI 2 "general_operand" "g,g")))
+   (clobber (reg:CC CC_REGNUM))
    (clobber (reg:SI 31))]
   "! TARGET_LONG_CALLS"
   {
@@ -1687,6 +1752,7 @@ 
   [(set (match_operand 0 "" "=r,r")
 	(call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
 	      (match_operand:SI 2 "general_operand" "g,g")))
+   (clobber (reg:CC CC_REGNUM))
    (clobber (reg:SI 31))]
   "TARGET_LONG_CALLS"
 {
@@ -1719,6 +1785,7 @@ 
 ;; EXTEND INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
+;; We only need the CC clobber because of the andi alternative
 (define_insn "*zero_extendhisi2_v850e"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
 	(zero_extend:SI
@@ -1791,8 +1858,7 @@ 
 
 (define_insn "*extendhisi_insn"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
-	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))
-   (clobber (reg:CC CC_REGNUM))]
+	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))]
   "(TARGET_V850E_UP)"
   "@
    sxh %0
@@ -1822,8 +1888,7 @@ 
 
 (define_insn "*extendqisi_insn"
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
-	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))
-   (clobber (reg:CC CC_REGNUM))]
+	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))]
   "(TARGET_V850E_UP)"
   "@
    sxb %0
@@ -1853,7 +1918,18 @@ 
 ;; SHIFTS
 ;; ----------------------------------------------------------------------
 
-(define_insn "ashlsi3"
+(define_insn_and_split "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+      (ashift:SI
+	(match_operand:SI 1 "register_operand" "0,0")
+	(match_operand:SI 2 "nonmemory_operand" "r,N")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "ashlsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
       (ashift:SI
 	(match_operand:SI 1 "register_operand" "0,0")
@@ -1865,7 +1941,7 @@ 
   shl %2,%0"
   [(set_attr "length" "4,2")])
 
-(define_insn "ashlsi3_v850e2"
+(define_insn "ashlsi3_v850e2_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r")
       (ashift:SI
 	(match_operand:SI 1 "register_operand" "r")
@@ -1875,7 +1951,18 @@ 
   "shl %2,%1,%0"
   [(set_attr "length" "4")])
 
-(define_insn "lshrsi3"
+(define_insn_and_split "lshrsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+      (lshiftrt:SI
+	(match_operand:SI 1 "register_operand" "0,0")
+        (match_operand:SI 2 "nonmemory_operand" "r,N")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "lshrsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
       (lshiftrt:SI
 	(match_operand:SI 1 "register_operand" "0,0")
@@ -1887,7 +1974,7 @@ 
   shr %2,%0"
   [(set_attr "length" "4,2")])
 
-(define_insn "lshrsi3_v850e2"
+(define_insn "lshrsi3_v850e2_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r")
       (lshiftrt:SI
 	(match_operand:SI 1 "register_operand" "r")
@@ -1897,7 +1984,18 @@ 
   "shr %2,%1,%0"
   [(set_attr "length" "4")])
 
-(define_insn "ashrsi3"
+(define_insn_and_split "ashrsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+      (ashiftrt:SI
+	(match_operand:SI 1 "register_operand" "0,0")
+	(match_operand:SI 2 "nonmemory_operand" "r,N")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn "ashrsi3_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
       (ashiftrt:SI
 	(match_operand:SI 1 "register_operand" "0,0")
@@ -1909,7 +2007,7 @@ 
   sar %2,%0"
   [(set_attr "length" "4,2")])
 
-(define_insn "ashrsi3_v850e2"
+(define_insn "ashrsi3_v850e2_clobber_flags"
   [(set (match_operand:SI 0 "register_operand" "=r")
       (ashiftrt:SI
 	(match_operand:SI 1 "register_operand" "r")
@@ -2279,6 +2377,8 @@ 
 ;; ---------------- special insns
 ;;
 
+;; reciprocal
+
 ;; Generic code demands that the recip and rsqrt named patterns
 ;; have precisely one operand.  So that's what we expose in the
 ;; expander via the strange UNSPEC.  However, those expanders
@@ -2417,7 +2517,7 @@ 
   [(set (reg:CC_FPU_LE FCC_REGNUM)
         (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.s le, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2426,7 +2526,7 @@ 
   [(set (reg:CC_FPU_LT FCC_REGNUM)
         (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.s lt, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2435,7 +2535,7 @@ 
   [(set (reg:CC_FPU_GE FCC_REGNUM)
         (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.s le, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2444,7 +2544,7 @@ 
   [(set (reg:CC_FPU_GT FCC_REGNUM)
         (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.s lt, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2453,7 +2553,7 @@ 
   [(set (reg:CC_FPU_EQ FCC_REGNUM)
         (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r")
 			   (match_operand:SF 1 "register_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.s eq, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2464,7 +2564,7 @@ 
   [(set (reg:CC_FPU_LE FCC_REGNUM)
         (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.d le, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2473,7 +2573,7 @@ 
   [(set (reg:CC_FPU_LT FCC_REGNUM)
         (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.d lt, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2482,7 +2582,7 @@ 
   [(set (reg:CC_FPU_GE FCC_REGNUM)
         (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.d le, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2491,7 +2591,7 @@ 
   [(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")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.d lt, %z1, %z0"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2500,7 +2600,7 @@ 
   [(set (reg:CC_FPU_EQ FCC_REGNUM)
         (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r")
 			   (match_operand:DF 1 "even_reg_operand" "r")))]
-  "TARGET_USE_FPU"
+  "reload_completed && TARGET_USE_FPU"
   "cmpf.d eq, %z0, %z1"
   [(set_attr "length" "4")
    (set_attr "type" "fpu")])
@@ -2512,7 +2612,8 @@ 
 
 (define_insn "trfsr"
   [(set (match_operand 0 "" "") (match_operand 1 "" ""))]
-  "TARGET_USE_FPU
+  "reload_completed
+   && TARGET_USE_FPU
    && GET_MODE(operands[0]) == GET_MODE(operands[1])
    && GET_CODE(operands[0]) == REG && REGNO (operands[0]) == CC_REGNUM
    && GET_CODE(operands[1]) == REG && REGNO (operands[1]) == FCC_REGNUM
@@ -2668,7 +2769,8 @@ 
 
 ;; Initialize an interrupt function.  Do not depend on TARGET_PROLOG_FUNCTION.
 (define_insn "callt_save_interrupt"
-  [(unspec_volatile [(const_int 0)] 2)]
+  [(unspec_volatile [(const_int 0)] 2)
+   (clobber (reg:CC CC_REGNUM))]
     "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
     ;; The CALLT instruction stores the next address of CALLT to CTPC register
     ;; without saving its previous value.  So if the interrupt handler
@@ -2689,7 +2791,8 @@ 
    [(set_attr "length" "26")])
 
 (define_insn "callt_return_interrupt"
-  [(unspec_volatile [(const_int 0)] 3)]
+  [(unspec_volatile [(const_int 0)] 3)
+   (clobber (reg:CC CC_REGNUM))]
   "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
   "callt ctoff(__callt_return_interrupt)"
   [(set_attr "length" "2")])
@@ -2700,7 +2803,8 @@ 
    (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 4))
    (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))
    (set (mem:SI (plus:SI (reg:SI 3) (const_int  -8))) (reg:SI 10))
-   (set (mem:SI (plus:SI (reg:SI 3) (const_int  -4))) (reg:SI 11))]
+   (set (mem:SI (plus:SI (reg:SI 3) (const_int  -4))) (reg:SI 11))
+   (clobber (reg:CC CC_REGNUM))]
   ""
 {
   if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
@@ -2733,7 +2837,8 @@ 
    (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
    (set (reg:SI 1)  (mem:SI (plus:SI (reg:SI 3) (const_int  8))))
    (set (reg:SI 4)  (mem:SI (plus:SI (reg:SI 3) (const_int  4))))
-   (set (reg:SI 30) (mem:SI (reg:SI 3)))]
+   (set (reg:SI 30) (mem:SI (reg:SI 3)))
+   (clobber (reg:CC CC_REGNUM))]
   ""
 {
   if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
@@ -2763,13 +2868,15 @@ 
 ;; insns this complicated.
 
 (define_insn "callt_save_all_interrupt"
-  [(unspec_volatile [(const_int 0)] 0)]
+  [(unspec_volatile [(const_int 0)] 0)
+   (clobber (reg:CC CC_REGNUM))]
   "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
   "callt ctoff(__callt_save_all_interrupt)"
   [(set_attr "length" "2")])
 
 (define_insn "save_all_interrupt"
-  [(unspec_volatile [(const_int 0)] 0)]
+  [(unspec_volatile [(const_int 0)] 0)
+   (clobber (reg:CC CC_REGNUM))]
   ""
 {
   if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
@@ -2844,10 +2951,12 @@ 
   [(set (attr "length")
         (if_then_else (match_test "TARGET_LONG_CALLS")
                        (const_int 4)
-                       (const_int 62)))])
+                       (const_int 62)
+	))])
 
 (define_insn "_save_all_interrupt"
-  [(unspec_volatile [(const_int 0)] 0)]
+  [(unspec_volatile [(const_int 0)] 0)
+   (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850 && ! TARGET_LONG_CALLS"
   "jarl __save_all_interrupt,r10"
   [(set_attr "length" "4")])
@@ -2859,13 +2968,15 @@ 
 ;; insns this complicated.
 
 (define_insn "callt_restore_all_interrupt"
-  [(unspec_volatile [(const_int 0)] 1)]
+  [(unspec_volatile [(const_int 0)] 1)
+   (clobber (reg:CC CC_REGNUM))]
   "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
   "callt ctoff(__callt_restore_all_interrupt)"
   [(set_attr "length" "2")])
 
 (define_insn "restore_all_interrupt"
-  [(unspec_volatile [(const_int 0)] 1)]
+  [(unspec_volatile [(const_int 0)] 1)
+   (clobber (reg:CC CC_REGNUM))]
   ""
 {
   if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
@@ -2942,7 +3053,8 @@ 
 	))])
 
 (define_insn "_restore_all_interrupt"
-  [(unspec_volatile [(const_int 0)] 1)]
+  [(unspec_volatile [(const_int 0)] 1)
+   (clobber (reg:CC CC_REGNUM))]
   "TARGET_V850 && ! TARGET_LONG_CALLS"
   "jarl __restore_all_interrupt,r10"
   [(set_attr "length" "4")])