diff mbox series

[30/31] PR target/95294: VAX: Convert backend to MODE_CC representation

Message ID alpine.LFD.2.21.2011200302400.656242@eddie.linux-mips.org
State Accepted
Headers show
Series VAX: Bring the port up to date (yes, MODE_CC conversion is included) | expand

Commit Message

Maciej W. Rozycki Nov. 20, 2020, 3:36 a.m. UTC
In the VAX ISA INSV bitfield insert instruction is the only computational
operation that keeps the condition codes, held in the PSL or Processor
Status Longword register, intact.  The instruction is flexible enough it
could potentially be used for data moves post-reload, but then reportedly
it is not the best choice performance-wise, and then we have no addition
operation available that would keep the condition codes unchanged.

Futhermore, as usually with a complex CISC ISA, for many operations we
have several machine instructions or instruction sequences to choose
from that set condition codes in a different manner.

Use the approach then where the condition codes only get introduced by
reload, by definining instruction splitters for RTL insns that change
condition codes in some way, by default considering them clobbered.

Then to prevent code generated from regressing too much provide insns
that include a `compare' operation setting the condition codes in
parallel to the main operation.  The manner condition codes are set by
each insn is supposed to be provided by the whatever the SELECT_CC_MODE
macro expands to.

Given that individual patterns provided for the same RTL basic operation
may set the condion codes differently keeping the information away from
the insn patterns themselves would cause a maintenance nightmare and
would be bound to fail in a horrible way sooner or later.  Therefore
instead let the patterns themselves choose which condition modes they
support, by having one or more subst iterators applied and then have
individual comparison operators require the specific condition mode each
according to the codes used by the operation.

While subst iterators only support one alternative each, there is
actually no problem with applying multiple ones to a single insn with
the result as intended, and if the corresponding subst attribute
supplies an empty NO-SUBST-VALUE, then no mess results even.  Make use
of this observation.

Add appropriate subst iterators to all the computational patterns then,
according to the condition codes they usably set, including DImode ones
and a substitute DImode comparison instruction in the absence of a CMPQ
machine instruction, however do not provide a `cbranchdi4' named pattern
as without a further development it regresses code quality by resorting
to the `__cmpdi2' libcall where a simpler operation would do, e.g. to
check for negativity the TSTL machine instruction may be executed over
the upper longword only.  This is good material for further work.

Do not apply subst iterators to the increment- or decrement-and-branch
patterns at this time; these may yet have to be reviewed, in particular
whether `*jsobneq_minus_one' is still relevant in the context of the
recent integer constant cost review.

Also add a couple of peepholes to help eliminating comparisons in some
problematic cases, such as with the BIT instruction which is bitwise-AND
for condition codes only that has no direct counterpart for the actual
calculation, because the BIC instruction which does do bitwise-AND and
produces a result implements the operation with a bitwise negation of
its input `mask' operand.  Or the FFS instruction which sets the Z
condition code according to its `field' input operand rather than the
result produced.  Or the bitfield comparisons we don't have generic
middle-end support for.

Code size stats are as follows, obtained from 17640 and 9086 executables
built in `check-c' and `check-c++' GCC testing respectively:

                      check-c                 check-c++
              samples average  median  samples average  median
---------------------------------------------------------------
regressions      1813  0.578%  0.198%      289  0.349%  0.175%
unchanged       15160  0.000%  0.000%     8662  0.000%  0.000%
progressions      667 -0.589% -0.194%      135 -0.944% -0.191%
----------------------------------------------------------------
total           17640  0.037%  0.000%     9086 -0.003%  0.000%

Outliers:

old     new     change  %change filename
----------------------------------------------------
2406    2950    +544    +22.610 20111208-1.exe
4314    5329    +1015   +23.528 pr39417.exe
2235    3055    +820    +36.689 990404-1.exe
2631    4213    +1582   +60.129 pr57521.exe
3063    5579    +2516   +82.142 20000422-1.exe

and:

old     new     change  %change filename
----------------------------------------------------
6317    4845    -1472   -23.302 vector-compare-1.exe
6313    4845    -1468   -23.254 vector-compare-1.exe
6474    5002    -1472   -22.737 vector-compare-1.exe
6470    5002    -1468   -22.689 vector-compare-1.exe

We have some code quality regressions like:

    10861:	9e ef d9 12 	movab 11b40 <p>,r0
    10865:	00 00 50
    10868:	90 a0 03 a0 	movb 0x3(r0),0x2(r0)
    1086c:	02
    1086d:	d1 60 8f 61 	cmpl (r0),$0x64646261
    10871:	62 64 64
    10874:	13 07 		beql 1087d <main_test+0x21>

to:

    10861:	9e ef e1 12	movab 11b48 <p>,r0
    10865:	00 00 50
    10868:	90 a0 03 a0 	movb 0x3(r0),0x2(r0)
    1086c:	02
    1086d:	d1 ef d5 12 	cmpl 11b48 <p>,$0x64646261
    10871:	00 00 8f 61
    10875:	62 64 64
    10878:	13 07 		beql 10881 <main_test+0x25>

(from `memmove-2.x2') due to the constant propagation passes eagerly
replacing pseudo registers with direct symbol references where possible,
which does not happen with CC0 even though the passes do run regardless.

There are further code quality regressions due to earlier compilation
stages trying to push expression evaluation earlier where possible so
as to make data dependencies further apart from each other.  This works
well for computations and architectures that do not involve condition
codes set as a side effect of calculations.  However for integer
negation that makes assembly code produced like:

	movb *8(%ap),%r0
	mnegb %r0,%r1
	tstb %r0
	jeql .L2

the RTL equibvalent of which the comparison elimination pass cannot
really do anything about, because the comparison is made on the source
rather than the target operand of the negation (we could add a peephole
for this, but this seems futile an effort, as one'd have to iterate over
all the possible such cases), even though this is really equivalent to:

	movb *8(%ap),%r0
	mnegb %r0,%r1
	jeql .L2

or, if R0 is dead at the conclusion of the branch, even:

	mnegb *8(%ap),%r1
	jeql .L2

Since the compiler insists on doing the comparison on the source of the
negation it obviously has to load it into a temporary so as to avoid
accessing the original memory location twice, hence the sequence of
three instructions rather than just a single one.  A similar phenomenon
can be observed with the XOR operation and in other cases.

In some cases a comparison does get eliminated, however useless moves
into registers done in preparation to it remain, such as with:

	movb *8(%ap),%r2
	movb *12(%ap),%r1
	subb3 %r1,%r2,%r0
	jlssu .L2

where R1 and R2 are both dead at conclusion and therefore:

	subb3 *12(%ap),*8(%ap),%r0
	jlssu .L2

would obviously do, but there was to be a comparison before the branch:

	cmpb %r2,%r1

All this looks like material for future improvement.

Test cases for comparison elimination and the peepholes will be supplied
separately.

	gcc/
	PR target/95294
	* config/vax/elf.h (REGISTER_NAMES): Append `%psl'.
	* config/vax/vax-modes.def (CCN, CCNZ, CCZ): New modes.
	* config/vax/vax-protos.h (vax_select_cc_mode): New prototype.
	(vax_maybe_split_dimode_move): Likewise.
	(vax_notice_update_cc): Remove prototype.
	* config/vax/vax.c (TARGET_FLAGS_REGNUM): New macro.
	(TARGET_CC_MODES_COMPATIBLE): Likewise.
	(TARGET_MD_ASM_ADJUST): Likewise.
	(vax_select_cc_mode): New function
	(vax_cc_modes_compatible): Likewise.
	(vax_md_asm_adjust): Likewise.
	(vax_notice_update_cc): Remove function.
	(vax_output_int_move): Factor out code checking if a DImode move
	may have to be split...
	(vax_maybe_split_dimode_move): ... into this new function.
	* config/vax/vax.h (FIRST_PSEUDO_REGISTER): Bump up.
	(FIXED_REGISTERS): Append an entry for PSL.
	(CALL_USED_REGISTERS): Likewise.
	(NOTICE_UPDATE_CC, OUTPUT_JUMP): Remove macros.
	(SELECT_CC_MODE): New macro.
	(REGISTER_NAMES): Append `psl'.
	* config/vax/predicates.md (const_zero_operand)
	(vax_cc_comparison_operator, vax_ccn_comparison_operator)
	(vax_ccnz_comparison_operator, vax_ccz_comparison_operator):
	New predicates.
	* config/vax/builtins.md: Rewrite for MODE_CC representation.
	* config/vax/vax.md: Likewise.
---
 gcc/config/vax/builtins.md   |  109 ++-
 gcc/config/vax/elf.h         |    3 +-
 gcc/config/vax/predicates.md |   20 +
 gcc/config/vax/vax-modes.def |   11 +
 gcc/config/vax/vax-protos.h  |    3 +-
 gcc/config/vax/vax.c         |  203 +++--
 gcc/config/vax/vax.h         |   32 +-
 gcc/config/vax/vax.md        | 1788 ++++++++++++++++++++++++++++++++++++++----
 8 files changed, 1904 insertions(+), 265 deletions(-)

Comments

Jeff Law Nov. 22, 2020, 3:27 a.m. UTC | #1
On 11/19/20 8:36 PM, Maciej W. Rozycki wrote:
> In the VAX ISA INSV bitfield insert instruction is the only computational
> operation that keeps the condition codes, held in the PSL or Processor
> Status Longword register, intact.  The instruction is flexible enough it
> could potentially be used for data moves post-reload, but then reportedly
> it is not the best choice performance-wise, and then we have no addition
> operation available that would keep the condition codes unchanged.
>
> Futhermore, as usually with a complex CISC ISA, for many operations we
> have several machine instructions or instruction sequences to choose
> from that set condition codes in a different manner.
>
> Use the approach then where the condition codes only get introduced by
> reload, by definining instruction splitters for RTL insns that change
> condition codes in some way, by default considering them clobbered.
>
> Then to prevent code generated from regressing too much provide insns
> that include a `compare' operation setting the condition codes in
> parallel to the main operation.  The manner condition codes are set by
> each insn is supposed to be provided by the whatever the SELECT_CC_MODE
> macro expands to.
>
> Given that individual patterns provided for the same RTL basic operation
> may set the condion codes differently keeping the information away from
> the insn patterns themselves would cause a maintenance nightmare and
> would be bound to fail in a horrible way sooner or later.  Therefore
> instead let the patterns themselves choose which condition modes they
> support, by having one or more subst iterators applied and then have
> individual comparison operators require the specific condition mode each
> according to the codes used by the operation.
>
> While subst iterators only support one alternative each, there is
> actually no problem with applying multiple ones to a single insn with
> the result as intended, and if the corresponding subst attribute
> supplies an empty NO-SUBST-VALUE, then no mess results even.  Make use
> of this observation.
>
> Add appropriate subst iterators to all the computational patterns then,
> according to the condition codes they usably set, including DImode ones
> and a substitute DImode comparison instruction in the absence of a CMPQ
> machine instruction, however do not provide a `cbranchdi4' named pattern
> as without a further development it regresses code quality by resorting
> to the `__cmpdi2' libcall where a simpler operation would do, e.g. to
> check for negativity the TSTL machine instruction may be executed over
> the upper longword only.  This is good material for further work.
>
> Do not apply subst iterators to the increment- or decrement-and-branch
> patterns at this time; these may yet have to be reviewed, in particular
> whether `*jsobneq_minus_one' is still relevant in the context of the
> recent integer constant cost review.
>
> Also add a couple of peepholes to help eliminating comparisons in some
> problematic cases, such as with the BIT instruction which is bitwise-AND
> for condition codes only that has no direct counterpart for the actual
> calculation, because the BIC instruction which does do bitwise-AND and
> produces a result implements the operation with a bitwise negation of
> its input `mask' operand.  Or the FFS instruction which sets the Z
> condition code according to its `field' input operand rather than the
> result produced.  Or the bitfield comparisons we don't have generic
> middle-end support for.
>
> Code size stats are as follows, obtained from 17640 and 9086 executables
> built in `check-c' and `check-c++' GCC testing respectively:
>
>                       check-c                 check-c++
>               samples average  median  samples average  median
> ---------------------------------------------------------------
> regressions      1813  0.578%  0.198%      289  0.349%  0.175%
> unchanged       15160  0.000%  0.000%     8662  0.000%  0.000%
> progressions      667 -0.589% -0.194%      135 -0.944% -0.191%
> ----------------------------------------------------------------
> total           17640  0.037%  0.000%     9086 -0.003%  0.000%
>
> Outliers:
>
> old     new     change  %change filename
> ----------------------------------------------------
> 2406    2950    +544    +22.610 20111208-1.exe
> 4314    5329    +1015   +23.528 pr39417.exe
> 2235    3055    +820    +36.689 990404-1.exe
> 2631    4213    +1582   +60.129 pr57521.exe
> 3063    5579    +2516   +82.142 20000422-1.exe
>
> and:
>
> old     new     change  %change filename
> ----------------------------------------------------
> 6317    4845    -1472   -23.302 vector-compare-1.exe
> 6313    4845    -1468   -23.254 vector-compare-1.exe
> 6474    5002    -1472   -22.737 vector-compare-1.exe
> 6470    5002    -1468   -22.689 vector-compare-1.exe
>
> We have some code quality regressions like:
>
>     10861:	9e ef d9 12 	movab 11b40 <p>,r0
>     10865:	00 00 50
>     10868:	90 a0 03 a0 	movb 0x3(r0),0x2(r0)
>     1086c:	02
>     1086d:	d1 60 8f 61 	cmpl (r0),$0x64646261
>     10871:	62 64 64
>     10874:	13 07 		beql 1087d <main_test+0x21>
>
> to:
>
>     10861:	9e ef e1 12	movab 11b48 <p>,r0
>     10865:	00 00 50
>     10868:	90 a0 03 a0 	movb 0x3(r0),0x2(r0)
>     1086c:	02
>     1086d:	d1 ef d5 12 	cmpl 11b48 <p>,$0x64646261
>     10871:	00 00 8f 61
>     10875:	62 64 64
>     10878:	13 07 		beql 10881 <main_test+0x25>
>
> (from `memmove-2.x2') due to the constant propagation passes eagerly
> replacing pseudo registers with direct symbol references where possible,
> which does not happen with CC0 even though the passes do run regardless.
>
> There are further code quality regressions due to earlier compilation
> stages trying to push expression evaluation earlier where possible so
> as to make data dependencies further apart from each other.  This works
> well for computations and architectures that do not involve condition
> codes set as a side effect of calculations.  However for integer
> negation that makes assembly code produced like:
>
> 	movb *8(%ap),%r0
> 	mnegb %r0,%r1
> 	tstb %r0
> 	jeql .L2
>
> the RTL equibvalent of which the comparison elimination pass cannot
> really do anything about, because the comparison is made on the source
> rather than the target operand of the negation (we could add a peephole
> for this, but this seems futile an effort, as one'd have to iterate over
> all the possible such cases), even though this is really equivalent to:
>
> 	movb *8(%ap),%r0
> 	mnegb %r0,%r1
> 	jeql .L2
>
> or, if R0 is dead at the conclusion of the branch, even:
>
> 	mnegb *8(%ap),%r1
> 	jeql .L2
>
> Since the compiler insists on doing the comparison on the source of the
> negation it obviously has to load it into a temporary so as to avoid
> accessing the original memory location twice, hence the sequence of
> three instructions rather than just a single one.  A similar phenomenon
> can be observed with the XOR operation and in other cases.
>
> In some cases a comparison does get eliminated, however useless moves
> into registers done in preparation to it remain, such as with:
>
> 	movb *8(%ap),%r2
> 	movb *12(%ap),%r1
> 	subb3 %r1,%r2,%r0
> 	jlssu .L2
>
> where R1 and R2 are both dead at conclusion and therefore:
>
> 	subb3 *12(%ap),*8(%ap),%r0
> 	jlssu .L2
>
> would obviously do, but there was to be a comparison before the branch:
>
> 	cmpb %r2,%r1
>
> All this looks like material for future improvement.
>
> Test cases for comparison elimination and the peepholes will be supplied
> separately.
>
> 	gcc/
> 	PR target/95294
> 	* config/vax/elf.h (REGISTER_NAMES): Append `%psl'.
> 	* config/vax/vax-modes.def (CCN, CCNZ, CCZ): New modes.
> 	* config/vax/vax-protos.h (vax_select_cc_mode): New prototype.
> 	(vax_maybe_split_dimode_move): Likewise.
> 	(vax_notice_update_cc): Remove prototype.
> 	* config/vax/vax.c (TARGET_FLAGS_REGNUM): New macro.
> 	(TARGET_CC_MODES_COMPATIBLE): Likewise.
> 	(TARGET_MD_ASM_ADJUST): Likewise.
> 	(vax_select_cc_mode): New function
> 	(vax_cc_modes_compatible): Likewise.
> 	(vax_md_asm_adjust): Likewise.
> 	(vax_notice_update_cc): Remove function.
> 	(vax_output_int_move): Factor out code checking if a DImode move
> 	may have to be split...
> 	(vax_maybe_split_dimode_move): ... into this new function.
> 	* config/vax/vax.h (FIRST_PSEUDO_REGISTER): Bump up.
> 	(FIXED_REGISTERS): Append an entry for PSL.
> 	(CALL_USED_REGISTERS): Likewise.
> 	(NOTICE_UPDATE_CC, OUTPUT_JUMP): Remove macros.
> 	(SELECT_CC_MODE): New macro.
> 	(REGISTER_NAMES): Append `psl'.
> 	* config/vax/predicates.md (const_zero_operand)
> 	(vax_cc_comparison_operator, vax_ccn_comparison_operator)
> 	(vax_ccnz_comparison_operator, vax_ccz_comparison_operator):
> 	New predicates.
> 	* config/vax/builtins.md: Rewrite for MODE_CC representation.
> 	* config/vax/vax.md: Likewise.
So I just spot-checked this and the bits I looked at were quite sane. 
Given that and the fact that the port is on the chopping block if we
don't get the conversion done, I think it is fine to ACK this now and if
we want to iterate on things further we certainly can.

Jeff
Maciej W. Rozycki Dec. 9, 2020, 4:09 p.m. UTC | #2
On Fri, 20 Nov 2020, Maciej W. Rozycki wrote:

> Outliers:
> 
> old     new     change  %change filename
> ----------------------------------------------------
> 2406    2950    +544    +22.610 20111208-1.exe
> 4314    5329    +1015   +23.528 pr39417.exe
> 2235    3055    +820    +36.689 990404-1.exe
> 2631    4213    +1582   +60.129 pr57521.exe
> 3063    5579    +2516   +82.142 20000422-1.exe

 So as a matter of interest I have actually looked into the worst offender 
shown above.  As I have just learnt by chance, GNU `size' in its default 
BSD mode reports code combined with rodata as text, so I have rerun it in 
the recently introduced GNU mode with `20000422-1.exe' and the results are 
worse yet:

       text       data        bss      total filename
-      1985       1466         68       3519 ./20000422-1.exe
+      4501       1466         68       6035 ./20000422-1.exe

However upon actual inspection code produced looks sound and it's just 
that the loops the test case has get unrolled further.  With speed 
optimisation this is not necessarily bad.  Mind that the options used for 
this particular compilation are `-O3 -fomit-frame-pointer -funroll-loops 
-fpeel-loops -ftracer -finline-functions' meaning that, well, ahem, we do 
want loops to get unrolled and we want speed rather than size.  So all is 
well.

 I have tried to run some benchmarking with this test case, by putting all 
the files involved in tmpfs (i.e. RAM) so as to limit any I/O influence 
and looping the executable 1000 times, which yielded elapsed times of 
around 340s, i.e. with a good resolution, but results are inconclusive and 
the execution time oscillates on individual runs around the value shown, 
regardless of whether this change has been applied or not.

 So I have to conclude that either both variants of code are virtually 
equivalent in terms of performance or that the test environment keeps 
execution I/O-bound despite the measures I have taken.  Sadly the VAX 
architecture does not provide a user-accessible cycle count (I would know 
of) that could be used for more accurate measurements, and I do not feel 
right now like fiddling with the code of the test case any further so as 
to make it more suited for performance evaluation.

 I have to note however on this occasion that this part of the change:

-(define_insn "*cmp<mode>"
-  [(set (cc0)
-	(compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT,nrmT")
-		 (match_operand:VAXint 1 "general_operand" "I,nrmT")))]
+(define_insn "*cmp<VAXint:mode>_<VAXcc:mode>"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc (match_operand:VAXint 0 "general_operand" "nrmT,nrmT")
+		       (match_operand:VAXint 1 "general_operand" "I,nrmT")))]

which allowed an immediate with operand #0 has improved code generation a 
little bit with this test case as well, because rather than this:

	clrl %r0
[...]
	cmpl %r0,%r1
[...]
	cmpl %r0,%r3
[...]

this:

	cmpl $0,%r1
[...]
	cmpl $0,%r3
[...]

is produced, which does not waste a register to hold the value of 0 which 
can be supplied in the literal addressing mode, i.e. with the operand 
specifier byte itself just like with register operands, and therefore does 
not require extra space or execution time.

 I don't know however why the middle end insists on supplying constant 0 
as operand #0 to the comparison operation (or the `cbranch4' insn it has 
originated from).  While we have machine support for such a comparison, 
having constant 0 supplied as operand #1 would permit the use of the TST 
instruction, one byte shorter.  Of course that would require reversing the 
condition of any branches using the output of the comparison, but unlike 
typical RISC ISAs the VAX ISA supports all the conditions as does our MD.

 Oddly enough making constant 0 more expensive in operand #0 than in 
operand #1 for comparison operations or COMPARE does not persuade the 
middle end to try and swap the operands, and making the `cbranch4' insns 
reject an immediate in operand #0 only makes reload put it back in a 
register.  All this despite COMPARE documentation saying:

    "If one of the operands is a constant, it should be placed in the
     second operand and the comparison code adjusted as appropriate."

So this looks like a missed optimisation and something to investigate at 
one point.

 Also, interestingly, we have this comment in our MD:

;; The VAX move instructions have space-time tradeoffs.  On a MicroVAX
;; register-register mov instructions take 3 bytes and 2 CPU cycles.  clrl
;; takes 2 bytes and 3 cycles.  mov from constant to register takes 2 cycles
;; if the constant is smaller than 4 bytes, 3 cycles for a longword
;; constant.  movz, mneg, and mcom are as fast as mov, so movzwl is faster
;; than movl for positive constants that fit in 16 bits but not 6 bits.  cvt
;; instructions take 4 cycles.  inc takes 3 cycles.  The machine description
;; is willing to trade 1 byte for 1 cycle (clrl instead of movl $0; cvtwl
;; instead of movl).

which clearly states that the cost of a const 0 rtx varies depending on 
whether it is implied as with the CLR instruction or explicitly encoded as 
with MOV.  This must surely be true for the MicroVAX microarchitecture 
referred.  Which I gather however must have been solely microcoded unlike 
at least some later implementations such as the NVAX, which used a mixed 
pipeline/microcode microarchitecture familiar to many from modern x86 
processors.  I doubt with such an implementation an implicit 0 operand 
would require an extra machine clock for execution.  Which means we'd 
better review the costs at some point and make them model-specific.

  Maciej
diff mbox series

Patch

diff --git a/gcc/config/vax/builtins.md b/gcc/config/vax/builtins.md
index e96ac3f52ab..846d1f352ff 100644
--- a/gcc/config/vax/builtins.md
+++ b/gcc/config/vax/builtins.md
@@ -39,10 +39,10 @@  (define_expand "ffs<mode>2"
 {
   rtx label = gen_label_rtx ();
   rtx label_ref = gen_rtx_LABEL_REF (VOIDmode, label);
-  rtx cond = gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx);
+  rtx cond = gen_rtx_NE (VOIDmode, operands[1], const0_rtx);
   rtx target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label_ref, pc_rtx);
 
-  emit_insn (gen_ctz<mode>2 (operands[0], operands[1]));
+  emit_insn (gen_ctz<mode>2_ccz (operands[0], operands[1]));
   emit_jump_insn (gen_rtx_SET (pc_rtx, target));
   emit_insn (gen_neg<mode>2 (operands[0], const1_rtx));
   emit_label (label);
@@ -50,33 +50,114 @@  (define_expand "ffs<mode>2"
   DONE;
 }")
 
-(define_insn "ctz<mode>2"
+(define_insn_and_split "ctz<mode>2"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
+	(ctz:SI (match_operand:VAXint 1 "general_operand" "nrQT")))]
+  ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ctz:SI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ctz<mode>2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
 	(ctz:SI (match_operand:VAXint 1 "general_operand" "nrQT")))
-   (set (cc0)
-	(compare (match_dup 1)
-		 (const_int 0)))]
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
+  "ffs $0,$<width>,%1,%0")
+
+(define_insn_and_split "ctz<mode>2_ccz"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
+	(ctz:SI (match_operand:VAXint 1 "general_operand" "nrQT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (reg:CCZ VAX_PSL_REGNUM)
+	   (compare:CCZ (match_dup 1)
+			(const_int 0)))
+      (set (match_dup 0)
+	   (ctz:SI (match_dup 1)))])]
+  "")
+
+(define_insn "*ctz<mode>2_ccz"
+  [(set (reg:CCZ VAX_PSL_REGNUM)
+	(compare:CCZ (match_operand:VAXint 1 "general_operand" "nrQT")
+		     (const_int 0)))
+   (set (match_operand:SI 0 "nonimmediate_operand" "=rQ")
+	(ctz:SI (match_dup 1)))]
+  "reload_completed"
   "ffs $0,$<width>,%1,%0")
 
 ;; Our FFS hardware instruction supports any field width,
 ;; so handle narrower inputs directly as well.
 (define_peephole2
-  [(set (match_operand:SI 0 "register_operand")
-        (any_extend:SI (match_operand:VAXintQH 1 "general_operand")))
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand")
+	   (any_extend:SI (match_operand:VAXintQH 1 "general_operand")))
+      (clobber (reg:CC VAX_PSL_REGNUM))])
    (parallel
      [(set (match_operand:SI 2 "nonimmediate_operand")
 	   (ctz:SI (match_dup 0)))
-      (set (cc0)
-	   (compare (match_dup 2)
-		    (const_int 0)))])]
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
   "rtx_equal_p (operands[0], operands[2]) || peep2_reg_dead_p (2, operands[0])"
   [(parallel
      [(set (match_dup 2)
 	   (ctz:SI (match_dup 1)))
-      (set (cc0)
-	   (compare (match_dup 1)
-		    (const_int 0)))])]
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+;; The FFS hardware instruction sets the Z condition code based on
+;; the input field rather than the output operand, so the compare
+;; elimination pass cannot handle it.  Try to get rid of the extra
+;; operation by hand.
+;;
+;; The "ctz<mode>2_ccz" patterns require their `operands[1]' not to
+;; have a mode dependent address, so all we need to verify is that
+;; the two operands are not the same, in which case it's the FFS
+;; output rather than input that condition codes are checked for.
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "nonimmediate_operand")
+	   (ctz:SI (match_operand:VAXint 1 "general_operand")))
+      (clobber (reg:CC VAX_PSL_REGNUM))])
+   (set (reg:CCZ VAX_PSL_REGNUM)
+	(compare:CCZ (match_dup 1)
+		     (const_int 0)))]
+  "!rtx_equal_p (operands[0], operands[1])"
+  [(parallel
+     [(set (reg:CCZ VAX_PSL_REGNUM)
+	   (compare:CCZ (match_dup 1)
+			(const_int 0)))
+      (set (match_dup 0)
+	   (ctz:SI (match_dup 1)))])]
+  "")
+
+;; This effectively combines the two peepholes above,
+;; matching the sequence produced by `ffs<mode>2'.
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand")
+	   (any_extend:SI (match_operand:VAXintQH 1 "general_operand")))
+      (clobber (reg:CC VAX_PSL_REGNUM))])
+   (parallel
+     [(set (match_operand:SI 2 "nonimmediate_operand")
+	   (ctz:SI (match_dup 0)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])
+   (set (reg:CCZ VAX_PSL_REGNUM)
+	(compare:CCZ (match_dup 0)
+		     (const_int 0)))]
+  "!rtx_equal_p (operands[0], operands[2])
+   && peep2_reg_dead_p (3, operands[0])"
+  [(parallel
+     [(set (reg:CCZ VAX_PSL_REGNUM)
+	   (compare:CCZ (match_dup 1)
+			(const_int 0)))
+      (set (match_dup 2)
+	   (ctz:SI (match_dup 1)))])]
   "")
 
 (define_expand "sync_lock_test_and_set<mode>"
diff --git a/gcc/config/vax/elf.h b/gcc/config/vax/elf.h
index 555ccef0921..52d340b53ed 100644
--- a/gcc/config/vax/elf.h
+++ b/gcc/config/vax/elf.h
@@ -26,7 +26,8 @@  along with GCC; see the file COPYING3.  If not see
 #define REGISTER_PREFIX "%"
 #define REGISTER_NAMES \
   { "%r0", "%r1",  "%r2",  "%r3", "%r4", "%r5", "%r6", "%r7", \
-    "%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", }
+    "%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", \
+    "%psl" }
 
 #undef SIZE_TYPE
 #define SIZE_TYPE "long unsigned int"
diff --git a/gcc/config/vax/predicates.md b/gcc/config/vax/predicates.md
index 7c97b366604..92caf8384fa 100644
--- a/gcc/config/vax/predicates.md
+++ b/gcc/config/vax/predicates.md
@@ -17,6 +17,10 @@ 
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+;; Return true if OP is a constant zero operand.
+(define_predicate "const_zero_operand"
+  (match_test "op == CONST0_RTX (mode)"))
+
 ;; Special case of a symbolic operand that's used as a
 ;; operand.
 
@@ -109,3 +113,19 @@  (define_predicate "volatile_mem_operand"
 (define_predicate "any_memory_operand"
   (ior (match_operand 0 "memory_operand")
        (match_operand 0 "volatile_mem_operand")))
+
+;; Return true if OP is a comparison operator that requires at least CCmode.
+(define_predicate "vax_cc_comparison_operator"
+  (match_code "geu,gtu,leu,ltu"))
+
+;; Return true if OP is a comparison operator that requires at least CCNmode.
+(define_predicate "vax_ccn_comparison_operator"
+  (match_code "ge,lt"))
+
+;; Return true if OP is a comparison operator that requires at least CCNZmode.
+(define_predicate "vax_ccnz_comparison_operator"
+  (match_code "gt,le"))
+
+;; Return true if OP is a comparison operator that requires at least CCZmode.
+(define_predicate "vax_ccz_comparison_operator"
+  (match_code "ne,eq"))
diff --git a/gcc/config/vax/vax-modes.def b/gcc/config/vax/vax-modes.def
index 5f1c9946653..2a7438ee77f 100644
--- a/gcc/config/vax/vax-modes.def
+++ b/gcc/config/vax/vax-modes.def
@@ -20,3 +20,14 @@  along with GCC; see the file COPYING3.  If not see
 /* We just need to reset the floating point formats.  */
 RESET_FLOAT_FORMAT (SF, vax_f_format);
 RESET_FLOAT_FORMAT (DF, vax_d_format);
+
+/* `DImode' addition and subtraction operations do their calculation
+   on the low and then the high longword with separate instructions,
+   and therefore only usably set N.  */
+CC_MODE (CCN);
+/* Non-arithmetic integer instructions such as MOV or XOR as well as
+   instructions that produce a floating-point result only usably set
+   N and Z.  */
+CC_MODE (CCNZ);
+/* The FFC and FFS instructions only usably set Z.  */
+CC_MODE (CCZ);
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index 454d35e3383..aa949c598d7 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -22,13 +22,14 @@  extern void vax_expand_prologue (void);
 
 #ifdef RTX_CODE
 extern bool vax_acceptable_pic_operand_p (rtx, bool, bool);
+extern machine_mode vax_select_cc_mode (enum rtx_code, rtx, rtx);
 extern const char *cond_name (rtx);
 extern bool adjacent_operands_p (rtx, rtx, machine_mode);
 extern const char *rev_cond_name (rtx);
 extern void print_operand_address (FILE *, rtx);
 extern void print_operand (FILE *, rtx, int);
-extern void vax_notice_update_cc (rtx, rtx);
 extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code);
+extern bool vax_maybe_split_dimode_move (rtx *);
 extern const char * vax_output_int_move (rtx, rtx *, machine_mode);
 extern const char * vax_output_int_add (rtx_insn *, rtx *, machine_mode);
 extern const char * vax_output_int_subtract (rtx_insn *, rtx *, machine_mode);
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index 69a05b33e95..54d83dc1da2 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -54,6 +54,10 @@  static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
 static int vax_address_cost_1 (rtx);
 static int vax_address_cost (rtx, machine_mode, addr_space_t, bool);
 static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+static machine_mode vax_cc_modes_compatible (machine_mode, machine_mode);
+static rtx_insn *vax_md_asm_adjust (vec<rtx> &, vec<rtx> &,
+				    vec<const char *> &,
+				    vec<rtx> &, HARD_REG_SET &);
 static rtx vax_function_arg (cumulative_args_t, const function_arg_info &);
 static void vax_function_arg_advance (cumulative_args_t,
 				      const function_arg_info &);
@@ -81,11 +85,23 @@  static HOST_WIDE_INT vax_starting_frame_offset (void);
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
 
+/* Enable compare elimination pass.  */
+#undef TARGET_FLAGS_REGNUM
+#define TARGET_FLAGS_REGNUM VAX_PSL_REGNUM
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS vax_rtx_costs
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST vax_address_cost
 
+/* Return the narrowest CC mode that spans both modes offered.  */
+#undef TARGET_CC_MODES_COMPATIBLE
+#define TARGET_CC_MODES_COMPATIBLE vax_cc_modes_compatible
+
+/* Mark PSL as clobbered for compatibility with the CC0 representation.  */
+#undef TARGET_MD_ASM_ADJUST
+#define TARGET_MD_ASM_ADJUST vax_md_asm_adjust
+
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 
@@ -1070,6 +1086,102 @@  vax_acceptable_pic_operand_p (rtx x ATTRIBUTE_UNUSED,
   return true;
 }
 
+/* Given a comparison code (NE, EQ, etc.) and the operands of a COMPARE,
+   return the mode to be used for the comparison.  As we have the same
+   interpretation of condition codes across all the instructions we just
+   return the narrowest mode suitable for the comparison code requested.  */
+
+extern machine_mode
+vax_select_cc_mode (enum rtx_code op,
+		    rtx x ATTRIBUTE_UNUSED, rtx y ATTRIBUTE_UNUSED)
+{
+  switch (op)
+    {
+    default:
+      gcc_unreachable ();
+    case NE:
+    case EQ:
+      return CCZmode;
+    case GE:
+    case LT:
+      return CCNmode;
+    case GT:
+    case LE:
+      return CCNZmode;
+    case GEU:
+    case GTU:
+    case LEU:
+    case LTU:
+      return CCmode;
+    }
+}
+
+/* Return the narrowest CC mode that spans both modes offered.  If they
+   intersect, this will be the wider of the two, and if they do not then
+   find find one that is a superset of both (i.e. CCNZmode for a pair
+   consisting of CCNmode and CCZmode).  A wider CC writer will satisfy
+   a narrower CC reader, e.g. a comparison operator that uses CCZmode
+   can use a CCNZmode output of a previous instruction.  */
+
+static machine_mode
+vax_cc_modes_compatible (machine_mode m1, machine_mode m2)
+{
+  switch (m1)
+    {
+    default:
+      gcc_unreachable ();
+    case E_CCmode:
+      switch (m2)
+	{
+	default:
+	  gcc_unreachable ();
+	case E_CCmode:
+	case E_CCNZmode:
+	case E_CCNmode:
+	case E_CCZmode:
+	  return m1;
+	}
+    case E_CCNZmode:
+      switch (m2)
+	{
+	default:
+	  gcc_unreachable ();
+	case E_CCmode:
+	  return m2;
+	case E_CCNmode:
+	case E_CCNZmode:
+	case E_CCZmode:
+	  return m1;
+	}
+    case E_CCNmode:
+    case E_CCZmode:
+      switch (m2)
+	{
+	default:
+	  gcc_unreachable ();
+	case E_CCmode:
+	case E_CCNZmode:
+	  return m2;
+	case E_CCNmode:
+	case E_CCZmode:
+	  return m1 == m2 ? m1 : E_CCNZmode;
+	}
+    }
+}
+
+/* Mark PSL as clobbered for compatibility with the CC0 representation.  */
+
+static rtx_insn *
+vax_md_asm_adjust (vec<rtx> &outputs ATTRIBUTE_UNUSED,
+		   vec<rtx> &inputs ATTRIBUTE_UNUSED,
+		   vec<const char *> &constraints ATTRIBUTE_UNUSED,
+		   vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs)
+{
+  clobbers.safe_push (gen_rtx_REG (CCmode, VAX_PSL_REGNUM));
+  SET_HARD_REG_BIT (clobbered_regs, VAX_PSL_REGNUM);
+  return NULL;
+}
+
 /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
    Used for C++ multiple inheritance.
 	.mask	^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>  #conservative entry mask
@@ -1102,81 +1214,21 @@  vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
   return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM);
 }
 
-/* Worker function for NOTICE_UPDATE_CC.  */
+/* Output integer move instructions.  */
 
-void
-vax_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
+bool
+vax_maybe_split_dimode_move (rtx *operands)
 {
-  if (GET_CODE (exp) == SET)
-    {
-      if (GET_CODE (SET_SRC (exp)) == CALL)
-	CC_STATUS_INIT;
-      else if (GET_CODE (SET_DEST (exp)) != ZERO_EXTRACT
-	       && GET_CODE (SET_DEST (exp)) != PC)
-	{
-	  cc_status.flags = 0;
-	  /* The integer operations below don't set carry or
-	     set it in an incompatible way.  That's ok though
-	     as the Z bit is all we need when doing unsigned
-	     comparisons on the result of these insns (since
-	     they're always with 0).  Set CC_NO_OVERFLOW to
-	     generate the correct unsigned branches.  */
-	  switch (GET_CODE (SET_SRC (exp)))
-	    {
-	    case NEG:
-	      if (GET_MODE_CLASS (GET_MODE (exp)) == MODE_FLOAT)
-		break;
-	      /* FALLTHRU */
-	    case AND:
-	    case IOR:
-	    case XOR:
-	    case NOT:
-	    case MEM:
-	    case REG:
-	      cc_status.flags = CC_NO_OVERFLOW;
-	      break;
-	    case CTZ:
-	      cc_status.flags = CC_NOT_NEGATIVE;
-	      break;
-	    default:
-	      break;
-	    }
-	  cc_status.value1 = SET_DEST (exp);
-	  cc_status.value2 = SET_SRC (exp);
-	}
-    }
-  else if (GET_CODE (exp) == PARALLEL
-	   && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
-    {
-      if (GET_CODE (SET_SRC (XVECEXP (exp, 0, 0))) == CALL)
-	CC_STATUS_INIT;
-      else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) != PC)
-	{
-	  cc_status.flags = 0;
-	  cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0));
-	  cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0));
-	}
-      else
-	/* PARALLELs whose first element sets the PC are aob,
-	   sob insns.  They do change the cc's.  */
-	CC_STATUS_INIT;
-    }
-  else
-    CC_STATUS_INIT;
-  if (cc_status.value1 && REG_P (cc_status.value1)
-      && cc_status.value2
-      && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
-    cc_status.value2 = 0;
-  if (cc_status.value1 && MEM_P (cc_status.value1)
-      && cc_status.value2
-      && MEM_P (cc_status.value2))
-    cc_status.value2 = 0;
-  /* Actual condition, one line up, should be that value2's address
-     depends on value1, but that is too much of a pain.  */
+  return (TARGET_QMATH
+	  && (!MEM_P (operands[0])
+	      || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+	      || GET_CODE (XEXP (operands[0], 0)) == POST_INC
+	      || !illegal_addsub_di_memory_operand (operands[0], DImode))
+	  && ((CONST_INT_P (operands[1])
+	       && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64)
+	      || GET_CODE (operands[1]) == CONST_DOUBLE));
 }
 
-/* Output integer move instructions.  */
-
 const char *
 vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
 		     machine_mode mode)
@@ -1252,14 +1304,7 @@  vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
 	    }
 	}
 
-      if (TARGET_QMATH
-	  && (!MEM_P (operands[0])
-	      || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-	      || GET_CODE (XEXP (operands[0], 0)) == POST_INC
-	      || !illegal_addsub_di_memory_operand (operands[0], DImode))
-	  && ((CONST_INT_P (operands[1])
-	       && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64)
-	      || GET_CODE (operands[1]) == CONST_DOUBLE))
+      if (vax_maybe_split_dimode_move (operands))
 	{
 	  hi[0] = operands[0];
 	  hi[1] = operands[1];
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index 43182ff1d88..8b2b2d17704 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -120,12 +120,12 @@  along with GCC; see the file COPYING3.  If not see
    from 0 to just below FIRST_PSEUDO_REGISTER.
    All registers that the compiler knows about must be given numbers,
    even those that are not normally considered general registers.  */
-#define FIRST_PSEUDO_REGISTER 16
+#define FIRST_PSEUDO_REGISTER 17
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
    On the VAX, these are the AP, FP, SP and PC.  */
-#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -133,7 +133,7 @@  along with GCC; see the file COPYING3.  If not see
    The latter must include the registers where values are returned
    and the register where structure-value addresses are passed.
    Aside from that, you can include as many other registers as you like.  */
-#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
@@ -465,24 +465,11 @@  enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 #define BRANCH_COST(speed_p, predictable_p) 0
 
-/* Tell final.c how to eliminate redundant test instructions.  */
-
-/* Here we define machine-dependent flags and fields in cc_status
-   (see `conditions.h').  No extra ones are needed for the VAX.  */
-
-/* Store in cc_status the expressions
-   that the condition codes will describe
-   after execution of an instruction whose pattern is EXP.
-   Do not alter them if the instruction would not alter the cc's.  */
-
-#define NOTICE_UPDATE_CC(EXP, INSN)	\
-  vax_notice_update_cc ((EXP), (INSN))
-
-#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV)	\
-  { if (cc_status.flags & CC_NO_OVERFLOW)	\
-      return NO_OV;				\
-    return NORMAL;				\
-  }
+/* Given a comparison code (NE, EQ, etc.) and the operands of a COMPARE,
+   return the mode to be used for the comparison.  As we have the same
+   interpretation of condition codes across all the instructions we just
+   return the narrowest mode suitable for the comparison code requested.  */
+#define SELECT_CC_MODE(OP, X, Y) vax_select_cc_mode (OP, X, Y)
 
 /* Control the assembler format that we output.  */
 
@@ -517,7 +504,8 @@  enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 #define REGISTER_PREFIX ""
 #define REGISTER_NAMES					\
   { "r0", "r1",  "r2",  "r3", "r4", "r5", "r6", "r7",	\
-    "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", }
+    "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc",	\
+    "psl" }
 
 /* This is BSD, so it wants DBX format.  */
 
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index 1bb4e300cae..b8cf4eed4bc 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -22,9 +22,6 @@ 
 ;;- the first one in the file is chosen.
 ;;-
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et al.
-;;-
-;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
-;;- updates for most instructions.
 
 ;; UNSPEC_VOLATILE usage:
 
@@ -40,6 +37,8 @@  (define_constants
    (VAX_FP_REGNUM 13)	    ; Register 13 contains the frame pointer
    (VAX_SP_REGNUM 14)	    ; Register 14 contains the stack pointer
    (VAX_PC_REGNUM 15)	    ; Register 15 contains the program counter
+   (VAX_PSL_REGNUM 16)	    ; Register 16 contains the processor status
+			    ; and condition codes in particular
   ]
 )
 
@@ -57,34 +56,96 @@  (define_mode_attr  fsfx [(SF "f") (DF "%#")])
 ;; Some output patterns want integer immediates with a prefix...
 (define_mode_attr  iprefx [(QI "B") (HI "H") (SI "N")])
 
+(define_mode_iterator VAXcc [CC CCN CCNZ CCZ])
+(define_mode_iterator VAXccnz [CCN CCNZ CCZ])
+(define_mode_attr cc [(CC "cc") (CCN "ccn") (CCNZ "ccnz") (CCZ "ccz")])
+
+(define_code_iterator any_extract [sign_extract zero_extract])
+
 ;;
 (include "constraints.md")
 (include "predicates.md")
 
-(define_insn "*cmp<mode>"
-  [(set (cc0)
-	(compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT,nrmT")
-		 (match_operand:VAXint 1 "general_operand" "I,nrmT")))]
+;; Make instructions that set the N, N+Z, and Z condition codes respectively.
+(define_subst "subst_<cc>"
+  [(set (match_operand 0 "")
+	(match_operand 1 ""))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
   ""
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz (match_dup 1)
+			 (const_int 0)))
+   (set (match_dup 0)
+	(match_dup 1))])
+
+(define_subst "subst_f<cc>"
+  [(set (match_operand 0 "")
+	(match_operand 1 ""))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  ""
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz (match_dup 1)
+			 (const_double_zero)))
+   (set (match_dup 0)
+	(match_dup 1))])
+
+;; Select all from the attributes below that apply to a given insn that
+;; has a clobber on CC for the comparison elimination pass to use it in
+;; place of a subsequent comparison instruction matching the mode used
+;; by a comparison operator in branch.
+;;
+;; For example a branch doing `eq' in SImode will use `*cmpsi_ccz', so
+;; to eliminate it a `*movsi_ccz', etc. pattern will be required via the
+;; `ccz' substitution.  Analogously for the other CC modes.
+;;
+;; The general `cc' mode, which sets all of the C, N, V and Z condition
+;; codes, has to be handled specially as it makes no sense for the usual
+;; comparison against zero, so no substitution has been defined for it.
+(define_subst_attr "ccn" "subst_ccn" "" "_ccn")
+(define_subst_attr "ccnz" "subst_ccnz" "" "_ccnz")
+(define_subst_attr "ccz" "subst_ccz" "" "_ccz")
+(define_subst_attr "fccn" "subst_fccn" "" "_ccn")
+(define_subst_attr "fccnz" "subst_fccnz" "" "_ccnz")
+(define_subst_attr "fccz" "subst_fccz" "" "_ccz")
+
+(define_insn "*cmp<VAXint:mode>_<VAXcc:mode>"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc (match_operand:VAXint 0 "general_operand" "nrmT,nrmT")
+		       (match_operand:VAXint 1 "general_operand" "I,nrmT")))]
+  "reload_completed"
   "@
    tst<VAXint:isfx> %0
    cmp<VAXint:isfx> %0,%1")
 
-(define_insn "*cmp<mode>"
-  [(set (cc0)
-	(compare (match_operand:VAXfp 0 "general_operand" "gF,gF")
-		 (match_operand:VAXfp 1 "general_operand" "G,gF")))]
-  ""
+;; We don't have a CMPQ instruction, but we can set the N and Z condition
+;; codes with MOVQ, and also this comparison can be folded into a preceding
+;; operation by the post-reload comparison elimination pass.
+(define_insn "*cmpdi_<VAXccnz:mode>"
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz (match_operand:DI 0 "general_operand" "r,nmT")
+			 (match_operand:DI 1 "const_zero_operand" "I,I")))
+   (clobber (match_scratch:DI 2 "=X,r"))]
+  "reload_completed"
+  "@
+   movq %0,%0
+   movq %0,%2")
+
+(define_insn "*cmp<VAXfp:mode>_<VAXccnz:mode>"
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz (match_operand:VAXfp 0 "general_operand" "gF,gF")
+			 (match_operand:VAXfp 1 "general_operand" "G,gF")))]
+  "reload_completed"
   "@
    tst<VAXfp:fsfx> %0
    cmp<VAXfp:fsfx> %0,%1")
 
-(define_insn "*bit<mode>"
-  [(set (cc0)
-	(compare (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
-			     (match_operand:VAXint 1 "general_operand" "nrmT"))
-		 (const_int 0)))]
-  ""
+(define_insn "*bit<VAXint:mode>_<VAXccnz:mode>"
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz
+	  (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
+		      (match_operand:VAXint 1 "general_operand" "nrmT"))
+	  (const_int 0)))]
+  "reload_completed"
   "bit<VAXint:isfx> %0,%1")
 
 ;; The VAX has no sCOND insns.  It does have add/subtract with carry
@@ -95,25 +156,76 @@  (define_insn "*bit<mode>"
 ;; and has been deleted.
 
 
-(define_insn "mov<mode>"
+(define_insn_and_split "mov<mode>"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
 	(match_operand:VAXfp 1 "general_operand" "G,gF"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*mov<mode><fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
+	(match_operand:VAXfp 1 "general_operand" "G,gF"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    clr<VAXfp:fsfx> %0
    mov<VAXfp:fsfx> %1,%0")
 
 ;; Some VAXen don't support this instruction.
-;;(define_insn "movti"
+;;(define_insn_and_split "movti"
 ;;  [(set (match_operand:TI 0 "nonimmediate_operand" "=g")
 ;;	(match_operand:TI 1 "general_operand" "g"))]
 ;;  ""
+;;  "#"
+;;  "reload_completed"
+;;  [(parallel
+;;     [(set (match_dup 0)
+;;	   (match_dup 1))
+;;      (clobber (reg:CC VAX_PSL_REGNUM))])]
+;;  "")
+;;
+;;(define_insn "*movti<ccn><ccnz><ccz>"
+;;  [(set (match_operand:TI 0 "nonimmediate_operand" "=g")
+;;	(match_operand:TI 1 "general_operand" "g"))
+;;   (clobber (reg:CC VAX_PSL_REGNUM))]
+;;  "reload_completed"
 ;;  "movo %1,%0")
 
-(define_insn "movdi"
+(define_insn_and_split "movdi"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
 	(match_operand:DI 1 "general_operand" "g"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+;; In some cases `vax_output_int_move' splits a `DImode' move into a pair
+;; of `SImode' moves, in which case the flags aren't usefully set.  Have
+;; separate patterns then, for the cases where the move may and may not be
+;; split each.  We use the outer condition only so in some cases we will
+;; fail to notice the move does not actually get split, but this is OK.
+(define_insn "*movdi_maybe_split"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(match_operand:DI 1 "general_operand" "g"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed && vax_maybe_split_dimode_move (operands)"
+  "* return vax_output_int_move (insn, operands, DImode);")
+
+(define_insn "*movdi_unsplit<ccn><ccnz><ccz>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(match_operand:DI 1 "general_operand" "g"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed && !vax_maybe_split_dimode_move (operands)"
   "* return vax_output_int_move (insn, operands, DImode);")
 
 ;; The VAX move instructions have space-time tradeoffs.  On a MicroVAX
@@ -155,22 +267,61 @@  (define_expand "movsi"
 #endif
 }")
 
-(define_insn "movsi_2"
+(define_insn_and_split "movsi_2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(match_operand:SI 1 "nonsymbolic_operand" "nrmT"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movsi_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(match_operand:SI 1 "nonsymbolic_operand" "nrmT"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "* return vax_output_int_move (insn, operands, SImode);")
 
-(define_insn "mov<mode>"
+(define_insn_and_split "mov<mode>"
   [(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g")
 	(match_operand:VAXintQH 1 "general_operand" "g"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*mov<mode><ccn><ccnz><ccz>"
+  [(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g")
+	(match_operand:VAXintQH 1 "general_operand" "g"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "* return vax_output_int_move (insn, operands, <MODE>mode);")
 
-(define_insn "movstricthi"
-  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+g"))
+(define_insn_and_split "movstricthi"
+  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
 	(match_operand:HI 1 "general_operand" "g"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (strict_low_part (match_dup 0))
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movstricthi<ccn><ccnz><ccz>"
+  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
+	(match_operand:HI 1 "general_operand" "g"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (CONST_INT_P (operands[1]))
@@ -188,10 +339,23 @@  (define_insn "movstricthi"
   return \"movw %1,%0\";
 }")
 
-(define_insn "movstrictqi"
-  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+g"))
+(define_insn_and_split "movstrictqi"
+  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
 	(match_operand:QI 1 "general_operand" "g"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (strict_low_part (match_dup 0))
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movstrictqi<ccn><ccnz><ccz>"
+  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
+	(match_operand:QI 1 "general_operand" "g"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (CONST_INT_P (operands[1]))
@@ -236,7 +400,7 @@  (define_expand "movmemhi"
 ;; that anything generated as this insn will be recognized as one
 ;; and that it won't successfully combine with anything.
 
-(define_insn "movmemhi1"
+(define_insn_and_split "movmemhi1"
   [(set (match_operand:BLK 0 "memory_operand" "=o")
 	(match_operand:BLK 1 "memory_operand" "o"))
    (use (match_operand:HI 2 "general_operand" "g"))
@@ -247,90 +411,286 @@  (define_insn "movmemhi1"
    (clobber (reg:SI 4))
    (clobber (reg:SI 5))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (use (match_dup 2))
+      (clobber (reg:SI 0))
+      (clobber (reg:SI 1))
+      (clobber (reg:SI 2))
+      (clobber (reg:SI 3))
+      (clobber (reg:SI 4))
+      (clobber (reg:SI 5))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movmemhi1"
+  [(set (match_operand:BLK 0 "memory_operand" "=o")
+	(match_operand:BLK 1 "memory_operand" "o"))
+   (use (match_operand:HI 2 "general_operand" "g"))
+   (clobber (reg:SI 0))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:SI 3))
+   (clobber (reg:SI 4))
+   (clobber (reg:SI 5))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "movc3 %2,%1,%0")
 
 ;; Extension and truncation insns.
 
-(define_insn "truncsiqi2"
+(define_insn_and_split "truncsiqi2"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
 	(truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (truncate:QI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*truncsiqi2<ccn><ccnz><ccz>"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
+	(truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtlb %1,%0")
 
-(define_insn "truncsihi2"
+(define_insn_and_split "truncsihi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
 	(truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (truncate:HI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*truncsihi2<ccn><ccnz><ccz>"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
+	(truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))
+      (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtlw %1,%0")
 
-(define_insn "trunchiqi2"
+(define_insn_and_split "trunchiqi2"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
 	(truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (truncate:QI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*trunchiqi2<ccn><ccnz><ccz>"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
+	(truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtwb %1,%0")
 
-(define_insn "extendhisi2"
+(define_insn_and_split "extendhisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (sign_extend:SI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extendhisi2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtwl %1,%0")
 
-(define_insn "extendqihi2"
+(define_insn_and_split "extendqihi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
 	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (sign_extend:HI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extendqihi2<ccn><ccnz><ccz>"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
+	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtbw %1,%0")
 
-(define_insn "extendqisi2"
+(define_insn_and_split "extendqisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (sign_extend:SI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extendqisi2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtbl %1,%0")
 
-(define_insn "extendsfdf2"
+(define_insn_and_split "extendsfdf2"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=g")
 	(float_extend:DF (match_operand:SF 1 "general_operand" "gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (float_extend:DF (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extendsfdf2<fccn><fccnz><fccz>"
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=g")
+	(float_extend:DF (match_operand:SF 1 "general_operand" "gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvtf%# %1,%0")
 
-(define_insn "truncdfsf2"
+(define_insn_and_split "truncdfsf2"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=g")
 	(float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (float_truncate:SF (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*truncdfsf2<fccn><fccnz><fccz>"
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=g")
+	(float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvt%#f %1,%0")
 
-(define_insn "zero_extendhisi2"
+(define_insn_and_split "zero_extendhisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (zero_extend:SI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*zero_extendhisi2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "movzwl %1,%0")
 
-(define_insn "zero_extendqihi2"
+(define_insn_and_split "zero_extendqihi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
 	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (zero_extend:HI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*zero_extendqihi2<ccn><ccnz><ccz>"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
+	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "movzbw %1,%0")
 
-(define_insn "zero_extendqisi2"
+(define_insn_and_split "zero_extendqisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (zero_extend:SI (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*zero_extendqisi2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "movzbl %1,%0")
 
 ;; Fix-to-float conversion insns.
 
-(define_insn "float<VAXint:mode><VAXfp:mode>2"
+(define_insn_and_split "float<VAXint:mode><VAXfp:mode>2"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
 	(float:VAXfp (match_operand:VAXint 1 "nonimmediate_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (float:VAXfp (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*float<VAXint:mode><VAXfp:mode>2<fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
+	(float:VAXfp (match_operand:VAXint 1 "nonimmediate_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvt<VAXint:isfx><VAXfp:fsfx> %1,%0")
 
 ;; Float-to-fix conversion insns.
 
-(define_insn "fix_trunc<VAXfp:mode><VAXint:mode>2"
+(define_insn_and_split "fix_trunc<VAXfp:mode><VAXint:mode>2"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
 	(fix:VAXint (match_operand:VAXfp 1 "general_operand" "gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (fix:VAXint (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*fix_trunc<VAXfp:mode><VAXint:mode>2<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+	(fix:VAXint (match_operand:VAXfp 1 "general_operand" "gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "cvt<VAXfp:fsfx><VAXint:isfx> %1,%0")
 
 (define_expand "fixuns_trunc<VAXfp:mode><VAXint:mode>2"
@@ -340,21 +700,51 @@  (define_expand "fixuns_trunc<VAXfp:mode><VAXint:mode>2"
 
 ;;- All kinds of add instructions.
 
-(define_insn "add<mode>3"
+(define_insn_and_split "add<mode>3"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
 	(plus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
 		    (match_operand:VAXfp 2 "general_operand" "gF,0,gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:VAXfp (match_dup 1)
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*add<mode>3<fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
+	(plus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
+		    (match_operand:VAXfp 2 "general_operand" "gF,0,gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    add<VAXfp:fsfx>2 %2,%0
    add<VAXfp:fsfx>2 %1,%0
    add<VAXfp:fsfx>3 %1,%2,%0")
 
-(define_insn "add<mode>3"
+(define_insn_and_split "add<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
 	(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
 		     (match_operand:VAXint 2 "general_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:VAXint (match_dup 1)
+			(match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*add<mode>3<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+	(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
+		     (match_operand:VAXint 2 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "* return vax_output_int_add (insn, operands, <MODE>mode);")
 
 (define_expand "adddi3"
@@ -364,37 +754,109 @@  (define_expand "adddi3"
   "!reload_in_progress"
   "vax_expand_addsub_di_operands (operands, PLUS); DONE;")
 
-(define_insn "adcdi3"
+(define_insn_and_split "adcdi3"
   [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr")
 	(plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
 		 (match_operand:DI 2 "general_addsub_di_operand" "nRr")))]
   "TARGET_QMATH"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:DI (match_dup 1)
+		    (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*adcdi3<ccn>"
+  [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr")
+	(plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
+		 (match_operand:DI 2 "general_addsub_di_operand" "nRr")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "TARGET_QMATH && reload_completed"
   "* return vax_output_int_add (insn, operands, DImode);")
 
 ;; The add-with-carry (adwc) instruction only accepts two operands.
-(define_insn "adddi3_old"
+(define_insn_and_split "adddi3_old"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>")
 	(plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
 		 (match_operand:DI 2 "general_operand" "Fsro,Fs")))]
   "!TARGET_QMATH"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:DI (match_dup 1)
+		    (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*adddi3_old<ccn>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>")
+	(plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
+		 (match_operand:DI 2 "general_operand" "Fsro,Fs")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_QMATH && reload_completed"
   "* return vax_output_int_add (insn, operands, DImode);")
 
 ;;- All kinds of subtract instructions.
 
-(define_insn "sub<mode>3"
+(define_insn_and_split "sub<mode>3"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
 	(minus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
 		     (match_operand:VAXfp 2 "general_operand" "gF,gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (minus:VAXfp (match_dup 1)
+			(match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*sub<mode>3<fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
+	(minus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
+		     (match_operand:VAXfp 2 "general_operand" "gF,gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    sub<VAXfp:fsfx>2 %2,%0
    sub<VAXfp:fsfx>3 %2,%1,%0")
 
-(define_insn "sub<mode>3"
+(define_insn_and_split "sub<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
 	(minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
 		      (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (minus:VAXint (match_dup 1)
+			 (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*sub<mode>3<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+	(minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
+		      (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
+  "@
+   sub<VAXint:isfx>2 %2,%0
+   sub<VAXint:isfx>3 %2,%1,%0")
+
+(define_insn "*sub<mode>3_cc"
+  [(set (reg:CC VAX_PSL_REGNUM)
+	(compare:CC (match_operand:VAXint 1 "general_operand" "0,nrmT")
+		    (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
+   (set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+	(minus:VAXint (match_dup 1)
+		      (match_dup 2)))]
+  "reload_completed"
   "@
    sub<VAXint:isfx>2 %2,%0
    sub<VAXint:isfx>3 %2,%1,%0")
@@ -406,52 +868,129 @@  (define_expand "subdi3"
   "!reload_in_progress"
   "vax_expand_addsub_di_operands (operands, MINUS); DONE;")
 
-(define_insn "sbcdi3"
+(define_insn_and_split "sbcdi3"
   [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
 	(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
 		  (match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))]
   "TARGET_QMATH"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (minus:DI (match_dup 1)
+		     (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*sbcdi3<ccn>"
+  [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
+	(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
+		  (match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "TARGET_QMATH && reload_completed"
   "* return vax_output_int_subtract (insn, operands, DImode);")
 
 ;; The subtract-with-carry (sbwc) instruction only takes two operands.
-(define_insn "subdi3_old"
+(define_insn_and_split "subdi3_old"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>")
 	(minus:DI (match_operand:DI 1 "general_operand" "0,or>")
 		  (match_operand:DI 2 "general_operand" "Fsor,Fs")))]
   "!TARGET_QMATH"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (minus:DI (match_dup 1)
+		     (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*subdi3_old<ccn>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>")
+	(minus:DI (match_operand:DI 1 "general_operand" "0,or>")
+		  (match_operand:DI 2 "general_operand" "Fsor,Fs")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_QMATH && reload_completed"
   "* return vax_output_int_subtract (insn, operands, DImode);")
 
 ;;- Multiply instructions.
 
-(define_insn "mul<mode>3"
+(define_insn_and_split "mul<mode>3"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
 	(mult:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
 		    (match_operand:VAXfp 2 "general_operand" "gF,0,gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (mult:VAXfp (match_dup 1)
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*mul<mode>3<fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
+	(mult:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
+		    (match_operand:VAXfp 2 "general_operand" "gF,0,gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    mul<VAXfp:fsfx>2 %2,%0
    mul<VAXfp:fsfx>2 %1,%0
    mul<VAXfp:fsfx>3 %1,%2,%0")
 
-(define_insn "mul<mode>3"
+(define_insn_and_split "mul<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
 	(mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
 		     (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (mult:VAXint (match_dup 1)
+			(match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*mul<mode>3<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
+	(mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
+		     (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    mul<VAXint:isfx>2 %2,%0
    mul<VAXint:isfx>2 %1,%0
    mul<VAXint:isfx>3 %1,%2,%0")
 
-(define_insn "mulsidi3"
+(define_insn_and_split "mulsidi3"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
 	(mult:DI
 	  (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
 	  (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT"))))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (mult:DI
+	     (sign_extend:DI (match_dup 1))
+	     (sign_extend:DI (match_dup 2))))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*mulsidi3<ccn><ccnz><ccz>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(mult:DI
+	  (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+	  (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT"))))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "emul %1,%2,$0,%0")
 
-(define_insn "*maddsidi4"
+(define_insn_and_split "*maddsidi4"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
 	(plus:DI
 	  (mult:DI
@@ -459,10 +998,31 @@  (define_insn "*maddsidi4"
 	    (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
 	  (sign_extend:DI (match_operand:SI 3 "general_operand" "g"))))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:DI
+	     (mult:DI
+	       (sign_extend:DI (match_dup 1))
+	       (sign_extend:DI (match_dup 2)))
+	     (sign_extend:DI (match_dup 3))))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*maddsidi4_2<ccn><ccnz><ccz>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(plus:DI
+	  (mult:DI
+	    (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+	    (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
+	  (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "g"))))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "emul %1,%2,%3,%0")
 
 ;; 'F' constraint means type CONST_DOUBLE
-(define_insn "*maddsidi4_const"
+(define_insn_and_split "*maddsidi4_const"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
 	(plus:DI
 	  (mult:DI
@@ -471,6 +1031,29 @@  (define_insn "*maddsidi4_const"
 	  (match_operand:DI 3 "immediate_operand" "F")))]
   "GET_CODE (operands[3]) == CONST_DOUBLE
    && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:DI
+	     (mult:DI
+	       (sign_extend:DI (match_dup 1))
+	       (sign_extend:DI (match_dup 2)))
+	     (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*maddsidi4_const_2<ccn><ccnz><ccz>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(plus:DI
+	  (mult:DI
+	    (sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
+	    (sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
+	  (match_operand:DI 3 "immediate_operand" "F")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "GET_CODE (operands[3]) == CONST_DOUBLE
+   && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)
+   && reload_completed"
   "*
 {
   if (CONST_DOUBLE_HIGH (operands[3]))
@@ -480,27 +1063,57 @@  (define_insn "*maddsidi4_const"
 
 ;;- Divide instructions.
 
-(define_insn "div<mode>3"
+(define_insn_and_split "div<mode>3"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
 	(div:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
 		   (match_operand:VAXfp 2 "general_operand" "gF,gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (div:VAXfp (match_dup 1)
+		      (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*div<mode>3<fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
+	(div:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
+		   (match_operand:VAXfp 2 "general_operand" "gF,gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    div<VAXfp:fsfx>2 %2,%0
    div<VAXfp:fsfx>3 %2,%1,%0")
 
-(define_insn "div<mode>3"
+(define_insn_and_split "div<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
 	(div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
 		    (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (div:VAXint (match_dup 1)
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*div<mode>3<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+	(div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
+		    (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    div<VAXint:isfx>2 %2,%0
    div<VAXint:isfx>3 %2,%1,%0")
 
 ;; This is left out because it is very slow;
 ;; we are better off programming around the "lack" of this insn.
-;;(define_insn "divmoddisi4"
+;;(define_insn_and_split "divmoddisi4"
 ;;  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 ;;	(div:SI (match_operand:DI 1 "general_operand" "g")
 ;;		(match_operand:SI 2 "general_operand" "g")))
@@ -508,6 +1121,27 @@  (define_insn "div<mode>3"
 ;;	(mod:SI (match_dup 1)
 ;;		(match_dup 2)))]
 ;;  ""
+;;  "#"
+;;  "reload_completed"
+;;  [(parallel
+;;     [(set (match_dup 0)
+;;	   (div:SI (match_dup 1)
+;;		   (match_dup 2)))
+;;      (set (match_dup 3)
+;;	   (mod:SI (match_dup 1)
+;;		   (match_dup 2)))
+;;      (clobber (reg:CC VAX_PSL_REGNUM))])]
+;;  "")
+;;
+;;(define_insn "*divmoddisi4<ccn><ccnz><ccz>"
+;;  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;;	(div:SI (match_operand:DI 1 "general_operand" "g")
+;;		(match_operand:SI 2 "general_operand" "g")))
+;;   (set (match_operand:SI 3 "nonimmediate_operand" "=g")
+;;	(mod:SI (match_dup 1)
+;;		(match_dup 2)))
+;;   (clobber (reg:CC VAX_PSL_REGNUM))]
+;;  "reload_completed"
 ;;  "ediv %2,%1,%0,%3")
 
 ;; Bit-and on the VAX is done with a clear-bits insn.
@@ -534,11 +1168,29 @@  (define_expand "and<mode>3"
     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
 }")
 
-(define_insn "*and<mode>"
+(define_insn_and_split "*and<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
-	(and:VAXint (not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
+	(and:VAXint (not:VAXint
+		      (match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
 		    (match_operand:VAXint 2 "general_operand" "0,nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (and:VAXint (not:VAXint
+			 (match_dup 1))
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*and<mode>3_2<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+	(and:VAXint (not:VAXint
+		      (match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
+		    (match_operand:VAXint 2 "general_operand" "0,nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    bic<VAXint:isfx>2 %1,%0
    bic<VAXint:isfx>3 %1,%2,%0")
@@ -548,23 +1200,80 @@  (define_insn "*and<mode>"
 ;; longer a problem.  However, having these patterns allows optimization
 ;; opportunities in combine.c.
 
-(define_insn "*and<mode>_const_int"
+(define_insn_and_split "*and<mode>3_const_int"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
 	(and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
 		    (match_operand:VAXint 2 "const_int_operand" "n,n")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (and:VAXint (match_dup 1)
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*and<mode>3_2_const_int<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+	(and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
+		    (match_operand:VAXint 2 "const_int_operand" "n,n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    bic<VAXint:isfx>2 %<VAXint:iprefx>2,%0
    bic<VAXint:isfx>3 %<VAXint:iprefx>2,%1,%0")
 
+;; We have no direct AND operation and consequently the RTL sequence
+;; the "and<mode>3" pattern produces does not match the instruction
+;; the "*bit<mode>" pattern does for the purpose of the compare
+;; elimination pass.  Try to get rid of the extra operation by hand
+;; and where the sequence is used to set the condition codes only
+;; convert MNEG/BIC => BIT.
+(define_peephole2
+  [(parallel
+     [(set (match_operand:VAXint 0 "register_operand")
+	   (not:VAXint (match_operand:VAXint 1 "general_operand")))
+      (clobber (reg:CC VAX_PSL_REGNUM))])
+   (parallel
+     [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	   (compare:VAXccnz
+	     (and:VAXint (not:VAXint (match_dup 0))
+			 (match_operand:VAXint 3 "general_operand"))
+	     (const_int 0)))
+      (set (match_operand:VAXint 2 "register_operand")
+	   (and:VAXint (not:VAXint (match_dup 0))
+		       (match_dup 3)))])]
+  "peep2_reg_dead_p (2, operands[0]) && peep2_reg_dead_p (2, operands[2])"
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz
+	  (and:VAXint (match_dup 1)
+		      (match_dup 3))
+	  (const_int 0)))]
+  "")
 
 ;;- Bit set instructions.
 
-(define_insn "ior<mode>3"
+(define_insn_and_split "ior<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
 	(ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
 		    (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ior:VAXint (match_dup 1)
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ior<mode>3<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
+	(ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
+		    (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    bis<VAXint:isfx>2 %2,%0
    bis<VAXint:isfx>2 %1,%0
@@ -572,35 +1281,97 @@  (define_insn "ior<mode>3"
 
 ;;- xor instructions.
 
-(define_insn "xor<mode>3"
+(define_insn_and_split "xor<mode>3"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
 	(xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
 		    (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (xor:VAXint (match_dup 1)
+		       (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*xor<mode>3<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
+	(xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
+		    (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "@
    xor<VAXint:isfx>2 %2,%0
    xor<VAXint:isfx>2 %1,%0
    xor<VAXint:isfx>3 %2,%1,%0")
-
 
-(define_insn "neg<mode>2"
+(define_insn_and_split "neg<mode>2"
   [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
 	(neg:VAXfp (match_operand:VAXfp 1 "general_operand" "gF")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (neg:VAXfp (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*neg<mode>2<fccn><fccnz><fccz>"
+  [(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
+	(neg:VAXfp (match_operand:VAXfp 1 "general_operand" "gF")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "mneg<VAXfp:fsfx> %1,%0")
 
-(define_insn "neg<mode>2"
+(define_insn_and_split "neg<mode>2"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
 	(neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (neg:VAXint (match_dup 1)))
+	 (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*neg<mode>2<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+	(neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
+  "mneg<VAXint:isfx> %1,%0")
+
+(define_insn "*neg<mode>2_cc"
+  [(set (reg:CC VAX_PSL_REGNUM)
+	(compare:CC (const_int 0)
+		    (neg:VAXint
+		      (match_operand:VAXint 1 "general_operand" "0,nrmT"))))
+   (set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
+	(neg:VAXint (match_dup 1)))]
+  "reload_completed"
   "mneg<VAXint:isfx> %1,%0")
 
-(define_insn "one_cmpl<mode>2"
+(define_insn_and_split "one_cmpl<mode>2"
   [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
 	(not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))]
   ""
-  "mcom<VAXint:isfx> %1,%0")
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (not:VAXint (match_dup 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
 
+(define_insn "*one_cmpl<mode>2<ccn><ccnz><ccz>"
+  [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
+	(not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
+  "mcom<VAXint:isfx> %1,%0")
 
 ;; Arithmetic right shift on the VAX works by negating the shift count,
 ;; then emitting a right shift with the shift count negated.  This means
@@ -618,25 +1389,70 @@  (define_expand "ashrsi3"
     operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
 }")
 
-(define_insn ""
+(define_insn_and_split "*ashlnegsi3_const_int"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
 		     (match_operand:QI 2 "const_int_operand" "n")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ashiftrt:SI (match_dup 1)
+			(match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ashlnegsi3_const_int_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
+		     (match_operand:QI 2 "const_int_operand" "n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "ashl $%n2,%1,%0")
 
-(define_insn ""
+(define_insn_and_split "*ashlnegsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
 		     (neg:QI (match_operand:QI 2 "general_operand" "g"))))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ashiftrt:SI (match_dup 1)
+			(neg:QI (match_dup 2))))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ashlnegsi3_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
+		     (neg:QI (match_operand:QI 2 "general_operand" "g"))))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "ashl %2,%1,%0")
 
-(define_insn "ashlsi3"
+(define_insn_and_split "ashlsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
 		   (match_operand:QI 2 "general_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ashift:SI (match_dup 1)
+		      (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ashlsi3<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
+		   (match_operand:QI 2 "general_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1]))
@@ -673,18 +1489,48 @@  (define_expand "ashrdi3"
   operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
 }")
 
-(define_insn "ashldi3"
+(define_insn_and_split "ashldi3"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
 	(ashift:DI (match_operand:DI 1 "general_operand" "g")
 		   (match_operand:QI 2 "general_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ashift:DI (match_dup 1)
+		      (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ashldi3<ccn><ccnz><ccz>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(ashift:DI (match_operand:DI 1 "general_operand" "g")
+		   (match_operand:QI 2 "general_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "ashq %2,%D1,%0")
 
-(define_insn ""
+(define_insn_and_split "*ashlnegdi3"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
 	(ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
 		     (neg:QI (match_operand:QI 2 "general_operand" "g"))))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (ashiftrt:DI (match_dup 1)
+			(neg:QI (match_dup 2))))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*ashlnegdi3_2<ccn><ccnz><ccz>"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g")
+	(ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
+		     (neg:QI (match_operand:QI 2 "general_operand" "g"))))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "ashq %2,%D1,%0")
 
 ;; We used to have expand_shift handle logical right shifts by using extzv,
@@ -719,34 +1565,96 @@  (define_expand "rotrsi3"
     operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
 }")
 
-(define_insn "rotlsi3"
+(define_insn_and_split "rotlsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(rotate:SI (match_operand:SI 1 "general_operand" "nrmT")
 		   (match_operand:QI 2 "general_operand" "g")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (rotate:SI (match_dup 1)
+		      (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*rotlsi3<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(rotate:SI (match_operand:SI 1 "general_operand" "nrmT")
+		   (match_operand:QI 2 "general_operand" "g")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "rotl %2,%1,%0")
 
-(define_insn ""
+(define_insn_and_split "*rotrsi3_const_int"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
 		     (match_operand:QI 2 "const_int_operand" "n")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (rotatert:SI (match_dup 1)
+			(match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*rotrsi3_const_int_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
+		     (match_operand:QI 2 "const_int_operand" "n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "rotl %R2,%1,%0")
 
-(define_insn ""
+(define_insn_and_split "*rotrnegsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
 		     (neg:QI (match_operand:QI 2 "general_operand" "g"))))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (rotatert:SI (match_dup 1)
+			(neg:QI (match_dup 2))))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*rotrnegsi3_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
+		     (neg:QI (match_operand:QI 2 "general_operand" "g"))))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "rotl %2,%1,%0")
 
 ;; This insn is probably slower than a multiply and an add.
-;;(define_insn "*amulsi4"
+;;(define_insn_and_split "*amulsi4"
 ;;  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 ;;	(mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g")
 ;;			  (match_operand:SI 2 "general_operand" "g"))
 ;;		 (match_operand:SI 3 "general_operand" "g")))]
 ;;  ""
+;;  "#"
+;;  "reload_completed"
+;;  [(parallel
+;;     [(set (match_dup 0)
+;;	   (mult:SI (plus:SI (match_dup 1)
+;;			     (match_dup 2))
+;;		    (match_dup 3)))
+;;      (clobber (reg:CC VAX_PSL_REGNUM))])]
+;;  "")
+;;
+;;(define_insn "*amulsi4_2<ccn><ccnz><ccz>"
+;;  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;;	(mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g")
+;;			  (match_operand:SI 2 "general_operand" "g"))
+;;		 (match_operand:SI 3 "general_operand" "g")))
+;;   (clobber (reg:CC VAX_PSL_REGNUM))]
+;;  "reload_completed"
 ;;  "index %1,$0x80000000,$0x7fffffff,%3,%2,%0")
 
 ;; Special cases of bit-field insns which we should
@@ -754,7 +1662,7 @@  (define_insn ""
 ;; These handle aligned 8-bit and 16-bit fields
 ;; that can be done with move or convert instructions.
 
-(define_insn "*insv_aligned"
+(define_insn_and_split "*insv_aligned"
   [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+ro")
 			 (match_operand:QI 1 "const_int_operand" "n")
 			 (match_operand:SI 2 "const_int_operand" "n"))
@@ -770,6 +1678,34 @@  (define_insn "*insv_aligned"
    && (!(REG_P (operands[0])
 	 || (SUBREG_P (operands[0]) && REG_P (SUBREG_REG (operands[0]))))
        || INTVAL (operands[2]) == 0)"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (zero_extract:SI (match_dup 0)
+			    (match_dup 1)
+			    (match_dup 2))
+	   (match_dup 3))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*insv_aligned_2<ccn><ccnz><ccz>"
+  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+ro")
+			 (match_operand:QI 1 "const_int_operand" "n")
+			 (match_operand:SI 2 "const_int_operand" "n"))
+	(match_operand:SI 3 "general_operand" "g"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+   && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+   && (!MEM_P (operands[0])
+       || ((!flag_pic
+	    || vax_acceptable_pic_operand_p (XEXP (operands[0], 0),
+					     true, true))
+	   && !mode_dependent_address_p (XEXP (operands[0], 0),
+					 MEM_ADDR_SPACE (operands[0]))))
+   && (!(REG_P (operands[0])
+	 || (SUBREG_P (operands[0]) && REG_P (SUBREG_REG (operands[0]))))
+       || INTVAL (operands[2]) == 0)
+   && reload_completed"
   "*
 {
   if (!REG_P (operands[0]))
@@ -780,13 +1716,12 @@  (define_insn "*insv_aligned"
   else
     gcc_assert (INTVAL (operands[2]) == 0);
 
-  CC_STATUS_INIT;
   if (INTVAL (operands[1]) == 8)
     return \"movb %3,%0\";
   return \"movw %3,%0\";
 }")
 
-(define_insn "*extzv_aligned"
+(define_insn_and_split "*extzv_aligned"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=&g")
 	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
 			 (match_operand:QI 2 "const_int_operand" "n")
@@ -802,6 +1737,34 @@  (define_insn "*extzv_aligned"
    && (!(REG_P (operands[1])
 	 || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
        || INTVAL (operands[3]) == 0)"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (zero_extract:SI (match_dup 1)
+			    (match_dup 2)
+			    (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extzv_aligned_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=&g")
+	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+   && (!MEM_P (operands[1])
+       || ((!flag_pic
+	    || vax_acceptable_pic_operand_p (XEXP (operands[1], 0),
+					     true, true))
+	   && !mode_dependent_address_p (XEXP (operands[1], 0),
+					 MEM_ADDR_SPACE (operands[1]))))
+   && (!(REG_P (operands[1])
+	 || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
+       || INTVAL (operands[3]) == 0)
+   && reload_completed"
   "*
 {
   if (!REG_P (operands[1]))
@@ -817,7 +1780,7 @@  (define_insn "*extzv_aligned"
   return \"movzwl %1,%0\";
 }")
 
-(define_insn "*extv_aligned"
+(define_insn_and_split "*extv_aligned"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
 			 (match_operand:QI 2 "const_int_operand" "n")
@@ -833,6 +1796,34 @@  (define_insn "*extv_aligned"
    && (!(REG_P (operands[1])
 	 || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
        || INTVAL (operands[3]) == 0)"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (sign_extract:SI (match_dup 1)
+			    (match_dup 2)
+			    (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extv_aligned_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+			 (match_operand:QI 2 "const_int_operand" "n")
+			 (match_operand:SI 3 "const_int_operand" "n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+   && (!MEM_P (operands[1])
+       || ((!flag_pic
+	    || vax_acceptable_pic_operand_p (XEXP (operands[1], 0),
+					     true, true))
+	   && !mode_dependent_address_p (XEXP (operands[1], 0),
+					 MEM_ADDR_SPACE (operands[1]))))
+   && (!(REG_P (operands[1])
+	 || (SUBREG_P (operands[1]) && REG_P (SUBREG_REG (operands[1]))))
+       || INTVAL (operands[3]) == 0)
+   && reload_completed"
   "*
 {
   if (!REG_P (operands[1]))
@@ -850,24 +1841,24 @@  (define_insn "*extv_aligned"
 
 ;; Register and non-offsettable-memory SImode cases of bit-field insns.
 
-(define_insn "*cmpv"
-  [(set (cc0)
-	(compare
+(define_insn "*cmpv_<mode>"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc
 	 (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "ro")
 			  (match_operand:QI 1 "general_operand" "g")
 			  (match_operand:SI 2 "general_operand" "nrmT"))
 	 (match_operand:SI 3 "general_operand" "nrmT")))]
-  ""
+  "reload_completed"
   "cmpv %2,%1,%0,%3")
 
-(define_insn "*cmpzv"
-  [(set (cc0)
-	(compare
+(define_insn "*cmpzv_<mode>"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc
 	 (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "ro")
 			  (match_operand:QI 1 "general_operand" "g")
 			  (match_operand:SI 2 "general_operand" "nrmT"))
 	 (match_operand:SI 3 "general_operand" "nrmT")))]
-  ""
+  "reload_completed"
   "cmpzv %2,%1,%0,%3")
 
 ;; When the field position and size are constant and the destination
@@ -875,12 +1866,29 @@  (define_insn "*cmpzv"
 ;; by a bicl or sign extension.  Because we might end up choosing ext[z]v
 ;; anyway, we can't allow immediate values for the primary source operand.
 
-(define_insn "*extv_non_const"
+(define_insn_and_split "*extv_non_const"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
 			 (match_operand:QI 2 "general_operand" "g")
 			 (match_operand:SI 3 "general_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (sign_extract:SI (match_dup 1)
+			    (match_dup 2)
+			    (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extv_non_const_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+			 (match_operand:QI 2 "general_operand" "g")
+			 (match_operand:SI 3 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2])
@@ -892,12 +1900,29 @@  (define_insn "*extv_non_const"
   return \"rotl %R3,%1,%0\;cvtwl %0,%0\";
 }")
 
-(define_insn "*extzv_non_const"
+(define_insn_and_split "*extzv_non_const"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
 			 (match_operand:QI 2 "general_operand" "g")
 			 (match_operand:SI 3 "general_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (zero_extract:SI (match_dup 1)
+			    (match_dup 2)
+			    (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extzv_non_const_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+			 (match_operand:QI 2 "general_operand" "g")
+			 (match_operand:SI 3 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2])
@@ -918,24 +1943,24 @@  (define_insn "*extzv_non_const"
 ;; nonimmediate_operand is used to make sure that mode-ambiguous cases
 ;; don't match these (and therefore match the cases above instead).
 
-(define_insn "*cmpv_2"
-  [(set (cc0)
-	(compare
+(define_insn "*cmpv_2_<mode>"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc
 	 (sign_extract:SI (match_operand:QI 0 "memory_operand" "m")
 			  (match_operand:QI 1 "general_operand" "g")
 			  (match_operand:SI 2 "general_operand" "nrmT"))
 	 (match_operand:SI 3 "general_operand" "nrmT")))]
-  ""
+  "reload_completed"
   "cmpv %2,%1,%0,%3")
 
-(define_insn "*cmpzv_2"
-  [(set (cc0)
-	(compare
+(define_insn "*cmpzv_2_<mode>"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc
 	 (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
 			  (match_operand:QI 1 "general_operand" "g")
 			  (match_operand:SI 2 "general_operand" "nrmT"))
 	 (match_operand:SI 3 "general_operand" "nrmT")))]
-  ""
+  "reload_completed"
   "cmpzv %2,%1,%0,%3")
 
 (define_expand "extv"
@@ -946,12 +1971,29 @@  (define_expand "extv"
   ""
   "")
 
-(define_insn "*extv"
+(define_insn_and_split "*extv"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
 			 (match_operand:QI 2 "general_operand" "g")
 			 (match_operand:SI 3 "general_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (sign_extract:SI (match_dup 1)
+			    (match_dup 2)
+			    (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extv_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
+			 (match_operand:QI 2 "general_operand" "g")
+			 (match_operand:SI 3 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (!REG_P (operands[0]) || !CONST_INT_P (operands[2])
@@ -976,12 +2018,29 @@  (define_expand "extzv"
   ""
   "")
 
-(define_insn "*extzv"
+(define_insn_and_split "*extzv"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
 			 (match_operand:QI 2 "general_operand" "g")
 			 (match_operand:SI 3 "general_operand" "nrmT")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (zero_extract:SI (match_dup 1)
+			    (match_dup 2)
+			    (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*extzv_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
+			 (match_operand:QI 2 "general_operand" "g")
+			 (match_operand:SI 3 "general_operand" "nrmT")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   if (!REG_P (operands[0]) || !CONST_INT_P (operands[2])
@@ -1021,6 +2080,28 @@  (define_insn "*extzv"
   return \"rotl %R3,%1,%0\;bicl2 %M2,%0\";
 }")
 
+;; Combine EXTV/CMPL and EXTZV/CMPL sequences where the output of
+;; extraction is used for the comparison only into CMPV and CMPZV
+;; respectively.
+(define_peephole2
+  [(parallel
+     [(set (match_operand:SI 0 "register_operand")
+	   (any_extract:SI (match_operand 1 "general_operand")
+			   (match_operand:QI 2 "general_operand")
+			   (match_operand:SI 3 "general_operand")))
+      (clobber (reg:CC VAX_PSL_REGNUM))])
+   (set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc (match_dup 0)
+		       (match_operand:SI 4 "general_operand")))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc
+	  (any_extract:SI (match_dup 1)
+			  (match_dup 2)
+			  (match_dup 3))
+	  (match_dup 4)))]
+  "")
+
 (define_expand "insv"
   [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
 			 (match_operand:QI 1 "general_operand" "")
@@ -1029,6 +2110,7 @@  (define_expand "insv"
   ""
   "")
 
+;; This one actually doesn't change CC.
 (define_insn "*insv"
   [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
 			 (match_operand:QI 1 "general_operand" "g")
@@ -1060,6 +2142,7 @@  (define_insn "*insv"
   return \"insv %3,%2,%1,%0\";
 }")
 
+;; This one actually doesn't change CC.
 (define_insn "*insv_2"
   [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+ro")
 			 (match_operand:QI 1 "general_operand" "g")
@@ -1078,48 +2161,88 @@  (define_insn "jump"
 ;; Conditional jumps
 
 (define_expand "cbranch<mode>4"
-  [(set (cc0)
-        (compare (match_operand:VAXint 1 "nonimmediate_operand" "")
-                 (match_operand:VAXint 2 "general_operand" "")))
+  [(set (pc)
+	(if_then_else
+	  (match_operator 0 "ordered_comparison_operator"
+			  [(match_operand:VAXint 1 "general_operand" "")
+			   (match_operand:VAXint 2 "general_operand" "")])
+	  (label_ref (match_operand 3 "" ""))
+	  (pc)))]
+  ""
+  "")
+
+(define_insn_and_split "*cbranch<VAXint:mode>4_<VAXcc:mode>"
+  [(set (pc)
+	(if_then_else
+	  (match_operator 0 "vax_<cc>_comparison_operator"
+			  [(match_operand:VAXint 1 "general_operand" "nrmT")
+			   (match_operand:VAXint 2 "general_operand" "nrmT")])
+	  (label_ref (match_operand 3 "" ""))
+	  (pc)))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (reg:VAXcc VAX_PSL_REGNUM)
+	(compare:VAXcc (match_dup 1) (match_dup 2)))
    (set (pc)
-        (if_then_else
-              (match_operator 0 "ordered_comparison_operator" [(cc0)
-                                                               (const_int 0)])
-              (label_ref (match_operand 3 "" ""))
-              (pc)))]
- "")
+	(if_then_else
+	  (match_op_dup 0 [(reg:VAXcc VAX_PSL_REGNUM)
+			   (const_int 0)])
+	 (label_ref (match_operand 3 "" ""))
+	 (pc)))]
+  "")
 
 (define_expand "cbranch<mode>4"
-  [(set (cc0)
-        (compare (match_operand:VAXfp 1 "general_operand" "")
-                 (match_operand:VAXfp 2 "general_operand" "")))
+  [(set (pc)
+	(if_then_else
+	  (match_operator 0 "ordered_comparison_operator"
+			  [(match_operand:VAXfp 1 "general_operand" "")
+			   (match_operand:VAXfp 2 "general_operand" "")])
+	  (label_ref (match_operand 3 "" ""))
+	  (pc)))]
+  ""
+  "")
+
+(define_insn_and_split "*cbranch<VAXfp:mode>4_<VAXccnz:mode>"
+  [(set (pc)
+	(if_then_else
+	  (match_operator 0 "vax_<cc>_comparison_operator"
+			  [(match_operand:VAXfp 1 "general_operand" "gF")
+			   (match_operand:VAXfp 2 "general_operand" "gF")])
+	  (label_ref (match_operand 3 "" ""))
+	  (pc)))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (reg:VAXccnz VAX_PSL_REGNUM)
+	(compare:VAXccnz (match_dup 1) (match_dup 2)))
    (set (pc)
-        (if_then_else
-              (match_operator 0 "ordered_comparison_operator" [(cc0)
-                                                               (const_int 0)])
-              (label_ref (match_operand 3 "" ""))
-              (pc)))]
- "")
-
-(define_insn "*branch"
+	(if_then_else
+ 	  (match_op_dup 0 [(reg:VAXccnz VAX_PSL_REGNUM)
+			   (const_int 0)])
+	  (label_ref (match_operand 3 "" ""))
+	  (pc)))]
+  "")
+
+(define_insn "*branch_<mode>"
   [(set (pc)
-	(if_then_else (match_operator 0 "ordered_comparison_operator"
-				      [(cc0)
+	(if_then_else (match_operator 0 "vax_<cc>_comparison_operator"
+				      [(reg:VAXcc VAX_PSL_REGNUM)
 				       (const_int 0)])
 		      (label_ref (match_operand 1 "" ""))
 		      (pc)))]
-  ""
+  "reload_completed"
   "j%k0 %l1")
 
 ;; Recognize reversed jumps.
-(define_insn "*branch_reversed"
+(define_insn "*branch_<mode>_reversed"
   [(set (pc)
-	(if_then_else (match_operator 0 "ordered_comparison_operator"
-				      [(cc0)
+	(if_then_else (match_operator 0 "vax_<cc>_comparison_operator"
+				      [(reg:VAXcc VAX_PSL_REGNUM)
 				       (const_int 0)])
 		      (pc)
 		      (label_ref (match_operand 1 "" ""))))]
-  ""
+  "reload_completed"
   "j%K0 %l1") ; %K0 negates condition
 
 ;; Recognize jbs, jlbs, jbc and jlbc instructions.  Note that the operand
@@ -1189,7 +2312,7 @@  (define_insn ""
 
 ;; Normal sob insns.
 
-(define_insn ""
+(define_insn_and_split "*jsobgtr"
   [(set (pc)
 	(if_then_else
 	 (gt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1201,9 +2324,38 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int -1)))]
   "!TARGET_UNIX_ASM"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (gt (plus:SI (match_dup 0)
+			 (const_int -1))
+		(const_int 0))
+	    (label_ref (match_dup 1))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int -1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jsobgtr_2"
+  [(set (pc)
+	(if_then_else
+	 (gt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+		      (const_int -1))
+	     (const_int 0))
+	 (label_ref (match_operand 1 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int -1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_UNIX_ASM && reload_completed"
   "jsobgtr %0,%l1")
 
-(define_insn ""
+(define_insn_and_split "*jsobgeq"
   [(set (pc)
 	(if_then_else
 	 (ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1215,10 +2367,39 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int -1)))]
   "!TARGET_UNIX_ASM"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (ge (plus:SI (match_dup 0)
+			 (const_int -1))
+		(const_int 0))
+	    (label_ref (match_dup 1))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int -1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jsobgeq_2"
+  [(set (pc)
+	(if_then_else
+	 (ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+		      (const_int -1))
+	     (const_int 0))
+	 (label_ref (match_operand 1 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int -1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_UNIX_ASM && reload_completed"
   "jsobgeq %0,%l1")
 
 ;; Normal aob insns.  Define a version for when operands[1] is a constant.
-(define_insn ""
+(define_insn_and_split "*jaoblss"
   [(set (pc)
 	(if_then_else
 	 (lt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1230,9 +2411,38 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int 1)))]
   "!TARGET_UNIX_ASM"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (lt (plus:SI (match_dup 0)
+			 (const_int 1))
+		(match_dup 1))
+	    (label_ref (match_dup 2))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jaoblss_2"
+  [(set (pc)
+	(if_then_else
+	 (lt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+		      (const_int 1))
+	     (match_operand:SI 1 "general_operand" "nrmT"))
+	 (label_ref (match_operand 2 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int 1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_UNIX_ASM && reload_completed"
   "jaoblss %1,%0,%l2")
 
-(define_insn ""
+(define_insn_and_split "*jaoblss_const"
   [(set (pc)
 	(if_then_else
 	 (lt (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1243,9 +2453,36 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int 1)))]
   "!TARGET_UNIX_ASM && CONST_INT_P (operands[1])"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (lt (match_dup 0)
+		(match_dup 1))
+	    (label_ref (match_dup 2))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jaoblss_const_2"
+  [(set (pc)
+	(if_then_else
+	 (lt (match_operand:SI 0 "nonimmediate_operand" "+g")
+	     (match_operand:SI 1 "general_operand" "nrmT"))
+	 (label_ref (match_operand 2 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int 1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_UNIX_ASM && CONST_INT_P (operands[1]) && reload_completed"
   "jaoblss %P1,%0,%l2")
 
-(define_insn ""
+(define_insn_and_split "*jaobleq"
   [(set (pc)
 	(if_then_else
 	 (le (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1257,9 +2494,38 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int 1)))]
   "!TARGET_UNIX_ASM"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (le (plus:SI (match_dup 0)
+			 (const_int 1))
+		(match_dup 1))
+	    (label_ref (match_dup 2))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jaobleq_2"
+  [(set (pc)
+	(if_then_else
+	 (le (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g")
+		      (const_int 1))
+	     (match_operand:SI 1 "general_operand" "nrmT"))
+	 (label_ref (match_operand 2 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int 1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_UNIX_ASM && reload_completed"
   "jaobleq %1,%0,%l2")
 
-(define_insn ""
+(define_insn_and_split "*jaobleq_const"
   [(set (pc)
 	(if_then_else
 	 (le (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1270,12 +2536,39 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int 1)))]
   "!TARGET_UNIX_ASM && CONST_INT_P (operands[1])"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (le (match_dup 0)
+		(match_dup 1))
+	    (label_ref (match_dup 2))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int 1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jaobleq_const_2"
+  [(set (pc)
+	(if_then_else
+	 (le (match_operand:SI 0 "nonimmediate_operand" "+g")
+	     (match_operand:SI 1 "general_operand" "nrmT"))
+	 (label_ref (match_operand 2 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int 1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "!TARGET_UNIX_ASM && CONST_INT_P (operands[1]) && reload_completed"
   "jaobleq %P1,%0,%l2")
 
 ;; Something like a sob insn, but compares against -1.
 ;; This finds `while (foo--)' which was changed to `while (--foo != -1)'.
 
-(define_insn ""
+(define_insn_and_split "*jsobneq_minus_one"
   [(set (pc)
 	(if_then_else
 	 (ne (match_operand:SI 0 "nonimmediate_operand" "+g")
@@ -1286,6 +2579,33 @@  (define_insn ""
 	(plus:SI (match_dup 0)
 		 (const_int -1)))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (pc)
+	   (if_then_else
+	    (ne (match_dup 0)
+		(const_int 0))
+	    (label_ref (match_dup 1))
+	    (pc)))
+      (set (match_dup 0)
+	   (plus:SI (match_dup 0)
+		    (const_int -1)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*jsobneq_minus_one_2"
+  [(set (pc)
+	(if_then_else
+	 (ne (match_operand:SI 0 "nonimmediate_operand" "+g")
+	     (const_int 0))
+	 (label_ref (match_operand 1 "" ""))
+	 (pc)))
+   (set (match_dup 0)
+	(plus:SI (match_dup 0)
+		 (const_int -1)))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "decl %0\;jgequ %l1")
 
 (define_expand "call_pop"
@@ -1512,41 +2832,126 @@  (define_expand "casesi"
 ;; This insn is a bit of a lier.  It actually falls through if no case
 ;; matches.  But, we prevent that from ever happening by emitting a jump
 ;; before this, see the define_expand above.
-(define_insn "casesi1"
+(define_insn_and_split "casesi1"
   [(match_operand:SI 1 "const_int_operand" "n")
    (set (pc)
 	(plus:SI (sign_extend:SI
-		  (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "general_operand" "nrmT")
-					    (const_int 2))
-			  (pc))))
+		   (mem:HI (plus:SI
+			     (mult:SI
+			       (match_operand:SI 0 "general_operand" "nrmT")
+			       (const_int 2))
+			     (pc))))
 		 (label_ref:SI (match_operand 2 "" ""))))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(match_dup 1)
+      (set (pc)
+	   (plus:SI (sign_extend:SI
+		      (mem:HI (plus:SI
+				(mult:SI
+				  (match_dup 0)
+				  (const_int 2))
+				(pc))))
+		    (label_ref:SI (match_dup 2))))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*casesi1"
+  [(match_operand:SI 1 "const_int_operand" "n")
+   (set (pc)
+	(plus:SI (sign_extend:SI
+		   (mem:HI (plus:SI
+			     (mult:SI
+			       (match_operand:SI 0 "general_operand" "nrmT")
+			       (const_int 2))
+			     (pc))))
+		 (label_ref:SI (match_operand 2 "" ""))))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "casel %0,$0,%1")
 
-(define_insn "*pushsym"
+(define_insn_and_split "*pushsym"
   [(set (match_operand:SI 0 "push_operand" "=g")
 	(match_operand:SI 1 "pic_symbolic_operand" "A"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*pushsym_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "push_operand" "=g")
+	(match_operand:SI 1 "pic_symbolic_operand" "A"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "pushab %a1")
 
-(define_insn "*movsym"
+(define_insn_and_split "*movsym"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(match_operand:SI 1 "pic_symbolic_operand" "A"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movsym_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(match_operand:SI 1 "pic_symbolic_operand" "A"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "movab %a1,%0")
 
-(define_insn "*pushsymreg"
+(define_insn_and_split "*pushsymreg"
   [(set (match_operand:SI 0 "push_operand" "=g")
 	(plus:SI (match_operand:SI 1 "register_operand" "%r")
 		 (match_operand:SI 2 "pic_symbolic_operand" "A")))]
   "flag_pic"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:SI (match_dup 1)
+		    (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*pushsymreg_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "push_operand" "=g")
+	(plus:SI (match_operand:SI 1 "register_operand" "%r")
+		 (match_operand:SI 2 "pic_symbolic_operand" "A")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "flag_pic && reload_completed"
   "pushab %a2[%1]")
 
-(define_insn "*movsymreg"
+(define_insn_and_split "*movsymreg"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(plus:SI (match_operand:SI 1 "register_operand" "%r")
 		 (match_operand:SI 2 "pic_symbolic_operand" "A")))]
   "flag_pic"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (plus:SI (match_dup 1)
+		    (match_dup 2)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movsymreg_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(plus:SI (match_operand:SI 1 "register_operand" "%r")
+		 (match_operand:SI 2 "pic_symbolic_operand" "A")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "flag_pic && reload_completed"
   "movab %a2[%1],%0")
 
 ;;- load or push effective address
@@ -1557,28 +2962,80 @@  (define_insn "*movsymreg"
 ;; It does not work to use constraints to distinguish pushes from moves,
 ;; because < matches any autodecrement, not just a push.
 
-(define_insn "pushaddr<mode>"
+(define_insn_and_split "pushaddr<mode>"
   [(set (match_operand:SI 0 "push_operand" "=g")
 	(match_operand:VAXintQHSD 1 "address_operand" "p"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*pushaddr<mode><ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "push_operand" "=g")
+	(match_operand:VAXintQHSD 1 "address_operand" "p"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "pusha<VAXintQHSD:isfx> %a1")
 
-(define_insn "movaddr<mode>"
+(define_insn_and_split "movaddr<mode>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(match_operand:VAXintQHSD 1 "address_operand" "p"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movaddr<mode><ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(match_operand:VAXintQHSD 1 "address_operand" "p"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "mova<VAXintQHSD:isfx> %a1,%0")
 
-(define_insn "pushaddr<mode>"
+(define_insn_and_split "pushaddr<mode>"
   [(set (match_operand:SI 0 "push_operand" "=g")
 	(match_operand:VAXfp 1 "address_operand" "p"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*pushaddr<mode><ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "push_operand" "=g")
+	(match_operand:VAXfp 1 "address_operand" "p"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "pusha<VAXfp:fsfx> %a1")
 
-(define_insn "movaddr<mode>"
+(define_insn_and_split "movaddr<mode>"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
 	(match_operand:VAXfp 1 "address_operand" "p"))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (match_dup 1))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*movaddr<mode>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+	(match_operand:VAXfp 1 "address_operand" "p"))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "mova<VAXfp:fsfx> %a1,%0")
 
 ;; These used to be peepholes, but it is more straightforward to do them
@@ -1594,12 +3051,30 @@  (define_insn "movaddr<mode>"
 ;; with other operands constant.  This is what the combiner converts the
 ;; above sequences to before attempting to recognize the new insn.
 
-(define_insn ""
+(define_insn_and_split "*andashlnegsi4"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
 	(and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
 			     (match_operand:QI 2 "const_int_operand" "n"))
 		(match_operand:SI 3 "const_int_operand" "n")))]
   "(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0"
+  "#"
+  "&& reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (and:SI (ashiftrt:SI (match_dup 1)
+				(match_dup 2))
+		   (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*andashlnegsi4_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
+	(and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
+			     (match_operand:QI 2 "const_int_operand" "n"))
+		(match_operand:SI 3 "const_int_operand" "n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0
+   && reload_completed"
   "*
 {
   unsigned long mask1 = INTVAL (operands[3]);
@@ -1616,12 +3091,29 @@  (define_insn ""
 ;; bits that the ashl would anyways, in which case it should have been
 ;; optimized away.
 
-(define_insn ""
+(define_insn_and_split "*andashlsi4"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
 	(and:SI (ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
 			   (match_operand:QI 2 "const_int_operand" "n"))
 		(match_operand:SI 3 "const_int_operand" "n")))]
   ""
+  "#"
+  "reload_completed"
+  [(parallel
+     [(set (match_dup 0)
+	   (and:SI (ashift:SI (match_dup 1)
+			      (match_dup 2))
+		   (match_dup 3)))
+      (clobber (reg:CC VAX_PSL_REGNUM))])]
+  "")
+
+(define_insn "*andashlsi4_2<ccn><ccnz><ccz>"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=ro")
+	(and:SI (ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
+			   (match_operand:QI 2 "const_int_operand" "n"))
+		(match_operand:SI 3 "const_int_operand" "n")))
+   (clobber (reg:CC VAX_PSL_REGNUM))]
+  "reload_completed"
   "*
 {
   operands[3]