re PR target/60104 (load not folded into indirect branch on x86-64)

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.

From-SVN: r211089
This commit is contained in:
Kai Tietz 2014-05-30 20:00:11 +02:00 committed by Kai Tietz
parent 1007a55ca4
commit cb10592208
8 changed files with 92 additions and 6 deletions

View file

@ -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

View file

@ -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))

View file

@ -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)

View file

@ -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"

View file

@ -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" } } */

View file

@ -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" } } */

View file

@ -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" } } */

View file

@ -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" } } */