aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2003-06-04 09:50:27 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2003-06-04 07:50:27 +0000
commit253c7a0090928522c2bca312dc227ebf53b2dd99 (patch)
treeed3cdb18a97f6744254714f5f804504fd7ad402a
parent01d3224a48291c181104b127a4490379f54b9a31 (diff)
downloadgcc-253c7a0090928522c2bca312dc227ebf53b2dd99.zip
gcc-253c7a0090928522c2bca312dc227ebf53b2dd99.tar.gz
gcc-253c7a0090928522c2bca312dc227ebf53b2dd99.tar.bz2
i386.c (ix86_reorg): Replace the jump instead of adding nop.
* i386.c (ix86_reorg): Replace the jump instead of adding nop. * i386.md (UNSPEC_REP): New constant. (return_internal_long): New pattern. From-SVN: r67432
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/i386/i386.c20
-rw-r--r--gcc/config/i386/i386.md16
3 files changed, 34 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5c58596..b918c90 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+Wed Jun 4 09:49:21 CEST 2003 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (ix86_reorg): Replace the jump instead of adding nop.
+ * i386.md (UNSPEC_REP): New constant.
+ (return_internal_long): New pattern.
+
2003-06-04 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/11018
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 968bcde..7386ba5 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -15543,9 +15543,10 @@ ix86_reorg ()
basic_block bb = e->src;
rtx ret = bb->end;
rtx prev;
- bool insert = false;
+ bool replace = false;
- if (!returnjump_p (ret) || !maybe_hot_bb_p (bb))
+ if (GET_CODE (ret) != JUMP_INSN || GET_CODE (PATTERN (ret)) != RETURN
+ || !maybe_hot_bb_p (bb))
continue;
for (prev = PREV_INSN (ret); prev; prev = PREV_INSN (prev))
if (active_insn_p (prev) || GET_CODE (prev) == CODE_LABEL)
@@ -15556,22 +15557,25 @@ ix86_reorg ()
for (e = bb->pred; e; e = e->pred_next)
if (EDGE_FREQUENCY (e) && e->src->index >= 0
&& !(e->flags & EDGE_FALLTHRU))
- insert = 1;
+ replace = true;
}
- if (!insert)
+ if (!replace)
{
prev = prev_active_insn (ret);
if (prev
&& ((GET_CODE (prev) == JUMP_INSN && any_condjump_p (prev))
|| GET_CODE (prev) == CALL_INSN))
- insert = 1;
+ replace = true;
/* Empty functions get branch misspredict even when the jump destination
is not visible to us. */
if (!prev && cfun->function_frequency > FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
- insert = 1;
+ replace = true;
+ }
+ if (replace)
+ {
+ emit_insn_before (gen_return_internal_long (), ret);
+ delete_insn (ret);
}
- if (insert)
- emit_insn_before (gen_nop (), ret);
}
}
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 181cf7e..d192cc8 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -113,6 +113,9 @@
; x87 Floating point
(UNSPEC_FPATAN 65)
(UNSPEC_FYL2X 66)
+
+ ; REP instruction
+ (UNSPEC_REP 67)
])
(define_constants
@@ -14236,6 +14239,19 @@
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
+;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
+;; instruction Athlon and K8 have.
+
+(define_insn "return_internal_long"
+ [(return)
+ (unspec [(const_int 0)] UNSPEC_REP)]
+ "reload_completed"
+ "rep {;} ret"
+ [(set_attr "length" "1")
+ (set_attr "length_immediate" "0")
+ (set_attr "prefix_rep" "1")
+ (set_attr "modrm" "0")])
+
(define_insn "return_pop_internal"
[(return)
(use (match_operand:SI 0 "const_int_operand" ""))]