1
0
mirror of https://github.com/golang/go synced 2024-11-12 02:10:21 -07:00

cmd/compile: fix uint64 to float casts on ppc64

Adds the FCFIDU instruction and uses it instead of the FCFID
instruction for unsigned integer to float casts. This change means
that unsigned integers do not have to be cast to signed integers
before being cast to a floating point value. Therefore it is no
longer necessary to insert instructions to detect and fix
values that overflow int64.

The previous code generating the uint64 to int64 cast handled
overflow by truncating the uint64 value. This truncation can
change the result of the rounding performed by the integer to
float cast.

The FCFIDU instruction was added in Power ISA 2.06B.

Fixes #15539.

Change-Id: Ia37a9631293eff91032d4cd9a9bec759d2142437
Reviewed-on: https://go-review.googlesource.com/22772
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Michael Munday 2016-05-04 14:26:46 -04:00
parent 3747c00923
commit 1f4f2d0d39
6 changed files with 45 additions and 33 deletions

View File

@ -442,12 +442,8 @@ func gmove(f *gc.Node, t *gc.Node) {
return
//warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
//return;
// algorithm is:
// if small enough, use native int64 -> uint64 conversion.
// otherwise, halve (rounding to odd?), convert, and double.
/*
* integer to float
* signed integer to float
*/
case gc.TINT32<<16 | gc.TFLOAT32,
gc.TINT32<<16 | gc.TFLOAT64,
@ -456,31 +452,10 @@ 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.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()
gc.TINT8<<16 | gc.TFLOAT64:
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)
p2 := gins(ppc64.ASRD, nil, &r1)
p2.From.Type = obj.TYPE_CONST
p2.From.Offset = 1
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
@ -492,13 +467,36 @@ func gmove(f *gc.Node, t *gc.Node) {
p1.From.Offset = -8
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
/*
* 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)
gmove(&r2, t)
gc.Regfree(&r2)
return

View File

@ -628,6 +628,8 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
ppc64.AFCTIDZ,
ppc64.AFCFID,
ppc64.AFCFIDCC,
ppc64.AFCFIDU,
ppc64.AFCFIDUCC,
ppc64.AFMOVS,
ppc64.AFMOVD,
ppc64.AFRSP,

View File

@ -71,6 +71,7 @@ var progtable = [ppc64.ALAST & obj.AMask]obj.ProgInfo{
ppc64.AFDIVS & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
ppc64.AFCTIDZ & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
ppc64.AFCFID & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
ppc64.AFCFIDU & obj.AMask: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
ppc64.AFCMPU & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
ppc64.AFRSP & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
ppc64.AFSQRT & obj.AMask: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
@ -206,6 +207,7 @@ func initvariants() {
initvariant(ppc64.AFADD, ppc64.AFADDCC)
initvariant(ppc64.AFADDS, ppc64.AFADDSCC)
initvariant(ppc64.AFCFID, ppc64.AFCFIDCC)
initvariant(ppc64.AFCFIDU, ppc64.AFCFIDUCC)
initvariant(ppc64.AFCTID, ppc64.AFCTIDCC)
initvariant(ppc64.AFCTIDZ, ppc64.AFCTIDZCC)
initvariant(ppc64.AFCTIW, ppc64.AFCTIWCC)

View File

@ -480,6 +480,8 @@ const (
/* AFCFIW; AFCFIWCC */
AFCFID
AFCFIDCC
AFCFIDU
AFCFIDUCC
AFCTID
AFCTIDCC
AFCTIDZ

View File

@ -247,6 +247,8 @@ var Anames = []string{
"EXTSWCC",
"FCFID",
"FCFIDCC",
"FCFIDU",
"FCFIDUCC",
"FCTID",
"FCTIDCC",
"FCTIDZ",

View File

@ -1105,6 +1105,8 @@ func buildop(ctxt *obj.Link) {
opset(AFCTIDZCC, r0)
opset(AFCFID, r0)
opset(AFCFIDCC, r0)
opset(AFCFIDU, r0)
opset(AFCFIDUCC, r0)
opset(AFRES, r0)
opset(AFRESCC, r0)
opset(AFRSQRTE, r0)
@ -2716,6 +2718,10 @@ func oprrr(ctxt *obj.Link, a obj.As) uint32 {
return OPVCC(63, 846, 0, 0)
case AFCFIDCC:
return OPVCC(63, 846, 0, 1)
case AFCFIDU:
return OPVCC(63, 974, 0, 0)
case AFCFIDUCC:
return OPVCC(63, 974, 0, 1)
case AFCTIW:
return OPVCC(63, 14, 0, 0)
case AFCTIWCC: