+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>
* ggc-common.c: One can't subtract unsigned types
" 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.
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
case PR_REGS:
case PR_LO_REGS:
case PR_HI_REGS:
+ case FFR_REGS:
+ case PR_AND_FFR_REGS:
return 1;
default:
return CEIL (lowest_size, UNITS_PER_WORD);
return false;
if (vec_flags & VEC_SVE_PRED)
- return PR_REGNUM_P (regno);
+ return pr_or_ffr_regnum_p (regno);
- if (PR_REGNUM_P (regno))
- return 0;
+ if (pr_or_ffr_regnum_p (regno))
+ return false;
if (regno == SP_REGNUM)
/* The purpose of comparing with ptr_mode is to support the
if (PR_REGNUM_P (regno))
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;
}
case PR_REGS:
case PR_LO_REGS:
case PR_HI_REGS:
+ case FFR_REGS:
+ case PR_AND_FFR_REGS:
return 1;
case NO_REGS:
if (from == TAILCALL_ADDR_REGS || from == POINTER_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. */
if ((from == GENERAL_REGS && to == STACK_REG)
|| (to == GENERAL_REGS && from == STACK_REG))
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
to track the speculation state. It would be nice to just use
IP0 and IP1, but currently there are numerous places that just
P0-P7 Predicate low registers: valid in all predicate contexts
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 is the number of 64-bit elements in an SVE vector. We define
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, /* P8 - P15 */ \
+ 1, 1 /* FFR and FFRT */ \
}
/* X30 is marked as caller-saved which is in line with regular function call
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, /* P8 - P15 */ \
+ 1, 1 /* FFR and FFRT */ \
}
#define REGISTER_NAMES \
"sfp", "ap", "cc", "vg", \
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", \
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \
+ "ffr", "ffrt" \
}
/* Generate the register aliases for core register N */
#define FRAME_POINTER_REGNUM SFP_REGNUM
#define STACK_POINTER_REGNUM SP_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. */
#define NUM_ARG_REGS 8
PR_LO_REGS,
PR_HI_REGS,
PR_REGS,
+ FFR_REGS,
+ PR_AND_FFR_REGS,
ALL_REGS,
LIM_REG_CLASSES /* Last */
};
"PR_LO_REGS", \
"PR_HI_REGS", \
"PR_REGS", \
+ "FFR_REGS", \
+ "PR_AND_FFR_REGS", \
"ALL_REGS" \
}
{ 0x00000000, 0x00000000, 0x00000ff0 }, /* PR_LO_REGS */ \
{ 0x00000000, 0x00000000, 0x000ff000 }, /* PR_HI_REGS */ \
{ 0x00000000, 0x00000000, 0x000ffff0 }, /* PR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00300000 }, /* FFR_REGS */ \
+ { 0x00000000, 0x00000000, 0x003ffff0 }, /* PR_AND_FFR_REGS */ \
{ 0xffffffff, 0xffffffff, 0x000fffff } /* ALL_REGS */ \
}