From 8f3e7a26bde8797649fff46419ac6c6b71c95f78 Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Fri, 6 May 1994 17:43:38 -0400 Subject: [PATCH] (reg_used_between_p): Check usage exprs on CALL_INSNs. (reg_referenced_between_p, reg_set_p, dead_or_set_regno_p): Likewise. (find_reg{,no}_fusage): New functions. From-SVN: r7235 --- gcc/rtlanal.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 486ef5f8d22..980226f2b64 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -315,7 +315,10 @@ reg_used_between_p (reg, from_insn, to_insn) for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn)) if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' - && reg_overlap_mentioned_p (reg, PATTERN (insn))) + && (reg_overlap_mentioned_p (reg, PATTERN (insn)) + || (GET_CODE (insn) == CALL_INSN + && (find_reg_fusage (insn, USE, reg) + || find_reg_fusage (insn, CLOBBER, reg))))) return 1; return 0; } @@ -393,7 +396,9 @@ reg_referenced_between_p (reg, from_insn, to_insn) for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn)) if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' - && reg_referenced_p (reg, PATTERN (insn))) + && (reg_referenced_p (reg, PATTERN (insn)) + || (GET_CODE (insn) == CALL_INSN + && find_reg_fusage (insn, USE, reg)))) return 1; return 0; } @@ -448,10 +453,14 @@ reg_set_p (reg, insn) || (GET_CODE (insn) == CALL_INSN /* We'd like to test call_used_regs here, but rtlanal.c can't reference that variable due to its use in genattrtab. So - we'll just be more conservative. */ + we'll just be more conservative. + + ??? Unless we could ensure that the CALL_INSN_FUNCTION_USAGE + information holds all clobbered registers. */ && ((GET_CODE (reg) == REG && REGNO (reg) < FIRST_PSEUDO_REGISTER) - || GET_CODE (reg) == MEM))) + || GET_CODE (reg) == MEM + || find_reg_fusage (insn, CLOBBER, reg)))) return 1; body = PATTERN (insn); @@ -1130,6 +1139,10 @@ dead_or_set_regno_p (insn, test_regno) return 1; } + if (GET_CODE (insn) == CALL_INSN + && find_regno_fusage (insn, CLOBBER, test_regno)) + return 1; + if (GET_CODE (PATTERN (insn)) == SET) { rtx dest = SET_DEST (PATTERN (insn)); @@ -1233,6 +1246,90 @@ find_regno_note (insn, kind, regno) return link; return 0; } + +/* Return true if DATUM, or any overlap of DATUM, of kind CODE is found + in the CALL_INSN_FUNCTION_USAGE information of INSN. */ + +int +find_reg_fusage (insn, code, datum) + rtx insn; + enum rtx_code code; + rtx datum; +{ + /* If it's not a CALL_INSN, it can't possibly have a + CALL_INSN_FUNCTION_USAGE field, so don't bother checking. */ + if (GET_CODE (insn) != CALL_INSN) + return 0; + + if (! datum) + abort(); + + if (GET_CODE (datum) != REG) + { + register rtx link; + + for (link = CALL_INSN_FUNCTION_USAGE (insn); + link; + link = XEXP (link, 1)) + if (GET_CODE (XEXP (link, 0)) == code + && rtx_equal_p (datum, SET_DEST (XEXP (link, 0)))) + return 1; + } + else + { + register int regno = REGNO (datum); + + /* CALL_INSN_FUNCTION_USAGE information cannot contain references + to pseudo registers, so don't bother checking. */ + + if (regno < FIRST_PSEUDO_REGISTER) + { + int end_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (datum)); + int i; + + for (i = regno; i < end_regno; i++) + if (find_regno_fusage (insn, code, i)) + return 1; + } + } + + return 0; +} + +/* Return true if REGNO, or any overlap of REGNO, of kind CODE is found + in the CALL_INSN_FUNCTION_USAGE information of INSN. */ + +int +find_regno_fusage (insn, code, regno) + rtx insn; + enum rtx_code code; + int regno; +{ + register rtx link; + + /* CALL_INSN_FUNCTION_USAGE information cannot contain references + to pseudo registers, so don't bother checking. */ + + if (regno >= FIRST_PSEUDO_REGISTER + || GET_CODE (insn) != CALL_INSN ) + return 0; + + for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) + { + register int regnote; + register rtx op; + + if (GET_CODE (op = XEXP (link, 0)) == code + && GET_CODE (SET_DEST (op)) == REG + && (regnote = REGNO (SET_DEST (op))) <= regno + && regnote + + HARD_REGNO_NREGS (regnote, GET_MODE (SET_DEST (op))) + > regno) + return 1; + } + + return 0; +} /* Remove register note NOTE from the REG_NOTES of INSN. */ -- 2.30.2