xtensa-protos.h (xtensa_copy_incoming_a7): Update.
authorBob Wilson <bob.wilson@acm.org>
Tue, 10 Feb 2004 01:35:53 +0000 (01:35 +0000)
committerBob Wilson <bwilson@gcc.gnu.org>
Tue, 10 Feb 2004 01:35:53 +0000 (01:35 +0000)
* 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: r77583

gcc/ChangeLog
gcc/config/xtensa/xtensa-protos.h
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.h
gcc/config/xtensa/xtensa.md

index 9f7dfd2..3b19517 100644 (file)
@@ -1,3 +1,36 @@
+2004-02-09  Bob Wilson  <bob.wilson@acm.org>
+
+       * 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  <dj@redhat.com>
 
        * config/i386/xm-djgpp.h (GCC_DRIVER_HOST_INITIALIZATION): No
index 7d3208b..38a5dce 100644 (file)
@@ -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
index c6cc33d..09a2f34 100644 (file)
@@ -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.  */
 
index 1ba81d1..a956f1b 100644 (file)
@@ -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
 
index 51da712..6e13568 100644 (file)
   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"
   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"
   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"
 \f
 ;; 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")))]