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:
parent
3747c00923
commit
1f4f2d0d39
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -480,6 +480,8 @@ const (
|
||||
/* AFCFIW; AFCFIWCC */
|
||||
AFCFID
|
||||
AFCFIDCC
|
||||
AFCFIDU
|
||||
AFCFIDUCC
|
||||
AFCTID
|
||||
AFCTIDCC
|
||||
AFCTIDZ
|
||||
|
@ -247,6 +247,8 @@ var Anames = []string{
|
||||
"EXTSWCC",
|
||||
"FCFID",
|
||||
"FCFIDCC",
|
||||
"FCFIDU",
|
||||
"FCFIDUCC",
|
||||
"FCTID",
|
||||
"FCTIDCC",
|
||||
"FCTIDZ",
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user