From 853f8f1c1ced73b423dc1b56c81f4e78c6e5f734 Mon Sep 17 00:00:00 2001 From: Steven Bosscher Date: Sun, 2 Dec 2012 15:46:26 +0000 Subject: [PATCH] optabs.c (add_equal_note): Do not create self-referencing REG_EQUAL notes. * optabs.c (add_equal_note): Do not create self-referencing REG_EQUAL notes. * fwprop.c (forward_propagate_and_simplify): Likewise. From-SVN: r194054 --- gcc/ChangeLog | 6 ++++++ gcc/fwprop.c | 9 ++++++--- gcc/optabs.c | 29 ++++++++++------------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4b6c703b848..bada8f2acd1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-12-02 Steven Bosscher + + * optabs.c (add_equal_note): Do not create self-referencing REG_EQUAL + notes. + * fwprop.c (forward_propagate_and_simplify): Likewise. + 2012-12-02 Steven Bosscher * function.h (struct rtl_data): Remove epilogue_delay_list. diff --git a/gcc/fwprop.c b/gcc/fwprop.c index 0f2ee49ac14..35c82d7ed7f 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -1315,9 +1315,12 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set) /* Do not replace an existing REG_EQUAL note if the insn is not recognized. Either we're already replacing in the note, or we'll separately try plugging the definition in the note and simplifying. - And only install a REQ_EQUAL note when the destination is a REG, - as the note would be invalid otherwise. */ - set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set))); + And only install a REQ_EQUAL note when the destination is a REG + that isn't mentioned in USE_SET, as the note would be invalid + otherwise. */ + set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set)) + && ! reg_mentioned_p (SET_DEST (use_set), + SET_SRC (use_set))); } if (GET_MODE (*loc) == VOIDmode) diff --git a/gcc/optabs.c b/gcc/optabs.c index 353727f3324..d59a1eae3c1 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -170,14 +170,14 @@ optab_libfunc (optab optab, enum machine_mode mode) If the last insn does not set TARGET, don't do anything, but return 1. - If a previous insn sets TARGET and TARGET is one of OP0 or OP1, - don't add the REG_EQUAL note but return 0. Our caller can then try - again, ensuring that TARGET is not one of the operands. */ + If the last insn or a previous insn sets TARGET and TARGET is one of OP0 + or OP1, don't add the REG_EQUAL note but return 0. Our caller can then + try again, ensuring that TARGET is not one of the operands. */ static int add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) { - rtx last_insn, insn, set; + rtx last_insn, set; rtx note; gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns)); @@ -192,6 +192,12 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) if (GET_CODE (target) == ZERO_EXTRACT) return 1; + /* If TARGET is in OP0 or OP1, punt. We'd end up with a note referencing + a value changing in the insn, so the note would be invalid for CSE. */ + if (reg_overlap_mentioned_p (target, op0) + || (op1 && reg_overlap_mentioned_p (target, op1))) + return 0; + for (last_insn = insns; NEXT_INSN (last_insn) != NULL_RTX; last_insn = NEXT_INSN (last_insn)) @@ -207,21 +213,6 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target))) return 1; - /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET - besides the last insn. */ - if (reg_overlap_mentioned_p (target, op0) - || (op1 && reg_overlap_mentioned_p (target, op1))) - { - insn = PREV_INSN (last_insn); - while (insn != NULL_RTX) - { - if (reg_set_p (target, insn)) - return 0; - - insn = PREV_INSN (insn); - } - } - if (GET_RTX_CLASS (code) == RTX_UNARY) switch (code) {