As noted in fixed_reg_p comment /* Return whether REG is a global user reg or has been specifed by -ffixed-REG. We should not restore these, and so cannot use lmw or out-of-line restore functions if there are any. We also can't save them (well, emit frame notes for them), because frame unwinding during exception handling will restore saved registers. */
* config/rs6000/rs6000.c (rs6000_savres_strategy): Don't restore fixed regs. Bootstrapped and regression tested powerpc64-linux (-m32 too) and powerpc64le-linux. OK? diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 74158cd..b628808 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -24309,6 +24309,7 @@ rs6000_savres_strategy (rs6000_stack_t *info, bool using_static_chain_p) { int strategy = 0; + int i; /* Select between in-line and out-of-line save and restore of regs. First, all the obvious cases where we don't use out-of-line. */ @@ -24383,6 +24384,17 @@ rs6000_savres_strategy (rs6000_stack_t *info, | SAVE_INLINE_GPRS | SAVE_INLINE_VRS); + /* Don't ever restore fixed regs. That means we can't use the + out-of-line register restore functions if a fixed reg is in the + range of regs restored. */ + if (!(strategy & REST_INLINE_FPRS)) + for (i = info->first_fp_reg_save; i < 64; i++) + if (fixed_regs[i]) + { + strategy |= REST_INLINE_FPRS; + break; + } + /* We can only use the out-of-line routines to restore fprs if we've saved all the registers from first_fp_reg_save in the prologue. Otherwise, we risk loading garbage. Of course, if we have saved @@ -24390,10 +24402,8 @@ rs6000_savres_strategy (rs6000_stack_t *info, if ((strategy & SAVE_INLINE_FPRS) && !(strategy & REST_INLINE_FPRS)) { - int i; - for (i = info->first_fp_reg_save; i < 64; i++) - if (fixed_regs[i] || !save_reg_p (i)) + if (!save_reg_p (i)) { strategy |= REST_INLINE_FPRS; break; @@ -24401,13 +24411,19 @@ rs6000_savres_strategy (rs6000_stack_t *info, } /* Similarly, for altivec regs. */ + if (!(strategy & REST_INLINE_VRS)) + for (i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++) + if (fixed_regs[i]) + { + strategy |= REST_INLINE_VRS; + break; + } + if ((strategy & SAVE_INLINE_VRS) && !(strategy & REST_INLINE_VRS)) { - int i; - for (i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++) - if (fixed_regs[i] || !save_reg_p (i)) + if (!save_reg_p (i)) { strategy |= REST_INLINE_VRS; break; @@ -24467,6 +24483,16 @@ rs6000_savres_strategy (rs6000_stack_t *info, } } + /* Don't ever restore fixed regs. */ + if ((strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS) + for (i = info->first_gp_reg_save; i < 32; i++) + if (fixed_reg_p (i)) + { + strategy |= REST_INLINE_GPRS; + strategy &= ~REST_MULTIPLE; + break; + } + /* We can only use load multiple or the out-of-line routines to restore gprs if we've saved all the registers from first_gp_reg_save. Otherwise, we risk loading garbage. @@ -24475,10 +24501,8 @@ rs6000_savres_strategy (rs6000_stack_t *info, if ((strategy & (SAVE_INLINE_GPRS | SAVE_MULTIPLE)) == SAVE_INLINE_GPRS && (strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS) { - int i; - for (i = info->first_gp_reg_save; i < 32; i++) - if (fixed_reg_p (i) || !save_reg_p (i)) + if (!save_reg_p (i)) { strategy |= REST_INLINE_GPRS; strategy &= ~REST_MULTIPLE; -- Alan Modra Australia Development Lab, IBM