rs6000: Unaligned stfiwx on older CPUs (PR89746)
authorSegher Boessenkool <segher@kernel.crashing.org>
Tue, 19 Mar 2019 16:58:42 +0000 (17:58 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Tue, 19 Mar 2019 16:58:42 +0000 (17:58 +0100)
The "classic" PowerPCs (6xx/7xx) are not STRICT_ALIGNMENT, but their
floating point units are.  This is not normally a problem, the ABIs
make everything FP aligned.  The RTL patterns converting FP to integer
however get a potentially unaligned destination, and we do not want to
do an stfiwx on that on such older CPUs.

This fixes it.  It does not change anything for TARGET_MFCRF targets
(POWER4 and later).  It also won't change anything for strict-alignment
targets, or CPUs without hardware FP of course, or CPUs that do not
implement stfiwx (older 4xx/5xx/8xx).

It does not change the corresponding fixuns* pattern, because that can
not be enabled on any CPU that cannot handle unaligned FP well.

PR target/89746
* config/rs6000/rs6000.md (fix_trunc<mode>si2_stfiwx): If we have a
non-TARGET_MFCRF target, and the dest is memory but not 32-bit aligned,
go via a stack temporary.

From-SVN: r269802

gcc/ChangeLog
gcc/config/rs6000/rs6000.md

index f2ce11d..510faab 100644 (file)
@@ -1,3 +1,10 @@
+2018-03-19  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR target/89746
+       * config/rs6000/rs6000.md (fix_trunc<mode>si2_stfiwx): If we have a
+       non-TARGET_MFCRF target, and the dest is memory but not 32-bit aligned,
+       go via a stack temporary.
+
 2019-03-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/89378
index 584b9da..297b884 100644 (file)
     tmp = gen_reg_rtx (DImode);
 
   emit_insn (gen_fctiwz_<mode> (tmp, src));
-  if (MEM_P (dest))
+  if (MEM_P (dest) && (TARGET_MFCRF || MEM_ALIGN (dest) >= 32))
     {
       dest = rs6000_force_indexed_or_indirect_mem (dest);
       emit_insn (gen_stfiwx (dest, tmp));
       DONE;
     }
-  else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+  else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE) && !MEM_P (dest))
     {
       dest = gen_lowpart (DImode, dest);
       emit_move_insn (dest, tmp);