Message ID | 110adf99-5023-0f74-e090-a6ebe72498b2@codesourcery.com |
---|---|
State | New |
Headers | show |
Series | Check suitability of spill register for mode | expand |
On 11/14/19 7:34 AM, Kwok Cheung Yeung wrote: > Hello > > Currently, when choosing a spill register, GCC just picks the first > available register in the register class returned by the > TAQRGET_SPILL_CLASS hook that doesn't conflict. > > On AMD GCN this can cause problems as DImode values stored in SGPRs > must start on an even register number and TImode values on a multiple > of 4. This is enforced by defining TARGET_HARD_REGNO_MODE_OK to be > false when this condition is not satisfied. However, > assign_spill_hard_regs does not check TARGET_HARD_REGNO_MODE_OK, so it > can assign an unsuitable hard register for the mode. I have fixed this > by rejecting spill registers that do not satisfy > TARGET_HARD_REGNO_MODE_OK for the largest mode of the spilt register. > > Built and tested for an AMD GCN target. This fixes failures in: > > gcc.dg/vect/no-scevccp-outer-9.c > gcc.dg/vect/no-scevccp-outer-10.c > > I have also ensured that the code bootstraps on x86_64, though it > currently does not use spill registers. > > Okay for trunk? > Spilling into registers of another class was an experimental feature. On some x86-64 micro-architectures, it resulted in a worse performance code. But I guess in your case, it is profitable. I hope after your patches it can be switched on for some x86-64 micro-architectures. As for the patch, it is OK to commit. Thank you. > 2019-11-14 Kwok Cheung Yeung <kcy@codesourcery.com> > > gcc/ > * lra-spills.c (assign_spill_hard_regs): Check that the spill > register is suitable for the mode. > --- > gcc/lra-spills.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c > index 54f76cc..8fbd3a8 100644 > --- a/gcc/lra-spills.c > +++ b/gcc/lra-spills.c > @@ -283,7 +283,8 @@ assign_spill_hard_regs (int *pseudo_regnos, int n) > for (k = 0; k < spill_class_size; k++) > { > hard_regno = ira_class_hard_regs[spill_class][k]; > - if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno)) > + if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno) > + || !targetm.hard_regno_mode_ok (hard_regno, mode)) > continue; > if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, > hard_regno)) > break;
diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 54f76cc..8fbd3a8 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -283,7 +283,8 @@ assign_spill_hard_regs (int *pseudo_regnos, int n) for (k = 0; k < spill_class_size; k++) { hard_regno = ira_class_hard_regs[spill_class][k]; - if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno)) + if (TEST_HARD_REG_BIT (eliminable_regset, hard_regno) + || !targetm.hard_regno_mode_ok (hard_regno, mode)) continue; if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno)) break;