xtensa: Improve indirect sibling call handling

No longer needs the dedicated hard register (A11) for the address of the
call and the split patterns for fixups, due to the introduction of appropriate
register class and constraint.

(Note: "ISC_REGS" contains a hard register A8 used as a "static chain"
 pointer for nested functions, but no problem;  Pointer to nested function
 actually points to "trampoline", and trampoline itself doesn't receive
 "static chain" pointer to its parent's stack frame from the caller.)

gcc/ChangeLog:

	* config/xtensa/xtensa.h
	(enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS):
	Add new register class "ISC_REGS".
	* config/xtensa/constraints.md (c): Add new register constraint.
	* config/xtensa/xtensa.md (define_constants): Remove "A11_REG".
	(sibcall_internal, sibcall_value_internal):
	Change to use the new register constraint, and remove two split
	patterns for fixups that are no longer needed.

gcc/testsuite/ChangeLog:

	* gcc.target/xtensa/sibcalls.c: Add a new test function to ensure
	that registers for arguments (occupy from A2 to A7) and for indirect
	sibcall (should be assigned to A8) neither conflict nor spill out.
This commit is contained in:
Takayuki 'January June' Suwa 2022-08-18 19:03:51 +09:00 committed by Max Filippov
parent ca170ed9f8
commit 8731aa9867
4 changed files with 15 additions and 27 deletions

View file

@ -27,6 +27,11 @@
"Boolean registers @code{b0}-@code{b15}; only available if the Xtensa
Boolean Option is configured.")
(define_register_constraint "c" "TARGET_WINDOWED_ABI ? NO_REGS : ISC_REGS"
"@internal
General-purpose AR registers for indirect sibling calls, @code{a2}-
@code{a8}.")
(define_register_constraint "d" "TARGET_DENSITY ? AR_REGS: NO_REGS"
"@internal
All AR registers, including sp, but only if the Xtensa Code Density

View file

@ -378,6 +378,7 @@ enum reg_class
FP_REGS, /* floating point registers */
ACC_REG, /* MAC16 accumulator */
SP_REG, /* sp register (aka a1) */
ISC_REGS, /* registers for indirect sibling calls */
RL_REGS, /* preferred reload regs (not sp or fp) */
GR_REGS, /* integer registers except sp */
AR_REGS, /* all integer registers */
@ -399,6 +400,7 @@ enum reg_class
"FP_REGS", \
"ACC_REG", \
"SP_REG", \
"ISC_REGS", \
"RL_REGS", \
"GR_REGS", \
"AR_REGS", \
@ -415,6 +417,7 @@ enum reg_class
{ 0xfff80000, 0x00000007 }, /* floating-point registers */ \
{ 0x00000000, 0x00000008 }, /* MAC16 accumulator */ \
{ 0x00000002, 0x00000000 }, /* stack pointer register */ \
{ 0x000001fc, 0x00000000 }, /* registers for indirect sibling calls */ \
{ 0x0000fffd, 0x00000000 }, /* preferred reload registers */ \
{ 0x0000fffd, 0x00000000 }, /* general-purpose registers */ \
{ 0x0003ffff, 0x00000000 }, /* integer registers */ \

View file

@ -25,7 +25,6 @@
(A7_REG 7)
(A8_REG 8)
(A9_REG 9)
(A11_REG 11)
(UNSPEC_NOP 2)
(UNSPEC_PLT 3)
@ -2279,7 +2278,7 @@
})
(define_insn "sibcall_internal"
[(call (mem:SI (match_operand:SI 0 "call_insn_operand" "nir"))
[(call (mem:SI (match_operand:SI 0 "call_insn_operand" "nic"))
(match_operand 1 "" "i"))]
"!TARGET_WINDOWED_ABI && SIBLING_CALL_P (insn)"
{
@ -2289,17 +2288,6 @@
(set_attr "mode" "none")
(set_attr "length" "3")])
(define_split
[(call (mem:SI (match_operand:SI 0 "register_operand"))
(match_operand 1 ""))]
"reload_completed
&& !TARGET_WINDOWED_ABI && SIBLING_CALL_P (insn)
&& ! call_used_or_fixed_reg_p (REGNO (operands[0]))"
[(set (reg:SI A11_REG)
(match_dup 0))
(call (mem:SI (reg:SI A11_REG))
(match_dup 1))])
(define_expand "sibcall_value"
[(set (match_operand 0 "register_operand" "")
(call (match_operand 1 "memory_operand" "")
@ -2311,7 +2299,7 @@
(define_insn "sibcall_value_internal"
[(set (match_operand 0 "register_operand" "=a")
(call (mem:SI (match_operand:SI 1 "call_insn_operand" "nir"))
(call (mem:SI (match_operand:SI 1 "call_insn_operand" "nic"))
(match_operand 2 "" "i")))]
"!TARGET_WINDOWED_ABI && SIBLING_CALL_P (insn)"
{
@ -2321,19 +2309,6 @@
(set_attr "mode" "none")
(set_attr "length" "3")])
(define_split
[(set (match_operand 0 "register_operand")
(call (mem:SI (match_operand:SI 1 "register_operand"))
(match_operand 2 "")))]
"reload_completed
&& !TARGET_WINDOWED_ABI && SIBLING_CALL_P (insn)
&& ! call_used_or_fixed_reg_p (REGNO (operands[1]))"
[(set (reg:SI A11_REG)
(match_dup 1))
(set (match_dup 0)
(call (mem:SI (reg:SI A11_REG))
(match_dup 2)))])
(define_insn "entry"
[(set (reg:SI A1_REG)
(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "i")]

View file

@ -17,4 +17,9 @@ int test_2(int (*a)(void)) {
return a();
}
_Complex double test_3(_Complex double a, _Complex double (*b)(_Complex double, double)) {
bar(-1);
return b(a, 3.141592653589795);
}
/* { dg-final { scan-assembler-not "ret" } } */