+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
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)
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);
}
}
; x87 Floating point
(UNSPEC_FPATAN 65)
(UNSPEC_FYL2X 66)
+
+ ; REP instruction
+ (UNSPEC_REP 67)
])
(define_constants
(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" ""))]