From 194acded39a88ef3ffef175d639cc7f9be66fe0d Mon Sep 17 00:00:00 2001 From: Hans-Peter Nilsson Date: Sat, 6 Nov 2004 18:33:04 +0000 Subject: [PATCH] re PR rtl-optimization/17933 (ICE: in schedule_insns, at /sched-rgn.c:2555) PR rtl-optimization/17933 * rtlanal.c (dead_or_set_regno_p): Break out common code to... (covers_regno_p): New function. Handle SETs of PARALLEL, and defer the rest to... (covers_regno_no_parallel_p): New function. From-SVN: r90183 --- gcc/ChangeLog | 8 ++++ gcc/rtlanal.c | 102 ++++++++++++++++++++++++++++---------------------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1c0215796d3..00d25f18f9c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-11-06 Hans-Peter Nilsson + + PR rtl-optimization/17933 + * rtlanal.c (dead_or_set_regno_p): Break out common code to... + (covers_regno_p): New function. Handle SETs of PARALLEL, + and defer the rest to... + (covers_regno_no_parallel_p): New function. + 2004-11-06 Eric Botcazou * config/sparc/sparc.c (function_arg_record_value_1): Skip diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 8ada3974c1b..de5478823b2 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -41,6 +41,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* Forward declarations */ static int global_reg_mentioned_p_1 (rtx *, void *); static void set_of_1 (rtx, rtx, void *); +static bool covers_regno_p (rtx, unsigned int); +static bool covers_regno_no_parallel_p (rtx, unsigned int); static int rtx_referenced_p_1 (rtx *, void *); static int computed_jump_p_1 (rtx); static void parms_set (rtx, rtx, void *); @@ -1549,13 +1551,64 @@ dead_or_set_p (rtx insn, rtx x) return 1; } +/* Return TRUE iff DEST is a register or subreg of a register and + doesn't change the number of words of the inner register, and any + part of the register is TEST_REGNO. */ + +static bool +covers_regno_no_parallel_p (rtx dest, unsigned int test_regno) +{ + unsigned int regno, endregno; + + if (GET_CODE (dest) == SUBREG + && (((GET_MODE_SIZE (GET_MODE (dest)) + + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) + + UNITS_PER_WORD - 1) / UNITS_PER_WORD))) + dest = SUBREG_REG (dest); + + if (!REG_P (dest)) + return false; + + regno = REGNO (dest); + endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1 + : regno + hard_regno_nregs[regno][GET_MODE (dest)]); + return (test_regno >= regno && test_regno < endregno); +} + +/* Like covers_regno_no_parallel_p, but also handles PARALLELs where + any member matches the covers_regno_no_parallel_p criteria. */ + +static bool +covers_regno_p (rtx dest, unsigned int test_regno) +{ + if (GET_CODE (dest) == PARALLEL) + { + /* Some targets place small structures in registers for return + values of functions, and those registers are wrapped in + PARALLELs that we may see as the destination of a SET. */ + int i; + + for (i = XVECLEN (dest, 0) - 1; i >= 0; i--) + { + rtx inner = XEXP (XVECEXP (dest, 0, i), 0); + if (inner != NULL_RTX + && covers_regno_no_parallel_p (inner, test_regno)) + return true; + } + + return false; + } + else + return covers_regno_no_parallel_p (dest, test_regno); +} + /* Utility function for dead_or_set_p to check an individual register. Also called from flow.c. */ int dead_or_set_regno_p (rtx insn, unsigned int test_regno) { - unsigned int regno, endregno; rtx pattern; /* See if there is a death note for something that includes TEST_REGNO. */ @@ -1572,28 +1625,7 @@ dead_or_set_regno_p (rtx insn, unsigned int test_regno) pattern = COND_EXEC_CODE (pattern); if (GET_CODE (pattern) == SET) - { - rtx dest = SET_DEST (pattern); - - /* A value is totally replaced if it is the destination or the - destination is a SUBREG of REGNO that does not change the number of - words in it. */ - if (GET_CODE (dest) == SUBREG - && (((GET_MODE_SIZE (GET_MODE (dest)) - + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) - + UNITS_PER_WORD - 1) / UNITS_PER_WORD))) - dest = SUBREG_REG (dest); - - if (!REG_P (dest)) - return 0; - - regno = REGNO (dest); - endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1 - : regno + hard_regno_nregs[regno][GET_MODE (dest)]); - - return (test_regno >= regno && test_regno < endregno); - } + return covers_regno_p (SET_DEST (pattern), test_regno); else if (GET_CODE (pattern) == PARALLEL) { int i; @@ -1605,27 +1637,9 @@ dead_or_set_regno_p (rtx insn, unsigned int test_regno) if (GET_CODE (body) == COND_EXEC) body = COND_EXEC_CODE (body); - if (GET_CODE (body) == SET || GET_CODE (body) == CLOBBER) - { - rtx dest = SET_DEST (body); - - if (GET_CODE (dest) == SUBREG - && (((GET_MODE_SIZE (GET_MODE (dest)) - + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) - + UNITS_PER_WORD - 1) / UNITS_PER_WORD))) - dest = SUBREG_REG (dest); - - if (!REG_P (dest)) - continue; - - regno = REGNO (dest); - endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1 - : regno + hard_regno_nregs[regno][GET_MODE (dest)]); - - if (test_regno >= regno && test_regno < endregno) - return 1; - } + if ((GET_CODE (body) == SET || GET_CODE (body) == CLOBBER) + && covers_regno_p (SET_DEST (body), test_regno)) + return 1; } } -- 2.30.2