@@ -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>"
@@ -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"
@@ -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"))
@@ -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);
@@ -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);
@@ -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];
@@ -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. */
@@ -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]