Off list, Segher asked that I break the patch eliminating a shift right when
transfering SFmode from a vector register to a GPR register down into smaller
chunks.  The power7 and power8 instructions that convert values in the double
precision format to single precision actually duplicate the 32-bits in the
first word and second word (the ISA says the second word is undefined).  We are
in the process of issuing an update to ISA 3.0 to clarify that this will be the
required behavior going forward.

I have broken the patches down to 8 chunks.  Some of the patch are just
cosmetic of things I noticed while doing the main patch.  One patch eliminates
the shift.  Another fixes up the peephole2 that optimizes putting a SFmode into
a union and then doing masking on the value.  And the final patch updates the
tests that need to be changed.

I have verified that each of these sub-patches build, and after all 8 patches
have been applied, I did the full bootstrap and regresion test, and like the
previous combination patch there were no regressions.  If only some of the
patches are applied, then there will be 3 regressions until the remaining
patches are applied.

This is patch #3.  Can I check this into the trunk?  I noticed that sometimes
you want to convert a DFmode to SFmode and then move it to a GPR register.
This patch adds a combiner insn to use the XSCVDPSP instruction (which does the
proper rounding and handles out of bound values) instead of the XSCVDPSPN
instruction (which assumes the value has already been rounded, and does not
raise an exception in case of a Nan).

2017-09-25  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        * config/rs6000/rs6000.md (movsi_from_df): Optimize converting a
        DFmode to a SFmode, and then needing to move the SFmode to a GPR
        to use the XSCVDPSP instruction instead of FRSP and XSCVDPSPN.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 253170)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -6919,6 +6919,26 @@ (define_insn_and_split "*movdi_from_sf_z
                "4,          4,           4,           4,        8,
                 8,          4")])
 
+;; Like movsi_from_sf, but combine a convert from DFmode to SFmode before
+;; moving it to SImode.  We can do a SFmode store without having to do the
+;; conversion explicitly.  If we are doing a register->register conversion, use
+;; XSCVDPSP instead of XSCVDPSPN, since the former handles cases where the
+;; input will not fit in a SFmode, and the later assumes the value has already
+;; been rounded.
+(define_insn "*movsi_from_df"
+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=wa,m,wY,Z")
+       (unspec:SI [(float_truncate:SF
+                    (match_operand:DF 1 "gpc_reg_operand" "wa, f,wb,wa"))]
+                   UNSPEC_SI_FROM_SF))]
+
+  "TARGET_NO_SF_SUBREG"
+  "@
+   xscvdpsp %x0,%x1
+   stfs%U0%X0 %1,%0
+   stxssp %1,%0
+   stxsspx %x1,%y0"
+  [(set_attr "type"   "fp,fpstore,fpstore,fpstore")])
+
 ;; Split a load of a large constant into the appropriate two-insn
 ;; sequence.
 

Reply via email to