mirror of
https://github.com/golang/go
synced 2024-11-25 20:17:57 -07:00
cmd/internal/obj/ppc64: on Power10, use xxspltidp for float constants
Any normal float32 constant can be generated by this instruction; use xxspltidp when possible. This prefixed instruction is much faster than the two instruction load sequence from the float32/float64 constant pool. Change-Id: Id751d9ffdae71463adbde66427b986f0b2ef74c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/575555 Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Paul Murphy <murp@ibm.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
This commit is contained in:
parent
0f10ffec13
commit
ebf7747dbe
@ -37,6 +37,7 @@ import (
|
|||||||
"internal/abi"
|
"internal/abi"
|
||||||
"internal/buildcfg"
|
"internal/buildcfg"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -90,6 +91,29 @@ func isNOTOCfunc(name string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try converting FMOVD/FMOVS to XXSPLTIDP. If it is converted,
|
||||||
|
// return true.
|
||||||
|
func convertFMOVtoXXSPLTIDP(p *obj.Prog) bool {
|
||||||
|
if p.From.Type != obj.TYPE_FCONST || buildcfg.GOPPC64 < 10 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
v := p.From.Val.(float64)
|
||||||
|
if float64(float32(v)) != v {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Secondly, is this value a normal value?
|
||||||
|
ival := int64(math.Float32bits(float32(v)))
|
||||||
|
isDenorm := ival&0x7F800000 == 0 && ival&0x007FFFFF != 0
|
||||||
|
if !isDenorm {
|
||||||
|
p.As = AXXSPLTIDP
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = ival
|
||||||
|
// Convert REG_Fx into equivalent REG_VSx
|
||||||
|
p.To.Reg = REG_VS0 + (p.To.Reg & 31)
|
||||||
|
}
|
||||||
|
return !isDenorm
|
||||||
|
}
|
||||||
|
|
||||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||||
p.From.Class = 0
|
p.From.Class = 0
|
||||||
p.To.Class = 0
|
p.To.Class = 0
|
||||||
@ -111,7 +135,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
|||||||
// Rewrite float constants to values stored in memory.
|
// Rewrite float constants to values stored in memory.
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case AFMOVS:
|
case AFMOVS:
|
||||||
if p.From.Type == obj.TYPE_FCONST {
|
if p.From.Type == obj.TYPE_FCONST && !convertFMOVtoXXSPLTIDP(p) {
|
||||||
f32 := float32(p.From.Val.(float64))
|
f32 := float32(p.From.Val.(float64))
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Sym = ctxt.Float32Sym(f32)
|
p.From.Sym = ctxt.Float32Sym(f32)
|
||||||
@ -123,7 +147,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
|||||||
if p.From.Type == obj.TYPE_FCONST {
|
if p.From.Type == obj.TYPE_FCONST {
|
||||||
f64 := p.From.Val.(float64)
|
f64 := p.From.Val.(float64)
|
||||||
// Constant not needed in memory for float +/- 0
|
// Constant not needed in memory for float +/- 0
|
||||||
if f64 != 0 {
|
if f64 != 0 && !convertFMOVtoXXSPLTIDP(p) {
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Sym = ctxt.Float64Sym(f64)
|
p.From.Sym = ctxt.Float64Sym(f64)
|
||||||
p.From.Name = obj.NAME_EXTERN
|
p.From.Name = obj.NAME_EXTERN
|
||||||
|
@ -196,3 +196,34 @@ func Float32Max(a, b float32) float32 {
|
|||||||
// ppc64/power10:"XSMAXJDP"
|
// ppc64/power10:"XSMAXJDP"
|
||||||
return max(a, b)
|
return max(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------ //
|
||||||
|
// Constant Optimizations //
|
||||||
|
// ------------------------ //
|
||||||
|
|
||||||
|
func Float32Constant() float32 {
|
||||||
|
// ppc64x/power8:"FMOVS\t[$]f32\\.42440000\\(SB\\)"
|
||||||
|
// ppc64x/power9:"FMOVS\t[$]f32\\.42440000\\(SB\\)"
|
||||||
|
// ppc64x/power10:"XXSPLTIDP\t[$]1111752704,"
|
||||||
|
return 49.0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float64Constant() float64 {
|
||||||
|
// ppc64x/power8:"FMOVD\t[$]f64\\.4048800000000000\\(SB\\)"
|
||||||
|
// ppc64x/power9:"FMOVD\t[$]f64\\.4048800000000000\\(SB\\)"
|
||||||
|
// ppc64x/power10:"XXSPLTIDP\t[$]1111752704,"
|
||||||
|
return 49.0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Float32DenormalConstant() float32 {
|
||||||
|
// ppc64x:"FMOVS\t[$]f32\\.00400000\\(SB\\)"
|
||||||
|
return 0x1p-127
|
||||||
|
}
|
||||||
|
|
||||||
|
// A float64 constant which can be exactly represented as a
|
||||||
|
// denormal float32 value. On ppc64x, denormal values cannot
|
||||||
|
// be used with XXSPLTIDP.
|
||||||
|
func Float64DenormalFloat32Constant() float64 {
|
||||||
|
// ppc64x:"FMOVD\t[$]f64\\.3800000000000000\\(SB\\)"
|
||||||
|
return 0x1p-127
|
||||||
|
}
|
||||||
|
@ -204,7 +204,9 @@ func constantCheck32() bool {
|
|||||||
func constantConvert32(x float32) float32 {
|
func constantConvert32(x float32) float32 {
|
||||||
// amd64:"MOVSS\t[$]f32.3f800000\\(SB\\)"
|
// amd64:"MOVSS\t[$]f32.3f800000\\(SB\\)"
|
||||||
// s390x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
// s390x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
||||||
// ppc64x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
// ppc64x/power8:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
||||||
|
// ppc64x/power9:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
||||||
|
// ppc64x/power10:"XXSPLTIDP\t[$]1065353216, VS0"
|
||||||
// arm64:"FMOVS\t[$]\\(1.0\\)"
|
// arm64:"FMOVS\t[$]\\(1.0\\)"
|
||||||
if x > math.Float32frombits(0x3f800000) {
|
if x > math.Float32frombits(0x3f800000) {
|
||||||
return -x
|
return -x
|
||||||
|
Loading…
Reference in New Issue
Block a user