From: Bob Wilson Date: Tue, 24 Feb 2004 19:44:12 +0000 (+0000) Subject: backport: xtensa_reorg instead; remove irrelevant portions of the patch) X-Git-Tag: releases/gcc-3.3.4~231 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3a25c5dc995666e2c9c965b90f58f06059043cf2;p=thirdparty%2Fgcc.git backport: xtensa_reorg instead; remove irrelevant portions of the patch) Backport from mainline (changes to xtensa_expand_prologue go into xtensa_reorg instead; remove irrelevant portions of the patch) 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. From-SVN: r78381 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 84c6ec068035..9957c6472ca3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2004-02-24 Bob Wilson + + Backport from mainline (changes to xtensa_expand_prologue go into + xtensa_reorg instead; remove irrelevant portions of the patch) + + 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-22 Jakub Jelinek * config/i386/i386.c (override_options): Don't imply 3DNow! for -m64 diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 47befc04be98..ec689792daee 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -1,5 +1,5 @@ /* Prototypes of target machine for GNU compiler for Xtensa. - Copyright 2001,2002,2003 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. This file is part of GCC. @@ -70,14 +70,14 @@ extern int xtensa_expand_conditional_move PARAMS ((rtx *, int)); extern int xtensa_expand_scc PARAMS ((rtx *)); extern int xtensa_expand_block_move PARAMS ((rtx *)); extern int xtensa_emit_move_sequence PARAMS ((rtx *, enum machine_mode)); -extern bool xtensa_copy_incoming_a7 PARAMS ((rtx *, enum machine_mode)); +extern rtx xtensa_copy_incoming_a7 PARAMS ((rtx)); extern void xtensa_emit_block_move PARAMS ((rtx *, rtx *, int)); extern void xtensa_expand_nonlocal_goto PARAMS ((rtx *)); extern void xtensa_emit_loop_end PARAMS ((rtx, rtx *)); extern char * xtensa_emit_call PARAMS ((int, rtx *)); #ifdef TREE_CODE -extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx)); +extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, int)); extern void xtensa_va_start PARAMS ((tree, rtx)); extern rtx xtensa_va_arg PARAMS ((tree, tree)); #endif /* TREE_CODE */ @@ -93,7 +93,6 @@ extern enum reg_class xtensa_preferred_reload_class PARAMS ((rtx, enum reg_class, int)); extern enum reg_class xtensa_secondary_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx, int)); -extern int a7_overlap_mentioned_p PARAMS ((rtx x)); #endif /* RTX_CODE */ #ifdef TREE_CODE diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index d72a3e94cc2b..426aa328be29 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Tensilica's Xtensa architecture. - Copyright 2001,2002,2003 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. This file is part of GCC. @@ -90,7 +90,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 @@ -1276,8 +1278,7 @@ xtensa_emit_move_sequence (operands, mode) if (!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 @@ -1309,71 +1310,115 @@ fixup_subreg_mem (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 (operands, mode) - rtx *operands; - enum machine_mode mode; +rtx +xtensa_copy_incoming_a7 (opnd) + 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; - 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 (); - } + 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; - /* 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 (); + /* 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 (); - /* 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. */ + cfun->machine->need_a7_copy = false; - cfun->machine->incoming_a7_copied = true; + /* 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. */ - return 1; + push_to_sequence (entry_insns); + tmp = gen_reg_rtx (mode); + + 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; } @@ -1721,12 +1766,12 @@ xtensa_dbx_register_number (regno) /* Initialize CUMULATIVE_ARGS for a function. */ void -init_cumulative_args (cum, fntype, libname) +init_cumulative_args (cum, incoming) CUMULATIVE_ARGS *cum; /* argument info to initialize */ - tree fntype ATTRIBUTE_UNUSED; /* tree ptr for function decl */ - rtx libname ATTRIBUTE_UNUSED; /* SYMBOL_REF of library name or 0 */ + int incoming; { cum->arg_words = 0; + cum->incoming = incoming; } /* Advance the argument to the next argument position. */ @@ -1767,7 +1812,6 @@ function_arg (cum, mode, type, incoming_p) 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); @@ -1784,33 +1828,11 @@ function_arg (cum, mode, type, incoming_p) 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 BLKmode and - modes bigger than 2 words (because we only have patterns for - modes of 2 words or smaller), we can't control the expansion - unless we explicitly list the individual registers in a PARALLEL. */ - - if ((mode == BLKmode || words > 2) - && regno < A7_REG - && regno + words > 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); } @@ -2187,8 +2209,6 @@ void xtensa_reorg (first) rtx first; { - rtx insn, set_frame_ptr_insn = 0; - unsigned long tsize = compute_frame_size (get_frame_size ()); if (tsize < (1 << (12+3))) frame_size_const = 0; @@ -2204,34 +2224,15 @@ xtensa_reorg (first) if (!frame_pointer_needed) return; - /* 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; + rtx insn; - if (!INSN_P (insn)) - continue; - - 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; - } - } - - 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 = NEXT_INSN (insn)) + for (insn = first; + insn != cfun->machine->set_frame_ptr_insn; + insn = NEXT_INSN (insn)) { if (INSN_P (insn)) PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)), @@ -2379,9 +2380,8 @@ xtensa_builtin_saveregs () 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 */ @@ -2394,15 +2394,10 @@ xtensa_builtin_saveregs () 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, + gp_left * UNITS_PER_WORD); return XEXP (gp_regs, 0); } @@ -2722,56 +2717,6 @@ order_regs_for_local_alloc () } -/* 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 (x) - 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 3a5a7343a010..6e80e1635270 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -1,5 +1,5 @@ /* Definitions of Tensilica's Xtensa target machine for GNU compiler. - Copyright 2001,2002,2003 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. This file is part of GCC. @@ -853,23 +853,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) \ - 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. diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index cc722b932a92..92a25a175214 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1,5 +1,5 @@ ;; GCC machine description for Tensilica's Xtensa architecture. -;; Copyright (C) 2001 Free Software Foundation, Inc. +;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. ;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. ;; This file is part of GCC. @@ -942,8 +942,7 @@ && !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]); } }") @@ -1116,8 +1115,7 @@ && constantpool_mem_p (operands[1])))) operands[1] = force_reg (SFmode, operands[1]); - if (xtensa_copy_incoming_a7 (operands, SFmode)) - DONE; + operands[1] = xtensa_copy_incoming_a7 (operands[1]); } }") @@ -1198,8 +1196,7 @@ && !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]); } }") @@ -1302,7 +1299,16 @@ ;; .................... ;; -(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")))]