From f3d54789f764f0f6dba1d2f12ad01986d66ea31c Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Thu, 16 Jun 2016 18:12:48 -0400 Subject: [PATCH] cmd/compile: use power5 instructions for uint64 to float casts 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 Run-TryBot: Michael Munday TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/ppc64/gsubr.go | 73 ++++++++++++++----------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/src/cmd/compile/internal/ppc64/gsubr.go b/src/cmd/compile/internal/ppc64/gsubr.go index cb93ae0d53..f875999718 100644 --- a/src/cmd/compile/internal/ppc64/gsubr.go +++ b/src/cmd/compile/internal/ppc64/gsubr.go @@ -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,10 +451,42 @@ 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: + 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, + gc.TUINT32<<16 | gc.TFLOAT32, + 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.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 @@ -467,36 +498,12 @@ func gmove(f *gc.Node, t *gc.Node) { 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.TUINT16<<16 | gc.TFLOAT64, - gc.TUINT8<<16 | gc.TFLOAT32, - gc.TUINT8<<16 | gc.TFLOAT64, - gc.TUINT32<<16 | gc.TFLOAT32, - gc.TUINT32<<16 | gc.TFLOAT64, - gc.TUINT64<<16 | gc.TFLOAT32, - gc.TUINT64<<16 | gc.TFLOAT64: - - var r1 gc.Node - gc.Regalloc(&r1, gc.Types[gc.TUINT64], 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.AFCFIDU, &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