From e060c9dfada09e5597b92fd8e60e917d8bef51af Mon Sep 17 00:00:00 2001 From: bwilson Date: Tue, 10 Feb 2004 01:35:53 +0000 Subject: [PATCH] * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Update. (init_cumulative_args): Likewise. (a7_overlap_mentioned_p): Delete prototype. * config/xtensa/xtensa.c (struct machine_function): Replace incoming_a7_copied field with need_a7_copy and vararg_a7 flags. Add set_frame_ptr_insn field. (xtensa_emit_move_sequence): Update call to xtensa_copy_incoming_a7. (xtensa_copy_incoming_a7): Rewrite to check need_a7_copy flag and check if the operand is an argument in a7. If so, copy a7 to a new pseudo at the function entry and replace the operand with the pseudo. (init_cumulative_args): Remove unused arguments. Add new "incoming" argument and record this flag in CUMULATIVE_ARGS. (function_arg): Remove result_mode and special-case code to handle arguments in a7. Instead, set need_a7_copy flag when there is an incoming argument in a7. (xtensa_expand_prologue): Remove code to search for set_frame_ptr insn and use the value recorded in cfun->machine->set_frame_ptr_insn. (xtensa_builtin_saveregs): Check for negative gp_left value. Set need_a7_copy and vararg_a7 flags. Use move_block_from_reg instead of special-case code. (a7_overlap_mentioned_p): Delete. * config/xtensa/xtensa.h (CUMULATIVE_ARGS): Add "incoming" flag. (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Remove useless arguments to init_cumulative_args and pass "incoming" flag instead. (BLOCK_REG_PADDING): Delete. * config/xtensa/xtensa.md (movdi, movsf, movdf): Remove unnecessary checks for reload_in_progress and reload_completed. Update calls to xtensa_copy_incoming_a7. (ashlsi3): Rename existing insn to ashlsi3_internal. Add expander to call xtensa_copy_incoming_a7. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@77583 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 33 ++++ gcc/config/xtensa/xtensa-protos.h | 5 +- gcc/config/xtensa/xtensa.c | 324 ++++++++++++++------------------------ gcc/config/xtensa/xtensa.h | 33 ++-- gcc/config/xtensa/xtensa.md | 56 ++++--- 5 files changed, 192 insertions(+), 259 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f7dfd2029b..3b19517e936 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2004-02-09 Bob Wilson + + * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Update. + (init_cumulative_args): Likewise. + (a7_overlap_mentioned_p): Delete prototype. + * config/xtensa/xtensa.c (struct machine_function): Replace + incoming_a7_copied field with need_a7_copy and vararg_a7 flags. + Add set_frame_ptr_insn field. + (xtensa_emit_move_sequence): Update call to xtensa_copy_incoming_a7. + (xtensa_copy_incoming_a7): Rewrite to check need_a7_copy flag and check + if the operand is an argument in a7. If so, copy a7 to a new pseudo + at the function entry and replace the operand with the pseudo. + (init_cumulative_args): Remove unused arguments. Add new "incoming" + argument and record this flag in CUMULATIVE_ARGS. + (function_arg): Remove result_mode and special-case code to handle + arguments in a7. Instead, set need_a7_copy flag when there is an + incoming argument in a7. + (xtensa_expand_prologue): Remove code to search for set_frame_ptr insn + and use the value recorded in cfun->machine->set_frame_ptr_insn. + (xtensa_builtin_saveregs): Check for negative gp_left value. Set + need_a7_copy and vararg_a7 flags. Use move_block_from_reg instead of + special-case code. + (a7_overlap_mentioned_p): Delete. + * config/xtensa/xtensa.h (CUMULATIVE_ARGS): Add "incoming" flag. + (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Remove useless + arguments to init_cumulative_args and pass "incoming" flag instead. + (BLOCK_REG_PADDING): Delete. + * config/xtensa/xtensa.md (movdi, movsf, movdf): Remove unnecessary + checks for reload_in_progress and reload_completed. Update calls to + xtensa_copy_incoming_a7. + (ashlsi3): Rename existing insn to ashlsi3_internal. Add expander + to call xtensa_copy_incoming_a7. + 2004-02-09 DJ Delorie * config/i386/xm-djgpp.h (GCC_DRIVER_HOST_INITIALIZATION): No diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 7d3208be7cd..38a5dce985e 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -68,14 +68,14 @@ extern int xtensa_expand_scc (rtx *); extern int xtensa_expand_block_move (rtx *); extern void xtensa_split_operand_pair (rtx *, enum machine_mode); extern int xtensa_emit_move_sequence (rtx *, enum machine_mode); -extern bool xtensa_copy_incoming_a7 (rtx *, enum machine_mode); +extern rtx xtensa_copy_incoming_a7 (rtx); extern void xtensa_emit_block_move (rtx *, rtx *, int); extern void xtensa_expand_nonlocal_goto (rtx *); extern void xtensa_emit_loop_end (rtx, rtx *); extern char *xtensa_emit_call (int, rtx *); #ifdef TREE_CODE -extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx); +extern void init_cumulative_args (CUMULATIVE_ARGS *, int); extern void xtensa_va_start (tree, rtx); extern rtx xtensa_va_arg (tree, tree); #endif /* TREE_CODE */ @@ -88,7 +88,6 @@ extern enum reg_class xtensa_preferred_reload_class (rtx, enum reg_class, int); extern enum reg_class xtensa_secondary_reload_class (enum reg_class, enum machine_mode, rtx, int); -extern int a7_overlap_mentioned_p (rtx); #endif /* RTX_CODE */ #ifdef TREE_CODE diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index c6cc33d608f..09a2f34941f 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -91,7 +91,9 @@ const char *xtensa_st_opcodes[(int) MAX_MACHINE_MODE]; struct machine_function GTY(()) { int accesses_prev_frame; - bool incoming_a7_copied; + bool need_a7_copy; + bool vararg_a7; + rtx set_frame_ptr_insn; }; /* Vector, indexed by hard register number, which contains 1 for a @@ -1271,14 +1273,11 @@ xtensa_emit_move_sequence (rtx *operands, enum machine_mode mode) } } - if (!(reload_in_progress | reload_completed)) - { - if (!xtensa_valid_move (mode, operands)) - operands[1] = force_reg (mode, operands[1]); + if (!(reload_in_progress | reload_completed) + && !xtensa_valid_move (mode, operands)) + operands[1] = force_reg (mode, operands[1]); - if (xtensa_copy_incoming_a7 (operands, mode)) - return 1; - } + operands[1] = xtensa_copy_incoming_a7 (operands[1]); /* During reload we don't want to emit (subreg:X (mem:Y)) since that instruction won't be recognized after reload, so we remove the @@ -1309,89 +1308,114 @@ fixup_subreg_mem (rtx x) } -/* Check if this move is copying an incoming argument in a7. If so, - emit the move, followed by the special "set_frame_ptr" - unspec_volatile insn, at the very beginning of the function. This - is necessary because the register allocator will ignore conflicts - with a7 and may assign some other pseudo to a7. If that pseudo was - assigned prior to this move, it would clobber the incoming argument - in a7. By copying the argument out of a7 as the very first thing, - and then immediately following that with an unspec_volatile to keep - the scheduler away, we should avoid any problems. */ +/* Check if an incoming argument in a7 is expected to be used soon and + if OPND is a register or register pair that includes a7. If so, + create a new pseudo and copy a7 into that pseudo at the very + beginning of the function, followed by the special "set_frame_ptr" + unspec_volatile insn. The return value is either the original + operand, if it is not a7, or the new pseudo containing a copy of + the incoming argument. This is necessary because the register + allocator will ignore conflicts with a7 and may either assign some + other pseudo to a7 or use a7 as the hard_frame_pointer, clobbering + the incoming argument in a7. By copying the argument out of a7 as + the very first thing, and then immediately following that with an + unspec_volatile to keep the scheduler away, we should avoid any + problems. Putting the set_frame_ptr insn at the beginning, with + only the a7 copy before it, also makes it easier for the prologue + expander to initialize the frame pointer after the a7 copy and to + fix up the a7 copy to use the stack pointer instead of the frame + pointer. */ -bool -xtensa_copy_incoming_a7 (rtx *operands, enum machine_mode mode) +rtx +xtensa_copy_incoming_a7 (rtx opnd) { - if (a7_overlap_mentioned_p (operands[1]) - && !cfun->machine->incoming_a7_copied) + rtx entry_insns = 0; + rtx reg, tmp; + enum machine_mode mode; + + if (!cfun->machine->need_a7_copy) + return opnd; + + /* This function should never be called again once a7 has been copied. */ + if (cfun->machine->set_frame_ptr_insn) + abort (); + + mode = GET_MODE (opnd); + + /* The operand using a7 may come in a later instruction, so just return + the original operand if it doesn't use a7. */ + reg = opnd; + if (GET_CODE (reg) == SUBREG) { - rtx mov, src; - - /* Despite defining SPLIT_COMPLEX_ARGS, complex function - arguments may still appear if they are wrapped in a struct. - For CQImode and CHImode arguments, this results in a move - with a source operand of the form: "(subreg:SI (reg:CHI a7) - 0)". The subreg is later removed by the reload pass, - resulting in the RTL for a7 being regenerated using - hard_frame_pointer_rtx, and making it impossible for us to - distinguish the function argument. Detect this here when - generating the RTL and remove the subreg immediately so that - reload won't mess it up. */ - src = operands[1]; - if (GET_CODE (src) == SUBREG - && GET_CODE (SUBREG_REG (src)) == REG - && REGNO (SUBREG_REG (src)) == A7_REG - && SUBREG_BYTE (src) == 0 - && (GET_MODE (SUBREG_REG (src)) == CHImode - || GET_MODE (SUBREG_REG (src)) == CQImode)) - operands[1] = gen_raw_REG (mode, A7_REG); + if (SUBREG_BYTE (reg) != 0) + abort (); + reg = SUBREG_REG (reg); + } + if (GET_CODE (reg) != REG + || REGNO (reg) > A7_REG + || REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) <= A7_REG) + return opnd; - switch (mode) - { - case DFmode: - mov = gen_movdf_internal (operands[0], operands[1]); - break; - case SFmode: - mov = gen_movsf_internal (operands[0], operands[1]); - break; - case DImode: - mov = gen_movdi_internal (operands[0], operands[1]); - break; - case SImode: - mov = gen_movsi_internal (operands[0], operands[1]); - break; - case HImode: - mov = gen_movhi_internal (operands[0], operands[1]); - break; - case QImode: - mov = gen_movqi_internal (operands[0], operands[1]); - break; - default: - abort (); - } + /* 1-word args will always be in a7; 2-word args in a6/a7. */ + if (REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) - 1 != A7_REG) + abort (); - /* Insert the instructions before any other argument copies. - (The set_frame_ptr insn comes _after_ the move, so push it - out first.) */ - push_topmost_sequence (); - emit_insn_after (gen_set_frame_ptr (), get_insns ()); - emit_insn_after (mov, get_insns ()); - pop_topmost_sequence (); + cfun->machine->need_a7_copy = false; - /* Ideally the incoming argument in a7 would only be copied - once, since propagating a7 into the body of a function - will almost certainly lead to errors. However, there is - at least one harmless case (in GCSE) where the original - copy from a7 is changed to copy into a new pseudo. Thus, - we use a flag to only do this special treatment for the - first copy of a7. */ + /* Copy a7 to a new pseudo at the function entry. Use gen_raw_REG to + create the REG for a7 so that hard_frame_pointer_rtx is not used. */ - cfun->machine->incoming_a7_copied = true; + push_to_sequence (entry_insns); + tmp = gen_reg_rtx (mode); - return 1; + switch (mode) + { + case DFmode: + case DImode: + emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 0), + gen_rtx_REG (SImode, A7_REG - 1))); + emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 4), + gen_raw_REG (SImode, A7_REG))); + break; + case SFmode: + emit_insn (gen_movsf_internal (tmp, gen_raw_REG (mode, A7_REG))); + break; + case SImode: + emit_insn (gen_movsi_internal (tmp, gen_raw_REG (mode, A7_REG))); + break; + case HImode: + emit_insn (gen_movhi_internal (tmp, gen_raw_REG (mode, A7_REG))); + break; + case QImode: + emit_insn (gen_movqi_internal (tmp, gen_raw_REG (mode, A7_REG))); + break; + default: + abort (); } - return 0; + cfun->machine->set_frame_ptr_insn = emit_insn (gen_set_frame_ptr ()); + entry_insns = get_insns (); + end_sequence (); + + if (cfun->machine->vararg_a7) + { + /* This is called from within builtin_savereg, so we're already + inside a start_sequence that will be placed at the start of + the function. */ + emit_insn (entry_insns); + } + else + { + /* Put entry_insns after the NOTE that starts the function. If + this is inside a start_sequence, make the outer-level insn + chain current, so the code is placed at the start of the + function. */ + push_topmost_sequence (); + emit_insn_after (entry_insns, get_insns ()); + pop_topmost_sequence (); + } + + return tmp; } @@ -1727,11 +1751,10 @@ xtensa_dbx_register_number (int regno) /* Initialize CUMULATIVE_ARGS for a function. */ void -init_cumulative_args (CUMULATIVE_ARGS *cum, - tree fntype ATTRIBUTE_UNUSED, - rtx libname ATTRIBUTE_UNUSED) +init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming) { cum->arg_words = 0; + cum->incoming = incoming; } @@ -1768,7 +1791,6 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int regbase, words, max; int *arg_words; int regno; - enum machine_mode result_mode; arg_words = &cum->arg_words; regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST); @@ -1785,37 +1807,11 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, return (rtx)0; regno = regbase + *arg_words; - result_mode = (mode == BLKmode ? TYPE_MODE (type) : mode); - - /* We need to make sure that references to a7 are represented with - rtx that is not equal to hard_frame_pointer_rtx. For multi-word - modes for which we don't define move patterns, we can't control - the expansion unless we explicitly list the individual registers - in a PARALLEL. Likewise, a single-word BLKmode argument passed - in a7 must be wrapped in a PARALLEL to avoid code that takes the - register number and builds a new REG. This is extremely fragile - but seems to be the best solution for now. */ - - if ((mode != DImode && mode != DFmode - && regno < A7_REG - && regno + words > A7_REG) - || (mode == BLKmode && regno == A7_REG)) - { - rtx result; - int n; - result = gen_rtx_PARALLEL (result_mode, rtvec_alloc (words)); - for (n = 0; n < words; n++) - { - XVECEXP (result, 0, n) = - gen_rtx_EXPR_LIST (VOIDmode, - gen_raw_REG (SImode, regno + n), - GEN_INT (n * UNITS_PER_WORD)); - } - return result; - } + if (cum->incoming && regno <= A7_REG && regno + words > A7_REG) + cfun->machine->need_a7_copy = true; - return gen_raw_REG (result_mode, regno); + return gen_rtx_REG (mode, regno); } @@ -2264,41 +2260,18 @@ xtensa_expand_prologue (void) if (frame_pointer_needed) { - rtx first, insn, set_frame_ptr_insn = 0; - - push_topmost_sequence (); - first = get_insns (); - pop_topmost_sequence (); - - /* Search all instructions, looking for the insn that sets up the - frame pointer. This search will fail if the function does not - have an incoming argument in $a7, but in that case, we can just - set up the frame pointer at the very beginning of the - function. */ - - for (insn = first; insn; insn = NEXT_INSN (insn)) + if (cfun->machine->set_frame_ptr_insn) { - rtx pat; - - if (!INSN_P (insn)) - continue; + rtx first, insn; - pat = PATTERN (insn); - if (GET_CODE (pat) == SET - && GET_CODE (SET_SRC (pat)) == UNSPEC_VOLATILE - && (XINT (SET_SRC (pat), 1) == UNSPECV_SET_FP)) - { - set_frame_ptr_insn = insn; - break; - } - } + push_topmost_sequence (); + first = get_insns (); + pop_topmost_sequence (); - if (set_frame_ptr_insn) - { /* For all instructions prior to set_frame_ptr_insn, replace hard_frame_pointer references with stack_pointer. */ for (insn = first; - insn != set_frame_ptr_insn; + insn != cfun->machine->set_frame_ptr_insn; insn = NEXT_INSN (insn)) { if (INSN_P (insn)) @@ -2400,9 +2373,8 @@ xtensa_builtin_saveregs (void) rtx gp_regs, dest; int arg_words = current_function_arg_words; int gp_left = MAX_ARGS_IN_REGISTERS - arg_words; - int i; - if (gp_left == 0) + if (gp_left <= 0) return const0_rtx; /* Allocate the general-purpose register space. */ @@ -2414,16 +2386,9 @@ xtensa_builtin_saveregs (void) dest = change_address (gp_regs, SImode, plus_constant (XEXP (gp_regs, 0), arg_words * UNITS_PER_WORD)); - - /* Note: Don't use move_block_from_reg() here because the incoming - argument in a7 cannot be represented by hard_frame_pointer_rtx. - Instead, call gen_raw_REG() directly so that we get a distinct - instance of (REG:SI 7). */ - for (i = 0; i < gp_left; i++) - { - emit_move_insn (operand_subword (dest, i, 1, BLKmode), - gen_raw_REG (SImode, GP_ARG_FIRST + arg_words + i)); - } + cfun->machine->need_a7_copy = true; + cfun->machine->vararg_a7 = true; + move_block_from_reg (GP_ARG_FIRST + arg_words, dest, gp_left); return XEXP (gp_regs, 0); } @@ -2749,55 +2714,6 @@ order_regs_for_local_alloc (void) } -/* A customized version of reg_overlap_mentioned_p that only looks for - references to a7 (as opposed to hard_frame_pointer_rtx). */ - -int -a7_overlap_mentioned_p (rtx x) -{ - int i, j; - unsigned int x_regno; - const char *fmt; - - if (GET_CODE (x) == REG) - { - x_regno = REGNO (x); - return (x != hard_frame_pointer_rtx - && x_regno < A7_REG + 1 - && x_regno + HARD_REGNO_NREGS (A7_REG, GET_MODE (x)) > A7_REG); - } - - if (GET_CODE (x) == SUBREG - && GET_CODE (SUBREG_REG (x)) == REG - && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER) - { - x_regno = subreg_regno (x); - return (SUBREG_REG (x) != hard_frame_pointer_rtx - && x_regno < A7_REG + 1 - && x_regno + HARD_REGNO_NREGS (A7_REG, GET_MODE (x)) > A7_REG); - } - - /* X does not match, so try its subexpressions. */ - fmt = GET_RTX_FORMAT (GET_CODE (x)); - for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (a7_overlap_mentioned_p (XEXP (x, i))) - return 1; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >=0; j--) - if (a7_overlap_mentioned_p (XVECEXP (x, i, j))) - return 1; - } - } - - return 0; -} - - /* Some Xtensa targets support multiple bss sections. If the section name ends with ".bss", add SECTION_BSS to the flags. */ diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index 1ba81d192bc..a956f1b6bb4 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -736,23 +736,21 @@ extern enum reg_class xtensa_char_to_class[256]; #define FUNCTION_ARG_REGNO_P(N) \ ((N) >= GP_OUTGOING_ARG_FIRST && (N) <= GP_OUTGOING_ARG_LAST) -/* Define a data type for recording info about an argument list - during the scan of that argument list. This data type should - hold all necessary information about the function itself - and about the args processed so far, enough to enable macros - such as FUNCTION_ARG to determine where the next arg should go. */ -typedef struct xtensa_args { - int arg_words; /* # total words the arguments take */ +/* Record the number of argument words seen so far, along with a flag to + indicate whether these are incoming arguments. (FUNCTION_INCOMING_ARG + is used for both incoming and outgoing args, so a separate flag is + needed. */ +typedef struct xtensa_args +{ + int arg_words; + int incoming; } CUMULATIVE_ARGS; -/* Initialize a variable CUM of type CUMULATIVE_ARGS - for a call to a function whose data type is FNTYPE. - For a library call, FNTYPE is 0. */ #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME) + init_cumulative_args (&CUM, 0) #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ - init_cumulative_args (&CUM, FNTYPE, LIBNAME) + init_cumulative_args (&CUM, 1) /* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. @@ -798,12 +796,6 @@ typedef struct xtensa_args { /* Pass complex arguments independently. */ #define SPLIT_COMPLEX_ARGS 1 -/* Because Xtensa's function_arg() wraps BLKmode arguments passed in - a7 inside a PARALLEL, BLOCK_REG_PADDING needs to be defined - to get emit_group_store to do the right thing. */ -#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \ - FUNCTION_ARG_PADDING (MODE, TYPE) - /* Profiling Xtensa code is typically done with the built-in profiling feature of Tensilica's instruction set simulator, which does not require any compiler support. Profiling code on a real (i.e., @@ -1142,11 +1134,6 @@ typedef struct xtensa_args { /* Prefer word-sized loads. */ #define SLOW_BYTE_ACCESS 1 -/* ??? Xtensa doesn't have any instructions that set integer values - based on the results of comparisons, but the simplification code in - the combiner also uses STORE_FLAG_VALUE. The default value (1) is - fine for us, but (-1) might be better. */ - /* Shift instructions ignore all but the low-order few bits. */ #define SHIFT_COUNT_TRUNCATED 1 diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 51da7124b4b..6e13568a651 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -803,15 +803,11 @@ if (CONSTANT_P (operands[1]) && !TARGET_CONST16) operands[1] = force_const_mem (DImode, operands[1]); - if (!(reload_in_progress | reload_completed)) - { - if (!register_operand (operands[0], DImode) - && !register_operand (operands[1], DImode)) - operands[1] = force_reg (DImode, operands[1]); + if (!register_operand (operands[0], DImode) + && !register_operand (operands[1], DImode)) + operands[1] = force_reg (DImode, operands[1]); - if (xtensa_copy_incoming_a7 (operands, DImode)) - DONE; - } + operands[1] = xtensa_copy_incoming_a7 (operands[1]); }) (define_insn_and_split "movdi_internal" @@ -934,18 +930,15 @@ if (!TARGET_CONST16 && CONSTANT_P (operands[1])) operands[1] = force_const_mem (SFmode, operands[1]); - if (!(reload_in_progress | reload_completed)) - { - if ((!register_operand (operands[0], SFmode) - && !register_operand (operands[1], SFmode)) - || (FP_REG_P (xt_true_regnum (operands[0])) - && (constantpool_mem_p (operands[1]) - || CONSTANT_P (operands[1])))) - operands[1] = force_reg (SFmode, operands[1]); - - if (xtensa_copy_incoming_a7 (operands, SFmode)) - DONE; - } + if ((!register_operand (operands[0], SFmode) + && !register_operand (operands[1], SFmode)) + || (FP_REG_P (xt_true_regnum (operands[0])) + && !(reload_in_progress | reload_completed) + && (constantpool_mem_p (operands[1]) + || CONSTANT_P (operands[1])))) + operands[1] = force_reg (SFmode, operands[1]); + + operands[1] = xtensa_copy_incoming_a7 (operands[1]); }) (define_insn "movsf_internal" @@ -1015,15 +1008,11 @@ if (CONSTANT_P (operands[1]) && !TARGET_CONST16) operands[1] = force_const_mem (DFmode, operands[1]); - if (!(reload_in_progress | reload_completed)) - { - if (!register_operand (operands[0], DFmode) - && !register_operand (operands[1], DFmode)) - operands[1] = force_reg (DFmode, operands[1]); + if (!register_operand (operands[0], DFmode) + && !register_operand (operands[1], DFmode)) + operands[1] = force_reg (DFmode, operands[1]); - if (xtensa_copy_incoming_a7 (operands, DFmode)) - DONE; - } + operands[1] = xtensa_copy_incoming_a7 (operands[1]); }) (define_insn_and_split "movdf_internal" @@ -1081,7 +1070,16 @@ ;; Shift instructions. -(define_insn "ashlsi3" +(define_expand "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ashift:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "arith_operand" "")))] + "" +{ + operands[1] = xtensa_copy_incoming_a7 (operands[1]); +}) + +(define_insn "ashlsi3_internal" [(set (match_operand:SI 0 "register_operand" "=a,a") (ashift:SI (match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "arith_operand" "J,r")))] -- 2.11.0