From 6da26889318467b3df29c215f15d0c8369c969e3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 12 Feb 2013 11:37:38 +0100 Subject: re PR rtl-optimization/56151 (Performance degradation after r194054 on x86 Atom.) PR rtl-optimization/56151 * optabs.c (add_equal_note): Don't return 0 if target is a MEM, equal to op0 or op1, and last_insn pattern is CODE operation with MEM dest and one of the operands matches that MEM. * gcc.target/i386/pr56151.c: New test. Co-Authored-By: Steven Bosscher From-SVN: r195972 --- gcc/optabs.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'gcc/optabs.c') diff --git a/gcc/optabs.c b/gcc/optabs.c index 8a3d3a9..c1dacf4 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -190,17 +190,40 @@ 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)) ; + /* 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))) + { + if (MEM_P (target) + && (rtx_equal_p (target, op0) + || (op1 && rtx_equal_p (target, op1)))) + { + /* For MEM target, with MEM = MEM op X, prefer no REG_EQUAL note + over expanding it as temp = MEM op X, MEM = temp. If the target + supports MEM = MEM op X instructions, it is sometimes too hard + to reconstruct that form later, especially if X is also a memory, + and due to multiple occurrences of addresses the address might + be forced into register unnecessarily. + Note that not emitting the REG_EQUIV note might inhibit + CSE in some cases. */ + set = single_set (last_insn); + if (set + && GET_CODE (SET_SRC (set)) == code + && MEM_P (SET_DEST (set)) + && (rtx_equal_p (SET_DEST (set), XEXP (SET_SRC (set), 0)) + || (op1 && rtx_equal_p (SET_DEST (set), + XEXP (SET_SRC (set), 1))))) + return 1; + } + return 0; + } + set = single_set (last_insn); if (set == NULL_RTX) return 1; -- cgit v1.1