mirror of
https://github.com/golang/go.git
synced 2025-11-02 01:30:55 +00:00
This commit optimized math.Abs function implementation on mips64x.
Tested on loongson 3A2000.
goos: linux
goarch: mips64le
pkg: math
│ oldmath │ newmath │
│ sec/op │ sec/op vs base │
Acos-4 258.0n ± ∞ ¹ 257.1n ± ∞ ¹ -0.35% (p=0.008 n=5)
Acosh-4 417.0n ± ∞ ¹ 377.9n ± ∞ ¹ -9.38% (p=0.008 n=5)
Asin-4 248.0n ± ∞ ¹ 259.9n ± ∞ ¹ +4.80% (p=0.008 n=5)
Asinh-4 439.6n ± ∞ ¹ 408.3n ± ∞ ¹ -7.12% (p=0.008 n=5)
Atan-4 189.6n ± ∞ ¹ 188.8n ± ∞ ¹ ~ (p=0.056 n=5)
Atanh-4 390.0n ± ∞ ¹ 356.4n ± ∞ ¹ -8.62% (p=0.008 n=5)
Atan2-4 279.0n ± ∞ ¹ 263.9n ± ∞ ¹ -5.41% (p=0.008 n=5)
Cbrt-4 314.2n ± ∞ ¹ 322.3n ± ∞ ¹ +2.58% (p=0.008 n=5)
Ceil-4 139.7n ± ∞ ¹ 136.6n ± ∞ ¹ -2.22% (p=0.008 n=5)
Compare-4 21.11n ± ∞ ¹ 21.09n ± ∞ ¹ ~ (p=0.405 n=5)
Compare32-4 20.10n ± ∞ ¹ 20.12n ± ∞ ¹ ~ (p=0.206 n=5)
Copysign-4 32.17n ± ∞ ¹ 35.71n ± ∞ ¹ +11.00% (p=0.008 n=5)
Cos-4 222.8n ± ∞ ¹ 169.8n ± ∞ ¹ -23.79% (p=0.008 n=5)
Cosh-4 550.2n ± ∞ ¹ 477.4n ± ∞ ¹ -13.23% (p=0.008 n=5)
Erf-4 171.6n ± ∞ ¹ 174.5n ± ∞ ¹ ~ (p=0.635 n=5)
Erfc-4 182.6n ± ∞ ¹ 170.2n ± ∞ ¹ -6.79% (p=0.008 n=5)
Erfinv-4 177.6n ± ∞ ¹ 196.6n ± ∞ ¹ +10.70% (p=0.008 n=5)
Erfcinv-4 177.8n ± ∞ ¹ 197.8n ± ∞ ¹ +11.25% (p=0.008 n=5)
Exp-4 422.8n ± ∞ ¹ 382.1n ± ∞ ¹ -9.63% (p=0.008 n=5)
ExpGo-4 416.1n ± ∞ ¹ 383.2n ± ∞ ¹ -7.91% (p=0.008 n=5)
Expm1-4 232.9n ± ∞ ¹ 252.2n ± ∞ ¹ +8.29% (p=0.008 n=5)
Exp2-4 404.8n ± ∞ ¹ 389.1n ± ∞ ¹ -3.88% (p=0.008 n=5)
Exp2Go-4 407.0n ± ∞ ¹ 372.3n ± ∞ ¹ -8.53% (p=0.008 n=5)
Abs-4 30.120n ± ∞ ¹ 3.014n ± ∞ ¹ -89.99% (p=0.008 n=5)
Dim-4 5.021n ± ∞ ¹ 5.023n ± ∞ ¹ ~ (p=0.071 n=5)
Floor-4 127.8n ± ∞ ¹ 127.1n ± ∞ ¹ -0.55% (p=0.008 n=5)
Max-4 77.69n ± ∞ ¹ 76.33n ± ∞ ¹ -1.75% (p=0.008 n=5)
Min-4 83.27n ± ∞ ¹ 77.87n ± ∞ ¹ -6.48% (p=0.008 n=5)
Mod-4 906.2n ± ∞ ¹ 692.9n ± ∞ ¹ -23.54% (p=0.008 n=5)
Frexp-4 150.6n ± ∞ ¹ 108.6n ± ∞ ¹ -27.89% (p=0.008 n=5)
Gamma-4 418.4n ± ∞ ¹ 386.1n ± ∞ ¹ -7.72% (p=0.008 n=5)
Hypot-4 148.20n ± ∞ ¹ 93.78n ± ∞ ¹ -36.72% (p=0.008 n=5)
HypotGo-4 148.20n ± ∞ ¹ 94.47n ± ∞ ¹ -36.26% (p=0.008 n=5)
Ilogb-4 135.50n ± ∞ ¹ 92.38n ± ∞ ¹ -31.82% (p=0.008 n=5)
J0-4 937.7n ± ∞ ¹ 861.7n ± ∞ ¹ -8.10% (p=0.008 n=5)
J1-4 915.4n ± ∞ ¹ 875.9n ± ∞ ¹ -4.32% (p=0.008 n=5)
Jn-4 1.974µ ± ∞ ¹ 1.863µ ± ∞ ¹ -5.62% (p=0.008 n=5)
Ldexp-4 158.5n ± ∞ ¹ 129.3n ± ∞ ¹ -18.42% (p=0.008 n=5)
Lgamma-4 209.0n ± ∞ ¹ 211.8n ± ∞ ¹ ~ (p=0.095 n=5)
Log-4 326.4n ± ∞ ¹ 295.2n ± ∞ ¹ -9.56% (p=0.008 n=5)
Logb-4 147.7n ± ∞ ¹ 105.0n ± ∞ ¹ -28.91% (p=0.008 n=5)
Log1p-4 303.4n ± ∞ ¹ 266.3n ± ∞ ¹ -12.23% (p=0.008 n=5)
Log10-4 329.2n ± ∞ ¹ 298.3n ± ∞ ¹ -9.39% (p=0.008 n=5)
Log2-4 187.4n ± ∞ ¹ 153.0n ± ∞ ¹ -18.36% (p=0.008 n=5)
Modf-4 110.5n ± ∞ ¹ 103.5n ± ∞ ¹ -6.33% (p=0.008 n=5)
Nextafter32-4 128.4n ± ∞ ¹ 121.5n ± ∞ ¹ -5.37% (p=0.016 n=5)
Nextafter64-4 109.5n ± ∞ ¹ 110.5n ± ∞ ¹ +0.91% (p=0.008 n=5)
PowInt-4 603.3n ± ∞ ¹ 516.4n ± ∞ ¹ -14.40% (p=0.008 n=5)
PowFrac-4 1.365µ ± ∞ ¹ 1.183µ ± ∞ ¹ -13.33% (p=0.008 n=5)
Pow10Pos-4 15.07n ± ∞ ¹ 15.07n ± ∞ ¹ ~ (p=0.738 n=5)
Pow10Neg-4 21.11n ± ∞ ¹ 21.10n ± ∞ ¹ ~ (p=0.190 n=5)
Round-4 44.23n ± ∞ ¹ 44.22n ± ∞ ¹ ~ (p=0.635 n=5)
RoundToEven-4 50.25n ± ∞ ¹ 46.27n ± ∞ ¹ -7.92% (p=0.008 n=5)
Remainder-4 675.6n ± ∞ ¹ 530.4n ± ∞ ¹ -21.49% (p=0.008 n=5)
Signbit-4 17.07n ± ∞ ¹ 17.95n ± ∞ ¹ +5.16% (p=0.008 n=5)
Sin-4 171.6n ± ∞ ¹ 189.1n ± ∞ ¹ +10.20% (p=0.008 n=5)
Sincos-4 201.5n ± ∞ ¹ 200.5n ± ∞ ¹ ~ (p=0.421 n=5)
Sinh-4 529.6n ± ∞ ¹ 484.6n ± ∞ ¹ -8.50% (p=0.008 n=5)
SqrtIndirect-4 5.021n ± ∞ ¹ 5.023n ± ∞ ¹ +0.04% (p=0.048 n=5)
SqrtLatency-4 8.032n ± ∞ ¹ 8.039n ± ∞ ¹ +0.09% (p=0.024 n=5)
SqrtIndirectLatency-4 8.036n ± ∞ ¹ 8.038n ± ∞ ¹ ~ (p=0.056 n=5)
SqrtGoLatency-4 338.8n ± ∞ ¹ 338.7n ± ∞ ¹ ~ (p=0.841 n=5)
SqrtPrime-4 5.379µ ± ∞ ¹ 5.382µ ± ∞ ¹ +0.06% (p=0.048 n=5)
Tan-4 182.7n ± ∞ ¹ 191.8n ± ∞ ¹ +4.98% (p=0.008 n=5)
Tanh-4 558.7n ± ∞ ¹ 497.6n ± ∞ ¹ -10.94% (p=0.008 n=5)
Trunc-4 122.5n ± ∞ ¹ 122.6n ± ∞ ¹ ~ (p=0.405 n=5)
Y0-4 892.8n ± ∞ ¹ 851.7n ± ∞ ¹ -4.60% (p=0.008 n=5)
Y1-4 887.2n ± ∞ ¹ 863.2n ± ∞ ¹ -2.71% (p=0.008 n=5)
Yn-4 1.889µ ± ∞ ¹ 1.832µ ± ∞ ¹ -3.02% (p=0.008 n=5)
Float64bits-4 13.05n ± ∞ ¹ 13.06n ± ∞ ¹ +0.08% (p=0.040 n=5)
Float64frombits-4 13.05n ± ∞ ¹ 13.06n ± ∞ ¹ ~ (p=0.143 n=5)
Float32bits-4 13.05n ± ∞ ¹ 13.06n ± ∞ ¹ +0.08% (p=0.008 n=5)
Float32frombits-4 13.05n ± ∞ ¹ 13.08n ± ∞ ¹ +0.23% (p=0.016 n=5)
FMA-4 445.7n ± ∞ ¹ 448.1n ± ∞ ¹ +0.54% (p=0.008 n=5)
geomean 157.2n 142.8n -9.17%
Change-Id: I9bf104848b588c9ecf79401a81d483d7fcdb0a79
Reviewed-on: https://go-review.googlesource.com/c/go/+/481575
Reviewed-by: M Zhuo <mzh@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Than McIntosh <thanm@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Rong Zhang <rongrong@oss.cipunited.com>
246 lines
5.9 KiB
Go
246 lines
5.9 KiB
Go
// asmcheck
|
|
|
|
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package codegen
|
|
|
|
import "math"
|
|
|
|
var sink64 [8]float64
|
|
|
|
func approx(x float64) {
|
|
// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
|
|
// amd64:"ROUNDSD\t[$]2"
|
|
// s390x:"FIDBR\t[$]6"
|
|
// arm64:"FRINTPD"
|
|
// ppc64x:"FRIP"
|
|
// wasm:"F64Ceil"
|
|
sink64[0] = math.Ceil(x)
|
|
|
|
// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
|
|
// amd64:"ROUNDSD\t[$]1"
|
|
// s390x:"FIDBR\t[$]7"
|
|
// arm64:"FRINTMD"
|
|
// ppc64x:"FRIM"
|
|
// wasm:"F64Floor"
|
|
sink64[1] = math.Floor(x)
|
|
|
|
// s390x:"FIDBR\t[$]1"
|
|
// arm64:"FRINTAD"
|
|
// ppc64x:"FRIN"
|
|
sink64[2] = math.Round(x)
|
|
|
|
// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
|
|
// amd64:"ROUNDSD\t[$]3"
|
|
// s390x:"FIDBR\t[$]5"
|
|
// arm64:"FRINTZD"
|
|
// ppc64x:"FRIZ"
|
|
// wasm:"F64Trunc"
|
|
sink64[3] = math.Trunc(x)
|
|
|
|
// amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"
|
|
// amd64:"ROUNDSD\t[$]0"
|
|
// s390x:"FIDBR\t[$]4"
|
|
// arm64:"FRINTND"
|
|
// wasm:"F64Nearest"
|
|
sink64[4] = math.RoundToEven(x)
|
|
}
|
|
|
|
func sqrt(x float64) float64 {
|
|
// amd64:"SQRTSD"
|
|
// 386/sse2:"SQRTSD" 386/softfloat:-"SQRTD"
|
|
// arm64:"FSQRTD"
|
|
// arm/7:"SQRTD"
|
|
// mips/hardfloat:"SQRTD" mips/softfloat:-"SQRTD"
|
|
// mips64/hardfloat:"SQRTD" mips64/softfloat:-"SQRTD"
|
|
// wasm:"F64Sqrt"
|
|
// ppc64x:"FSQRT"
|
|
return math.Sqrt(x)
|
|
}
|
|
|
|
func sqrt32(x float32) float32 {
|
|
// amd64:"SQRTSS"
|
|
// 386/sse2:"SQRTSS" 386/softfloat:-"SQRTS"
|
|
// arm64:"FSQRTS"
|
|
// arm/7:"SQRTF"
|
|
// mips/hardfloat:"SQRTF" mips/softfloat:-"SQRTF"
|
|
// mips64/hardfloat:"SQRTF" mips64/softfloat:-"SQRTF"
|
|
// wasm:"F32Sqrt"
|
|
// ppc64x:"FSQRTS"
|
|
return float32(math.Sqrt(float64(x)))
|
|
}
|
|
|
|
// Check that it's using integer registers
|
|
func abs(x, y float64) {
|
|
// amd64:"BTRQ\t[$]63"
|
|
// arm64:"FABSD\t"
|
|
// s390x:"LPDFR\t",-"MOVD\t" (no integer load/store)
|
|
// ppc64x:"FABS\t"
|
|
// riscv64:"FABSD\t"
|
|
// wasm:"F64Abs"
|
|
// arm/6:"ABSD\t"
|
|
// mips64/hardfloat:"ABSD\t"
|
|
sink64[0] = math.Abs(x)
|
|
|
|
// amd64:"BTRQ\t[$]63","PXOR" (TODO: this should be BTSQ)
|
|
// s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
|
|
// ppc64x:"FNABS\t"
|
|
sink64[1] = -math.Abs(y)
|
|
}
|
|
|
|
// Check that it's using integer registers
|
|
func abs32(x float32) float32 {
|
|
// s390x:"LPDFR",-"LDEBR",-"LEDBR" (no float64 conversion)
|
|
return float32(math.Abs(float64(x)))
|
|
}
|
|
|
|
// Check that it's using integer registers
|
|
func copysign(a, b, c float64) {
|
|
// amd64:"BTRQ\t[$]63","ANDQ","ORQ"
|
|
// s390x:"CPSDR",-"MOVD" (no integer load/store)
|
|
// ppc64x:"FCPSGN"
|
|
// riscv64:"FSGNJD"
|
|
// wasm:"F64Copysign"
|
|
sink64[0] = math.Copysign(a, b)
|
|
|
|
// amd64:"BTSQ\t[$]63"
|
|
// s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
|
|
// ppc64x:"FCPSGN"
|
|
// riscv64:"FSGNJD"
|
|
// arm64:"ORR", -"AND"
|
|
sink64[1] = math.Copysign(c, -1)
|
|
|
|
// Like math.Copysign(c, -1), but with integer operations. Useful
|
|
// for platforms that have a copysign opcode to see if it's detected.
|
|
// s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
|
|
sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)
|
|
|
|
// amd64:"ANDQ","ORQ"
|
|
// s390x:"CPSDR\t",-"MOVD\t" (no integer load/store)
|
|
// ppc64x:"FCPSGN"
|
|
// riscv64:"FSGNJD"
|
|
sink64[3] = math.Copysign(-1, c)
|
|
}
|
|
|
|
func fma(x, y, z float64) float64 {
|
|
// amd64/v3:-".*x86HasFMA"
|
|
// amd64:"VFMADD231SD"
|
|
// arm/6:"FMULAD"
|
|
// arm64:"FMADDD"
|
|
// s390x:"FMADD"
|
|
// ppc64x:"FMADD"
|
|
// riscv64:"FMADDD"
|
|
return math.FMA(x, y, z)
|
|
}
|
|
|
|
func fms(x, y, z float64) float64 {
|
|
// riscv64:"FMSUBD"
|
|
return math.FMA(x, y, -z)
|
|
}
|
|
|
|
func fnma(x, y, z float64) float64 {
|
|
// riscv64:"FNMADDD"
|
|
return math.FMA(-x, y, z)
|
|
}
|
|
|
|
func fnms(x, y, z float64) float64 {
|
|
// riscv64:"FNMSUBD"
|
|
return math.FMA(x, -y, -z)
|
|
}
|
|
|
|
func fromFloat64(f64 float64) uint64 {
|
|
// amd64:"MOVQ\tX.*, [^X].*"
|
|
// arm64:"FMOVD\tF.*, R.*"
|
|
// ppc64x:"MFVSRD"
|
|
return math.Float64bits(f64+1) + 1
|
|
}
|
|
|
|
func fromFloat32(f32 float32) uint32 {
|
|
// amd64:"MOVL\tX.*, [^X].*"
|
|
// arm64:"FMOVS\tF.*, R.*"
|
|
return math.Float32bits(f32+1) + 1
|
|
}
|
|
|
|
func toFloat64(u64 uint64) float64 {
|
|
// amd64:"MOVQ\t[^X].*, X.*"
|
|
// arm64:"FMOVD\tR.*, F.*"
|
|
// ppc64x:"MTVSRD"
|
|
return math.Float64frombits(u64+1) + 1
|
|
}
|
|
|
|
func toFloat32(u32 uint32) float32 {
|
|
// amd64:"MOVL\t[^X].*, X.*"
|
|
// arm64:"FMOVS\tR.*, F.*"
|
|
return math.Float32frombits(u32+1) + 1
|
|
}
|
|
|
|
// Test that comparisons with constants converted to float
|
|
// are evaluated at compile-time
|
|
|
|
func constantCheck64() bool {
|
|
// amd64:"(MOVB\t[$]0)|(XORL\t[A-Z][A-Z0-9]+, [A-Z][A-Z0-9]+)",-"FCMP",-"MOVB\t[$]1"
|
|
// s390x:"MOV(B|BZ|D)\t[$]0,",-"FCMPU",-"MOV(B|BZ|D)\t[$]1,"
|
|
return 0.5 == float64(uint32(1)) || 1.5 > float64(uint64(1<<63))
|
|
}
|
|
|
|
func constantCheck32() bool {
|
|
// amd64:"MOV(B|L)\t[$]1",-"FCMP",-"MOV(B|L)\t[$]0"
|
|
// s390x:"MOV(B|BZ|D)\t[$]1,",-"FCMPU",-"MOV(B|BZ|D)\t[$]0,"
|
|
return float32(0.5) <= float32(int64(1)) && float32(1.5) >= float32(int32(-1<<31))
|
|
}
|
|
|
|
// Test that integer constants are converted to floating point constants
|
|
// at compile-time
|
|
|
|
func constantConvert32(x float32) float32 {
|
|
// amd64:"MOVSS\t[$]f32.3f800000\\(SB\\)"
|
|
// s390x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
|
// ppc64x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
|
|
// arm64:"FMOVS\t[$]\\(1.0\\)"
|
|
if x > math.Float32frombits(0x3f800000) {
|
|
return -x
|
|
}
|
|
return x
|
|
}
|
|
|
|
func constantConvertInt32(x uint32) uint32 {
|
|
// amd64:-"MOVSS"
|
|
// s390x:-"FMOVS"
|
|
// ppc64x:-"FMOVS"
|
|
// arm64:-"FMOVS"
|
|
if x > math.Float32bits(1) {
|
|
return -x
|
|
}
|
|
return x
|
|
}
|
|
|
|
func nanGenerate64() float64 {
|
|
// Test to make sure we don't generate a NaN while constant propagating.
|
|
// See issue 36400.
|
|
zero := 0.0
|
|
// amd64:-"DIVSD"
|
|
inf := 1 / zero // +inf. We can constant propagate this one.
|
|
negone := -1.0
|
|
|
|
// amd64:"DIVSD"
|
|
z0 := zero / zero
|
|
// amd64:"MULSD"
|
|
z1 := zero * inf
|
|
// amd64:"SQRTSD"
|
|
z2 := math.Sqrt(negone)
|
|
return z0 + z1 + z2
|
|
}
|
|
|
|
func nanGenerate32() float32 {
|
|
zero := float32(0.0)
|
|
// amd64:-"DIVSS"
|
|
inf := 1 / zero // +inf. We can constant propagate this one.
|
|
|
|
// amd64:"DIVSS"
|
|
z0 := zero / zero
|
|
// amd64:"MULSS"
|
|
z1 := zero * inf
|
|
return z0 + z1
|
|
}
|