From: Maciej W. Rozycki Date: Sat, 5 Dec 2020 18:26:27 +0000 (+0000) Subject: PR target/95294: VAX: Convert backend to MODE_CC representation X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e552abe2ba27ccec0d7c0d050b4617f2f636dd63;p=gcc.git PR target/95294: VAX: Convert backend to MODE_CC representation In the VAX ISA INSV bit-field insert instruction is the only computational operation that keeps the condition codes, held in the PSL or Processor Status Longword register, intact. The instruction is flexible enough it could potentially be used for data moves post-reload, but then reportedly it is not the best choice performance-wise, and then we have no addition operation available that would keep the condition codes unchanged. Futhermore, as usually with a complex CISC ISA, for many operations we have several machine instructions or instruction sequences to choose from that set condition codes in a different manner. Use the approach then where the condition codes only get introduced by reload, by definining instruction splitters for RTL insns that change condition codes in some way, by default considering them clobbered. Then to prevent code generated from regressing too much provide insns that include a `compare' operation setting the condition codes in parallel to the main operation. The manner condition codes are set by each insn is supposed to be provided by the whatever the SELECT_CC_MODE macro expands to. Given that individual patterns provided for the same RTL basic operation may set the condion codes differently keeping the information away from the insn patterns themselves would cause a maintenance nightmare and would be bound to fail in a horrible way sooner or later. Therefore instead let the patterns themselves choose which condition modes they support, by having one or more subst iterators applied and then have individual comparison operators require the specific condition mode each according to the codes used by the operation. While subst iterators only support one alternative each, there is actually no problem with applying multiple ones to a single insn with the result as intended, and if the corresponding subst attribute supplies an empty NO-SUBST-VALUE, then no mess results even. Make use of this observation. Add appropriate subst iterators to all the computational patterns then, according to the condition codes they usably set, including DImode ones and a substitute DImode comparison instruction in the absence of a CMPQ machine instruction, however do not provide a `cbranchdi4' named pattern as without a further development it regresses code quality by resorting to the `__cmpdi2' libcall where a simpler operation would do, e.g. to check for negativity the TSTL machine instruction may be executed over the upper longword only. This is good material for further work. Do not apply subst iterators to the increment- or decrement-and-branch patterns at this time; these may yet have to be reviewed, in particular whether `*jsobneq_minus_one' is still relevant in the context of the recent integer constant cost review. Also add a couple of peepholes to help eliminating comparisons in some problematic cases, such as with the BIT instruction which is bitwise-AND for condition codes only that has no direct counterpart for the actual calculation, because the BIC instruction which does do bitwise-AND and produces a result implements the operation with a bitwise negation of its input `mask' operand. Or the FFS instruction which sets the Z condition code according to its `field' input operand rather than the result produced. Or the bit-field comparisons we don't have generic middle-end support for. Code size stats are as follows, obtained from 17640 and 9086 executables built in `check-c' and `check-c++' GCC testing respectively: check-c check-c++ samples average median samples average median --------------------------------------------------------------- regressions 1813 0.578% 0.198% 289 0.349% 0.175% unchanged 15160 0.000% 0.000% 8662 0.000% 0.000% progressions 667 -0.589% -0.194% 135 -0.944% -0.191% ---------------------------------------------------------------- total 17640 0.037% 0.000% 9086 -0.003% 0.000% Outliers: old new change %change filename ---------------------------------------------------- 2406 2950 +544 +22.610 20111208-1.exe 4314 5329 +1015 +23.528 pr39417.exe 2235 3055 +820 +36.689 990404-1.exe 2631 4213 +1582 +60.129 pr57521.exe 3063 5579 +2516 +82.142 20000422-1.exe and: old new change %change filename ---------------------------------------------------- 6317 4845 -1472 -23.302 vector-compare-1.exe 6313 4845 -1468 -23.254 vector-compare-1.exe 6474 5002 -1472 -22.737 vector-compare-1.exe 6470 5002 -1468 -22.689 vector-compare-1.exe We have some code quality regressions like: 10861: 9e ef d9 12 movab 11b40

,r0 10865: 00 00 50 10868: 90 a0 03 a0 movb 0x3(r0),0x2(r0) 1086c: 02 1086d: d1 60 8f 61 cmpl (r0),$0x64646261 10871: 62 64 64 10874: 13 07 beql 1087d to: 10861: 9e ef e1 12 movab 11b48

,r0 10865: 00 00 50 10868: 90 a0 03 a0 movb 0x3(r0),0x2(r0) 1086c: 02 1086d: d1 ef d5 12 cmpl 11b48

,$0x64646261 10871: 00 00 8f 61 10875: 62 64 64 10878: 13 07 beql 10881 (from `memmove-2.x2') due to the constant propagation passes eagerly replacing pseudo registers with direct symbol references where possible, which does not happen with CC0 even though the passes do run regardless. There are further code quality regressions due to earlier compilation stages trying to push expression evaluation earlier where possible so as to make data dependencies further apart from each other. This works well for computations and architectures that do not involve condition codes set as a side effect of calculations. However for integer negation that makes assembly code produced like: movb *8(%ap),%r0 mnegb %r0,%r1 tstb %r0 jeql .L2 the RTL equibvalent of which the comparison elimination pass cannot really do anything about, because the comparison is made on the source rather than the target operand of the negation (we could add a peephole for this, but this seems futile an effort, as one'd have to iterate over all the possible such cases), even though this is really equivalent to: movb *8(%ap),%r0 mnegb %r0,%r1 jeql .L2 or, if R0 is dead at the conclusion of the branch, even: mnegb *8(%ap),%r1 jeql .L2 Since the compiler insists on doing the comparison on the source of the negation it obviously has to load it into a temporary so as to avoid accessing the original memory location twice, hence the sequence of three instructions rather than just a single one. A similar phenomenon can be observed with the XOR operation and in other cases. In some cases a comparison does get eliminated, however useless moves into registers done in preparation to it remain, such as with: movb *8(%ap),%r2 movb *12(%ap),%r1 subb3 %r1,%r2,%r0 jlssu .L2 where R1 and R2 are both dead at conclusion and therefore: subb3 *12(%ap),*8(%ap),%r0 jlssu .L2 would obviously do, but there was to be a comparison before the branch: cmpb %r2,%r1 All this looks like material for future improvement. Test cases for comparison elimination and the peepholes will be supplied separately. gcc/ PR target/95294 * config/vax/elf.h (REGISTER_NAMES): Append `%psl'. * config/vax/vax-modes.def (CCN, CCNZ, CCZ): New modes. * config/vax/vax-protos.h (vax_select_cc_mode): New prototype. (vax_maybe_split_dimode_move): Likewise. (vax_notice_update_cc): Remove prototype. * config/vax/vax.c (TARGET_FLAGS_REGNUM): New macro. (TARGET_CC_MODES_COMPATIBLE): Likewise. (TARGET_MD_ASM_ADJUST): Likewise. (vax_select_cc_mode): New function (vax_cc_modes_compatible): Likewise. (vax_md_asm_adjust): Likewise. (vax_notice_update_cc): Remove function. (vax_output_int_move): Factor out code checking if a DImode move may have to be split... (vax_maybe_split_dimode_move): ... into this new function. * config/vax/vax.h (FIRST_PSEUDO_REGISTER): Bump up. (FIXED_REGISTERS): Append an entry for PSL. (CALL_USED_REGISTERS): Likewise. (NOTICE_UPDATE_CC, OUTPUT_JUMP): Remove macros. (SELECT_CC_MODE): New macro. (REGISTER_NAMES): Append `psl'. * config/vax/predicates.md (const_zero_operand) (vax_cc_comparison_operator, vax_ccn_comparison_operator) (vax_ccnz_comparison_operator, vax_ccz_comparison_operator): New predicates. * config/vax/builtins.md: Rewrite for MODE_CC representation. * config/vax/vax.md: Likewise. --- diff --git a/gcc/config/vax/builtins.md b/gcc/config/vax/builtins.md index e96ac3f52ab..846d1f352ff 100644 --- a/gcc/config/vax/builtins.md +++ b/gcc/config/vax/builtins.md @@ -39,10 +39,10 @@ { 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_ctz2 (operands[0], operands[1])); + emit_insn (gen_ctz2_ccz (operands[0], operands[1])); emit_jump_insn (gen_rtx_SET (pc_rtx, target)); emit_insn (gen_neg2 (operands[0], const1_rtx)); emit_label (label); @@ -50,33 +50,114 @@ DONE; }") -(define_insn "ctz2" +(define_insn_and_split "ctz2" + [(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 "*ctz2" [(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,$,%1,%0") + +(define_insn_and_split "ctz2_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 "*ctz2_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,$,%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 "ctz2_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 `ffs2'. +(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" diff --git a/gcc/config/vax/elf.h b/gcc/config/vax/elf.h index 530b2c05ed2..f6485eca3f4 100644 --- a/gcc/config/vax/elf.h +++ b/gcc/config/vax/elf.h @@ -26,7 +26,8 @@ along with GCC; see the file COPYING3. If not see #define REGISTER_PREFIX "%" #define REGISTER_NAMES \ { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", \ - "%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", } + "%r8", "%r9", "%r10", "%r11", "%ap", "%fp", "%sp", "%pc", \ + "%psl" } #undef SIZE_TYPE #define SIZE_TYPE "long unsigned int" diff --git a/gcc/config/vax/predicates.md b/gcc/config/vax/predicates.md index 7c97b366604..92caf8384fa 100644 --- a/gcc/config/vax/predicates.md +++ b/gcc/config/vax/predicates.md @@ -17,6 +17,10 @@ ;; along with GCC; see the file COPYING3. If not see ;; . +;; 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 "any_memory_operand" (ior (match_operand 0 "memory_operand") (match_operand 0 "volatile_mem_operand"))) + +;; Return true if OP is a comparison operator that requires at least CCmode. +(define_predicate "vax_cc_comparison_operator" + (match_code "geu,gtu,leu,ltu")) + +;; Return true if OP is a comparison operator that requires at least CCNmode. +(define_predicate "vax_ccn_comparison_operator" + (match_code "ge,lt")) + +;; Return true if OP is a comparison operator that requires at least CCNZmode. +(define_predicate "vax_ccnz_comparison_operator" + (match_code "gt,le")) + +;; Return true if OP is a comparison operator that requires at least CCZmode. +(define_predicate "vax_ccz_comparison_operator" + (match_code "ne,eq")) diff --git a/gcc/config/vax/vax-modes.def b/gcc/config/vax/vax-modes.def index 5f1c9946653..2a7438ee77f 100644 --- a/gcc/config/vax/vax-modes.def +++ b/gcc/config/vax/vax-modes.def @@ -20,3 +20,14 @@ along with GCC; see the file COPYING3. If not see /* We just need to reset the floating point formats. */ RESET_FLOAT_FORMAT (SF, vax_f_format); RESET_FLOAT_FORMAT (DF, vax_d_format); + +/* `DImode' addition and subtraction operations do their calculation + on the low and then the high longword with separate instructions, + and therefore only usably set N. */ +CC_MODE (CCN); +/* Non-arithmetic integer instructions such as MOV or XOR as well as + instructions that produce a floating-point result only usably set + N and Z. */ +CC_MODE (CCNZ); +/* The FFC and FFS instructions only usably set Z. */ +CC_MODE (CCZ); diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h index 454d35e3383..aa949c598d7 100644 --- a/gcc/config/vax/vax-protos.h +++ b/gcc/config/vax/vax-protos.h @@ -22,13 +22,14 @@ extern void vax_expand_prologue (void); #ifdef RTX_CODE extern bool vax_acceptable_pic_operand_p (rtx, bool, bool); +extern machine_mode vax_select_cc_mode (enum rtx_code, rtx, rtx); extern const char *cond_name (rtx); extern bool adjacent_operands_p (rtx, rtx, machine_mode); extern const char *rev_cond_name (rtx); extern void print_operand_address (FILE *, rtx); extern void print_operand (FILE *, rtx, int); -extern void vax_notice_update_cc (rtx, rtx); extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code); +extern bool vax_maybe_split_dimode_move (rtx *); extern const char * vax_output_int_move (rtx, rtx *, machine_mode); extern const char * vax_output_int_add (rtx_insn *, rtx *, machine_mode); extern const char * vax_output_int_subtract (rtx_insn *, rtx *, machine_mode); diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index 69a05b33e95..54d83dc1da2 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -54,6 +54,10 @@ static void vax_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, static int vax_address_cost_1 (rtx); static int vax_address_cost (rtx, machine_mode, addr_space_t, bool); static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool); +static machine_mode vax_cc_modes_compatible (machine_mode, machine_mode); +static rtx_insn *vax_md_asm_adjust (vec &, vec &, + vec &, + vec &, 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 &outputs ATTRIBUTE_UNUSED, + vec &inputs ATTRIBUTE_UNUSED, + vec &constraints ATTRIBUTE_UNUSED, + vec &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 #conservative entry mask @@ -1102,81 +1214,21 @@ vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM); } -/* Worker function for NOTICE_UPDATE_CC. */ +/* Output integer move instructions. */ -void -vax_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) +bool +vax_maybe_split_dimode_move (rtx *operands) { - if (GET_CODE (exp) == SET) - { - if (GET_CODE (SET_SRC (exp)) == CALL) - CC_STATUS_INIT; - else if (GET_CODE (SET_DEST (exp)) != ZERO_EXTRACT - && GET_CODE (SET_DEST (exp)) != PC) - { - cc_status.flags = 0; - /* The integer operations below don't set carry or - set it in an incompatible way. That's ok though - as the Z bit is all we need when doing unsigned - comparisons on the result of these insns (since - they're always with 0). Set CC_NO_OVERFLOW to - generate the correct unsigned branches. */ - switch (GET_CODE (SET_SRC (exp))) - { - case NEG: - if (GET_MODE_CLASS (GET_MODE (exp)) == MODE_FLOAT) - break; - /* FALLTHRU */ - case AND: - case IOR: - case XOR: - case NOT: - case MEM: - case REG: - cc_status.flags = CC_NO_OVERFLOW; - break; - case CTZ: - cc_status.flags = CC_NOT_NEGATIVE; - break; - default: - break; - } - cc_status.value1 = SET_DEST (exp); - cc_status.value2 = SET_SRC (exp); - } - } - else if (GET_CODE (exp) == PARALLEL - && GET_CODE (XVECEXP (exp, 0, 0)) == SET) - { - if (GET_CODE (SET_SRC (XVECEXP (exp, 0, 0))) == CALL) - CC_STATUS_INIT; - else if (GET_CODE (SET_DEST (XVECEXP (exp, 0, 0))) != PC) - { - cc_status.flags = 0; - cc_status.value1 = SET_DEST (XVECEXP (exp, 0, 0)); - cc_status.value2 = SET_SRC (XVECEXP (exp, 0, 0)); - } - else - /* PARALLELs whose first element sets the PC are aob, - sob insns. They do change the cc's. */ - CC_STATUS_INIT; - } - else - CC_STATUS_INIT; - if (cc_status.value1 && REG_P (cc_status.value1) - && cc_status.value2 - && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) - cc_status.value2 = 0; - if (cc_status.value1 && MEM_P (cc_status.value1) - && cc_status.value2 - && MEM_P (cc_status.value2)) - cc_status.value2 = 0; - /* Actual condition, one line up, should be that value2's address - depends on value1, but that is too much of a pain. */ + return (TARGET_QMATH + && (!MEM_P (operands[0]) + || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC + || GET_CODE (XEXP (operands[0], 0)) == POST_INC + || !illegal_addsub_di_memory_operand (operands[0], DImode)) + && ((CONST_INT_P (operands[1]) + && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64) + || GET_CODE (operands[1]) == CONST_DOUBLE)); } -/* Output integer move instructions. */ - const char * vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands, machine_mode mode) @@ -1252,14 +1304,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands, } } - if (TARGET_QMATH - && (!MEM_P (operands[0]) - || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC - || GET_CODE (XEXP (operands[0], 0)) == POST_INC - || !illegal_addsub_di_memory_operand (operands[0], DImode)) - && ((CONST_INT_P (operands[1]) - && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64) - || GET_CODE (operands[1]) == CONST_DOUBLE)) + if (vax_maybe_split_dimode_move (operands)) { hi[0] = operands[0]; hi[1] = operands[1]; diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index 43182ff1d88..8b2b2d17704 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -120,12 +120,12 @@ along with GCC; see the file COPYING3. If not see from 0 to just below FIRST_PSEUDO_REGISTER. All registers that the compiler knows about must be given numbers, even those that are not normally considered general registers. */ -#define FIRST_PSEUDO_REGISTER 16 +#define FIRST_PSEUDO_REGISTER 17 /* 1 for registers that have pervasive standard uses and are not available for the register allocator. On the VAX, these are the AP, FP, SP and PC. */ -#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1} +#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} /* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any @@ -133,7 +133,7 @@ along with GCC; see the file COPYING3. If not see The latter must include the registers where values are returned and the register where structure-value addresses are passed. Aside from that, you can include as many other registers as you like. */ -#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1} +#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1} /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -465,24 +465,11 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; #define BRANCH_COST(speed_p, predictable_p) 0 -/* Tell final.c how to eliminate redundant test instructions. */ - -/* Here we define machine-dependent flags and fields in cc_status - (see `conditions.h'). No extra ones are needed for the VAX. */ - -/* Store in cc_status the expressions - that the condition codes will describe - after execution of an instruction whose pattern is EXP. - Do not alter them if the instruction would not alter the cc's. */ - -#define NOTICE_UPDATE_CC(EXP, INSN) \ - vax_notice_update_cc ((EXP), (INSN)) - -#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \ - { if (cc_status.flags & CC_NO_OVERFLOW) \ - return NO_OV; \ - return NORMAL; \ - } +/* Given a comparison code (NE, EQ, etc.) and the operands of a COMPARE, + return the mode to be used for the comparison. As we have the same + interpretation of condition codes across all the instructions we just + return the narrowest mode suitable for the comparison code requested. */ +#define SELECT_CC_MODE(OP, X, Y) vax_select_cc_mode (OP, X, Y) /* Control the assembler format that we output. */ @@ -517,7 +504,8 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; #define REGISTER_PREFIX "" #define REGISTER_NAMES \ { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", } + "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", \ + "psl" } /* This is BSD, so it wants DBX format. */ diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md index 1bb4e300cae..b8cf4eed4bc 100644 --- a/gcc/config/vax/vax.md +++ b/gcc/config/vax/vax.md @@ -22,9 +22,6 @@ ;;- the first one in the file is chosen. ;;- ;;- See file "rtl.def" for documentation on define_insn, match_*, et al. -;;- -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. ;; UNSPEC_VOLATILE usage: @@ -40,6 +37,8 @@ (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 @@ ;; 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" - [(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_" + [(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" + [(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_" + [(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 %0 cmp %0,%1") -(define_insn "*cmp" - [(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_" + [(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_" + [(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 %0 cmp %0,%1") -(define_insn "*bit" - [(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_" + [(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 %0,%1") ;; The VAX has no sCOND insns. It does have add/subtract with carry @@ -95,25 +156,76 @@ ;; and has been deleted. -(define_insn "mov" +(define_insn_and_split "mov" [(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" + [(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 %0 mov %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" +;; [(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" + [(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 @@ #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" + [(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" +(define_insn_and_split "mov" [(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" + [(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);") -(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" + [(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 @@ 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" + [(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 @@ ;; 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 @@ (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" + [(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" + [(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" + [(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" + [(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" + [(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" + [(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" + [(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" + [(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" + [(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" + [(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" + [(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 "float2" +(define_insn_and_split "float2" [(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 "*float2" + [(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 %1,%0") ;; Float-to-fix conversion insns. -(define_insn "fix_trunc2" +(define_insn_and_split "fix_trunc2" [(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_trunc2" + [(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 %1,%0") (define_expand "fixuns_trunc2" @@ -340,21 +700,51 @@ ;;- All kinds of add instructions. -(define_insn "add3" +(define_insn_and_split "add3" [(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 "*add3" + [(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" "@ add2 %2,%0 add2 %1,%0 add3 %1,%2,%0") -(define_insn "add3" +(define_insn_and_split "add3" [(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 "*add3" + [(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);") (define_expand "adddi3" @@ -364,37 +754,109 @@ "!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" + [(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" + [(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 "sub3" +(define_insn_and_split "sub3" [(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 "*sub3" + [(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" "@ sub2 %2,%0 sub3 %2,%1,%0") -(define_insn "sub3" +(define_insn_and_split "sub3" [(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 "*sub3" + [(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" + "@ + sub2 %2,%0 + sub3 %2,%1,%0") + +(define_insn "*sub3_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" "@ sub2 %2,%0 sub3 %2,%1,%0") @@ -406,52 +868,129 @@ "!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" + [(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" + [(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 "mul3" +(define_insn_and_split "mul3" [(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 "*mul3" + [(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" "@ mul2 %2,%0 mul2 %1,%0 mul3 %1,%2,%0") -(define_insn "mul3" +(define_insn_and_split "mul3" [(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 "*mul3" + [(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" "@ mul2 %2,%0 mul2 %1,%0 mul3 %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" + [(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 @@ (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" + [(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 @@ (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" + [(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 @@ ;;- Divide instructions. -(define_insn "div3" +(define_insn_and_split "div3" [(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 "*div3" + [(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" "@ div2 %2,%0 div3 %2,%1,%0") -(define_insn "div3" +(define_insn_and_split "div3" [(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 "*div3" + [(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" "@ div2 %2,%0 div3 %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 @@ ;; (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" +;; [(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 @@ operands[1] = expand_unop (mode, one_cmpl_optab, op1, 0, 1); }") -(define_insn "*and" +(define_insn_and_split "*and3" [(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 "*and3_2" + [(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" "@ bic2 %1,%0 bic3 %1,%2,%0") @@ -548,23 +1200,80 @@ ;; longer a problem. However, having these patterns allows optimization ;; opportunities in combine.c. -(define_insn "*and_const_int" +(define_insn_and_split "*and3_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 "*and3_2_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"))) + (clobber (reg:CC VAX_PSL_REGNUM))] + "reload_completed" "@ bic2 %2,%0 bic3 %2,%1,%0") +;; We have no direct AND operation and consequently the RTL sequence +;; the "and3" pattern produces does not match the instruction +;; the "*bit" 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 "ior3" +(define_insn_and_split "ior3" [(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 "*ior3" + [(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" "@ bis2 %2,%0 bis2 %1,%0 @@ -572,35 +1281,97 @@ ;;- xor instructions. -(define_insn "xor3" +(define_insn_and_split "xor3" [(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 "*xor3" + [(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" "@ xor2 %2,%0 xor2 %1,%0 xor3 %2,%1,%0") - -(define_insn "neg2" +(define_insn_and_split "neg2" [(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 "*neg2" + [(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 %1,%0") -(define_insn "neg2" +(define_insn_and_split "neg2" [(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 "*neg2" + [(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 %1,%0") + +(define_insn "*neg2_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 %1,%0") -(define_insn "one_cmpl2" +(define_insn_and_split "one_cmpl2" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g") (not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))] "" - "mcom %1,%0") + "#" + "reload_completed" + [(parallel + [(set (match_dup 0) + (not:VAXint (match_dup 1))) + (clobber (reg:CC VAX_PSL_REGNUM))])] + "") +(define_insn "*one_cmpl2" + [(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 %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 @@ 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" + [(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" + [(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" + [(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 @@ 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" + [(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" + [(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 @@ 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" + [(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" + [(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" + [(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" +;; [(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 @@ ;; 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 @@ && (!(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" + [(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 @@ 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 @@ && (!(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" + [(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 @@ 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 @@ && (!(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" + [(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 @@ ;; Register and non-offsettable-memory SImode cases of bit-field insns. -(define_insn "*cmpv" - [(set (cc0) - (compare +(define_insn "*cmpv_" + [(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_" + [(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 @@ ;; 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" + [(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 @@ 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" + [(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 @@ ;; 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_" + [(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_" + [(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_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" + [(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_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" + [(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 @@ 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 @@ "" "") +;; 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 @@ 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 @@ ;; Conditional jumps (define_expand "cbranch4" - [(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 "*cbranch4_" + [(set (pc) + (if_then_else + (match_operator 0 "vax__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 "cbranch4" - [(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 "*cbranch4_" + [(set (pc) + (if_then_else + (match_operator 0 "vax__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_" [(set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) + (if_then_else (match_operator 0 "vax__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__reversed" [(set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(cc0) + (if_then_else (match_operator 0 "vax__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 @@ ;; 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 @@ (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 @@ (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 @@ (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 @@ (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 @@ (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 @@ (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 @@ (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 @@ ;; 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" + [(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" + [(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" + [(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" + [(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 @@ ;; It does not work to use constraints to distinguish pushes from moves, ;; because < matches any autodecrement, not just a push. -(define_insn "pushaddr" +(define_insn_and_split "pushaddr" [(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" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:VAXintQHSD 1 "address_operand" "p")) + (clobber (reg:CC VAX_PSL_REGNUM))] + "reload_completed" "pusha %a1") -(define_insn "movaddr" +(define_insn_and_split "movaddr" [(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" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (match_operand:VAXintQHSD 1 "address_operand" "p")) + (clobber (reg:CC VAX_PSL_REGNUM))] + "reload_completed" "mova %a1,%0") -(define_insn "pushaddr" +(define_insn_and_split "pushaddr" [(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" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:VAXfp 1 "address_operand" "p")) + (clobber (reg:CC VAX_PSL_REGNUM))] + "reload_completed" "pusha %a1") -(define_insn "movaddr" +(define_insn_and_split "movaddr" [(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" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (match_operand:VAXfp 1 "address_operand" "p")) + (clobber (reg:CC VAX_PSL_REGNUM))] + "reload_completed" "mova %a1,%0") ;; These used to be peepholes, but it is more straightforward to do them @@ -1594,12 +3051,30 @@ ;; 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" + [(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 @@ ;; 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" + [(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]