aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-03-18 11:01:04 -0800
committerRichard Henderson <rth@gcc.gnu.org>2000-03-18 11:01:04 -0800
commitcbbf65e012ad4532ef9e312f3dd8d6b89fbeb992 (patch)
tree2d7cd0a26caa8a38b483ebc5d56f363e55ce10a6
parentb6c5a81ce3c1ddc364f57dda8ab3ff45203f4c61 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/i386/i386-protos.h3
-rw-r--r--gcc/config/i386/i386.c36
-rw-r--r--gcc/config/i386/i386.h6
-rw-r--r--gcc/config/i386/i386.md152
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")])