v850-protos.h (notice_update_cc): Remove.
authorJeff Law <law@redhat.com>
Wed, 27 Jun 2018 18:31:10 +0000 (12:31 -0600)
committerJeff Law <law@gcc.gnu.org>
Wed, 27 Jun 2018 18:31:10 +0000 (12:31 -0600)
* 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.

Co-Authored-By: Austin Law <austinklaw@gmail.com>
From-SVN: r262190

gcc/ChangeLog
gcc/config/v850/v850-protos.h
gcc/config/v850/v850.c
gcc/config/v850/v850.h
gcc/config/v850/v850.md

index d9abfff5d0c771403c6ad9481225a7440dabd34c..9cd59b2723659ee5e758b97699093be09409fbe7 100644 (file)
@@ -1,6 +1,55 @@
 2018-06-27  Jeff Law  <law@redhat.com>
            Austin Law  <austinklaw@gmail.com>
 
+       * 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.
+
        * config/v850/v850-modes.def (CCZ, CCNZ): Add new modes.
        * config/v850/v850.c (notice_update_cc): Remove.
        * config/v850/v850.h  (CC_OVERFLOW_UNUSABLE): Remove
index e8ff280f83da5a19558a8e87b1483c1aaa3fc344..ca99703248b65e171c01668ccbdfa78cd538126e 100644 (file)
@@ -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
index e184718e1ef02f9a0b5ddb390eea42ce1e17039d..cb2debf46f17b6a74011e2ed756c21d7466e08c8 100644 (file)
@@ -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"
index 96bddc25801338e7453b6bba54c630ab91061eb6..04d226a8e05d823c44971c3e8b212e947feb977a 100644 (file)
@@ -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
index 0fad9ea501dec8e003f2baa615dffc7f3326d3b4..3cfec74324f6c985aa4129a57b1e3e6ce3afb435 100644 (file)
 ;;
 ;; 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.
 
 ;; ----------------------------------------------------------------------
 
 (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)
   [(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)
   [(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
 ;; ----------------------------------------------------------------------
 ;; 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")))
   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))]
                (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")])
 
                 (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")])
 \f
   [(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
   [(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")))
   [(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")))
   xor %.,%0
   xori %2,%1,%0"
   [(set_attr "length" "2,2,4")])
+
 \f
 ;; ----------------------------------------------------------------------
 ;; 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))]
   [(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")])
 ;; 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"
       }
   })
 
-;; ??? 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
                          [(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")])
 
                          [(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"
         (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
                           (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
                           (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")])
 ;; 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
        [(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")])
        [(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")])
   }
 )
 
+;; 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)
 
 ;; 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)))
                      (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)))
 (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"
   {
 (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"
 {
   [(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"
   {
   [(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"
 {
 ;; 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
 
 (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
 
 (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
 ;; 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")
   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")
   "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")
   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")
   "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")
   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")
 ;; ---------------- 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
   [(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")])
   [(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")])
   [(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")])
   [(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")])
   [(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")])
   [(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")])
   [(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")])
   [(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")])
   [(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")])
   [(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")])
 
 (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
 
 ;; 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
    [(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")])
    (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)
    (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)
 ;; 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)
   [(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")])
 ;; 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)
        ))])
 
 (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")])