OSDN Git Service

* i386.c (call_insn_operand): Always allow SYMBOL_REF,
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 18 Mar 2000 19:01:04 +0000 (19:01 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 18 Mar 2000 19:01:04 +0000 (19:01 +0000)
        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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32620 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index 68ac1f2..f9aa222 100644 (file)
@@ -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
index d489ec9..81afd7b 100644 (file)
@@ -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));
index e78809f..9fc4425 100644 (file)
@@ -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);
index afaa80d..2b81e8c 100644 (file)
@@ -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}},                                     \
index 7bac8ac..b188d91 100644 (file)
 \f
 ;; 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)
 }"
   [(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.
   "*
 {
   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 "" "")))])]
   ""
   "
 {
       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.
 (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))
 }"
   [(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")
   "*
 {
   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")])