On 12/05/14 17:30, Ian Bolton wrote: > Currently, on AArch64, when a caller-save register is saved/restored, > GCC is accessing the maximum size of the hard register. > > So an SImode integer (4 bytes) value is being stored as DImode (8 bytes) > because the int registers are 8 bytes wide, and an SFmode float (4 bytes) > and DFmode double (8 bytes) are being stored as TImode (16 bytes) to > capture the full 128-bits of the vector register. > > This patch corrects this, by implementing the HARD_REGNO_CALLER_SAVE_MODE > hook, which is called by LRA to determine the minimise size it might need > to save/restore. > > Tested on GCC regression suite and verified impact on a number of examples. > > OK for trunk? > > Cheers, > Ian > > > 2014-05-12 Ian Bolton <ian.bol...@arm.com> > > * config/aarch64/aarch64-protos.h > (aarch64_hard_regno_caller_save_mode): New prototype. > * config/aarch64/aarch64.c (aarch64_hard_regno_caller_save_mode): > New function. > * config/aarch64/aarch64.h (HARD_REGNO_CALLER_SAVE_MODE): New macro. >
This is ok. Watch your changelog entry though. Lines should be wrapped before 80 columns (and continuations indented accordingly). R. > > aarch64-caller-save-fix-patch-v2.txt > > > diff --git a/gcc/config/aarch64/aarch64-protos.h > b/gcc/config/aarch64/aarch64-protos.h > index 04cbc78..7cf7d9f 100644 > --- a/gcc/config/aarch64/aarch64-protos.h > +++ b/gcc/config/aarch64/aarch64-protos.h > @@ -202,6 +202,8 @@ enum aarch64_symbol_type aarch64_classify_symbol (rtx, > enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx); > enum reg_class aarch64_regno_regclass (unsigned); > int aarch64_asm_preferred_eh_data_format (int, int); > +enum machine_mode aarch64_hard_regno_caller_save_mode (unsigned, unsigned, > + enum machine_mode); > int aarch64_hard_regno_mode_ok (unsigned, enum machine_mode); > int aarch64_hard_regno_nregs (unsigned, enum machine_mode); > int aarch64_simd_attr_length_move (rtx); > diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c > index 8655f04..c2cc81b 100644 > --- a/gcc/config/aarch64/aarch64.c > +++ b/gcc/config/aarch64/aarch64.c > @@ -424,6 +424,24 @@ aarch64_hard_regno_mode_ok (unsigned regno, enum > machine_mode mode) > return 0; > } > > +/* Implement HARD_REGNO_CALLER_SAVE_MODE. */ > +enum machine_mode > +aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned nregs, > + enum machine_mode mode) > +{ > + /* Handle modes that fit within single registers. */ > + if (nregs == 1 && GET_MODE_SIZE (mode) <= 16) > + { > + if (GET_MODE_SIZE (mode) >= 4) > + return mode; > + else > + return SImode; > + } > + /* Fall back to generic for multi-reg and very large modes. */ > + else > + return choose_hard_reg_mode (regno, nregs, false); > +} > + > /* Return true if calls to DECL should be treated as > long-calls (ie called via a register). */ > static bool > diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h > index c9b30d0..0574593 100644 > --- a/gcc/config/aarch64/aarch64.h > +++ b/gcc/config/aarch64/aarch64.h > @@ -824,6 +824,11 @@ do { > \ > > #define SHIFT_COUNT_TRUNCATED !TARGET_SIMD > > +/* Choose appropriate mode for caller saves, so we do the minimum > + required size of load/store. */ > +#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \ > + aarch64_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE)) > + > /* Callee only saves lower 64-bits of a 128-bit register. Tell the > compiler the callee clobbers the top 64-bits when restoring the > bottom 64-bits. */ >