From 4f4b36794c9ccf9527df83fcb6a18603f4b6dcab Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 26 Oct 1998 05:35:39 -0800 Subject: [PATCH] combine.c (subst): Process the inputs to a parallel asm_operands only once. * combine.c (subst): Process the inputs to a parallel asm_operands only once. From-SVN: r23357 --- gcc/ChangeLog | 5 ++ gcc/combine.c | 217 ++++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 139 insertions(+), 83 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f7265a6..f675520 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Mon Oct 26 13:35:02 1998 Richard Henderson + + * combine.c (subst): Process the inputs to a parallel asm_operands + only once. + Mon Oct 26 13:32:31 1998 Richard Henderson * stmt.c (expand_asm_operands): Accept `=' or `+' at any position. diff --git a/gcc/combine.c b/gcc/combine.c index 88cc6c5..4094561 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3048,103 +3048,154 @@ subst (x, from, to, in_dest, unique_copy) if (COMBINE_RTX_EQUAL_P (x, to)) return to; - len = GET_RTX_LENGTH (code); - fmt = GET_RTX_FORMAT (code); + /* Parallel asm_operands need special attention because all of the + inputs are shared across the arms. Furthermore, unsharing the + rtl results in recognition failures. Failure to handle this case + specially can result in circular rtl. + + Solve this by doing a normal pass across the first entry of the + parallel, and only processing the SET_DESTs of the subsequent + entries. Ug. */ + + if (code == PARALLEL + && GET_CODE (XVECEXP (x, 0, 0)) == SET + && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS) + { + new = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy); - /* We don't need to process a SET_DEST that is a register, CC0, or PC, so - set up to skip this common case. All other cases where we want to - suppress replacing something inside a SET_SRC are handled via the - IN_DEST operand. */ - if (code == SET - && (GET_CODE (SET_DEST (x)) == REG - || GET_CODE (SET_DEST (x)) == CC0 - || GET_CODE (SET_DEST (x)) == PC)) - fmt = "ie"; - - /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a - constant. */ - if (fmt[0] == 'e') - op0_mode = GET_MODE (XEXP (x, 0)); + /* If this substitution failed, this whole thing fails. */ + if (GET_CODE (new) == CLOBBER + && XEXP (new, 0) == const0_rtx) + return new; - for (i = 0; i < len; i++) - { - if (fmt[i] == 'E') + SUBST (XVECEXP (x, 0, 0), new); + + for (i = XVECLEN (x, 0) - 1; i >= 1; i--) { - register int j; - for (j = XVECLEN (x, i) - 1; j >= 0; j--) + rtx dest = SET_DEST (XVECEXP (x, 0, i)); + + if (GET_CODE (dest) != REG + && GET_CODE (dest) != CC0 + && GET_CODE (dest) != PC) { - if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from)) - { - new = (unique_copy && n_occurrences ? copy_rtx (to) : to); - n_occurrences++; - } - else - { - new = subst (XVECEXP (x, i, j), from, to, 0, unique_copy); + new = subst (dest, from, to, 0, unique_copy); - /* If this substitution failed, this whole thing fails. */ - if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx) - return new; - } + /* If this substitution failed, this whole thing fails. */ + if (GET_CODE (new) == CLOBBER + && XEXP (new, 0) == const0_rtx) + return new; - SUBST (XVECEXP (x, i, j), new); + SUBST (SET_DEST (XVECEXP (x, 0, i)), new); } } - else if (fmt[i] == 'e') + } + else + { + len = GET_RTX_LENGTH (code); + fmt = GET_RTX_FORMAT (code); + + /* We don't need to process a SET_DEST that is a register, CC0, + or PC, so set up to skip this common case. All other cases + where we want to suppress replacing something inside a + SET_SRC are handled via the IN_DEST operand. */ + if (code == SET + && (GET_CODE (SET_DEST (x)) == REG + || GET_CODE (SET_DEST (x)) == CC0 + || GET_CODE (SET_DEST (x)) == PC)) + fmt = "ie"; + + /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a + constant. */ + if (fmt[0] == 'e') + op0_mode = GET_MODE (XEXP (x, 0)); + + for (i = 0; i < len; i++) { - if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from)) + if (fmt[i] == 'E') + { + register int j; + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + { + if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from)) + { + new = (unique_copy && n_occurrences + ? copy_rtx (to) : to); + n_occurrences++; + } + else + { + new = subst (XVECEXP (x, i, j), from, to, 0, + unique_copy); + + /* If this substitution failed, this whole thing + fails. */ + if (GET_CODE (new) == CLOBBER + && XEXP (new, 0) == const0_rtx) + return new; + } + + SUBST (XVECEXP (x, i, j), new); + } + } + else if (fmt[i] == 'e') { - /* In general, don't install a subreg involving two modes not - tieable. It can worsen register allocation, and can even - make invalid reload insns, since the reg inside may need to - be copied from in the outside mode, and that may be invalid - if it is an fp reg copied in integer mode. - - We allow two exceptions to this: It is valid if it is inside - another SUBREG and the mode of that SUBREG and the mode of - the inside of TO is tieable and it is valid if X is a SET - that copies FROM to CC0. */ - if (GET_CODE (to) == SUBREG - && ! MODES_TIEABLE_P (GET_MODE (to), - GET_MODE (SUBREG_REG (to))) - && ! (code == SUBREG - && MODES_TIEABLE_P (GET_MODE (x), - GET_MODE (SUBREG_REG (to)))) + if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from)) + { + /* In general, don't install a subreg involving two + modes not tieable. It can worsen register + allocation, and can even make invalid reload + insns, since the reg inside may need to be copied + from in the outside mode, and that may be invalid + if it is an fp reg copied in integer mode. + + We allow two exceptions to this: It is valid if + it is inside another SUBREG and the mode of that + SUBREG and the mode of the inside of TO is + tieable and it is valid if X is a SET that copies + FROM to CC0. */ + + if (GET_CODE (to) == SUBREG + && ! MODES_TIEABLE_P (GET_MODE (to), + GET_MODE (SUBREG_REG (to))) + && ! (code == SUBREG + && MODES_TIEABLE_P (GET_MODE (x), + GET_MODE (SUBREG_REG (to)))) #ifdef HAVE_cc0 - && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx) + && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx) #endif - ) - return gen_rtx_CLOBBER (VOIDmode, const0_rtx); + ) + return gen_rtx_CLOBBER (VOIDmode, const0_rtx); - new = (unique_copy && n_occurrences ? copy_rtx (to) : to); - n_occurrences++; + new = (unique_copy && n_occurrences ? copy_rtx (to) : to); + n_occurrences++; + } + else + /* If we are in a SET_DEST, suppress most cases unless we + have gone inside a MEM, in which case we want to + simplify the address. We assume here that things that + are actually part of the destination have their inner + parts in the first expression. This is true for SUBREG, + STRICT_LOW_PART, and ZERO_EXTRACT, which are the only + things aside from REG and MEM that should appear in a + SET_DEST. */ + new = subst (XEXP (x, i), from, to, + (((in_dest + && (code == SUBREG || code == STRICT_LOW_PART + || code == ZERO_EXTRACT)) + || code == SET) + && i == 0), unique_copy); + + /* If we found that we will have to reject this combination, + indicate that by returning the CLOBBER ourselves, rather than + an expression containing it. This will speed things up as + well as prevent accidents where two CLOBBERs are considered + to be equal, thus producing an incorrect simplification. */ + + if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx) + return new; + + SUBST (XEXP (x, i), new); } - else - /* If we are in a SET_DEST, suppress most cases unless we - have gone inside a MEM, in which case we want to - simplify the address. We assume here that things that - are actually part of the destination have their inner - parts in the first expression. This is true for SUBREG, - STRICT_LOW_PART, and ZERO_EXTRACT, which are the only - things aside from REG and MEM that should appear in a - SET_DEST. */ - new = subst (XEXP (x, i), from, to, - (((in_dest - && (code == SUBREG || code == STRICT_LOW_PART - || code == ZERO_EXTRACT)) - || code == SET) - && i == 0), unique_copy); - - /* If we found that we will have to reject this combination, - indicate that by returning the CLOBBER ourselves, rather than - an expression containing it. This will speed things up as - well as prevent accidents where two CLOBBERs are considered - to be equal, thus producing an incorrect simplification. */ - - if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx) - return new; - - SUBST (XEXP (x, i), new); } } -- 2.7.4