diff options
author | segher <segher@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-08-09 21:08:33 +0000 |
---|---|---|
committer | segher <segher@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-08-09 21:08:33 +0000 |
commit | 1823d5ff98404367f5f7fd2585f0761f31f6f553 (patch) | |
tree | 8630b82450ca497021fe09a477cf138ac39daa8f | |
parent | e7501c12a3bad73a93062aaa976644b0702236fa (diff) | |
download | gcc-1823d5ff98404367f5f7fd2585f0761f31f6f553.tar.gz |
rs6000: Use SAVE_MULTIPLE only if we restore what it saves (PR80938)
We can have SAVE_MULTIPLE while we do not have REST_MULTIPLE. If the
inline restore does not restore all registers, the CFI for the save
and restore can conflict if things are shrink-wrapped.
We could restore all registers that are saved (not ideal), or emit
the CFI notes to say we did (which will work fine, but is also not
so great); instead, let's not save the registers that are unused.
PR target/80938
* config/rs6000/rs6000.c (rs6000_savres_strategy): Don't use
SAVE_MULTIPLE if not all the registers that saves, should be saved.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@251005 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 15 |
2 files changed, 21 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d3f9d2d5150..f69aeed99d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-08-09 Segher Boessenkool <segher@kernel.crashing.org> + + PR target/80938 + * config/rs6000/rs6000.c (rs6000_savres_strategy): Don't use + SAVE_MULTIPLE if not all the registers that saves, should be saved. + 2017-08-09 Jim Wilson <jim.wilson@linaro.org> * config/aarch64/aarch64-cores.def (falkor): Use falkor pipeline. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 1fb98618186..8f502dbdf04 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -24431,6 +24431,21 @@ rs6000_savres_strategy (rs6000_stack_t *info, else if (!lr_save_p && info->first_gp_reg_save > 29) strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS; + /* We can only use save multiple if we need to save all the registers from + first_gp_reg_save. Otherwise, the CFI gets messed up (we save some + register we do not restore). */ + if (strategy & SAVE_MULTIPLE) + { + int i; + + for (i = info->first_gp_reg_save; i < 32; i++) + if (fixed_reg_p (i) || !save_reg_p (i)) + { + strategy &= ~SAVE_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. |