diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-01-20 03:59:00 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-01-20 03:59:00 +0000 |
commit | 91bc47b0da3cd48bd112287ebdbf508712647243 (patch) | |
tree | cda4b7c4fa5fd8c63fdd336bd609206fd5423cd2 /gcc/config/alpha | |
parent | 54d60d02d41bba36cdfa8aab8e7b7b923cdf336d (diff) | |
download | gcc-91bc47b0da3cd48bd112287ebdbf508712647243.tar.gz |
PR target/19518
* config/alpha/alpha.c (alpha_rtx_costs): Handle HIGH.
(alpha_preferred_reload_class): Handle CONST_VECTOR.
(alpha_emit_set_const_1): Add no_output parameter; don't emit
rtl if true.
(alpha_emit_set_const): Likewise. Make static.
(alpha_emit_set_long_const): Make static.
(alpha_extract_integer): Split out from alpha_expand_mov.
(alpha_split_const_mov): Likewise.
(alpha_expand_mov): Use them. Handle CONST_VECTOR.
(alpha_legitimate_constant_p): New.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.h (REGISTER_MOVE_COST): Correct fp<->gp cost.
(LEGITIMATE_CONSTANT_P): Re-implement with a function.
* config/alpha/alpha.md (movsi): Add n alternative.
(movsi_nt_vms, movdi_er_nofix, movdi_er_fix, movdi_fix): Likewise.
(mov<VEC>_fix, mov<VEC>_nofix): Add i alternative.
(splitters for all of the above): Use alpha_split_const_mov.
* config/alpha/predicates.md (non_add_const_operand): New.
(non_zero_const_operand): New.
(input_operand): Use alpha_legitimate_constant_p after reload.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@93943 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/alpha')
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 342 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 12 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 99 | ||||
-rw-r--r-- | gcc/config/alpha/predicates.md | 21 |
5 files changed, 335 insertions, 143 deletions
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 24f24e6b2bf..d1ffada3dcf 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -42,6 +42,7 @@ extern bool alpha_extra_constraint (rtx, int); extern rtx alpha_tablejump_addr_vec (rtx); extern rtx alpha_tablejump_best_label (rtx); +extern bool alpha_legitimate_constant_p (rtx); extern bool alpha_legitimate_address_p (enum machine_mode, rtx, int); extern rtx alpha_legitimize_address (rtx, rtx, enum machine_mode); extern rtx alpha_legitimize_reload_address (rtx, enum machine_mode, @@ -56,8 +57,7 @@ extern enum reg_class secondary_reload_class (enum reg_class, enum machine_mode, rtx, int); extern void alpha_set_memflags (rtx, rtx); -extern rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT, int); -extern rtx alpha_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT); +extern bool alpha_split_const_mov (enum machine_mode, rtx *); extern bool alpha_expand_mov (enum machine_mode, rtx *); extern bool alpha_expand_mov_nobwx (enum machine_mode, rtx *); extern void alpha_expand_movmisalign (enum machine_mode, rtx *); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index aed7ada5619..037dc4ad33e 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1384,6 +1384,11 @@ alpha_rtx_costs (rtx x, int code, int outer_code, int *total) *total = COSTS_N_INSNS (optimize_size ? 1 : alpha_memory_latency); return true; + case HIGH: + /* This is effectively an add_operand. */ + *total = 2; + return true; + case PLUS: case MINUS: if (float_mode_p) @@ -1557,7 +1562,9 @@ alpha_preferred_reload_class(rtx x, enum reg_class class) return class; /* These sorts of constants we can easily drop to memory. */ - if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) + if (GET_CODE (x) == CONST_INT + || GET_CODE (x) == CONST_DOUBLE + || GET_CODE (x) == CONST_VECTOR) { if (class == FLOAT_REGS) return NO_REGS; @@ -1679,11 +1686,16 @@ alpha_set_memflags (rtx insn, rtx ref) for_each_rtx (base_ptr, alpha_set_memflags_1, (void *) ref); } -/* Internal routine for alpha_emit_set_const to check for N or below insns. */ +static rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT, + int, bool); + +/* Internal routine for alpha_emit_set_const to check for N or below insns. + If NO_OUTPUT is true, then we only check to see if N insns are possible, + and return pc_rtx if successful. */ static rtx alpha_emit_set_const_1 (rtx target, enum machine_mode mode, - HOST_WIDE_INT c, int n) + HOST_WIDE_INT c, int n, bool no_output) { HOST_WIDE_INT new; int i, bits; @@ -1722,6 +1734,8 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, emit_move_insn to gen_movdi. So instead, since we know exactly what we want, create it explicitly. */ + if (no_output) + return pc_rtx; if (target == NULL) target = gen_reg_rtx (mode); emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c))); @@ -1729,6 +1743,8 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, } else if (n >= 2 + (extra != 0)) { + if (no_output) + return pc_rtx; if (no_new_pseudos) { emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (high << 16))); @@ -1781,14 +1797,26 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, high bits. */ new = ((c & 0xffff) ^ 0x8000) - 0x8000; - if (new != 0 - && (temp = alpha_emit_set_const (subtarget, mode, c - new, i)) != 0) - return expand_binop (mode, add_optab, temp, GEN_INT (new), - target, 0, OPTAB_WIDEN); + if (new != 0) + { + temp = alpha_emit_set_const (subtarget, mode, c - new, i, no_output); + if (temp) + { + if (no_output) + return temp; + return expand_binop (mode, add_optab, temp, GEN_INT (new), + target, 0, OPTAB_WIDEN); + } + } /* Next try complementing. */ - if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0) - return expand_unop (mode, one_cmpl_optab, temp, target, 0); + temp = alpha_emit_set_const (subtarget, mode, ~c, i, no_output); + if (temp) + { + if (no_output) + return temp; + return expand_unop (mode, one_cmpl_optab, temp, target, 0); + } /* Next try to form a constant and do a left shift. We can do this if some low-order bits are zero; the exact_log2 call below tells @@ -1799,16 +1827,26 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, bits to shift, but try all possibilities in case a ZAPNOT will be useful. */ - if ((bits = exact_log2 (c & - c)) > 0) + bits = exact_log2 (c & -c); + if (bits > 0) for (; bits > 0; bits--) - if ((temp = (alpha_emit_set_const - (subtarget, mode, c >> bits, i))) != 0 - || ((temp = (alpha_emit_set_const - (subtarget, mode, - ((unsigned HOST_WIDE_INT) c) >> bits, i))) - != 0)) - return expand_binop (mode, ashl_optab, temp, GEN_INT (bits), - target, 0, OPTAB_WIDEN); + { + new = c >> bits; + temp = alpha_emit_set_const (subtarget, mode, new, i, no_output); + if (!temp && c < 0) + { + new = (unsigned HOST_WIDE_INT)c >> bits; + temp = alpha_emit_set_const (subtarget, mode, new, + i, no_output); + } + if (temp) + { + if (no_output) + return temp; + return expand_binop (mode, ashl_optab, temp, GEN_INT (bits), + target, 0, OPTAB_WIDEN); + } + } /* Now try high-order zero bits. Here we try the shifted-in bits as all zero and all ones. Be careful to avoid shifting outside the @@ -1816,35 +1854,53 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, /* On narrow hosts, don't shift a 1 into the high bit, since we'll confuse the recursive call and set all of the high 32 bits. */ - if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) - - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0) + bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) + - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64)); + if (bits > 0) for (; bits > 0; bits--) - if ((temp = alpha_emit_set_const (subtarget, mode, - c << bits, i)) != 0 - || ((temp = (alpha_emit_set_const - (subtarget, mode, - ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)), - i))) - != 0)) - return expand_binop (mode, lshr_optab, temp, GEN_INT (bits), - target, 1, OPTAB_WIDEN); + { + new = c << bits; + temp = alpha_emit_set_const (subtarget, mode, new, i, no_output); + if (!temp) + { + new = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1); + temp = alpha_emit_set_const (subtarget, mode, new, + i, no_output); + } + if (temp) + { + if (no_output) + return temp; + return expand_binop (mode, lshr_optab, temp, GEN_INT (bits), + target, 1, OPTAB_WIDEN); + } + } /* Now try high-order 1 bits. We get that with a sign-extension. But one bit isn't enough here. Be careful to avoid shifting outside the mode and to avoid shifting outside the host wide int size. */ - if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) - - floor_log2 (~ c) - 2)) > 0) + bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8) + - floor_log2 (~ c) - 2); + if (bits > 0) for (; bits > 0; bits--) - if ((temp = alpha_emit_set_const (subtarget, mode, - c << bits, i)) != 0 - || ((temp = (alpha_emit_set_const - (subtarget, mode, - ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)), - i))) - != 0)) - return expand_binop (mode, ashr_optab, temp, GEN_INT (bits), - target, 0, OPTAB_WIDEN); + { + new = c << bits; + temp = alpha_emit_set_const (subtarget, mode, new, i, no_output); + if (!temp) + { + new = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1); + temp = alpha_emit_set_const (subtarget, mode, new, + i, no_output); + } + if (temp) + { + if (no_output) + return temp; + return expand_binop (mode, ashr_optab, temp, GEN_INT (bits), + target, 0, OPTAB_WIDEN); + } + } } #if HOST_BITS_PER_WIDE_INT == 64 @@ -1863,10 +1919,17 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, if (mode == SImode) new = ((new & 0xffffffff) ^ 0x80000000) - 0x80000000; - if (new != c && new != -1 - && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0) - return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new), - target, 0, OPTAB_WIDEN); + if (new != c) + { + temp = alpha_emit_set_const (subtarget, mode, new, n - 1, no_output); + if (temp) + { + if (no_output) + return temp; + return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new), + target, 0, OPTAB_WIDEN); + } + } #endif return 0; @@ -1878,32 +1941,46 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode, emitted. If it would take more than N insns, zero is returned and no insns and emitted. */ -rtx +static rtx alpha_emit_set_const (rtx target, enum machine_mode mode, - HOST_WIDE_INT c, int n) + HOST_WIDE_INT c, int n, bool no_output) { - rtx result = 0; + enum machine_mode orig_mode = mode; rtx orig_target = target; + rtx result = 0; int i; /* If we can't make any pseudos, TARGET is an SImode hard register, we can't load this constant in one insn, do this in DImode. */ if (no_new_pseudos && mode == SImode - && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER - && (result = alpha_emit_set_const_1 (target, mode, c, 1)) == 0) + && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER) + { + result = alpha_emit_set_const_1 (target, mode, c, 1, no_output); + if (result) + return result; + + target = no_output ? NULL : gen_lowpart (DImode, target); + mode = DImode; + } + else if (mode == V8QImode || mode == V4HImode || mode == V2SImode) { - target = gen_lowpart (DImode, target); + target = no_output ? NULL : gen_lowpart (DImode, target); mode = DImode; } /* Try 1 insn, then 2, then up to N. */ for (i = 1; i <= n; i++) { - result = alpha_emit_set_const_1 (target, mode, c, i); + result = alpha_emit_set_const_1 (target, mode, c, i, no_output); if (result) { - rtx insn = get_last_insn (); - rtx set = single_set (insn); + rtx insn, set; + + if (no_output) + return result; + + insn = get_last_insn (); + set = single_set (insn); if (! CONSTANT_P (SET_SRC (set))) set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c)); break; @@ -1911,8 +1988,13 @@ alpha_emit_set_const (rtx target, enum machine_mode mode, } /* Allow for the case where we changed the mode of TARGET. */ - if (result == target) - result = orig_target; + if (result) + { + if (result == target) + result = orig_target; + else if (mode != orig_mode) + result = gen_lowpart (orig_mode, result); + } return result; } @@ -1922,7 +2004,7 @@ alpha_emit_set_const (rtx target, enum machine_mode mode, exponential run times encountered when looking for longer sequences with alpha_emit_set_const. */ -rtx +static rtx alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2) { HOST_WIDE_INT d1, d2, d3, d4; @@ -1976,6 +2058,114 @@ alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2) return target; } +/* Given an integral CONST_INT, CONST_DOUBLE, or CONST_VECTOR, return + the low 64 bits. */ + +static void +alpha_extract_integer (rtx x, HOST_WIDE_INT *p0, HOST_WIDE_INT *p1) +{ + HOST_WIDE_INT i0, i1; + + if (GET_CODE (x) == CONST_VECTOR) + x = simplify_subreg (DImode, x, GET_MODE (x), 0); + + + if (GET_CODE (x) == CONST_INT) + { + i0 = INTVAL (x); + i1 = -(i0 < 0); + } + else if (HOST_BITS_PER_WIDE_INT >= 64) + { + i0 = CONST_DOUBLE_LOW (x); + i1 = -(i0 < 0); + } + else + { + i0 = CONST_DOUBLE_LOW (x); + i1 = CONST_DOUBLE_HIGH (x); + } + + *p0 = i0; + *p1 = i1; +} + +/* Implement LEGITIMATE_CONSTANT_P. This is all constants for which we + are willing to load the value into a register via a move pattern. + Normally this is all symbolic constants, integral constants that + take three or fewer instructions, and floating-point zero. */ + +bool +alpha_legitimate_constant_p (rtx x) +{ + enum machine_mode mode = GET_MODE (x); + HOST_WIDE_INT i0, i1; + + switch (GET_CODE (x)) + { + case CONST: + case LABEL_REF: + case SYMBOL_REF: + case HIGH: + return true; + + case CONST_DOUBLE: + if (x == CONST0_RTX (mode)) + return true; + if (FLOAT_MODE_P (mode)) + return false; + goto do_integer; + + case CONST_VECTOR: + if (x == CONST0_RTX (mode)) + return true; + if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) + return false; + if (GET_MODE_SIZE (mode) != 8) + return false; + goto do_integer; + + case CONST_INT: + do_integer: + if (TARGET_BUILD_CONSTANTS) + return true; + alpha_extract_integer (x, &i0, &i1); + if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == (-i0 < 0)) + return alpha_emit_set_const_1 (x, mode, i0, 3, true) != NULL; + return false; + + default: + return false; + } +} + +/* Operand 1 is known to be a constant, and should require more than one + instruction to load. Emit that multi-part load. */ + +bool +alpha_split_const_mov (enum machine_mode mode, rtx *operands) +{ + HOST_WIDE_INT i0, i1; + rtx temp = NULL_RTX; + + alpha_extract_integer (operands[1], &i0, &i1); + + if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0)) + temp = alpha_emit_set_const (operands[0], mode, i0, 3, false); + + if (!temp && TARGET_BUILD_CONSTANTS) + temp = alpha_emit_set_long_const (operands[0], i0, i1); + + if (temp) + { + if (!rtx_equal_p (operands[0], temp)) + emit_move_insn (operands[0], temp); + return true; + } + + return false; +} + /* Expand a move instruction; return true if all work is done. We don't handle non-bwx subword loads here. */ @@ -2008,40 +2198,11 @@ alpha_expand_mov (enum machine_mode mode, rtx *operands) /* Split large integers. */ if (GET_CODE (operands[1]) == CONST_INT - || GET_CODE (operands[1]) == CONST_DOUBLE) + || GET_CODE (operands[1]) == CONST_DOUBLE + || GET_CODE (operands[1]) == CONST_VECTOR) { - HOST_WIDE_INT i0, i1; - rtx temp = NULL_RTX; - - if (GET_CODE (operands[1]) == CONST_INT) - { - i0 = INTVAL (operands[1]); - i1 = -(i0 < 0); - } - else if (HOST_BITS_PER_WIDE_INT >= 64) - { - i0 = CONST_DOUBLE_LOW (operands[1]); - i1 = -(i0 < 0); - } - else - { - i0 = CONST_DOUBLE_LOW (operands[1]); - i1 = CONST_DOUBLE_HIGH (operands[1]); - } - - if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0)) - temp = alpha_emit_set_const (operands[0], mode, i0, 3); - - if (!temp && TARGET_BUILD_CONSTANTS) - temp = alpha_emit_set_long_const (operands[0], i0, i1); - - if (temp) - { - if (rtx_equal_p (operands[0], temp)) - return true; - operands[1] = temp; - return false; - } + if (alpha_split_const_mov (mode, operands)) + return true; } /* Otherwise we've nothing left but to drop the thing to memory. */ @@ -7029,7 +7190,8 @@ alpha_expand_epilogue (void) else { rtx tmp = gen_rtx_REG (DImode, 23); - FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3)); + FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, + 3, false)); if (!sp_adj2) { /* We can't drop new things to memory this late, afaik, diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index e9a409816a1..21a634c39ec 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -884,10 +884,10 @@ enum reg_class { reduce the impact of not being able to allocate a pseudo to a hard register. */ -#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \ - (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) \ - ? 2 \ - : TARGET_FIX ? 3 : 4+2*alpha_memory_latency) +#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \ + (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) ? 2 \ + : TARGET_FIX ? ((CLASS1) == FLOAT_REGS ? 6 : 8) \ + : 4+2*alpha_memory_latency) /* A C expressions returning the cost of moving data of MODE from a register to or from memory. @@ -1213,9 +1213,7 @@ do { \ /* Include all constant integers and constant doubles, but not floating-point, except for floating-point zero. */ -#define LEGITIMATE_CONSTANT_P(X) \ - (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ - || (X) == CONST0_RTX (GET_MODE (X))) +#define LEGITIMATE_CONSTANT_P alpha_legitimate_constant_p /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its validity for a certain class. diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 2679324d10a..0f68d36b93b 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -5128,8 +5128,8 @@ }) (define_insn "*movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m") - (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m") + (match_operand:SI 1 "input_operand" "rJ,K,L,n,m,rJ"))] "(TARGET_ABI_OSF || TARGET_ABI_UNICOSMK) && (register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode))" @@ -5137,13 +5137,14 @@ bis $31,%r1,%0 lda %0,%1($31) ldah %0,%h1($31) + # ldl %0,%1 stl %r1,%0" - [(set_attr "type" "ilog,iadd,iadd,ild,ist")]) + [(set_attr "type" "ilog,iadd,iadd,multi,ild,ist")]) (define_insn "*movsi_nt_vms" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m") - (match_operand:SI 1 "input_operand" "rJ,K,L,s,m,rJ"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m") + (match_operand:SI 1 "input_operand" "rJ,K,L,s,n,m,rJ"))] "(TARGET_ABI_WINDOWS_NT || TARGET_ABI_OPEN_VMS) && (register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode))" @@ -5152,9 +5153,10 @@ lda %0,%1 ldah %0,%h1 lda %0,%1 + # ldl %0,%1 stl %r1,%0" - [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist")]) + [(set_attr "type" "ilog,iadd,iadd,ldsym,multi,ild,ist")]) (define_insn "*movhi_nobwx" [(set (match_operand:HI 0 "register_operand" "=r,r") @@ -5221,15 +5223,11 @@ (define_split [(set (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "const_int_operand" ""))] - "! add_operand (operands[1], SImode)" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] + (match_operand:SI 1 "non_add_const_operand" ""))] + "" + [(const_int 0)] { - rtx tem - = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 2); - - if (tem == operands[0]) + if (alpha_split_const_mov (SImode, operands)) DONE; else FAIL; @@ -5452,8 +5450,8 @@ }) (define_insn "*movdi_er_nofix" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q") - (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,*f,*f,Q") + (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,n,m,rJ,*fJ,Q,*f"))] "TARGET_EXPLICIT_RELOCS && ! TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -5463,21 +5461,22 @@ ldah %0,%h1($31) # # + # ldq%A1 %0,%1 stq%A0 %r1,%0 fmov %R1,%0 ldt %0,%1 stt %R1,%0" - [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst") - (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*")]) + [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,multi,ild,ist,fcpys,fld,fst") + (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*")]) ;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should ;; have been split up by the rules above but we shouldn't reject the ;; possibility of them getting through. (define_insn "*movdi_nofix" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q") - (match_operand:DI 1 "input_operand" "rJ,K,L,U,s,m,rJ,*fJ,Q,*f"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,*f,*f,Q") + (match_operand:DI 1 "input_operand" "rJ,K,L,U,s,n,m,rJ,*fJ,Q,*f"))] "! TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -5487,19 +5486,20 @@ ldah %0,%h1($31) laum %0,%t1($31)\;sll %0,32,%0\;lalm %0,%t1(%0)\;lal %0,%t1(%0) lda %0,%1 + # ldq%A1 %0,%1 stq%A0 %r1,%0 cpys %R1,%R1,%0 ldt %0,%1 stt %R1,%0" - [(set_attr "type" "ilog,iadd,iadd,ldsym,ldsym,ild,ist,fcpys,fld,fst") - (set_attr "length" "*,*,*,16,*,*,*,*,*,*")]) + [(set_attr "type" "ilog,iadd,iadd,ldsym,ldsym,multi,ild,ist,fcpys,fld,fst") + (set_attr "length" "*,*,*,16,*,*,*,*,*,*,*")]) (define_insn "*movdi_er_fix" [(set (match_operand:DI 0 "nonimmediate_operand" - "=r,r,r,r,r,r, m, *f,*f, Q, r,*f") + "=r,r,r,r,r,r,r, m, *f,*f, Q, r,*f") (match_operand:DI 1 "input_operand" - "rJ,K,L,T,s,m,rJ,*fJ, Q,*f,*f, r"))] + "rJ,K,L,T,s,n,m,rJ,*fJ, Q,*f,*f, r"))] "TARGET_EXPLICIT_RELOCS && TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -5509,6 +5509,7 @@ ldah %0,%h1($31) # # + # ldq%A1 %0,%1 stq%A0 %r1,%0 fmov %R1,%0 @@ -5516,12 +5517,12 @@ stt %R1,%0 ftoit %1,%0 itoft %1,%0" - [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof") - (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*,*")]) + [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,multi,ild,ist,fcpys,fld,fst,ftoi,itof") + (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*,*,*")]) (define_insn "*movdi_fix" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f") - (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,Q,*f,*f,r"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q,r,*f") + (match_operand:DI 1 "input_operand" "rJ,K,L,s,n,m,rJ,*fJ,Q,*f,*f,r"))] "! TARGET_EXPLICIT_RELOCS && TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -5530,6 +5531,7 @@ lda %0,%1($31) ldah %0,%h1($31) lda %0,%1 + # ldq%A1 %0,%1 stq%A0 %r1,%0 cpys %R1,%R1,%0 @@ -5537,7 +5539,7 @@ stt %R1,%0 ftoit %1,%0 itoft %1,%0" - [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")]) + [(set_attr "type" "ilog,iadd,iadd,ldsym,multi,ild,ist,fcpys,fld,fst,ftoi,itof")]) ;; VMS needs to set up "vms_base_regno" for unwinding. This move ;; often appears dead to the life analysis code, at which point we @@ -5568,15 +5570,11 @@ (define_split [(set (match_operand:DI 0 "register_operand" "") - (match_operand:DI 1 "const_int_operand" ""))] - "! add_operand (operands[1], DImode)" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] + (match_operand:DI 1 "non_add_const_operand" ""))] + "" + [(const_int 0)] { - rtx tem - = alpha_emit_set_const (operands[0], DImode, INTVAL (operands[1]), 2); - - if (tem == operands[0]) + if (alpha_split_const_mov (DImode, operands)) DONE; else FAIL; @@ -6103,6 +6101,19 @@ DONE; }) +(define_split + [(set (match_operand:VEC 0 "register_operand" "") + (match_operand:VEC 1 "non_zero_const_operand" ""))] + "" + [(const_int 0)] +{ + if (alpha_split_const_mov (<MODE>mode, operands)) + DONE; + else + FAIL; +}) + + (define_expand "movmisalign<mode>" [(set (match_operand:VEC 0 "nonimmediate_operand" "") (match_operand:VEC 1 "general_operand" ""))] @@ -6113,13 +6124,14 @@ }) (define_insn "*mov<mode>_fix" - [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f") - (match_operand:VEC 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))] + [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,m,r,*f") + (match_operand:VEC 1 "input_operand" "rW,i,m,rW,*fW,m,*f,*f,r"))] "TARGET_FIX && (register_operand (operands[0], <MODE>mode) || reg_or_0_operand (operands[1], <MODE>mode))" "@ bis $31,%r1,%0 + # ldq %0,%1 stq %r1,%0 cpys %R1,%R1,%0 @@ -6127,22 +6139,23 @@ stt %R1,%0 ftoit %1,%0 itoft %1,%0" - [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")]) + [(set_attr "type" "ilog,multi,ild,ist,fcpys,fld,fst,ftoi,itof")]) (define_insn "*mov<mode>_nofix" - [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,m,*f,*f,m") - (match_operand:VEC 1 "input_operand" "rW,m,rW,*fW,m,*f"))] + [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,m") + (match_operand:VEC 1 "input_operand" "rW,i,m,rW,*fW,m,*f"))] "! TARGET_FIX && (register_operand (operands[0], <MODE>mode) || reg_or_0_operand (operands[1], <MODE>mode))" "@ bis $31,%r1,%0 + # ldq %0,%1 stq %r1,%0 cpys %R1,%R1,%0 ldt %0,%1 stt %R1,%0" - [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")]) + [(set_attr "type" "ilog,multi,ild,ist,fcpys,fld,fst")]) (define_insn "uminv8qi3" [(set (match_operand:V8QI 0 "register_operand" "=r") diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md index b060dd17741..6a58ed67905 100644 --- a/gcc/config/alpha/predicates.md +++ b/gcc/config/alpha/predicates.md @@ -66,6 +66,17 @@ || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O')") (match_operand 0 "register_operand"))) +;; Return 1 if the operand is a non-symbolic constant operand that +;; does not satisfy add_operand. +(define_predicate "non_add_const_operand" + (and (match_code "const_int,const_double,const_vector") + (not (match_operand 0 "add_operand")))) + +;; Return 1 if the operand is a non-symbolic, non-zero constant operand. +(define_predicate "non_zero_const_operand" + (and (match_code "const_int,const_double,const_vector") + (match_test "op != CONST0_RTX (mode)"))) + ;; Return 1 if OP is the constant 4 or 8. (define_predicate "const48_operand" (and (match_code "const_int") @@ -205,11 +216,19 @@ && general_operand (op, mode)); case CONST_DOUBLE: + return op == CONST0_RTX (mode); + case CONST_VECTOR: + if (reload_in_progress || reload_completed) + return alpha_legitimate_constant_p (op); return op == CONST0_RTX (mode); case CONST_INT: - return mode == QImode || mode == HImode || add_operand (op, mode); + if (mode == QImode || mode == HImode) + return true; + if (reload_in_progress || reload_completed) + return alpha_legitimate_constant_p (op); + return add_operand (op, mode); default: abort (); |