summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-22 11:55:42 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2005-07-22 11:55:42 +0000
commitb440a47b74c8774870719e531fa1ebc547f5050b (patch)
treeed8acf9614f17e7c4ca5b66817f428b45beaa2ad
parent5b7178c86c030f45f211bf6d3dc636af6f3bb315 (diff)
downloadgcc-b440a47b74c8774870719e531fa1ebc547f5050b.tar.gz
PR rtl-optimization/22258
* combine.c (likely_spilled_retval_1, likely_spilled_retval_p): New functions. (try_combine): Use likely_spilled_retval_p. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102279 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/combine.c80
2 files changed, 87 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 94fa4b2b85e..98a7747d8ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-07-22 J"orn Rennecke <joern.rennecke@st.com>
+
+ PR rtl-optimization/22258
+ * combine.c (likely_spilled_retval_1, likely_spilled_retval_p):
+ New functions.
+ (try_combine): Use likely_spilled_retval_p.
+
2005-07-22 Paul Woegerer <paul.woegerer@nsc.com>
* config.gcc: Add crx-elf support.
diff --git a/gcc/combine.c b/gcc/combine.c
index 24170608edd..d8d3baf982a 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1557,6 +1557,85 @@ cant_combine_insn_p (rtx insn)
return 0;
}
+struct likely_spilled_retval_info
+{
+ unsigned regno, nregs;
+ unsigned mask;
+};
+
+/* Called via note_stores by likely_spilled_retval_p. Remove from info->mask
+ hard registers that are known to be written to / clobbered in full. */
+static void
+likely_spilled_retval_1 (rtx x, rtx set, void *data)
+{
+ struct likely_spilled_retval_info *info = data;
+ unsigned regno, nregs;
+ unsigned new_mask;
+
+ if (!REG_P (XEXP (set, 0)))
+ return;
+ regno = REGNO (x);
+ if (regno >= info->regno + info->nregs)
+ return;
+ nregs = hard_regno_nregs[regno][GET_MODE (x)];
+ if (regno + nregs <= info->regno)
+ return;
+ new_mask = (2U << (nregs - 1)) - 1;
+ if (regno < info->regno)
+ new_mask >>= info->regno - regno;
+ else
+ new_mask <<= regno - info->regno;
+ info->mask &= new_mask;
+}
+
+/* Return nonzero iff part of the return value is live during INSN, and
+ it is likely spilled. This can happen when more than one insn is needed
+ to copy the return value, e.g. when we consider to combine into the
+ second copy insn for a complex value. */
+
+static int
+likely_spilled_retval_p (rtx insn)
+{
+ rtx use = BB_END (this_basic_block);
+ rtx reg, p;
+ unsigned regno, nregs;
+ /* We assume here that no machine mode needs more than
+ 32 hard registers when the value overlaps with a register
+ for which FUNCTION_VALUE_REGNO_P is true. */
+ unsigned mask;
+ struct likely_spilled_retval_info info;
+
+ if (!NONJUMP_INSN_P (use) || GET_CODE (PATTERN (use)) != USE || insn == use)
+ return 0;
+ reg = XEXP (PATTERN (use), 0);
+ if (!REG_P (reg) || !FUNCTION_VALUE_REGNO_P (REGNO (reg)))
+ return 0;
+ regno = REGNO (reg);
+ nregs = hard_regno_nregs[regno][GET_MODE (reg)];
+ if (nregs == 1)
+ return 0;
+ mask = (2U << (nregs - 1)) - 1;
+
+ /* Disregard parts of the return value that are set later. */
+ info.regno = regno;
+ info.nregs = nregs;
+ info.mask = mask;
+ for (p = PREV_INSN (use); info.mask && p != insn; p = PREV_INSN (p))
+ note_stores (PATTERN (insn), likely_spilled_retval_1, &info);
+ mask = info.mask;
+
+ /* Check if any of the (probably) live return value registers is
+ likely spilled. */
+ nregs --;
+ do
+ {
+ if ((mask & 1 << nregs)
+ && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno + nregs)))
+ return 1;
+ } while (nregs--);
+ return 0;
+}
+
/* Adjust INSN after we made a change to its destination.
Changing the destination can invalidate notes that say something about
@@ -1644,6 +1723,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
if (cant_combine_insn_p (i3)
|| cant_combine_insn_p (i2)
|| (i1 && cant_combine_insn_p (i1))
+ || likely_spilled_retval_p (i3)
/* 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. */