Commit 183bfdaf by Richard Sandiford Committed by Richard Sandiford

[AArch64] Add FFR and FFRT registers

This patch adds the First Fault Register to the AArch64 port, as well
as a fake register known as the FFR Token or FFRT.  The main ACLE
patch explains what the FFRT does and how it works.

2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* config/aarch64/aarch64.md (FFR_REGNUM, FFRT_REGNUM): New constants.
	* config/aarch64/aarch64.h (FIRST_PSEUDO_REGISTER): Bump to
	FFRT_REGNUM + 1.
	(FFR_REGS, PR_AND_FFR_REGS): New register classes.
	(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add entries for them.
	* config/aarch64/aarch64.c (pr_or_ffr_regnum_p): New function.
	(aarch64_hard_regno_nregs): Handle the new register classes.
	(aarch64_hard_regno_mode_ok): Likewise.
	(aarch64_regno_regclass): Likewise.
	(aarch64_class_max_nregs): Likewise.
	(aarch64_register_move_cost): Likewise.
	(aarch64_conditional_register_usage): Don't treat FFR and FFRT
	as general register_operands.

From-SVN: r277561
parent 50a2d3be
2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
* config/aarch64/aarch64.md (FFR_REGNUM, FFRT_REGNUM): New constants.
* config/aarch64/aarch64.h (FIRST_PSEUDO_REGISTER): Bump to
FFRT_REGNUM + 1.
(FFR_REGS, PR_AND_FFR_REGS): New register classes.
(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add entries for them.
* config/aarch64/aarch64.c (pr_or_ffr_regnum_p): New function.
(aarch64_hard_regno_nregs): Handle the new register classes.
(aarch64_hard_regno_mode_ok): Likewise.
(aarch64_regno_regclass): Likewise.
(aarch64_class_max_nregs): Likewise.
(aarch64_register_move_cost): Likewise.
(aarch64_conditional_register_usage): Don't treat FFR and FFRT
as general register_operands.
2019-10-29 Martin Liska <mliska@suse.cz> 2019-10-29 Martin Liska <mliska@suse.cz>
* ggc-common.c: One can't subtract unsigned types * ggc-common.c: One can't subtract unsigned types
...@@ -1426,6 +1426,14 @@ aarch64_err_no_fpadvsimd (machine_mode mode) ...@@ -1426,6 +1426,14 @@ aarch64_err_no_fpadvsimd (machine_mode mode)
" vector types", "+nofp"); " vector types", "+nofp");
} }
/* Return true if REGNO is P0-P15 or one of the special FFR-related
registers. */
inline bool
pr_or_ffr_regnum_p (unsigned int regno)
{
return PR_REGNUM_P (regno) || regno == FFR_REGNUM || regno == FFRT_REGNUM;
}
/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS. /* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS.
The register allocator chooses POINTER_AND_FP_REGS if FP_REGS and The register allocator chooses POINTER_AND_FP_REGS if FP_REGS and
GENERAL_REGS have the same cost - even if POINTER_AND_FP_REGS has a much GENERAL_REGS have the same cost - even if POINTER_AND_FP_REGS has a much
...@@ -1810,6 +1818,8 @@ aarch64_hard_regno_nregs (unsigned regno, machine_mode mode) ...@@ -1810,6 +1818,8 @@ aarch64_hard_regno_nregs (unsigned regno, machine_mode mode)
case PR_REGS: case PR_REGS:
case PR_LO_REGS: case PR_LO_REGS:
case PR_HI_REGS: case PR_HI_REGS:
case FFR_REGS:
case PR_AND_FFR_REGS:
return 1; return 1;
default: default:
return CEIL (lowest_size, UNITS_PER_WORD); return CEIL (lowest_size, UNITS_PER_WORD);
...@@ -1836,10 +1846,10 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode) ...@@ -1836,10 +1846,10 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode)
return false; return false;
if (vec_flags & VEC_SVE_PRED) if (vec_flags & VEC_SVE_PRED)
return PR_REGNUM_P (regno); return pr_or_ffr_regnum_p (regno);
if (PR_REGNUM_P (regno)) if (pr_or_ffr_regnum_p (regno))
return 0; return false;
if (regno == SP_REGNUM) if (regno == SP_REGNUM)
/* The purpose of comparing with ptr_mode is to support the /* The purpose of comparing with ptr_mode is to support the
...@@ -9163,6 +9173,9 @@ aarch64_regno_regclass (unsigned regno) ...@@ -9163,6 +9173,9 @@ aarch64_regno_regclass (unsigned regno)
if (PR_REGNUM_P (regno)) if (PR_REGNUM_P (regno))
return PR_LO_REGNUM_P (regno) ? PR_LO_REGS : PR_HI_REGS; return PR_LO_REGNUM_P (regno) ? PR_LO_REGS : PR_HI_REGS;
if (regno == FFR_REGNUM || regno == FFRT_REGNUM)
return FFR_REGS;
return NO_REGS; return NO_REGS;
} }
...@@ -9461,6 +9474,8 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode) ...@@ -9461,6 +9474,8 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode)
case PR_REGS: case PR_REGS:
case PR_LO_REGS: case PR_LO_REGS:
case PR_HI_REGS: case PR_HI_REGS:
case FFR_REGS:
case PR_AND_FFR_REGS:
return 1; return 1;
case NO_REGS: case NO_REGS:
...@@ -11641,6 +11656,14 @@ aarch64_register_move_cost (machine_mode mode, ...@@ -11641,6 +11656,14 @@ aarch64_register_move_cost (machine_mode mode,
if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS) if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS)
from = GENERAL_REGS; from = GENERAL_REGS;
/* Make RDFFR very expensive. In particular, if we know that the FFR
contains a PTRUE (e.g. after a SETFFR), we must never use RDFFR
as a way of obtaining a PTRUE. */
if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
&& hard_reg_set_subset_p (reg_class_contents[from_i],
reg_class_contents[FFR_REGS]))
return 80;
/* Moving between GPR and stack cost is the same as GP2GP. */ /* Moving between GPR and stack cost is the same as GP2GP. */
if ((from == GENERAL_REGS && to == STACK_REG) if ((from == GENERAL_REGS && to == STACK_REG)
|| (to == GENERAL_REGS && from == STACK_REG)) || (to == GENERAL_REGS && from == STACK_REG))
...@@ -14802,6 +14825,10 @@ aarch64_conditional_register_usage (void) ...@@ -14802,6 +14825,10 @@ aarch64_conditional_register_usage (void)
call_used_regs[i] = 1; call_used_regs[i] = 1;
} }
/* Only allow the FFR and FFRT to be accessed via special patterns. */
CLEAR_HARD_REG_BIT (operand_reg_set, FFR_REGNUM);
CLEAR_HARD_REG_BIT (operand_reg_set, FFRT_REGNUM);
/* When tracking speculation, we need a couple of call-clobbered registers /* When tracking speculation, we need a couple of call-clobbered registers
to track the speculation state. It would be nice to just use to track the speculation state. It would be nice to just use
IP0 and IP1, but currently there are numerous places that just IP0 and IP1, but currently there are numerous places that just
......
...@@ -366,6 +366,9 @@ extern unsigned aarch64_architecture_version; ...@@ -366,6 +366,9 @@ extern unsigned aarch64_architecture_version;
P0-P7 Predicate low registers: valid in all predicate contexts P0-P7 Predicate low registers: valid in all predicate contexts
P8-P15 Predicate high registers: used as scratch space P8-P15 Predicate high registers: used as scratch space
FFR First Fault Register, a fixed-use SVE predicate register
FFRT FFR token: a fake register used for modelling dependencies
VG Pseudo "vector granules" register VG Pseudo "vector granules" register
VG is the number of 64-bit elements in an SVE vector. We define VG is the number of 64-bit elements in an SVE vector. We define
...@@ -386,6 +389,7 @@ extern unsigned aarch64_architecture_version; ...@@ -386,6 +389,7 @@ extern unsigned aarch64_architecture_version;
1, 1, 1, 1, /* SFP, AP, CC, VG */ \ 1, 1, 1, 1, /* SFP, AP, CC, VG */ \
0, 0, 0, 0, 0, 0, 0, 0, /* P0 - P7 */ \ 0, 0, 0, 0, 0, 0, 0, 0, /* P0 - P7 */ \
0, 0, 0, 0, 0, 0, 0, 0, /* P8 - P15 */ \ 0, 0, 0, 0, 0, 0, 0, 0, /* P8 - P15 */ \
1, 1 /* FFR and FFRT */ \
} }
/* X30 is marked as caller-saved which is in line with regular function call /* X30 is marked as caller-saved which is in line with regular function call
...@@ -408,6 +412,7 @@ extern unsigned aarch64_architecture_version; ...@@ -408,6 +412,7 @@ extern unsigned aarch64_architecture_version;
1, 1, 1, 1, /* SFP, AP, CC, VG */ \ 1, 1, 1, 1, /* SFP, AP, CC, VG */ \
1, 1, 1, 1, 1, 1, 1, 1, /* P0 - P7 */ \ 1, 1, 1, 1, 1, 1, 1, 1, /* P0 - P7 */ \
1, 1, 1, 1, 1, 1, 1, 1, /* P8 - P15 */ \ 1, 1, 1, 1, 1, 1, 1, 1, /* P8 - P15 */ \
1, 1 /* FFR and FFRT */ \
} }
#define REGISTER_NAMES \ #define REGISTER_NAMES \
...@@ -423,6 +428,7 @@ extern unsigned aarch64_architecture_version; ...@@ -423,6 +428,7 @@ extern unsigned aarch64_architecture_version;
"sfp", "ap", "cc", "vg", \ "sfp", "ap", "cc", "vg", \
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", \ "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", \
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \
"ffr", "ffrt" \
} }
/* Generate the register aliases for core register N */ /* Generate the register aliases for core register N */
...@@ -471,7 +477,7 @@ extern unsigned aarch64_architecture_version; ...@@ -471,7 +477,7 @@ extern unsigned aarch64_architecture_version;
#define FRAME_POINTER_REGNUM SFP_REGNUM #define FRAME_POINTER_REGNUM SFP_REGNUM
#define STACK_POINTER_REGNUM SP_REGNUM #define STACK_POINTER_REGNUM SP_REGNUM
#define ARG_POINTER_REGNUM AP_REGNUM #define ARG_POINTER_REGNUM AP_REGNUM
#define FIRST_PSEUDO_REGISTER (P15_REGNUM + 1) #define FIRST_PSEUDO_REGISTER (FFRT_REGNUM + 1)
/* The number of (integer) argument register available. */ /* The number of (integer) argument register available. */
#define NUM_ARG_REGS 8 #define NUM_ARG_REGS 8
...@@ -601,6 +607,8 @@ enum reg_class ...@@ -601,6 +607,8 @@ enum reg_class
PR_LO_REGS, PR_LO_REGS,
PR_HI_REGS, PR_HI_REGS,
PR_REGS, PR_REGS,
FFR_REGS,
PR_AND_FFR_REGS,
ALL_REGS, ALL_REGS,
LIM_REG_CLASSES /* Last */ LIM_REG_CLASSES /* Last */
}; };
...@@ -621,6 +629,8 @@ enum reg_class ...@@ -621,6 +629,8 @@ enum reg_class
"PR_LO_REGS", \ "PR_LO_REGS", \
"PR_HI_REGS", \ "PR_HI_REGS", \
"PR_REGS", \ "PR_REGS", \
"FFR_REGS", \
"PR_AND_FFR_REGS", \
"ALL_REGS" \ "ALL_REGS" \
} }
...@@ -638,6 +648,8 @@ enum reg_class ...@@ -638,6 +648,8 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000ff0 }, /* PR_LO_REGS */ \ { 0x00000000, 0x00000000, 0x00000ff0 }, /* PR_LO_REGS */ \
{ 0x00000000, 0x00000000, 0x000ff000 }, /* PR_HI_REGS */ \ { 0x00000000, 0x00000000, 0x000ff000 }, /* PR_HI_REGS */ \
{ 0x00000000, 0x00000000, 0x000ffff0 }, /* PR_REGS */ \ { 0x00000000, 0x00000000, 0x000ffff0 }, /* PR_REGS */ \
{ 0x00000000, 0x00000000, 0x00300000 }, /* FFR_REGS */ \
{ 0x00000000, 0x00000000, 0x003ffff0 }, /* PR_AND_FFR_REGS */ \
{ 0xffffffff, 0xffffffff, 0x000fffff } /* ALL_REGS */ \ { 0xffffffff, 0xffffffff, 0x000fffff } /* ALL_REGS */ \
} }
......
...@@ -107,6 +107,10 @@ ...@@ -107,6 +107,10 @@
(P13_REGNUM 81) (P13_REGNUM 81)
(P14_REGNUM 82) (P14_REGNUM 82)
(P15_REGNUM 83) (P15_REGNUM 83)
(FFR_REGNUM 84)
;; "FFR token": a fake register used for representing the scheduling
;; restrictions on FFR-related operations.
(FFRT_REGNUM 85)
;; Scratch register used by stack clash protection to calculate ;; Scratch register used by stack clash protection to calculate
;; SVE CFA offsets during probing. ;; SVE CFA offsets during probing.
(STACK_CLASH_SVE_CFA_REGNUM 11) (STACK_CLASH_SVE_CFA_REGNUM 11)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment