]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use power5 instructions for uint64 to float casts
authorMichael Munday <munday@ca.ibm.com>
Thu, 16 Jun 2016 22:12:48 +0000 (18:12 -0400)
committerMichael Munday <munday@ca.ibm.com>
Fri, 17 Jun 2016 19:15:29 +0000 (19:15 +0000)
Use the same technique as mips64 for these casts (CL 22835).

We could use the FCFIDU instruction for ppc64le however it seems
better to keep it the same as ppc64 for now.

Updates #15539, updates #16004.

Change-Id: I550680e485327568bf3238c4615a6cc8de6438d7
Reviewed-on: https://go-review.googlesource.com/24191
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Michael Munday <munday@ca.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ppc64/gsubr.go

index cb93ae0d5363f17737a2220f7fe65572ce58b0c9..f875999718b23d74d744f06b49d051e64b5311bf 100644 (file)
@@ -441,9 +441,8 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.Regfree(&r3)
                return
 
-               //warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
        /*
-        * signed integer to float
+        * integer to float
         */
        case gc.TINT32<<16 | gc.TFLOAT32,
                gc.TINT32<<16 | gc.TFLOAT64,
@@ -452,29 +451,8 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TINT16<<16 | gc.TFLOAT32,
                gc.TINT16<<16 | gc.TFLOAT64,
                gc.TINT8<<16 | gc.TFLOAT32,
-               gc.TINT8<<16 | gc.TFLOAT64:
-               var r1 gc.Node
-               gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
-               gmove(f, &r1)
-               gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
-               p1 := gins(ppc64.AMOVD, &r1, nil)
-               p1.To.Type = obj.TYPE_MEM
-               p1.To.Reg = ppc64.REGSP
-               p1.To.Offset = -8
-               p1 = gins(ppc64.AFMOVD, nil, &r2)
-               p1.From.Type = obj.TYPE_MEM
-               p1.From.Reg = ppc64.REGSP
-               p1.From.Offset = -8
-               gins(ppc64.AFCFID, &r2, &r2)
-               gc.Regfree(&r1)
-               gmove(&r2, t)
-               gc.Regfree(&r2)
-               return
-
-       /*
-        * unsigned integer to float
-        */
-       case gc.TUINT16<<16 | gc.TFLOAT32,
+               gc.TINT8<<16 | gc.TFLOAT64,
+               gc.TUINT16<<16 | gc.TFLOAT32,
                gc.TUINT16<<16 | gc.TFLOAT64,
                gc.TUINT8<<16 | gc.TFLOAT32,
                gc.TUINT8<<16 | gc.TFLOAT64,
@@ -482,10 +460,33 @@ func gmove(f *gc.Node, t *gc.Node) {
                gc.TUINT32<<16 | gc.TFLOAT64,
                gc.TUINT64<<16 | gc.TFLOAT32,
                gc.TUINT64<<16 | gc.TFLOAT64:
+               bignodes()
 
+               // The algorithm is:
+               //      if small enough, use native int64 -> float64 conversion,
+               //      otherwise halve (x -> (x>>1)|(x&1)), convert, and double.
+               // Note: could use FCFIDU instead if target supports it.
                var r1 gc.Node
-               gc.Regalloc(&r1, gc.Types[gc.TUINT64], nil)
+               gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
                gmove(f, &r1)
+               if ft == gc.TUINT64 {
+                       gc.Nodreg(&r2, gc.Types[gc.TUINT64], ppc64.REGTMP)
+                       gmove(&bigi, &r2)
+                       gins(ppc64.ACMPU, &r1, &r2)
+                       p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1)
+                       var r3 gc.Node
+                       gc.Regalloc(&r3, gc.Types[gc.TUINT64], nil)
+                       p2 := gins(ppc64.AANDCC, nil, &r3) // andi.
+                       p2.Reg = r1.Reg
+                       p2.From.Type = obj.TYPE_CONST
+                       p2.From.Offset = 1
+                       p3 := gins(ppc64.ASRD, nil, &r1)
+                       p3.From.Type = obj.TYPE_CONST
+                       p3.From.Offset = 1
+                       gins(ppc64.AOR, &r3, &r1)
+                       gc.Regfree(&r3)
+                       gc.Patch(p1, gc.Pc)
+               }
                gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
                p1 := gins(ppc64.AMOVD, &r1, nil)
                p1.To.Type = obj.TYPE_MEM
@@ -495,8 +496,14 @@ func gmove(f *gc.Node, t *gc.Node) {
                p1.From.Type = obj.TYPE_MEM
                p1.From.Reg = ppc64.REGSP
                p1.From.Offset = -8
-               gins(ppc64.AFCFIDU, &r2, &r2)
+               gins(ppc64.AFCFID, &r2, &r2)
                gc.Regfree(&r1)
+               if ft == gc.TUINT64 {
+                       p1 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT64]), nil, +1) // use CR0 here again
+                       gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], ppc64.FREGTWO)
+                       gins(ppc64.AFMUL, &r1, &r2)
+                       gc.Patch(p1, gc.Pc)
+               }
                gmove(&r2, t)
                gc.Regfree(&r2)
                return