aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Tietz <ktietz@redhat.com>2014-05-30 18:00:11 +0000
committerKai Tietz <ktietz@redhat.com>2014-05-30 18:00:11 +0000
commit51c942c5e4a450eaaecf1b53108deed34d42be4c (patch)
tree8ad0314a3b818c2c80c4c2f059499561fe4e852b
parent377a27857e4ab74a56383db255a0be4e071e715d (diff)
PR target/60104
* 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. 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. * gcc.target/i386/sibcall-4.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@211089 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/i386/i386.c11
-rw-r--r--gcc/config/i386/i386.md8
-rw-r--r--gcc/config/i386/predicates.md10
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-3.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sibcall-4.c15
8 files changed, 92 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 68986b13a01..3653520446f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2014-05-30 Kai Tietz <ktietz@redhat.com>
+
+ PR target/60104
+ * 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.
+
2014-05-30 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* config/avr/avr-mcus.def: Change ATA6289 ISA to AVR4
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 83d3ba3c089..f48adfd39ee 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 44e80ecc5cf..8d363bda0b3 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -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)
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 2ef1384246e..efc3a090d08 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -71,6 +71,12 @@
return ANY_QI_REG_P (op);
})
+(define_predicate "sibcall_memory_operand"
+ (match_operand 0 "memory_operand")
+{
+ return CONSTANT_P (XEXP (op, 0));
+})
+
;; Match an SI or HImode register for a zero_extract.
(define_special_predicate "ext_register_operand"
(match_operand 0 "register_operand")
@@ -600,7 +606,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"
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-1.c b/gcc/testsuite/gcc.target/i386/sibcall-1.c
new file mode 100644
index 00000000000..5a9ff475a1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-1.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-2.c b/gcc/testsuite/gcc.target/i386/sibcall-2.c
new file mode 100644
index 00000000000..f42e83c2bf6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-2.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-3.c b/gcc/testsuite/gcc.target/i386/sibcall-3.c
new file mode 100644
index 00000000000..439b422482d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-3.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sibcall-4.c b/gcc/testsuite/gcc.target/i386/sibcall-4.c
new file mode 100644
index 00000000000..e157338e52f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sibcall-4.c
@@ -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" } } */