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
7package codegen
8
9// This file contains codegen tests related to arithmetic
10// simplifications and optimizations on float types.
11// For codegen tests on integer types, see arithmetic.go.
12
13// --------------------- //
14//    Strength-reduce    //
15// --------------------- //
16
17func Mul2(f float64) float64 {
18	// 386/sse2:"ADDSD",-"MULSD"
19	// amd64:"ADDSD",-"MULSD"
20	// arm/7:"ADDD",-"MULD"
21	// arm64:"FADDD",-"FMULD"
22	// ppc64x:"FADD",-"FMUL"
23	// riscv64:"FADDD",-"FMULD"
24	return f * 2.0
25}
26
27func DivPow2(f1, f2, f3 float64) (float64, float64, float64) {
28	// 386/sse2:"MULSD",-"DIVSD"
29	// amd64:"MULSD",-"DIVSD"
30	// arm/7:"MULD",-"DIVD"
31	// arm64:"FMULD",-"FDIVD"
32	// ppc64x:"FMUL",-"FDIV"
33	// riscv64:"FMULD",-"FDIVD"
34	x := f1 / 16.0
35
36	// 386/sse2:"MULSD",-"DIVSD"
37	// amd64:"MULSD",-"DIVSD"
38	// arm/7:"MULD",-"DIVD"
39	// arm64:"FMULD",-"FDIVD"
40	// ppc64x:"FMUL",-"FDIVD"
41	// riscv64:"FMULD",-"FDIVD"
42	y := f2 / 0.125
43
44	// 386/sse2:"ADDSD",-"DIVSD",-"MULSD"
45	// amd64:"ADDSD",-"DIVSD",-"MULSD"
46	// arm/7:"ADDD",-"MULD",-"DIVD"
47	// arm64:"FADDD",-"FMULD",-"FDIVD"
48	// ppc64x:"FADD",-"FMUL",-"FDIV"
49	// riscv64:"FADDD",-"FMULD",-"FDIVD"
50	z := f3 / 0.5
51
52	return x, y, z
53}
54
55func indexLoad(b0 []float32, b1 float32, idx int) float32 {
56	// arm64:`FMOVS\s\(R[0-9]+\)\(R[0-9]+<<2\),\sF[0-9]+`
57	return b0[idx] * b1
58}
59
60func indexStore(b0 []float64, b1 float64, idx int) {
61	// arm64:`FMOVD\sF[0-9]+,\s\(R[0-9]+\)\(R[0-9]+<<3\)`
62	b0[idx] = b1
63}
64
65// ----------- //
66//    Fused    //
67// ----------- //
68
69func FusedAdd32(x, y, z float32) float32 {
70	// s390x:"FMADDS\t"
71	// ppc64x:"FMADDS\t"
72	// arm64:"FMADDS"
73	// riscv64:"FMADDS\t"
74	return x*y + z
75}
76
77func FusedSub32_a(x, y, z float32) float32 {
78	// s390x:"FMSUBS\t"
79	// ppc64x:"FMSUBS\t"
80	// riscv64:"FMSUBS\t"
81	return x*y - z
82}
83
84func FusedSub32_b(x, y, z float32) float32 {
85	// arm64:"FMSUBS"
86	// riscv64:"FNMSUBS\t"
87	return z - x*y
88}
89
90func FusedAdd64(x, y, z float64) float64 {
91	// s390x:"FMADD\t"
92	// ppc64x:"FMADD\t"
93	// arm64:"FMADDD"
94	// riscv64:"FMADDD\t"
95	return x*y + z
96}
97
98func FusedSub64_a(x, y, z float64) float64 {
99	// s390x:"FMSUB\t"
100	// ppc64x:"FMSUB\t"
101	// riscv64:"FMSUBD\t"
102	return x*y - z
103}
104
105func FusedSub64_b(x, y, z float64) float64 {
106	// arm64:"FMSUBD"
107	// riscv64:"FNMSUBD\t"
108	return z - x*y
109}
110
111func Cmp(f float64) bool {
112	// arm64:"FCMPD","(BGT|BLE|BMI|BPL)",-"CSET\tGT",-"CBZ"
113	return f > 4 || f < -4
114}
115
116func CmpZero64(f float64) bool {
117	// s390x:"LTDBR",-"FCMPU"
118	return f <= 0
119}
120
121func CmpZero32(f float32) bool {
122	// s390x:"LTEBR",-"CEBR"
123	return f <= 0
124}
125
126func CmpWithSub(a float64, b float64) bool {
127	f := a - b
128	// s390x:-"LTDBR"
129	return f <= 0
130}
131
132func CmpWithAdd(a float64, b float64) bool {
133	f := a + b
134	// s390x:-"LTDBR"
135	return f <= 0
136}
137
138// ---------------- //
139//    Non-floats    //
140// ---------------- //
141
142// We should make sure that the compiler doesn't generate floating point
143// instructions for non-float operations on Plan 9, because floating point
144// operations are not allowed in the note handler.
145
146func ArrayZero() [16]byte {
147	// amd64:"MOVUPS"
148	// plan9/amd64/:-"MOVUPS"
149	var a [16]byte
150	return a
151}
152
153func ArrayCopy(a [16]byte) (b [16]byte) {
154	// amd64:"MOVUPS"
155	// plan9/amd64/:-"MOVUPS"
156	b = a
157	return
158}
159
160// ---------------- //
161//  Float Min/Max   //
162// ---------------- //
163
164func Float64Min(a, b float64) float64 {
165	// amd64:"MINSD"
166	// arm64:"FMIND"
167	// riscv64:"FMIN"
168	// ppc64/power9:"XSMINJDP"
169	// ppc64/power10:"XSMINJDP"
170	return min(a, b)
171}
172
173func Float64Max(a, b float64) float64 {
174	// amd64:"MINSD"
175	// arm64:"FMAXD"
176	// riscv64:"FMAX"
177	// ppc64/power9:"XSMAXJDP"
178	// ppc64/power10:"XSMAXJDP"
179	return max(a, b)
180}
181
182func Float32Min(a, b float32) float32 {
183	// amd64:"MINSS"
184	// arm64:"FMINS"
185	// riscv64:"FMINS"
186	// ppc64/power9:"XSMINJDP"
187	// ppc64/power10:"XSMINJDP"
188	return min(a, b)
189}
190
191func Float32Max(a, b float32) float32 {
192	// amd64:"MINSS"
193	// arm64:"FMAXS"
194	// riscv64:"FMAXS"
195	// ppc64/power9:"XSMAXJDP"
196	// ppc64/power10:"XSMAXJDP"
197	return max(a, b)
198}
199
200// ------------------------ //
201//  Constant Optimizations  //
202// ------------------------ //
203
204func Float32Constant() float32 {
205	// ppc64x/power8:"FMOVS\t[$]f32\\.42440000\\(SB\\)"
206	// ppc64x/power9:"FMOVS\t[$]f32\\.42440000\\(SB\\)"
207	// ppc64x/power10:"XXSPLTIDP\t[$]1111752704,"
208	return 49.0
209}
210
211func Float64Constant() float64 {
212	// ppc64x/power8:"FMOVD\t[$]f64\\.4048800000000000\\(SB\\)"
213	// ppc64x/power9:"FMOVD\t[$]f64\\.4048800000000000\\(SB\\)"
214	// ppc64x/power10:"XXSPLTIDP\t[$]1111752704,"
215	return 49.0
216}
217
218func Float32DenormalConstant() float32 {
219	// ppc64x:"FMOVS\t[$]f32\\.00400000\\(SB\\)"
220	return 0x1p-127
221}
222
223// A float64 constant which can be exactly represented as a
224// denormal float32 value. On ppc64x, denormal values cannot
225// be used with XXSPLTIDP.
226func Float64DenormalFloat32Constant() float64 {
227	// ppc64x:"FMOVD\t[$]f64\\.3800000000000000\\(SB\\)"
228	return 0x1p-127
229}
230