mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-21 14:30:59 +08:00
i386.c (call_insn_operand): Always allow SYMBOL_REF, care for HALF_PIC_P.
* i386.c (call_insn_operand): Always allow SYMBOL_REF, care for HALF_PIC_P. (expander_call_insn_operand): Remove. (ix86_expand_epilogue): New arg `emit_return' to control return insn. * i386.h (PREDICATE_CODES): Update. * i386.md (all call expanders): Remove predicates, remove special handling for half-pic. (*call_1, *call_value_1): Handle SIBLING_CALL_P insns. (*call_pop_pic2, *call_pic2, *call_value_pop_2, *call_value_2): Remove. (sibcall_epilogue): New. From-SVN: r32620
This commit is contained in:
parent
b6c5a81ce3
commit
cbbf65e012
@ -1,3 +1,16 @@
|
||||
2000-03-18 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* i386.c (call_insn_operand): Always allow SYMBOL_REF,
|
||||
care for HALF_PIC_P.
|
||||
(expander_call_insn_operand): Remove.
|
||||
(ix86_expand_epilogue): New arg `emit_return' to control return insn.
|
||||
* i386.h (PREDICATE_CODES): Update.
|
||||
* i386.md (all call expanders): Remove predicates, remove special
|
||||
handling for half-pic.
|
||||
(*call_1, *call_value_1): Handle SIBLING_CALL_P insns.
|
||||
(*call_pop_pic2, *call_pic2, *call_value_pop_2, *call_value_2): Remove.
|
||||
(sibcall_epilogue): New.
|
||||
|
||||
2000-03-17 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* rtlanal.c (single_set): Reject if the parallel has anything
|
||||
|
@ -30,7 +30,7 @@ extern void asm_output_function_prefix PARAMS ((FILE *, const char *));
|
||||
extern void load_pic_register PARAMS ((void));
|
||||
extern HOST_WIDE_INT ix86_initial_elimination_offset PARAMS((int, int));
|
||||
extern void ix86_expand_prologue PARAMS ((void));
|
||||
extern void ix86_expand_epilogue PARAMS ((void));
|
||||
extern void ix86_expand_epilogue PARAMS ((int));
|
||||
|
||||
extern void ix86_output_function_block_profiler PARAMS ((FILE *, int));
|
||||
extern void ix86_output_block_profiler PARAMS ((FILE *, int));
|
||||
@ -44,7 +44,6 @@ extern int symbolic_reference_mentioned_p PARAMS ((rtx));
|
||||
extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int expander_call_insn_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int constant_call_address_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int const0_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int const1_operand PARAMS ((rtx, enum machine_mode));
|
||||
|
@ -1067,22 +1067,17 @@ call_insn_operand (op, mode)
|
||||
if (GET_CODE (op) == CONST_INT)
|
||||
return 0;
|
||||
|
||||
/* Otherwise we can allow any general_operand in the address. */
|
||||
return general_operand (op, Pmode);
|
||||
}
|
||||
|
||||
/* Like call_insn_operand but allow (mem (symbol_ref ...)) even if pic. */
|
||||
|
||||
int
|
||||
expander_call_insn_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (GET_CODE (op) == MEM
|
||||
&& GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
|
||||
/* Explicitly allow SYMBOL_REF even if pic. */
|
||||
if (GET_CODE (op) == SYMBOL_REF)
|
||||
return 1;
|
||||
|
||||
return call_insn_operand (op, mode);
|
||||
/* Half-pic doesn't allow anything but registers and constants.
|
||||
We've just taken care of the later. */
|
||||
if (HALF_PIC_P ())
|
||||
return register_operand (op, Pmode);
|
||||
|
||||
/* Otherwise we can allow any general_operand in the address. */
|
||||
return general_operand (op, Pmode);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1090,9 +1085,9 @@ constant_call_address_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return GET_CODE (op) == MEM &&
|
||||
CONSTANT_ADDRESS_P (XEXP (op, 0)) &&
|
||||
GET_CODE (XEXP (op, 0)) != CONST_INT;
|
||||
return (GET_CODE (op) == MEM
|
||||
&& CONSTANT_ADDRESS_P (XEXP (op, 0))
|
||||
&& GET_CODE (XEXP (op, 0)) != CONST_INT);
|
||||
}
|
||||
|
||||
/* Match exactly zero and one. */
|
||||
@ -1997,7 +1992,8 @@ ix86_emit_restore_regs_using_mov (pointer, offset)
|
||||
/* Restore function stack, frame, and registers. */
|
||||
|
||||
void
|
||||
ix86_expand_epilogue ()
|
||||
ix86_expand_epilogue (emit_return)
|
||||
int emit_return;
|
||||
{
|
||||
int nregs;
|
||||
int regno;
|
||||
@ -2082,6 +2078,10 @@ ix86_expand_epilogue ()
|
||||
emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
|
||||
}
|
||||
|
||||
/* Sibcall epilogues don't want a return instruction. */
|
||||
if (! emit_return)
|
||||
return;
|
||||
|
||||
if (current_function_pops_args && current_function_args_size)
|
||||
{
|
||||
rtx popc = GEN_INT (current_function_pops_args);
|
||||
|
@ -1230,6 +1230,11 @@ typedef struct ix86_args {
|
||||
|
||||
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
|
||||
|
||||
/* If PIC, we cannot optimize sibling calls to global functions
|
||||
because the PLT requires %ebx live. */
|
||||
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
|
||||
(DECL && (! flag_pic || ! TREE_PUBLIC (DECL)))
|
||||
|
||||
/* This macro is invoked just before the start of a function.
|
||||
It is used here to output code for -fpic that will load the
|
||||
return address into %ebx. */
|
||||
@ -2457,7 +2462,6 @@ do { long l; \
|
||||
LABEL_REF, SUBREG, REG, MEM}}, \
|
||||
{"pic_symbolic_operand", {CONST}}, \
|
||||
{"call_insn_operand", {MEM}}, \
|
||||
{"expander_call_insn_operand", {MEM}}, \
|
||||
{"constant_call_address_operand", {MEM}}, \
|
||||
{"const0_operand", {CONST_INT, CONST_DOUBLE}}, \
|
||||
{"const1_operand", {CONST_INT}}, \
|
||||
|
@ -7010,47 +7010,36 @@
|
||||
|
||||
;; Call instructions.
|
||||
|
||||
;; If generating PIC code, the predicate indirect_operand will fail
|
||||
;; for operands[0] containing symbolic references on all of the named
|
||||
;; call* patterns. Each named pattern is followed by an unnamed pattern
|
||||
;; that matches any call to a symbolic CONST (ie, a symbol_ref). The
|
||||
;; unnamed patterns are only used while generating PIC code, because
|
||||
;; otherwise the named patterns match.
|
||||
;; The predicates normally associated with named expanders are not properly
|
||||
;; checked for calls. This is a bug in the generic code, but it isn't that
|
||||
;; easy to fix. Ignore it for now and be prepared to fix things up.
|
||||
|
||||
;; Call subroutine returning no value.
|
||||
|
||||
(define_expand "call_pop"
|
||||
[(parallel [(call (match_operand:QI 0 "indirect_operand" "")
|
||||
(match_operand:SI 1 "general_operand" ""))
|
||||
[(parallel [(call (match_operand:QI 0 "" "")
|
||||
(match_operand:SI 1 "" ""))
|
||||
(set (reg:SI 7)
|
||||
(plus:SI (reg:SI 7)
|
||||
(match_operand:SI 3 "immediate_operand" "")))])]
|
||||
(match_operand:SI 3 "" "")))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx addr;
|
||||
|
||||
if (operands[3] == const0_rtx)
|
||||
{
|
||||
emit_insn (gen_call (operands[0], operands[1]));
|
||||
DONE;
|
||||
}
|
||||
|
||||
/* ??? Not true for calls to static functions. */
|
||||
if (flag_pic)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
|
||||
/* With half-pic, force the address into a register. */
|
||||
addr = XEXP (operands[0], 0);
|
||||
if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
|
||||
XEXP (operands[0], 0) = force_reg (Pmode, addr);
|
||||
|
||||
if (! expander_call_insn_operand (operands[0], QImode))
|
||||
operands[0]
|
||||
= change_address (operands[0], VOIDmode,
|
||||
copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
|
||||
if (! call_insn_operand (operands[0], QImode))
|
||||
XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
||||
}")
|
||||
|
||||
(define_insn "*call_pop_pic"
|
||||
(define_insn "*call_pop_1"
|
||||
[(call (match_operand:QI 0 "call_insn_operand" "m")
|
||||
(match_operand:SI 1 "general_operand" "g"))
|
||||
(set (reg:SI 7) (plus:SI (reg:SI 7)
|
||||
@ -7066,39 +7055,22 @@
|
||||
}"
|
||||
[(set_attr "type" "call")])
|
||||
|
||||
(define_insn "*call_pop_pic2"
|
||||
[(call (match_operand:QI 0 "constant_call_address_operand" "")
|
||||
(match_operand:SI 1 "general_operand" "g"))
|
||||
(set (reg:SI 7) (plus:SI (reg:SI 7)
|
||||
(match_operand:SI 3 "immediate_operand" "i")))]
|
||||
"!HALF_PIC_P ()"
|
||||
"call\\t%P0"
|
||||
[(set_attr "type" "call")])
|
||||
|
||||
(define_expand "call"
|
||||
[(call (match_operand:QI 0 "indirect_operand" "")
|
||||
(match_operand:SI 1 "general_operand" ""))]
|
||||
[(call (match_operand:QI 0 "" "")
|
||||
(match_operand:SI 1 "" ""))]
|
||||
;; Operand 1 not used on the i386.
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx addr;
|
||||
|
||||
/* ??? Not true for calls to static functions. */
|
||||
if (flag_pic)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
|
||||
/* With half-pic, force the address into a register. */
|
||||
addr = XEXP (operands[0], 0);
|
||||
if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
|
||||
XEXP (operands[0], 0) = force_reg (Pmode, addr);
|
||||
|
||||
if (! expander_call_insn_operand (operands[0], QImode))
|
||||
operands[0]
|
||||
= change_address (operands[0], VOIDmode,
|
||||
copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
|
||||
if (! call_insn_operand (operands[0], QImode))
|
||||
XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
||||
}")
|
||||
|
||||
(define_insn "*call_pic"
|
||||
(define_insn "*call_1"
|
||||
[(call (match_operand:QI 0 "call_insn_operand" "m")
|
||||
(match_operand:SI 1 "general_operand" "g"))]
|
||||
;; Operand 1 not used on the i386.
|
||||
@ -7106,18 +7078,19 @@
|
||||
"*
|
||||
{
|
||||
if (constant_call_address_operand (operands[0], GET_MODE (operands[0])))
|
||||
return \"call\\t%P0\";
|
||||
|
||||
operands[0] = XEXP (operands[0], 0);
|
||||
return \"call\\t%*%0\";
|
||||
}"
|
||||
[(set_attr "type" "call")])
|
||||
{
|
||||
if (SIBLING_CALL_P (insn))
|
||||
return \"jmp\\t%P0\";
|
||||
else
|
||||
return \"call\\t%P0\";
|
||||
}
|
||||
|
||||
(define_insn "*call_pic2"
|
||||
[(call (match_operand:QI 0 "constant_call_address_operand" "")
|
||||
(match_operand:SI 1 "general_operand" "g"))]
|
||||
"!HALF_PIC_P ()"
|
||||
"call\\t%P0"
|
||||
operands[0] = XEXP (operands[0], 0);
|
||||
if (SIBLING_CALL_P (insn))
|
||||
return \"jmp\\t%*%0\";
|
||||
else
|
||||
return \"call\\t%*%0\";
|
||||
}"
|
||||
[(set_attr "type" "call")])
|
||||
|
||||
;; Call subroutine, returning value in operand 0
|
||||
@ -7125,11 +7098,11 @@
|
||||
|
||||
(define_expand "call_value_pop"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (match_operand:QI 1 "indirect_operand" "")
|
||||
(match_operand:SI 2 "general_operand" "")))
|
||||
(call (match_operand:QI 1 "" "")
|
||||
(match_operand:SI 2 "" "")))
|
||||
(set (reg:SI 7)
|
||||
(plus:SI (reg:SI 7)
|
||||
(match_operand:SI 4 "immediate_operand" "")))])]
|
||||
(match_operand:SI 4 "" "")))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
@ -7141,42 +7114,30 @@
|
||||
DONE;
|
||||
}
|
||||
|
||||
/* ??? Not true for calls to static functions. */
|
||||
if (flag_pic)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
|
||||
/* With half-pic, force the address into a register. */
|
||||
addr = XEXP (operands[1], 0);
|
||||
if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
|
||||
XEXP (operands[1], 0) = force_reg (Pmode, addr);
|
||||
|
||||
if (! expander_call_insn_operand (operands[1], QImode))
|
||||
operands[1]
|
||||
= change_address (operands[1], VOIDmode,
|
||||
copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
|
||||
if (! call_insn_operand (operands[1], QImode))
|
||||
XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
|
||||
}")
|
||||
|
||||
(define_expand "call_value"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (match_operand:QI 1 "indirect_operand" "")
|
||||
(match_operand:SI 2 "general_operand" "")))]
|
||||
(call (match_operand:QI 1 "" "")
|
||||
(match_operand:SI 2 "" "")))]
|
||||
;; Operand 2 not used on the i386.
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx addr;
|
||||
|
||||
/* ??? Not true for calls to static functions. */
|
||||
if (flag_pic)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
|
||||
/* With half-pic, force the address into a register. */
|
||||
addr = XEXP (operands[1], 0);
|
||||
if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
|
||||
XEXP (operands[1], 0) = force_reg (Pmode, addr);
|
||||
|
||||
if (! expander_call_insn_operand (operands[1], QImode))
|
||||
operands[1]
|
||||
= change_address (operands[1], VOIDmode,
|
||||
copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
|
||||
if (! call_insn_operand (operands[1], QImode))
|
||||
XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
|
||||
}")
|
||||
|
||||
;; Call subroutine returning any type.
|
||||
@ -7309,7 +7270,12 @@
|
||||
(define_expand "epilogue"
|
||||
[(const_int 1)]
|
||||
""
|
||||
"ix86_expand_epilogue (); DONE;")
|
||||
"ix86_expand_epilogue (1); DONE;")
|
||||
|
||||
(define_expand "sibcall_epilogue"
|
||||
[(const_int 1)]
|
||||
""
|
||||
"ix86_expand_epilogue (0); DONE;")
|
||||
|
||||
(define_insn "leave"
|
||||
[(set (reg:SI 7) (reg:SI 6))
|
||||
@ -9414,16 +9380,6 @@
|
||||
}"
|
||||
[(set_attr "type" "callv")])
|
||||
|
||||
(define_insn "*call_value_pop_2"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (match_operand:QI 1 "constant_call_address_operand" "")
|
||||
(match_operand:SI 2 "general_operand" "g")))
|
||||
(set (reg:SI 7) (plus:SI (reg:SI 7)
|
||||
(match_operand:SI 4 "immediate_operand" "i")))]
|
||||
"!HALF_PIC_P ()"
|
||||
"call\\t%P1"
|
||||
[(set_attr "type" "callv")])
|
||||
|
||||
(define_insn "*call_value_1"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (match_operand:QI 1 "call_insn_operand" "m")
|
||||
@ -9433,17 +9389,17 @@
|
||||
"*
|
||||
{
|
||||
if (constant_call_address_operand (operands[1], GET_MODE (operands[1])))
|
||||
return \"call\\t%P1\";
|
||||
{
|
||||
if (SIBLING_CALL_P (insn))
|
||||
return \"jmp\\t%P1\";
|
||||
else
|
||||
return \"call\\t%P1\";
|
||||
}
|
||||
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
return \"call\\t%*%1\";
|
||||
if (SIBLING_CALL_P (insn))
|
||||
return \"jmp\\t%*%1\";
|
||||
else
|
||||
return \"call\\t%*%1\";
|
||||
}"
|
||||
[(set_attr "type" "callv")])
|
||||
|
||||
(define_insn "*call_value_2"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (match_operand:QI 1 "constant_call_address_operand" "")
|
||||
(match_operand:SI 2 "general_operand" "g")))]
|
||||
"!HALF_PIC_P ()"
|
||||
"call\\t%P1"
|
||||
[(set_attr "type" "callv")])
|
||||
|
Loading…
x
Reference in New Issue
Block a user