Source file test/codegen/floats.go
1 // asmcheck 2 3 // Copyright 2018 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package codegen 8 9 import "math" 10 11 // This file contains codegen tests related to arithmetic 12 // simplifications and optimizations on float types. 13 // For codegen tests on integer types, see arithmetic.go. 14 15 // --------------------- // 16 // Strength-reduce // 17 // --------------------- // 18 19 func Mul2(f float64) float64 { 20 // 386/sse2:"ADDSD" -"MULSD" 21 // amd64:"ADDSD" -"MULSD" 22 // arm/7:"ADDD" -"MULD" 23 // arm64:"FADDD" -"FMULD" 24 // loong64:"ADDD" -"MULD" 25 // ppc64x:"FADD" -"FMUL" 26 // riscv64:"FADDD" -"FMULD" 27 return f * 2.0 28 } 29 30 func DivPow2(f1, f2, f3 float64) (float64, float64, float64) { 31 // 386/sse2:"MULSD" -"DIVSD" 32 // amd64:"MULSD" -"DIVSD" 33 // arm/7:"MULD" -"DIVD" 34 // arm64:"FMULD" -"FDIVD" 35 // loong64:"MULD" -"DIVD" 36 // ppc64x:"FMUL" -"FDIV" 37 // riscv64:"FMULD" -"FDIVD" 38 x := f1 / 16.0 39 40 // 386/sse2:"MULSD" -"DIVSD" 41 // amd64:"MULSD" -"DIVSD" 42 // arm/7:"MULD" -"DIVD" 43 // arm64:"FMULD" -"FDIVD" 44 // loong64:"MULD" -"DIVD" 45 // ppc64x:"FMUL" -"FDIVD" 46 // riscv64:"FMULD" -"FDIVD" 47 y := f2 / 0.125 48 49 // 386/sse2:"ADDSD" -"DIVSD" -"MULSD" 50 // amd64:"ADDSD" -"DIVSD" -"MULSD" 51 // arm/7:"ADDD" -"MULD" -"DIVD" 52 // arm64:"FADDD" -"FMULD" -"FDIVD" 53 // loong64:"ADDD" -"MULD" -"DIVD" 54 // ppc64x:"FADD" -"FMUL" -"FDIV" 55 // riscv64:"FADDD" -"FMULD" -"FDIVD" 56 z := f3 / 0.5 57 58 return x, y, z 59 } 60 61 func indexLoad(b0 []float32, b1 float32, idx int) float32 { 62 // arm64:`FMOVS\s\(R[0-9]+\)\(R[0-9]+<<2\),\sF[0-9]+` 63 // loong64:`MOVF\s\(R[0-9]+\)\(R[0-9]+\),\sF[0-9]+` 64 return b0[idx] * b1 65 } 66 67 func indexStore(b0 []float64, b1 float64, idx int) { 68 // arm64:`FMOVD\sF[0-9]+,\s\(R[0-9]+\)\(R[0-9]+<<3\)` 69 // loong64:`MOVD\sF[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)` 70 b0[idx] = b1 71 } 72 73 // ----------- // 74 // Fused // 75 // ----------- // 76 77 func FusedAdd32(x, y, z float32) float32 { 78 // s390x:"FMADDS " 79 // ppc64x:"FMADDS " 80 // arm64:"FMADDS" 81 // loong64:"FMADDF " 82 // riscv64:"FMADDS " 83 // amd64/v3:"VFMADD231SS " 84 return x*y + z 85 } 86 87 func FusedSub32_a(x, y, z float32) float32 { 88 // s390x:"FMSUBS " 89 // ppc64x:"FMSUBS " 90 // riscv64:"FMSUBS " 91 // loong64:"FMSUBF " 92 return x*y - z 93 } 94 95 func FusedSub32_b(x, y, z float32) float32 { 96 // arm64:"FMSUBS" 97 // loong64:"FNMSUBF " 98 // riscv64:"FNMSUBS " 99 return z - x*y 100 } 101 102 func FusedAdd64(x, y, z float64) float64 { 103 // s390x:"FMADD " 104 // ppc64x:"FMADD " 105 // arm64:"FMADDD" 106 // loong64:"FMADDD " 107 // riscv64:"FMADDD " 108 // amd64/v3:"VFMADD231SD " 109 return x*y + z 110 } 111 112 func FusedSub64_a(x, y, z float64) float64 { 113 // s390x:"FMSUB " 114 // ppc64x:"FMSUB " 115 // riscv64:"FMSUBD " 116 // loong64:"FMSUBD " 117 return x*y - z 118 } 119 120 func FusedSub64_b(x, y, z float64) float64 { 121 // arm64:"FMSUBD" 122 // loong64:"FNMSUBD " 123 // riscv64:"FNMSUBD " 124 return z - x*y 125 } 126 127 func Cmp(f float64) bool { 128 // arm64:"FCMPD" "(BGT|BLE|BMI|BPL)" -"CSET GT" -"CBZ" 129 return f > 4 || f < -4 130 } 131 132 func CmpZero64(f float64) bool { 133 // s390x:"LTDBR" -"FCMPU" 134 return f <= 0 135 } 136 137 func CmpZero32(f float32) bool { 138 // s390x:"LTEBR" -"CEBR" 139 return f <= 0 140 } 141 142 func CmpWithSub(a float64, b float64) bool { 143 f := a - b 144 // s390x:-"LTDBR" 145 return f <= 0 146 } 147 148 func CmpWithAdd(a float64, b float64) bool { 149 f := a + b 150 // s390x:-"LTDBR" 151 return f <= 0 152 } 153 154 // ---------------- // 155 // Non-floats // 156 // ---------------- // 157 158 func ArrayZero() [16]byte { 159 // amd64:"MOVUPS" 160 var a [16]byte 161 return a 162 } 163 164 func ArrayCopy(a [16]byte) (b [16]byte) { 165 // amd64:"MOVUPS" 166 b = a 167 return 168 } 169 170 // ---------------- // 171 // Float Min/Max // 172 // ---------------- // 173 174 func Float64Min(a, b float64) float64 { 175 // amd64:"MINSD" 176 // arm64:"FMIND" 177 // loong64:"FMIND" 178 // riscv64:"FMIN" 179 // ppc64/power9:"XSMINJDP" 180 // ppc64/power10:"XSMINJDP" 181 // s390x: "WFMINDB" 182 return min(a, b) 183 } 184 185 func Float64Max(a, b float64) float64 { 186 // amd64:"MINSD" 187 // arm64:"FMAXD" 188 // loong64:"FMAXD" 189 // riscv64:"FMAX" 190 // ppc64/power9:"XSMAXJDP" 191 // ppc64/power10:"XSMAXJDP" 192 // s390x: "WFMAXDB" 193 return max(a, b) 194 } 195 196 func Float32Min(a, b float32) float32 { 197 // amd64:"MINSS" 198 // arm64:"FMINS" 199 // loong64:"FMINF" 200 // riscv64:"FMINS" 201 // ppc64/power9:"XSMINJDP" 202 // ppc64/power10:"XSMINJDP" 203 // s390x: "WFMINSB" 204 return min(a, b) 205 } 206 207 func Float32Max(a, b float32) float32 { 208 // amd64:"MINSS" 209 // arm64:"FMAXS" 210 // loong64:"FMAXF" 211 // riscv64:"FMAXS" 212 // ppc64/power9:"XSMAXJDP" 213 // ppc64/power10:"XSMAXJDP" 214 // s390x: "WFMAXSB" 215 return max(a, b) 216 } 217 218 // ------------------------ // 219 // Constant Optimizations // 220 // ------------------------ // 221 222 func Float32ConstantZero() float32 { 223 // arm64:"FMOVS ZR," 224 return 0.0 225 } 226 227 func Float32ConstantChipFloat() float32 { 228 // arm64:"FMOVS [$]\\(2\\.25\\)," 229 return 2.25 230 } 231 232 func Float32Constant() float32 { 233 // arm64:"FMOVS [$]f32\\.42440000\\(SB\\)" 234 // ppc64x/power8:"FMOVS [$]f32\\.42440000\\(SB\\)" 235 // ppc64x/power9:"FMOVS [$]f32\\.42440000\\(SB\\)" 236 // ppc64x/power10:"XXSPLTIDP [$]1111752704," 237 return 49.0 238 } 239 240 func Float64ConstantZero() float64 { 241 // arm64:"FMOVD ZR," 242 return 0.0 243 } 244 245 func Float64ConstantChipFloat() float64 { 246 // arm64:"FMOVD [$]\\(2\\.25\\)," 247 return 2.25 248 } 249 250 func Float64Constant() float64 { 251 // arm64:"FMOVD [$]f64\\.4048800000000000\\(SB\\)" 252 // ppc64x/power8:"FMOVD [$]f64\\.4048800000000000\\(SB\\)" 253 // ppc64x/power9:"FMOVD [$]f64\\.4048800000000000\\(SB\\)" 254 // ppc64x/power10:"XXSPLTIDP [$]1111752704," 255 return 49.0 256 } 257 258 func Float32DenormalConstant() float32 { 259 // ppc64x:"FMOVS [$]f32\\.00400000\\(SB\\)" 260 return 0x1p-127 261 } 262 263 // A float64 constant which can be exactly represented as a 264 // denormal float32 value. On ppc64x, denormal values cannot 265 // be used with XXSPLTIDP. 266 func Float64DenormalFloat32Constant() float64 { 267 // ppc64x:"FMOVD [$]f64\\.3800000000000000\\(SB\\)" 268 return 0x1p-127 269 } 270 271 func Float32ConstantStore(p *float32) { 272 // amd64:"MOVL [$]1085133554" 273 // riscv64: "MOVF [$]f32.40add2f2" 274 *p = 5.432 275 } 276 277 func Float64ConstantStore(p *float64) { 278 // amd64: "MOVQ [$]4617801906721357038" 279 // riscv64: "MOVD [$]f64.4015ba5e353f7cee" 280 *p = 5.432 281 } 282 283 // ------------------------ // 284 // Subnormal tests // 285 // ------------------------ // 286 287 func isSubnormal(x float64) bool { 288 // riscv64:"FCLASSD" -"FABSD" 289 return math.Abs(x) < 2.2250738585072014e-308 290 } 291 292 func isNormal(x float64) bool { 293 // riscv64:"FCLASSD" -"FABSD" 294 return math.Abs(x) >= 0x1p-1022 295 } 296 297 func isPosSubnormal(x float64) bool { 298 // riscv64:"FCLASSD" 299 return x > 0 && x < 2.2250738585072014e-308 300 } 301 302 func isNegSubnormal(x float64) bool { 303 // riscv64:"FCLASSD" 304 return x < 0 && x > -0x1p-1022 305 } 306 307 func isPosNormal(x float64) bool { 308 // riscv64:"FCLASSD" 309 return x >= 2.2250738585072014e-308 310 } 311 312 func isNegNormal(x float64) bool { 313 // riscv64:"FCLASSD" 314 return x <= -2.2250738585072014e-308 315 } 316