codekingpro/portable-devtools
114k
1// asmcheck -gcflags=-d=converthash=qy2 3// Copyright 2018 The Go Authors. All rights reserved.4// Use of this source code is governed by a BSD-style5// license that can be found in the LICENSE file.6 7package codegen8 9import "math"10 11var sink64 [8]float6412 13func approx(x float64) {14 // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"15 // amd64:"ROUNDSD [$]2"16 // s390x:"FIDBR [$]6"17 // arm64:"FRINTPD"18 // ppc64x:"FRIP"19 // wasm:"F64Ceil"20 sink64[0] = math.Ceil(x)21 22 // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"23 // amd64:"ROUNDSD [$]1"24 // s390x:"FIDBR [$]7"25 // arm64:"FRINTMD"26 // ppc64x:"FRIM"27 // wasm:"F64Floor"28 sink64[1] = math.Floor(x)29 30 // s390x:"FIDBR [$]1"31 // arm64:"FRINTAD"32 // ppc64x:"FRIN"33 sink64[2] = math.Round(x)34 35 // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"36 // amd64:"ROUNDSD [$]3"37 // s390x:"FIDBR [$]5"38 // arm64:"FRINTZD"39 // ppc64x:"FRIZ"40 // wasm:"F64Trunc"41 sink64[3] = math.Trunc(x)42 43 // amd64/v2:-".*x86HasSSE41" amd64/v3:-".*x86HasSSE41"44 // amd64:"ROUNDSD [$]0"45 // s390x:"FIDBR [$]4"46 // arm64:"FRINTND"47 // wasm:"F64Nearest"48 sink64[4] = math.RoundToEven(x)49}50 51func sqrt(x float64) float64 {52 // amd64:"SQRTSD"53 // 386/sse2:"SQRTSD" 386/softfloat:-"SQRTD"54 // arm64:"FSQRTD"55 // arm/7:"SQRTD"56 // loong64:"SQRTD"57 // mips/hardfloat:"SQRTD" mips/softfloat:-"SQRTD"58 // mips64/hardfloat:"SQRTD" mips64/softfloat:-"SQRTD"59 // wasm:"F64Sqrt"60 // ppc64x:"FSQRT"61 // riscv64: "FSQRTD"62 return math.Sqrt(x)63}64 65func sqrt32(x float32) float32 {66 // amd64:"SQRTSS"67 // 386/sse2:"SQRTSS" 386/softfloat:-"SQRTS"68 // arm64:"FSQRTS"69 // arm/7:"SQRTF"70 // loong64:"SQRTF"71 // mips/hardfloat:"SQRTF" mips/softfloat:-"SQRTF"72 // mips64/hardfloat:"SQRTF" mips64/softfloat:-"SQRTF"73 // wasm:"F32Sqrt"74 // ppc64x:"FSQRTS"75 // riscv64: "FSQRTS"76 return float32(math.Sqrt(float64(x)))77}78 79// Check that it's using integer registers80func abs(x, y float64) {81 // amd64:"BTRQ [$]63"82 // arm64:"FABSD "83 // loong64:"ABSD "84 // s390x:"LPDFR " -"MOVD " (no integer load/store)85 // ppc64x:"FABS "86 // riscv64:"FABSD "87 // wasm:"F64Abs"88 // arm/6:"ABSD "89 // mips64/hardfloat:"ABSD "90 // mips/hardfloat:"ABSD "91 sink64[0] = math.Abs(x)92 93 // amd64:"BTRQ [$]63" "PXOR" (TODO: this should be BTSQ)94 // s390x:"LNDFR " -"MOVD " (no integer load/store)95 // ppc64x:"FNABS "96 sink64[1] = -math.Abs(y)97}98 99// Check that it's using integer registers100func abs32(x float32) float32 {101 // s390x:"LPDFR" -"LDEBR" -"LEDBR" (no float64 conversion)102 return float32(math.Abs(float64(x)))103}104 105// Check that it's using integer registers106func copysign(a, b, c float64) {107 // amd64:"BTRQ [$]63" "ANDQ" "ORQ"108 // loong64:"FCOPYSGD"109 // s390x:"CPSDR" -"MOVD" (no integer load/store)110 // ppc64x:"FCPSGN"111 // riscv64:"FSGNJD"112 // wasm:"F64Copysign"113 sink64[0] = math.Copysign(a, b)114 115 // amd64:"BTSQ [$]63"116 // loong64:"FCOPYSGD"117 // s390x:"LNDFR " -"MOVD " (no integer load/store)118 // ppc64x:"FCPSGN"119 // riscv64:"FSGNJD"120 // arm64:"ORR", -"AND"121 sink64[1] = math.Copysign(c, -1)122 123 // Like math.Copysign(c, -1), but with integer operations. Useful124 // for platforms that have a copysign opcode to see if it's detected.125 // s390x:"LNDFR " -"MOVD " (no integer load/store)126 sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)127 128 // amd64:"ANDQ" "ORQ"129 // loong64:"FCOPYSGD"130 // s390x:"CPSDR " -"MOVD " (no integer load/store)131 // ppc64x:"FCPSGN"132 // riscv64:"FSGNJD"133 sink64[3] = math.Copysign(-1, c)134}135 136func fma(x, y, z float64) float64 {137 // amd64/v3:-".*x86HasFMA"138 // amd64:"VFMADD231SD"139 // arm/6:"FMULAD"140 // arm64:"FMADDD"141 // loong64:"FMADDD"142 // s390x:"FMADD"143 // ppc64x:"FMADD"144 // riscv64:"FMADDD"145 return math.FMA(x, y, z)146}147 148func fms(x, y, z float64) float64 {149 // riscv64:"FMSUBD"150 return math.FMA(x, y, -z)151}152 153func fnms(x, y, z float64) float64 {154 // riscv64:"FNMSUBD" -"FNMADDD"155 return math.FMA(-x, y, z)156}157 158func fnma(x, y, z float64) float64 {159 // riscv64:"FNMADDD" -"FNMSUBD"160 return math.FMA(x, -y, -z)161}162 163func isPosInf(x float64) bool {164 // riscv64:"FCLASSD"165 return math.IsInf(x, 1)166}167 168func isPosInfEq(x float64) bool {169 // riscv64:"FCLASSD"170 return x == math.Inf(1)171}172 173func isPosInfCmp(x float64) bool {174 // riscv64:"FCLASSD"175 return x > math.MaxFloat64176}177 178func isNotPosInf(x float64) bool {179 // riscv64:"FCLASSD"180 return !math.IsInf(x, 1)181}182 183func isNotPosInfEq(x float64) bool {184 // riscv64:"FCLASSD"185 return x != math.Inf(1)186}187 188func isNotPosInfCmp(x float64) bool {189 // riscv64:"FCLASSD"190 return x <= math.MaxFloat64191}192 193func isNegInf(x float64) bool {194 // riscv64:"FCLASSD"195 return math.IsInf(x, -1)196}197 198func isNegInfEq(x float64) bool {199 // riscv64:"FCLASSD"200 return x == math.Inf(-1)201}202 203func isNegInfCmp(x float64) bool {204 // riscv64:"FCLASSD"205 return x < -math.MaxFloat64206}207 208func isNotNegInf(x float64) bool {209 // riscv64:"FCLASSD"210 return !math.IsInf(x, -1)211}212 213func isNotNegInfEq(x float64) bool {214 // riscv64:"FCLASSD"215 return x != math.Inf(-1)216}217 218func isNotNegInfCmp(x float64) bool {219 // riscv64:"FCLASSD"220 return x >= -math.MaxFloat64221}222 223func fromFloat64(f64 float64) uint64 {224 // amd64:"MOVQ X.*, [^X].*"225 // arm64:"FMOVD F.*, R.*"226 // loong64:"MOVV F.*, R.*"227 // ppc64x:"MFVSRD"228 // mips64/hardfloat:"MOVV F.*, R.*"229 // riscv64:"FMVXD"230 return math.Float64bits(f64+1) + 1231}232 233func fromFloat32(f32 float32) uint32 {234 // amd64:"MOVL X.*, [^X].*"235 // arm64:"FMOVS F.*, R.*"236 // loong64:"MOVW F.*, R.*"237 // mips64/hardfloat:"MOVW F.*, R.*"238 // riscv64:"FMVXW"239 return math.Float32bits(f32+1) + 1240}241 242func toFloat64(u64 uint64) float64 {243 // amd64:"MOVQ [^X].*, X.*"244 // arm64:"FMOVD R.*, F.*"245 // loong64:"MOVV R.*, F.*"246 // ppc64x:"MTVSRD"247 // mips64/hardfloat:"MOVV R.*, F.*"248 // riscv64:"FMVDX"249 return math.Float64frombits(u64+1) + 1250}251 252func toFloat32(u32 uint32) float32 {253 // amd64:"MOVL [^X].*, X.*"254 // arm64:"FMOVS R.*, F.*"255 // loong64:"MOVW R.*, F.*"256 // mips64/hardfloat:"MOVW R.*, F.*"257 // riscv64:"FMVWX"258 return math.Float32frombits(u32+1) + 1259}260 261// Test that comparisons with constants converted to float262// are evaluated at compile-time263 264func constantCheck64() bool {265 // amd64:"(MOVB [$]0)|(XORL [A-Z][A-Z0-9]+, [A-Z][A-Z0-9]+)" -"FCMP" -"MOVB [$]1"266 // s390x:"MOV(B|BZ|D) [$]0," -"FCMPU" -"MOV(B|BZ|D) [$]1,"267 return 0.5 == float64(uint32(1)) || 1.5 > float64(uint64(1<<63))268}269 270func constantCheck32() bool {271 // amd64:"MOV(B|L) [$]1" -"FCMP" -"MOV(B|L) [$]0"272 // s390x:"MOV(B|BZ|D) [$]1," -"FCMPU" -"MOV(B|BZ|D) [$]0,"273 return float32(0.5) <= float32(int64(1)) && float32(1.5) >= float32(int32(-1<<31))274}275 276// Test that integer constants are converted to floating point constants277// at compile-time278 279func constantConvert32(x float32) float32 {280 // amd64:"MOVSS [$]f32.3f800000\\(SB\\)"281 // s390x:"FMOVS [$]f32.3f800000\\(SB\\)"282 // ppc64x/power8:"FMOVS [$]f32.3f800000\\(SB\\)"283 // ppc64x/power9:"FMOVS [$]f32.3f800000\\(SB\\)"284 // ppc64x/power10:"XXSPLTIDP [$]1065353216, VS0"285 // arm64:"FMOVS [$]\\(1.0\\)"286 if x > math.Float32frombits(0x3f800000) {287 return -x288 }289 return x290}291 292func constantConvertInt32(x uint32) uint32 {293 // amd64:-"MOVSS"294 // s390x:-"FMOVS"295 // ppc64x:-"FMOVS"296 // arm64:-"FMOVS"297 if x > math.Float32bits(1) {298 return -x299 }300 return x301}302 303func nanGenerate64() float64 {304 // Test to make sure we don't generate a NaN while constant propagating.305 // See issue 36400.306 zero := 0.0307 // amd64:-"DIVSD"308 inf := 1 / zero // +inf. We can constant propagate this one.309 negone := -1.0310 311 // amd64:"DIVSD"312 z0 := zero / zero313 // amd64/v1,amd64/v2:"MULSD"314 z1 := zero * inf315 // amd64:"SQRTSD"316 z2 := math.Sqrt(negone)317 // amd64/v3:"VFMADD231SD"318 return z0 + z1 + z2319}320 321func nanGenerate32() float32 {322 zero := float32(0.0)323 // amd64:-"DIVSS"324 inf := 1 / zero // +inf. We can constant propagate this one.325 326 // amd64:"DIVSS"327 z0 := zero / zero328 // amd64/v1,amd64/v2:"MULSS"329 z1 := zero * inf330 // amd64/v3:"VFMADD231SS"331 return z0 + z1332}333 334func outOfBoundsConv(i32 *[2]int32, u32 *[2]uint32, i64 *[2]int64, u64 *[2]uint64) {335 // arm64: "FCVTZSDW"336 // amd64: "CVTTSD2SL", "CVTSD2SS"337 i32[0] = int32(two40())338 // arm64: "FCVTZSDW"339 // amd64: "CVTTSD2SL", "CVTSD2SS"340 i32[1] = int32(-two40())341 // arm64: "FCVTZSDW"342 // amd64: "CVTTSD2SL", "CVTSD2SS"343 u32[0] = uint32(two41())344 // on arm64, this uses an explicit <0 comparison, so it constant folds.345 // on amd64, this uses an explicit <0 comparison, so it constant folds.346 // amd64: "MOVL [$]0,"347 u32[1] = uint32(minus1())348 // arm64: "FCVTZSD"349 // amd64: "CVTTSD2SQ"350 i64[0] = int64(two80())351 // arm64: "FCVTZSD"352 // amd64: "CVTTSD2SQ"353 i64[1] = int64(-two80())354 // arm64: "FCVTZUD"355 // amd64: "CVTTSD2SQ"356 u64[0] = uint64(two81())357 // arm64: "FCVTZUD"358 // on amd64, this uses an explicit <0 comparison, so it constant folds.359 // amd64: "MOVQ [$]0,"360 u64[1] = uint64(minus1())361}362 363func two40() float64 {364 return 1 << 40365}366func two41() float64 {367 return 1 << 41368}369func two80() float64 {370 return 1 << 80371}372func two81() float64 {373 return 1 << 81374}375func minus1() float64 {376 return -1377}378 