summaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-02-12 11:37:38 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2013-02-12 11:37:38 +0100
commit6da26889318467b3df29c215f15d0c8369c969e3 (patch)
treef65fc19aa8ddb84c4b86e34d59f3e05f225bb1c1 /gcc/optabs.c
parent1590a83511111c9621a72800b361589aa11734b9 (diff)
downloadgcc-6da26889318467b3df29c215f15d0c8369c969e3.tar.gz
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 <steven@gcc.gnu.org> From-SVN: r195972
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c35
1 files changed, 29 insertions, 6 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 8a3d3a921ab..c1dacf487a0 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;