Hi,

I modified prior patch so that it uses the new predicate sibcall_memory_operand 
to extend sibcall_insn_operand.
Just one change in i386.c remains about x86_output_mi_thunk.  Later one isn't 
pretty much essential.  Nevertheless it makes
code equivalent to none-memory-case for potential tail-sibcalls.

ChangeLog gcc

2014-05-28  Kai Tietz  <kti...@redhat.com>

        * config/i386/i386.c (x86_output_mi_thunk): Add memory case
        for sibling-tail-calls.
        * config/i386/i386.md (sibcall_insn_operand): Add memory-constrain
        to its use.
        * config/i386/predicates.md (sibcall_memory_operand): New predicate.
        (sibcall_insn_operand): Add check for sibcall_memory_operand.

ChangeLog testsuite

2014-05-28  Kai Tietz  <kti...@redhat.com>

        PR target/60104
        * gcc.target/i386/sibcall-1.c: New test.
        * gcc.target/i386/sibcall-2.c: New test.
        * gcc.target/i386/sibcall-3.c: New test.

Regression tested x86_64-unknown-linux-gnu multilib, x86_64-w64-mingw32, and 
i686-pc-cygwin.  Ok for apply?

Regards,
Kai


Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      (revision 210985)
+++ gcc/config/i386/i386.c      (working copy)
@@ -38893,7 +38893,16 @@ x86_output_mi_thunk (FILE *file,
      For our purposes here, we can get away with (ab)using a jump pattern,
      because we're going to do no optimization.  */
   if (MEM_P (fnaddr))
-    emit_jump_insn (gen_indirect_jump (fnaddr));
+    {
+      if (sibcall_insn_operand (fnaddr, word_mode))
+       {
+         tmp = gen_rtx_CALL (VOIDmode, fnaddr, const0_rtx);
+          tmp = emit_call_insn (tmp);
+          SIBLING_CALL_P (tmp) = 1;
+       }
+      else
+       emit_jump_insn (gen_indirect_jump (fnaddr));
+    }
   else
     {
       if (ix86_cmodel == CM_LARGE_PIC && SYMBOLIC_CONST (fnaddr))
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md     (revision 210985)
+++ gcc/config/i386/i386.md     (working copy)
@@ -11376,7 +11376,7 @@
   [(set_attr "type" "call")])
 
 (define_insn "*sibcall"
-  [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "Uz"))
+  [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "Uzm"))
         (match_operand 1))]
   "SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[0]);"
@@ -11406,7 +11406,7 @@
   [(set_attr "type" "call")])
 
 (define_insn "*sibcall_pop"
-  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uz"))
+  [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "Uzm"))
         (match_operand 1))
    (set (reg:SI SP_REG)
        (plus:SI (reg:SI SP_REG)
@@ -11451,7 +11451,7 @@
 
 (define_insn "*sibcall_value"
   [(set (match_operand 0)
-       (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "Uz"))
+       (call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "Uzm"))
              (match_operand 2)))]
   "SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[1]);"
@@ -11494,7 +11494,7 @@
 
 (define_insn "*sibcall_value_pop"
   [(set (match_operand 0)
-       (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uz"))
+       (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "Uzm"))
              (match_operand 2)))
    (set (reg:SI SP_REG)
        (plus:SI (reg:SI SP_REG)
Index: gcc/config/i386/predicates.md
===================================================================
--- gcc/config/i386/predicates.md       (revision 210985)
+++ gcc/config/i386/predicates.md       (working copy)
@@ -71,6 +71,16 @@
   return ANY_QI_REG_P (op);
 })
 
+(define_predicate "sibcall_memory_operand"
+  (match_operand 0 "memory_operand")
+{
+  op = XEXP (op, 0);
+
+  if (GET_CODE (op) == CONST)
+    op = XEXP (op, 0);
+  return (GET_CODE (op) == SYMBOL_REF || CONSTANT_P (op));
+})
+
 ;; Match an SI or HImode register for a zero_extract.
 (define_special_predicate "ext_register_operand"
   (match_operand 0 "register_operand")
@@ -600,7 +610,9 @@
 (define_special_predicate "sibcall_insn_operand"
   (ior (match_test "constant_call_address_operand
                     (op, mode == VOIDmode ? mode : Pmode)")
-       (match_operand 0 "register_no_elim_operand")))
+       (match_operand 0 "register_no_elim_operand")
+       (and (not (match_test "TARGET_X32"))
+           (match_operand 0 "sibcall_memory_operand"))))
 
 ;; Return true if OP is a call from MS ABI to SYSV ABI function.
 (define_predicate "call_rex64_ms_sysv_operation"
Index: gcc/testsuite/gcc.target/i386/sibcall-1.c
===================================================================
--- gcc/testsuite/gcc.target/i386/sibcall-1.c   (revision 0)
+++ gcc/testsuite/gcc.target/i386/sibcall-1.c   (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2" } */
+
+extern int (*foo)(int);
+
+int boo (int a)
+{
+  return (*foo) (a);
+}
+
+/* { dg-final { scan-assembler-not "mov" } } */
Index: gcc/testsuite/gcc.target/i386/sibcall-2.c
===================================================================
--- gcc/testsuite/gcc.target/i386/sibcall-2.c   (revision 0)
+++ gcc/testsuite/gcc.target/i386/sibcall-2.c   (working copy)
@@ -0,0 +1,16 @@
+/* { dg-do compile { xfail { *-*-* } } } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2" } */
+
+extern int doo1 (int);
+extern int doo2 (int);
+extern void bar (char *);
+
+int foo (int a)
+{
+  char s[256];
+  bar (s);
+  return (a < 0 ? doo1 : doo2) (a);
+}
+
+/* { dg-final { scan-assembler-not "call[ \t]*.%eax" } } */
Index: gcc/testsuite/gcc.target/i386/sibcall-3.c
===================================================================
--- gcc/testsuite/gcc.target/i386/sibcall-3.c   (revision 0)
+++ gcc/testsuite/gcc.target/i386/sibcall-3.c   (working copy)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2" } */
+
+extern 
+#ifdef _WIN32
+ __declspec (dllimport)
+#endif
+ void foo (int a);
+
+void bar (int a)
+{
+  return foo (a);
+}
+
+/* { dg-final { scan-assembler-not "jmp[ \t]*.%eax" } } */
Index: gcc/testsuite/gcc.target/i386/sibcall-4.c
===================================================================
--- gcc/testsuite/gcc.target/i386/sibcall-4.c   (revision 0)
+++ gcc/testsuite/gcc.target/i386/sibcall-4.c   (working copy)
@@ -0,0 +1,15 @@
+/* Testcase for PR target/46219.  */
+/* { dg-do compile { xfail { *-*-* } } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void male_indirect_jump (long offset)
+{
+  dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler-not "jmp[ \t]*.%eax" } } */

Reply via email to