aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2003-02-01 01:01:38 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2003-02-01 01:01:38 +0000
commit2f278625ee254d3293798efeb57003a42fc2871a (patch)
tree6695bfe875cd231e5b9de23862d2deddab1b9692 /gcc
parente4b9b5fb09bda446289e62fd40feb679187ad901 (diff)
downloadgcc-2f278625ee254d3293798efeb57003a42fc2871a.zip
gcc-2f278625ee254d3293798efeb57003a42fc2871a.tar.gz
gcc-2f278625ee254d3293798efeb57003a42fc2871a.tar.bz2
reload.c (find_reloads): Do not use the mode specified in the insn pattern as reload mode for address...
gcc/ * reload.c (find_reloads): Do not use the mode specified in the insn pattern as reload mode for address operands. Do not generate optional reloads for operands where a mandatory reload was already pushed. Generate optional reloads only in the final pass though find_reloads. (have_replacement_p): New function. gcc/testsuite/ * gcc.dg/20030129-1.c: New test. From-SVN: r62225
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/reload.c51
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/20030129-1.c37
4 files changed, 87 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dedd614..bd9a73d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2003-01-31 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload.c (find_reloads): Do not use the mode specified in the insn
+ pattern as reload mode for address operands. Do not generate optional
+ reloads for operands where a mandatory reload was already pushed.
+ Generate optional reloads only in the final pass though find_reloads.
+ (have_replacement_p): New function.
+
2003-01-31 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
* doc/install.texi (Testing): Remove a reference to our obsolete
diff --git a/gcc/reload.c b/gcc/reload.c
index 46d0d64..1a7434f 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -274,6 +274,7 @@ static void find_reloads_address_part PARAMS ((rtx, rtx *, enum reg_class,
static rtx find_reloads_subreg_address PARAMS ((rtx, int, int,
enum reload_type, int, rtx));
static void copy_replacements_1 PARAMS ((rtx *, rtx *, int));
+static bool have_replacement_p PARAMS ((rtx *));
static int find_inc_amount PARAMS ((rtx, rtx));
#ifdef HAVE_SECONDARY_RELOADS
@@ -2689,6 +2690,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
recog_data.operand[i] = *recog_data.operand_loc[i];
substed_operand[i] = recog_data.operand[i];
+
+ /* Address operands are reloaded in their existing mode,
+ no matter what is specified in the machine description. */
+ operand_mode[i] = GET_MODE (recog_data.operand[i]);
}
else if (code == MEM)
{
@@ -3302,10 +3307,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
the address into a base register. */
this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
badop = 0;
-
- /* Address constraints are reloaded in Pmode, no matter
- what mode is given in the machine description. */
- operand_mode[i] = Pmode;
break;
}
@@ -3876,9 +3877,20 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
return 0;
}
}
+
+ /* Generate optional reloads only when optimizing, and only
+ on the last pass through reload. Also, make sure we do not
+ make an optional reload where we already have a mandatory
+ one; this can happen in the case of address operands.
+
+ To check for mandatory reloads, we use have_replacement_p.
+ Note that this works only on the last pass through reload. */
+ else if (!optimize || !replace
+ || have_replacement_p (recog_data.operand_loc[i]))
+ ; /* Do nothing. */
+
else if (goal_alternative_matched[i] < 0
- && goal_alternative_matches[i] < 0
- && optimize)
+ && goal_alternative_matches[i] < 0)
{
/* For each non-matching operand that's a MEM or a pseudo-register
that didn't get a hard register, make an optional reload.
@@ -3928,11 +3940,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
reload, check if this is actually a pseudo register reference;
we then need to emit a USE and/or a CLOBBER so that reload
inheritance will do the right thing. */
- else if (replace
- && (GET_CODE (operand) == MEM
- || (GET_CODE (operand) == REG
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_renumber [REGNO (operand)] < 0)))
+ else if (GET_CODE (operand) == MEM
+ || (GET_CODE (operand) == REG
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber [REGNO (operand)] < 0))
{
operand = *recog_data.operand_loc[i];
@@ -3955,8 +3966,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
&& goal_alternative_win[goal_alternative_matches[i]]
&& modified[i] == RELOAD_READ
&& modified[goal_alternative_matches[i]] == RELOAD_WRITE
- && ! no_input_reloads && ! no_output_reloads
- && optimize)
+ && ! no_input_reloads && ! no_output_reloads)
{
/* Similarly, make an optional reload for a pair of matching
objects that are in MEM or a pseudo that didn't get a hard reg. */
@@ -6130,6 +6140,21 @@ find_replacement (loc)
return *loc;
}
+
+/* Return true if some replacement was scheduled at LOC. */
+
+static bool
+have_replacement_p (loc)
+ rtx *loc;
+{
+ struct replacement *r;
+
+ for (r = &replacements[0]; r < &replacements[n_replacements]; r++)
+ if (r->where == loc)
+ return true;
+
+ return false;
+}
/* Return nonzero if register in range [REGNO, ENDREGNO)
appears either explicitly or implicitly in X
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 87a814f..acf883d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-01-31 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * gcc.dg/20030129-1.c: New test.
+
2003-01-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/8849
diff --git a/gcc/testsuite/gcc.dg/20030129-1.c b/gcc/testsuite/gcc.dg/20030129-1.c
new file mode 100644
index 0000000..0b745a9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20030129-1.c
@@ -0,0 +1,37 @@
+/* This used to ICE due to a reload bug on s390*. */
+
+/* { dg-do compile { target s390*-*-* } } */
+/* { dg-options "-O2" } */
+
+int f (unsigned int);
+void g (void *);
+
+void test (void *p, void *dummy)
+{
+ unsigned int flags = 0;
+
+ if (dummy)
+ g (dummy);
+
+ if (p)
+ flags |= 0x80000000;
+
+ asm volatile ("" : : : "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
+
+ if (dummy)
+ g (dummy);
+
+ if (p)
+ {
+ flags |= 0x20000000|0x80000000;
+
+ if (!f (0))
+ flags &= ~0x80000000;
+ }
+
+ f (flags);
+
+ if (dummy)
+ g (dummy);
+}
+