Avoid hard register combinations
authorBernd Schmidt <bernds@redhat.co.uk>
Fri, 24 Nov 2000 11:28:51 +0000 (11:28 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Fri, 24 Nov 2000 11:28:51 +0000 (11:28 +0000)
From-SVN: r37704

gcc/ChangeLog
gcc/combine.c

index 650c5dcff092b1442297f472e42afc974a498381..d8801970ea680243a31a4706ae7833101a377e53 100644 (file)
@@ -1,3 +1,8 @@
+2000-11-24  Bernd Schmidt  <bernds@redhat.co.uk>
+
+       * combine.c (cant_combine_insn_p): New function.
+       (try_combine): Use it.
+
 2000-11-24  Nathan Sidwell  <nathan@codesourcery.com>
 
        * c-parse.in (unary_expr): Move VA_ARG from here ...
index 18c532238b6c353b98fa8dabb06cd8245e656db6..cd76aeefbb149bbfc2089271f9055fa4e578e08c 100644 (file)
@@ -366,6 +366,7 @@ static void do_SUBST_INT            PARAMS ((unsigned int *,
 static void init_reg_last_arrays       PARAMS ((void));
 static void setup_incoming_promotions   PARAMS ((void));
 static void set_nonzero_bits_and_sign_copies  PARAMS ((rtx, rtx, void *));
+static int cant_combine_insn_p PARAMS ((rtx));
 static int can_combine_p       PARAMS ((rtx, rtx, rtx, rtx, rtx *, rtx *));
 static int sets_function_arg_p PARAMS ((rtx));
 static int combinable_i3pat    PARAMS ((rtx, rtx *, rtx, rtx, int, rtx *));
@@ -1455,6 +1456,46 @@ contains_muldiv (x)
     }
 }
 \f
+/* Determine whether INSN can be used in a combination.  Return nonzero if
+   not.  This is used in try_combine to detect early some cases where we
+   can't perform combinations.  */
+
+static int
+cant_combine_insn_p (insn)
+     rtx insn;
+{
+  rtx set;
+  rtx src, dest;
+  
+  /* If this isn't really an insn, we can't do anything.
+     This can occur when flow deletes an insn that it has merged into an
+     auto-increment address.  */
+  if (! INSN_P (insn))
+    return 1;
+
+  /* Never combine loads and stores involving hard regs.  The register
+     allocator can usually handle such reg-reg moves by tying.  If we allow
+     the combiner to make substitutions of hard regs, we risk aborting in
+     reload on machines that have SMALL_REGISTER_CLASSES.
+     As an exception, we allow combinations involving fixed regs; these are
+     not available to the register allocator so there's no risk involved.  */
+
+  set = single_set (insn);
+  if (! set)
+    return 0;
+  src = SET_SRC (set);
+  dest = SET_DEST (set);
+  if (REG_P (src)
+      && REGNO (src) < FIRST_PSEUDO_REGISTER
+      && ! fixed_regs[REGNO (src)])
+    return 1;
+  if (REG_P (dest)
+      && REGNO (dest) < FIRST_PSEUDO_REGISTER
+      && ! fixed_regs[REGNO (dest)])
+    return 1;
+  return 0;
+}
+
 /* Try to combine the insns I1 and I2 into I3.
    Here I1 and I2 appear earlier than I3.
    I1 can be zero; then we combine just I2 into I3.
@@ -1509,13 +1550,14 @@ try_combine (i3, i2, i1, new_direct_jump_p)
   register rtx link;
   int i;
 
-  /* If any of I1, I2, and I3 isn't really an insn, we can't do anything.
-     This can occur when flow deletes an insn that it has merged into an
-     auto-increment address.  We also can't do anything if I3 has a
-     REG_LIBCALL note since we don't want to disrupt the contiguity of a
-     libcall.  */
-
-  if (! INSN_P (i3) || ! INSN_P (i2) || (i1 && ! INSN_P (i1))
+  /* Exit early if one of the insns involved can't be used for
+     combinations.  */
+  if (cant_combine_insn_p (i3)
+      || cant_combine_insn_p (i2)
+      || (i1 && cant_combine_insn_p (i1))
+      /* We also can't do anything if I3 has a
+        REG_LIBCALL note since we don't want to disrupt the contiguity of a
+        libcall.  */
 #if 0
       /* ??? This gives worse code, and appears to be unnecessary, since no
         pass after flow uses REG_LIBCALL/REG_RETVAL notes.  */