aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>1999-12-06 20:45:38 +0100
committerDavid S. Miller <davem@gcc.gnu.org>1999-12-06 11:45:38 -0800
commit732f2ac967fede4eb604a4575a862bab1bc309e6 (patch)
tree2a0c3098c4f80998e0552333248b50ec31e858c3 /gcc
parent0974e9fec8fbca107e6077874febb87ae22c8a83 (diff)
downloadgcc-732f2ac967fede4eb604a4575a862bab1bc309e6.zip
gcc-732f2ac967fede4eb604a4575a862bab1bc309e6.tar.gz
gcc-732f2ac967fede4eb604a4575a862bab1bc309e6.tar.bz2
combine.c (check_promoted_subreg, [...]): New functions.
* combine.c (check_promoted_subreg, record_promoted_value): New functions. (combine_instructions): Use them to retain nonzero and sign bit information after SUBREGs are eliminated by optimizations in this pass if PROMOTE_FUNCTION_RETURN. From-SVN: r30808
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/combine.c93
2 files changed, 99 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f2c3181..119a1db 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -17,6 +17,12 @@
always use move_by_pieces to avoid infinite recursion.
(restore_fixed_argument_area): Likewise.
+ * combine.c (check_promoted_subreg, record_promoted_value): New
+ functions.
+ (combine_instructions): Use them to retain nonzero and sign bit
+ information after SUBREGs are eliminated by optimizations in
+ this pass if PROMOTE_FUNCTION_RETURN.
+
Mon Dec 6 12:24:52 1999 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* fold-const.c (optimize_bit_field_compare): Only use one mode
diff --git a/gcc/combine.c b/gcc/combine.c
index f55bb66..825d8a7 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -403,6 +403,9 @@ static enum rtx_code simplify_comparison PROTO((enum rtx_code, rtx *, rtx *));
static int reversible_comparison_p PROTO((rtx));
static void update_table_tick PROTO((rtx));
static void record_value_for_reg PROTO((rtx, rtx, rtx));
+#ifdef PROMOTE_FUNCTION_RETURN
+static void check_promoted_subreg PROTO((rtx, rtx));
+#endif
static void record_dead_and_set_regs_1 PROTO((rtx, rtx, void *));
static void record_dead_and_set_regs PROTO((rtx));
static int get_last_value_validate PROTO((rtx *, rtx, int, int));
@@ -608,6 +611,12 @@ combine_instructions (f, nregs)
else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
+#ifdef PROMOTE_FUNCTION_RETURN
+ /* See if we know about function return values before this
+ insn based upon SUBREG flags. */
+ check_promoted_subreg (insn, PATTERN (insn));
+#endif
+
/* Try this insn with each insn it links back to. */
for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
@@ -11048,6 +11057,90 @@ record_dead_and_set_regs (insn)
note_stores (PATTERN (insn), record_dead_and_set_regs_1, insn);
}
+
+#ifdef PROMOTE_FUNCTION_RETURN
+/* If a SUBREG has the promoted bit set, it is in fact a property of the
+ register present in the SUBREG, so for each such SUBREG go back and
+ adjust nonzero and sign bit information of the registers that are
+ known to have some zero/sign bits set.
+
+ This is needed because when combine blows the SUBREGs away, the
+ information on zero/sign bits is lost and further combines can be
+ missed because of that. */
+
+static void
+record_promoted_value (insn, subreg)
+ rtx insn;
+ rtx subreg;
+{
+ rtx links, links2, set;
+ int regno = REGNO (SUBREG_REG (subreg));
+ enum machine_mode mode = GET_MODE (subreg);
+
+ if (GET_MODE_BITSIZE (mode) >= HOST_BITS_PER_WIDE_INT)
+ return;
+
+ for (links = LOG_LINKS (insn); links; )
+ {
+ insn = XEXP (links, 0);
+ set = single_set (insn);
+
+ if (! set || GET_CODE (SET_DEST (set)) != REG
+ || REGNO (SET_DEST (set)) != regno
+ || GET_MODE (SET_DEST (set)) != GET_MODE (SUBREG_REG (subreg)))
+ {
+ links = XEXP (links, 1);
+ continue;
+ }
+
+ if (reg_last_set [regno] == insn)
+ {
+ if (SUBREG_PROMOTED_UNSIGNED_P (subreg))
+ reg_last_set_nonzero_bits [regno] &= GET_MODE_MASK (mode);
+ }
+
+ if (GET_CODE (SET_SRC (set)) == REG)
+ {
+ regno = REGNO (SET_SRC (set));
+ links = LOG_LINKS (insn);
+ }
+ else
+ break;
+ }
+}
+
+/* Scan X for promoted SUBREGs. For each one found,
+ note what it implies to the registers used in it. */
+
+static void
+check_promoted_subreg (insn, x)
+ rtx insn;
+ rtx x;
+{
+ if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
+ && GET_CODE (SUBREG_REG (x)) == REG)
+ record_promoted_value (insn, x);
+ else
+ {
+ const char *format = GET_RTX_FORMAT (GET_CODE (x));
+ int i, j;
+
+ for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+ switch (format [i])
+ {
+ case 'e':
+ check_promoted_subreg (insn, XEXP (x, i));
+ break;
+ case 'V':
+ case 'E':
+ if (XVEC (x, i) != 0)
+ for (j = 0; j < XVECLEN (x, i); j++)
+ check_promoted_subreg (insn, XVECEXP (x, i, j));
+ break;
+ }
+ }
+}
+#endif
/* Utility routine for the following function. Verify that all the registers
mentioned in *LOC are valid when *LOC was part of a value set when