diff options
author | Richard Henderson <rth@cygnus.com> | 2000-03-18 11:01:04 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-03-18 11:01:04 -0800 |
commit | cbbf65e012ad4532ef9e312f3dd8d6b89fbeb992 (patch) | |
tree | 2d7cd0a26caa8a38b483ebc5d56f363e55ce10a6 /gcc | |
parent | b6c5a81ce3c1ddc364f57dda8ab3ff45203f4c61 (diff) | |
download | gcc-cbbf65e012ad4532ef9e312f3dd8d6b89fbeb992.zip gcc-cbbf65e012ad4532ef9e312f3dd8d6b89fbeb992.tar.gz gcc-cbbf65e012ad4532ef9e312f3dd8d6b89fbeb992.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 36 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 152 |
5 files changed, 91 insertions, 119 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 68ac1f2..f9aa222 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index d489ec9..81afd7b 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index e78809f..9fc4425 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index afaa80d..2b81e8c 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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}}, \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7bac8ac..b188d91 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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,30 +7078,31 @@ "* { if (constant_call_address_operand (operands[0], GET_MODE (operands[0]))) - return \"call\\t%P0\"; - + { + if (SIBLING_CALL_P (insn)) + return \"jmp\\t%P0\"; + else + return \"call\\t%P0\"; + } + operands[0] = XEXP (operands[0], 0); - return \"call\\t%*%0\"; + if (SIBLING_CALL_P (insn)) + return \"jmp\\t%*%0\"; + else + return \"call\\t%*%0\"; }" [(set_attr "type" "call")]) -(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" - [(set_attr "type" "call")]) - ;; Call subroutine, returning value in operand 0 ;; (which must be a hard register). (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")]) |