diff mbox series

rs6000: Unaligned stfiwx on older CPUs (PR89746)

Message ID 7edd800cf5779c489446bfce0ce3dcbb79a7b742.1553010590.git.segher@kernel.crashing.org
State New
Headers show
Series rs6000: Unaligned stfiwx on older CPUs (PR89746) | expand

Commit Message

Segher Boessenkool March 19, 2019, 4:26 p.m. UTC
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 correcponding fixuns* pattern, because that can
not be enabled on any CPU that cannot handle unaligned FP well.

Tested on powerpc64-linux {-m32,-m64}, committing to trunk.  Will do
backports later, too.


Segher


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.

---
 gcc/config/rs6000/rs6000.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Comments

Segher Boessenkool March 19, 2019, 4:56 p.m. UTC | #1
On Tue, Mar 19, 2019 at 04:26:18PM +0000, Segher Boessenkool wrote:
> 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 correcponding fixuns* pattern, because that can
> not be enabled on any CPU that cannot handle unaligned FP well.
> 
> Tested on powerpc64-linux {-m32,-m64}, committing to trunk.  Will do
> backports later, too.
> 
> 
> Segher
> 
> 
> 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.

The actual patch I committed is


Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 269801)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -5639,13 +5639,13 @@
     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);
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index aedba2c..e8885b6 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -5668,13 +5668,13 @@  (define_insn_and_split "fix_trunc<mode>si2_stfiwx"
     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_DIRECT_MOVE)
+  else if (TARGET_POWERPC64 && TARGET_DIRECT_MOVE && !MEM_P (dest))
     {
       dest = gen_lowpart (DImode, dest);
       emit_move_insn (dest, tmp);