Text file src/cmd/compile/internal/ssa/gen/MIPS64.rules
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 (Add(Ptr|64|32|16|8) x y) -> (ADDV x y)
6 (Add(32|64)F x y) -> (ADD(F|D) x y)
7
8 (Sub(Ptr|64|32|16|8) x y) -> (SUBV x y)
9 (Sub(32|64)F x y) -> (SUB(F|D) x y)
10
11 (Mul(64|32|16|8) x y) -> (Select1 (MULVU x y))
12 (Mul(32|64)F x y) -> (MUL(F|D) x y)
13
14 (Hmul64 x y) -> (Select0 (MULV x y))
15 (Hmul64u x y) -> (Select0 (MULVU x y))
16 (Hmul32 x y) -> (SRAVconst (Select1 <typ.Int64> (MULV (SignExt32to64 x) (SignExt32to64 y))) [32])
17 (Hmul32u x y) -> (SRLVconst (Select1 <typ.UInt64> (MULVU (ZeroExt32to64 x) (ZeroExt32to64 y))) [32])
18
19 (Div64 x y) -> (Select1 (DIVV x y))
20 (Div64u x y) -> (Select1 (DIVVU x y))
21 (Div32 x y) -> (Select1 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
22 (Div32u x y) -> (Select1 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
23 (Div16 x y) -> (Select1 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
24 (Div16u x y) -> (Select1 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
25 (Div8 x y) -> (Select1 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
26 (Div8u x y) -> (Select1 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
27 (Div(32|64)F x y) -> (DIV(F|D) x y)
28
29 (Mod64 x y) -> (Select0 (DIVV x y))
30 (Mod64u x y) -> (Select0 (DIVVU x y))
31 (Mod32 x y) -> (Select0 (DIVV (SignExt32to64 x) (SignExt32to64 y)))
32 (Mod32u x y) -> (Select0 (DIVVU (ZeroExt32to64 x) (ZeroExt32to64 y)))
33 (Mod16 x y) -> (Select0 (DIVV (SignExt16to64 x) (SignExt16to64 y)))
34 (Mod16u x y) -> (Select0 (DIVVU (ZeroExt16to64 x) (ZeroExt16to64 y)))
35 (Mod8 x y) -> (Select0 (DIVV (SignExt8to64 x) (SignExt8to64 y)))
36 (Mod8u x y) -> (Select0 (DIVVU (ZeroExt8to64 x) (ZeroExt8to64 y)))
37
38 // (x + y) / 2 with x>=y -> (x - y) / 2 + y
39 (Avg64u <t> x y) -> (ADDV (SRLVconst <t> (SUBV <t> x y) [1]) y)
40
41 (And(64|32|16|8) x y) -> (AND x y)
42 (Or(64|32|16|8) x y) -> (OR x y)
43 (Xor(64|32|16|8) x y) -> (XOR x y)
44
45 // shifts
46 // hardware instruction uses only the low 6 bits of the shift
47 // we compare to 64 to ensure Go semantics for large shifts
48 (Lsh64x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
49 (Lsh64x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
50 (Lsh64x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
51 (Lsh64x8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
52
53 (Lsh32x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
54 (Lsh32x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
55 (Lsh32x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
56 (Lsh32x8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
57
58 (Lsh16x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
59 (Lsh16x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
60 (Lsh16x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
61 (Lsh16x8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
62
63 (Lsh8x64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SLLV <t> x y))
64 (Lsh8x32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SLLV <t> x (ZeroExt32to64 y)))
65 (Lsh8x16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SLLV <t> x (ZeroExt16to64 y)))
66 (Lsh8x8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SLLV <t> x (ZeroExt8to64 y)))
67
68 (Rsh64Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> x y))
69 (Rsh64Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> x (ZeroExt32to64 y)))
70 (Rsh64Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> x (ZeroExt16to64 y)))
71 (Rsh64Ux8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> x (ZeroExt8to64 y)))
72
73 (Rsh32Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt32to64 x) y))
74 (Rsh32Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt32to64 y)))
75 (Rsh32Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt16to64 y)))
76 (Rsh32Ux8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt32to64 x) (ZeroExt8to64 y)))
77
78 (Rsh16Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt16to64 x) y))
79 (Rsh16Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt32to64 y)))
80 (Rsh16Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt16to64 y)))
81 (Rsh16Ux8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt16to64 x) (ZeroExt8to64 y)))
82
83 (Rsh8Ux64 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) y)) (SRLV <t> (ZeroExt8to64 x) y))
84 (Rsh8Ux32 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt32to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt32to64 y)))
85 (Rsh8Ux16 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt16to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt16to64 y)))
86 (Rsh8Ux8 <t> x y) -> (AND (NEGV <t> (SGTU (MOVVconst <typ.UInt64> [64]) (ZeroExt8to64 y))) (SRLV <t> (ZeroExt8to64 x) (ZeroExt8to64 y)))
87
88 (Rsh64x64 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
89 (Rsh64x32 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
90 (Rsh64x16 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
91 (Rsh64x8 <t> x y) -> (SRAV x (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
92
93 (Rsh32x64 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
94 (Rsh32x32 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
95 (Rsh32x16 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
96 (Rsh32x8 <t> x y) -> (SRAV (SignExt32to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
97
98 (Rsh16x64 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
99 (Rsh16x32 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
100 (Rsh16x16 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
101 (Rsh16x8 <t> x y) -> (SRAV (SignExt16to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
102
103 (Rsh8x64 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU y (MOVVconst <typ.UInt64> [63]))) y))
104 (Rsh8x32 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt32to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt32to64 y)))
105 (Rsh8x16 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
106 (Rsh8x8 <t> x y) -> (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
107
108 // rotates
109 (RotateLeft8 <t> x (MOVVconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVVconst [c&7])) (Rsh8Ux64 <t> x (MOVVconst [-c&7])))
110 (RotateLeft16 <t> x (MOVVconst [c])) -> (Or16 (Lsh16x64 <t> x (MOVVconst [c&15])) (Rsh16Ux64 <t> x (MOVVconst [-c&15])))
111 (RotateLeft32 <t> x (MOVVconst [c])) -> (Or32 (Lsh32x64 <t> x (MOVVconst [c&31])) (Rsh32Ux64 <t> x (MOVVconst [-c&31])))
112 (RotateLeft64 <t> x (MOVVconst [c])) -> (Or64 (Lsh64x64 <t> x (MOVVconst [c&63])) (Rsh64Ux64 <t> x (MOVVconst [-c&63])))
113
114 // unary ops
115 (Neg(64|32|16|8) x) -> (NEGV x)
116 (Neg(32|64)F x) -> (NEG(F|D) x)
117
118 (Com(64|32|16|8) x) -> (NOR (MOVVconst [0]) x)
119
120 (Sqrt x) -> (SQRTD x)
121
122 // boolean ops -- booleans are represented with 0=false, 1=true
123 (AndB x y) -> (AND x y)
124 (OrB x y) -> (OR x y)
125 (EqB x y) -> (XOR (MOVVconst [1]) (XOR <typ.Bool> x y))
126 (NeqB x y) -> (XOR x y)
127 (Not x) -> (XORconst [1] x)
128
129 // constants
130 (Const(64|32|16|8) [val]) -> (MOVVconst [val])
131 (Const(32|64)F [val]) -> (MOV(F|D)const [val])
132 (ConstNil) -> (MOVVconst [0])
133 (ConstBool [b]) -> (MOVVconst [b])
134
135 (Slicemask <t> x) -> (SRAVconst (NEGV <t> x) [63])
136
137 // truncations
138 // Because we ignore high parts of registers, truncates are just copies.
139 (Trunc16to8 x) -> x
140 (Trunc32to8 x) -> x
141 (Trunc32to16 x) -> x
142 (Trunc64to8 x) -> x
143 (Trunc64to16 x) -> x
144 (Trunc64to32 x) -> x
145
146 // Zero-/Sign-extensions
147 (ZeroExt8to16 x) -> (MOVBUreg x)
148 (ZeroExt8to32 x) -> (MOVBUreg x)
149 (ZeroExt16to32 x) -> (MOVHUreg x)
150 (ZeroExt8to64 x) -> (MOVBUreg x)
151 (ZeroExt16to64 x) -> (MOVHUreg x)
152 (ZeroExt32to64 x) -> (MOVWUreg x)
153
154 (SignExt8to16 x) -> (MOVBreg x)
155 (SignExt8to32 x) -> (MOVBreg x)
156 (SignExt16to32 x) -> (MOVHreg x)
157 (SignExt8to64 x) -> (MOVBreg x)
158 (SignExt16to64 x) -> (MOVHreg x)
159 (SignExt32to64 x) -> (MOVWreg x)
160
161 // float <-> int conversion
162 (Cvt32to32F x) -> (MOVWF x)
163 (Cvt32to64F x) -> (MOVWD x)
164 (Cvt64to32F x) -> (MOVVF x)
165 (Cvt64to64F x) -> (MOVVD x)
166 (Cvt32Fto32 x) -> (TRUNCFW x)
167 (Cvt64Fto32 x) -> (TRUNCDW x)
168 (Cvt32Fto64 x) -> (TRUNCFV x)
169 (Cvt64Fto64 x) -> (TRUNCDV x)
170 (Cvt32Fto64F x) -> (MOVFD x)
171 (Cvt64Fto32F x) -> (MOVDF x)
172
173 (Round(32|64)F x) -> x
174
175 // comparisons
176 (Eq8 x y) -> (SGTU (MOVVconst [1]) (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)))
177 (Eq16 x y) -> (SGTU (MOVVconst [1]) (XOR (ZeroExt16to64 x) (ZeroExt16to64 y)))
178 (Eq32 x y) -> (SGTU (MOVVconst [1]) (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)))
179 (Eq64 x y) -> (SGTU (MOVVconst [1]) (XOR x y))
180 (EqPtr x y) -> (SGTU (MOVVconst [1]) (XOR x y))
181 (Eq(32|64)F x y) -> (FPFlagTrue (CMPEQ(F|D) x y))
182
183 (Neq8 x y) -> (SGTU (XOR (ZeroExt8to64 x) (ZeroExt8to64 y)) (MOVVconst [0]))
184 (Neq16 x y) -> (SGTU (XOR (ZeroExt16to32 x) (ZeroExt16to64 y)) (MOVVconst [0]))
185 (Neq32 x y) -> (SGTU (XOR (ZeroExt32to64 x) (ZeroExt32to64 y)) (MOVVconst [0]))
186 (Neq64 x y) -> (SGTU (XOR x y) (MOVVconst [0]))
187 (NeqPtr x y) -> (SGTU (XOR x y) (MOVVconst [0]))
188 (Neq(32|64)F x y) -> (FPFlagFalse (CMPEQ(F|D) x y))
189
190 (Less8 x y) -> (SGT (SignExt8to64 y) (SignExt8to64 x))
191 (Less16 x y) -> (SGT (SignExt16to64 y) (SignExt16to64 x))
192 (Less32 x y) -> (SGT (SignExt32to64 y) (SignExt32to64 x))
193 (Less64 x y) -> (SGT y x)
194 (Less(32|64)F x y) -> (FPFlagTrue (CMPGT(F|D) y x)) // reverse operands to work around NaN
195
196 (Less8U x y) -> (SGTU (ZeroExt8to64 y) (ZeroExt8to64 x))
197 (Less16U x y) -> (SGTU (ZeroExt16to64 y) (ZeroExt16to64 x))
198 (Less32U x y) -> (SGTU (ZeroExt32to64 y) (ZeroExt32to64 x))
199 (Less64U x y) -> (SGTU y x)
200
201 (Leq8 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt8to64 x) (SignExt8to64 y)))
202 (Leq16 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt16to64 x) (SignExt16to64 y)))
203 (Leq32 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt32to64 x) (SignExt32to64 y)))
204 (Leq64 x y) -> (XOR (MOVVconst [1]) (SGT x y))
205 (Leq(32|64)F x y) -> (FPFlagTrue (CMPGE(F|D) y x)) // reverse operands to work around NaN
206
207 (Leq8U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt8to64 x) (ZeroExt8to64 y)))
208 (Leq16U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt16to64 x) (ZeroExt16to64 y)))
209 (Leq32U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt32to64 x) (ZeroExt32to64 y)))
210 (Leq64U x y) -> (XOR (MOVVconst [1]) (SGTU x y))
211
212 (Greater8 x y) -> (SGT (SignExt8to64 x) (SignExt8to64 y))
213 (Greater16 x y) -> (SGT (SignExt16to64 x) (SignExt16to64 y))
214 (Greater32 x y) -> (SGT (SignExt32to64 x) (SignExt32to64 y))
215 (Greater64 x y) -> (SGT x y)
216 (Greater(32|64)F x y) -> (FPFlagTrue (CMPGT(F|D) x y))
217
218 (Greater8U x y) -> (SGTU (ZeroExt8to64 x) (ZeroExt8to64 y))
219 (Greater16U x y) -> (SGTU (ZeroExt16to64 x) (ZeroExt16to64 y))
220 (Greater32U x y) -> (SGTU (ZeroExt32to64 x) (ZeroExt32to64 y))
221 (Greater64U x y) -> (SGTU x y)
222
223 (Geq8 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt8to64 y) (SignExt8to64 x)))
224 (Geq16 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt16to64 y) (SignExt16to64 x)))
225 (Geq32 x y) -> (XOR (MOVVconst [1]) (SGT (SignExt32to64 y) (SignExt32to64 x)))
226 (Geq64 x y) -> (XOR (MOVVconst [1]) (SGT y x))
227 (Geq(32|64)F x y) -> (FPFlagTrue (CMPGE(F|D) x y))
228
229 (Geq8U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt8to64 y) (ZeroExt8to64 x)))
230 (Geq16U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt16to64 y) (ZeroExt16to64 x)))
231 (Geq32U x y) -> (XOR (MOVVconst [1]) (SGTU (ZeroExt32to64 y) (ZeroExt32to64 x)))
232 (Geq64U x y) -> (XOR (MOVVconst [1]) (SGTU y x))
233
234 (OffPtr [off] ptr:(SP)) -> (MOVVaddr [off] ptr)
235 (OffPtr [off] ptr) -> (ADDVconst [off] ptr)
236
237 (Addr {sym} base) -> (MOVVaddr {sym} base)
238 (LocalAddr {sym} base _) -> (MOVVaddr {sym} base)
239
240 // loads
241 (Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem)
242 (Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem)
243 (Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem)
244 (Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
245 (Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
246 (Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) -> (MOVWload ptr mem)
247 (Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) -> (MOVWUload ptr mem)
248 (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVVload ptr mem)
249 (Load <t> ptr mem) && is32BitFloat(t) -> (MOVFload ptr mem)
250 (Load <t> ptr mem) && is64BitFloat(t) -> (MOVDload ptr mem)
251
252 // stores
253 (Store {t} ptr val mem) && t.(*types.Type).Size() == 1 -> (MOVBstore ptr val mem)
254 (Store {t} ptr val mem) && t.(*types.Type).Size() == 2 -> (MOVHstore ptr val mem)
255 (Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
256 (Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && !is64BitFloat(val.Type) -> (MOVVstore ptr val mem)
257 (Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && is32BitFloat(val.Type) -> (MOVFstore ptr val mem)
258 (Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
259
260 // zeroing
261 (Zero [0] _ mem) -> mem
262 (Zero [1] ptr mem) -> (MOVBstore ptr (MOVVconst [0]) mem)
263 (Zero [2] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
264 (MOVHstore ptr (MOVVconst [0]) mem)
265 (Zero [2] ptr mem) ->
266 (MOVBstore [1] ptr (MOVVconst [0])
267 (MOVBstore [0] ptr (MOVVconst [0]) mem))
268 (Zero [4] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
269 (MOVWstore ptr (MOVVconst [0]) mem)
270 (Zero [4] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
271 (MOVHstore [2] ptr (MOVVconst [0])
272 (MOVHstore [0] ptr (MOVVconst [0]) mem))
273 (Zero [4] ptr mem) ->
274 (MOVBstore [3] ptr (MOVVconst [0])
275 (MOVBstore [2] ptr (MOVVconst [0])
276 (MOVBstore [1] ptr (MOVVconst [0])
277 (MOVBstore [0] ptr (MOVVconst [0]) mem))))
278 (Zero [8] {t} ptr mem) && t.(*types.Type).Alignment()%8 == 0 ->
279 (MOVVstore ptr (MOVVconst [0]) mem)
280 (Zero [8] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
281 (MOVWstore [4] ptr (MOVVconst [0])
282 (MOVWstore [0] ptr (MOVVconst [0]) mem))
283 (Zero [8] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
284 (MOVHstore [6] ptr (MOVVconst [0])
285 (MOVHstore [4] ptr (MOVVconst [0])
286 (MOVHstore [2] ptr (MOVVconst [0])
287 (MOVHstore [0] ptr (MOVVconst [0]) mem))))
288
289 (Zero [3] ptr mem) ->
290 (MOVBstore [2] ptr (MOVVconst [0])
291 (MOVBstore [1] ptr (MOVVconst [0])
292 (MOVBstore [0] ptr (MOVVconst [0]) mem)))
293 (Zero [6] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
294 (MOVHstore [4] ptr (MOVVconst [0])
295 (MOVHstore [2] ptr (MOVVconst [0])
296 (MOVHstore [0] ptr (MOVVconst [0]) mem)))
297 (Zero [12] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
298 (MOVWstore [8] ptr (MOVVconst [0])
299 (MOVWstore [4] ptr (MOVVconst [0])
300 (MOVWstore [0] ptr (MOVVconst [0]) mem)))
301 (Zero [16] {t} ptr mem) && t.(*types.Type).Alignment()%8 == 0 ->
302 (MOVVstore [8] ptr (MOVVconst [0])
303 (MOVVstore [0] ptr (MOVVconst [0]) mem))
304 (Zero [24] {t} ptr mem) && t.(*types.Type).Alignment()%8 == 0 ->
305 (MOVVstore [16] ptr (MOVVconst [0])
306 (MOVVstore [8] ptr (MOVVconst [0])
307 (MOVVstore [0] ptr (MOVVconst [0]) mem)))
308
309 // medium zeroing uses a duff device
310 // 8, and 128 are magic constants, see runtime/mkduff.go
311 (Zero [s] {t} ptr mem)
312 && s%8 == 0 && s > 24 && s <= 8*128
313 && t.(*types.Type).Alignment()%8 == 0 && !config.noDuffDevice ->
314 (DUFFZERO [8 * (128 - s/8)] ptr mem)
315
316 // large or unaligned zeroing uses a loop
317 (Zero [s] {t} ptr mem)
318 && (s > 8*128 || config.noDuffDevice) || t.(*types.Type).Alignment()%8 != 0 ->
319 (LoweredZero [t.(*types.Type).Alignment()]
320 ptr
321 (ADDVconst <ptr.Type> ptr [s-moveSize(t.(*types.Type).Alignment(), config)])
322 mem)
323
324 // moves
325 (Move [0] _ _ mem) -> mem
326 (Move [1] dst src mem) -> (MOVBstore dst (MOVBload src mem) mem)
327 (Move [2] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
328 (MOVHstore dst (MOVHload src mem) mem)
329 (Move [2] dst src mem) ->
330 (MOVBstore [1] dst (MOVBload [1] src mem)
331 (MOVBstore dst (MOVBload src mem) mem))
332 (Move [4] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
333 (MOVWstore dst (MOVWload src mem) mem)
334 (Move [4] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
335 (MOVHstore [2] dst (MOVHload [2] src mem)
336 (MOVHstore dst (MOVHload src mem) mem))
337 (Move [4] dst src mem) ->
338 (MOVBstore [3] dst (MOVBload [3] src mem)
339 (MOVBstore [2] dst (MOVBload [2] src mem)
340 (MOVBstore [1] dst (MOVBload [1] src mem)
341 (MOVBstore dst (MOVBload src mem) mem))))
342 (Move [8] {t} dst src mem) && t.(*types.Type).Alignment()%8 == 0 ->
343 (MOVVstore dst (MOVVload src mem) mem)
344 (Move [8] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
345 (MOVWstore [4] dst (MOVWload [4] src mem)
346 (MOVWstore dst (MOVWload src mem) mem))
347 (Move [8] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
348 (MOVHstore [6] dst (MOVHload [6] src mem)
349 (MOVHstore [4] dst (MOVHload [4] src mem)
350 (MOVHstore [2] dst (MOVHload [2] src mem)
351 (MOVHstore dst (MOVHload src mem) mem))))
352
353 (Move [3] dst src mem) ->
354 (MOVBstore [2] dst (MOVBload [2] src mem)
355 (MOVBstore [1] dst (MOVBload [1] src mem)
356 (MOVBstore dst (MOVBload src mem) mem)))
357 (Move [6] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
358 (MOVHstore [4] dst (MOVHload [4] src mem)
359 (MOVHstore [2] dst (MOVHload [2] src mem)
360 (MOVHstore dst (MOVHload src mem) mem)))
361 (Move [12] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
362 (MOVWstore [8] dst (MOVWload [8] src mem)
363 (MOVWstore [4] dst (MOVWload [4] src mem)
364 (MOVWstore dst (MOVWload src mem) mem)))
365 (Move [16] {t} dst src mem) && t.(*types.Type).Alignment()%8 == 0 ->
366 (MOVVstore [8] dst (MOVVload [8] src mem)
367 (MOVVstore dst (MOVVload src mem) mem))
368 (Move [24] {t} dst src mem) && t.(*types.Type).Alignment()%8 == 0 ->
369 (MOVVstore [16] dst (MOVVload [16] src mem)
370 (MOVVstore [8] dst (MOVVload [8] src mem)
371 (MOVVstore dst (MOVVload src mem) mem)))
372
373 // large or unaligned move uses a loop
374 (Move [s] {t} dst src mem)
375 && s > 24 || t.(*types.Type).Alignment()%8 != 0 ->
376 (LoweredMove [t.(*types.Type).Alignment()]
377 dst
378 src
379 (ADDVconst <src.Type> src [s-moveSize(t.(*types.Type).Alignment(), config)])
380 mem)
381
382 // calls
383 (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
384 (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
385 (InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
386
387 // atomic intrinsics
388 (AtomicLoad8 ptr mem) -> (LoweredAtomicLoad8 ptr mem)
389 (AtomicLoad32 ptr mem) -> (LoweredAtomicLoad32 ptr mem)
390 (AtomicLoad64 ptr mem) -> (LoweredAtomicLoad64 ptr mem)
391 (AtomicLoadPtr ptr mem) -> (LoweredAtomicLoad64 ptr mem)
392
393 (AtomicStore32 ptr val mem) -> (LoweredAtomicStore32 ptr val mem)
394 (AtomicStore64 ptr val mem) -> (LoweredAtomicStore64 ptr val mem)
395 (AtomicStorePtrNoWB ptr val mem) -> (LoweredAtomicStore64 ptr val mem)
396
397 (AtomicExchange32 ptr val mem) -> (LoweredAtomicExchange32 ptr val mem)
398 (AtomicExchange64 ptr val mem) -> (LoweredAtomicExchange64 ptr val mem)
399
400 (AtomicAdd32 ptr val mem) -> (LoweredAtomicAdd32 ptr val mem)
401 (AtomicAdd64 ptr val mem) -> (LoweredAtomicAdd64 ptr val mem)
402
403 (AtomicCompareAndSwap32 ptr old new_ mem) -> (LoweredAtomicCas32 ptr old new_ mem)
404 (AtomicCompareAndSwap64 ptr old new_ mem) -> (LoweredAtomicCas64 ptr old new_ mem)
405
406 // checks
407 (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
408 (IsNonNil ptr) -> (SGTU ptr (MOVVconst [0]))
409 (IsInBounds idx len) -> (SGTU len idx)
410 (IsSliceInBounds idx len) -> (XOR (MOVVconst [1]) (SGTU idx len))
411
412 // pseudo-ops
413 (GetClosurePtr) -> (LoweredGetClosurePtr)
414 (GetCallerSP) -> (LoweredGetCallerSP)
415 (GetCallerPC) -> (LoweredGetCallerPC)
416
417 (If cond yes no) -> (NE cond yes no)
418
419 // Write barrier.
420 (WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
421
422 (PanicBounds [kind] x y mem) && boundsABI(kind) == 0 -> (LoweredPanicBoundsA [kind] x y mem)
423 (PanicBounds [kind] x y mem) && boundsABI(kind) == 1 -> (LoweredPanicBoundsB [kind] x y mem)
424 (PanicBounds [kind] x y mem) && boundsABI(kind) == 2 -> (LoweredPanicBoundsC [kind] x y mem)
425
426 // Optimizations
427
428 // Absorb boolean tests into block
429 (NE (FPFlagTrue cmp) yes no) -> (FPT cmp yes no)
430 (NE (FPFlagFalse cmp) yes no) -> (FPF cmp yes no)
431 (EQ (FPFlagTrue cmp) yes no) -> (FPF cmp yes no)
432 (EQ (FPFlagFalse cmp) yes no) -> (FPT cmp yes no)
433 (NE (XORconst [1] cmp:(SGT _ _)) yes no) -> (EQ cmp yes no)
434 (NE (XORconst [1] cmp:(SGTU _ _)) yes no) -> (EQ cmp yes no)
435 (NE (XORconst [1] cmp:(SGTconst _)) yes no) -> (EQ cmp yes no)
436 (NE (XORconst [1] cmp:(SGTUconst _)) yes no) -> (EQ cmp yes no)
437 (EQ (XORconst [1] cmp:(SGT _ _)) yes no) -> (NE cmp yes no)
438 (EQ (XORconst [1] cmp:(SGTU _ _)) yes no) -> (NE cmp yes no)
439 (EQ (XORconst [1] cmp:(SGTconst _)) yes no) -> (NE cmp yes no)
440 (EQ (XORconst [1] cmp:(SGTUconst _)) yes no) -> (NE cmp yes no)
441 (NE (SGTUconst [1] x) yes no) -> (EQ x yes no)
442 (EQ (SGTUconst [1] x) yes no) -> (NE x yes no)
443 (NE (SGTU x (MOVVconst [0])) yes no) -> (NE x yes no)
444 (EQ (SGTU x (MOVVconst [0])) yes no) -> (EQ x yes no)
445 (NE (SGTconst [0] x) yes no) -> (LTZ x yes no)
446 (EQ (SGTconst [0] x) yes no) -> (GEZ x yes no)
447 (NE (SGT x (MOVVconst [0])) yes no) -> (GTZ x yes no)
448 (EQ (SGT x (MOVVconst [0])) yes no) -> (LEZ x yes no)
449
450 // fold offset into address
451 (ADDVconst [off1] (MOVVaddr [off2] {sym} ptr)) -> (MOVVaddr [off1+off2] {sym} ptr)
452
453 // fold address into load/store
454 (MOVBload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBload [off1+off2] {sym} ptr mem)
455 (MOVBUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBUload [off1+off2] {sym} ptr mem)
456 (MOVHload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHload [off1+off2] {sym} ptr mem)
457 (MOVHUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHUload [off1+off2] {sym} ptr mem)
458 (MOVWload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWload [off1+off2] {sym} ptr mem)
459 (MOVWUload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWUload [off1+off2] {sym} ptr mem)
460 (MOVVload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVVload [off1+off2] {sym} ptr mem)
461 (MOVFload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVFload [off1+off2] {sym} ptr mem)
462 (MOVDload [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVDload [off1+off2] {sym} ptr mem)
463
464 (MOVBstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVBstore [off1+off2] {sym} ptr val mem)
465 (MOVHstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVHstore [off1+off2] {sym} ptr val mem)
466 (MOVWstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVWstore [off1+off2] {sym} ptr val mem)
467 (MOVVstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVVstore [off1+off2] {sym} ptr val mem)
468 (MOVFstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVFstore [off1+off2] {sym} ptr val mem)
469 (MOVDstore [off1] {sym} (ADDVconst [off2] ptr) val mem) && is32Bit(off1+off2) -> (MOVDstore [off1+off2] {sym} ptr val mem)
470 (MOVBstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVBstorezero [off1+off2] {sym} ptr mem)
471 (MOVHstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVHstorezero [off1+off2] {sym} ptr mem)
472 (MOVWstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVWstorezero [off1+off2] {sym} ptr mem)
473 (MOVVstorezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(off1+off2) -> (MOVVstorezero [off1+off2] {sym} ptr mem)
474
475 (MOVBload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
476 (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
477 (MOVBUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
478 (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
479 (MOVHload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
480 (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
481 (MOVHUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
482 (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
483 (MOVWload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
484 (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
485 (MOVWUload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
486 (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
487 (MOVVload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
488 (MOVVload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
489 (MOVFload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
490 (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
491 (MOVDload [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
492 (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
493
494 (MOVBstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
495 (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
496 (MOVHstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
497 (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
498 (MOVWstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
499 (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
500 (MOVVstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
501 (MOVVstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
502 (MOVFstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
503 (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
504 (MOVDstore [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
505 (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
506 (MOVBstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
507 (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
508 (MOVHstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
509 (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
510 (MOVWstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
511 (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
512 (MOVVstorezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) && is32Bit(off1+off2) ->
513 (MOVVstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
514
515 // store zero
516 (MOVBstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
517 (MOVHstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVHstorezero [off] {sym} ptr mem)
518 (MOVWstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem)
519 (MOVVstore [off] {sym} ptr (MOVVconst [0]) mem) -> (MOVVstorezero [off] {sym} ptr mem)
520
521 // don't extend after proper load
522 (MOVBreg x:(MOVBload _ _)) -> (MOVVreg x)
523 (MOVBUreg x:(MOVBUload _ _)) -> (MOVVreg x)
524 (MOVHreg x:(MOVBload _ _)) -> (MOVVreg x)
525 (MOVHreg x:(MOVBUload _ _)) -> (MOVVreg x)
526 (MOVHreg x:(MOVHload _ _)) -> (MOVVreg x)
527 (MOVHUreg x:(MOVBUload _ _)) -> (MOVVreg x)
528 (MOVHUreg x:(MOVHUload _ _)) -> (MOVVreg x)
529 (MOVWreg x:(MOVBload _ _)) -> (MOVVreg x)
530 (MOVWreg x:(MOVBUload _ _)) -> (MOVVreg x)
531 (MOVWreg x:(MOVHload _ _)) -> (MOVVreg x)
532 (MOVWreg x:(MOVHUload _ _)) -> (MOVVreg x)
533 (MOVWreg x:(MOVWload _ _)) -> (MOVVreg x)
534 (MOVWUreg x:(MOVBUload _ _)) -> (MOVVreg x)
535 (MOVWUreg x:(MOVHUload _ _)) -> (MOVVreg x)
536 (MOVWUreg x:(MOVWUload _ _)) -> (MOVVreg x)
537
538 // fold double extensions
539 (MOVBreg x:(MOVBreg _)) -> (MOVVreg x)
540 (MOVBUreg x:(MOVBUreg _)) -> (MOVVreg x)
541 (MOVHreg x:(MOVBreg _)) -> (MOVVreg x)
542 (MOVHreg x:(MOVBUreg _)) -> (MOVVreg x)
543 (MOVHreg x:(MOVHreg _)) -> (MOVVreg x)
544 (MOVHUreg x:(MOVBUreg _)) -> (MOVVreg x)
545 (MOVHUreg x:(MOVHUreg _)) -> (MOVVreg x)
546 (MOVWreg x:(MOVBreg _)) -> (MOVVreg x)
547 (MOVWreg x:(MOVBUreg _)) -> (MOVVreg x)
548 (MOVWreg x:(MOVHreg _)) -> (MOVVreg x)
549 (MOVWreg x:(MOVHreg _)) -> (MOVVreg x)
550 (MOVWreg x:(MOVWreg _)) -> (MOVVreg x)
551 (MOVWUreg x:(MOVBUreg _)) -> (MOVVreg x)
552 (MOVWUreg x:(MOVHUreg _)) -> (MOVVreg x)
553 (MOVWUreg x:(MOVWUreg _)) -> (MOVVreg x)
554
555 // don't extend before store
556 (MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
557 (MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
558 (MOVBstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
559 (MOVBstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
560 (MOVBstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
561 (MOVBstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
562 (MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
563 (MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
564 (MOVHstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
565 (MOVHstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
566 (MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
567 (MOVWstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
568
569 // if a register move has only 1 use, just use the same register without emitting instruction
570 // MOVVnop doesn't emit instruction, only for ensuring the type.
571 (MOVVreg x) && x.Uses == 1 -> (MOVVnop x)
572
573 // fold constant into arithmatic ops
574 (ADDV x (MOVVconst [c])) && is32Bit(c) -> (ADDVconst [c] x)
575 (SUBV x (MOVVconst [c])) && is32Bit(c) -> (SUBVconst [c] x)
576 (AND x (MOVVconst [c])) && is32Bit(c) -> (ANDconst [c] x)
577 (OR x (MOVVconst [c])) && is32Bit(c) -> (ORconst [c] x)
578 (XOR x (MOVVconst [c])) && is32Bit(c) -> (XORconst [c] x)
579 (NOR x (MOVVconst [c])) && is32Bit(c) -> (NORconst [c] x)
580
581 (SLLV _ (MOVVconst [c])) && uint64(c)>=64 -> (MOVVconst [0])
582 (SRLV _ (MOVVconst [c])) && uint64(c)>=64 -> (MOVVconst [0])
583 (SRAV x (MOVVconst [c])) && uint64(c)>=64 -> (SRAVconst x [63])
584 (SLLV x (MOVVconst [c])) -> (SLLVconst x [c])
585 (SRLV x (MOVVconst [c])) -> (SRLVconst x [c])
586 (SRAV x (MOVVconst [c])) -> (SRAVconst x [c])
587
588 (SGT (MOVVconst [c]) x) && is32Bit(c) -> (SGTconst [c] x)
589 (SGTU (MOVVconst [c]) x) && is32Bit(c) -> (SGTUconst [c] x)
590
591 // mul by constant
592 (Select1 (MULVU x (MOVVconst [-1]))) -> (NEGV x)
593 (Select1 (MULVU _ (MOVVconst [0]))) -> (MOVVconst [0])
594 (Select1 (MULVU x (MOVVconst [1]))) -> x
595 (Select1 (MULVU x (MOVVconst [c]))) && isPowerOfTwo(c) -> (SLLVconst [log2(c)] x)
596
597 (Select1 (MULVU (MOVVconst [-1]) x)) -> (NEGV x)
598 (Select1 (MULVU (MOVVconst [0]) _)) -> (MOVVconst [0])
599 (Select1 (MULVU (MOVVconst [1]) x)) -> x
600 (Select1 (MULVU (MOVVconst [c]) x)) && isPowerOfTwo(c) -> (SLLVconst [log2(c)] x)
601
602 // div by constant
603 (Select1 (DIVVU x (MOVVconst [1]))) -> x
604 (Select1 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo(c) -> (SRLVconst [log2(c)] x)
605 (Select0 (DIVVU _ (MOVVconst [1]))) -> (MOVVconst [0]) // mod
606 (Select0 (DIVVU x (MOVVconst [c]))) && isPowerOfTwo(c) -> (ANDconst [c-1] x) // mod
607
608 // generic simplifications
609 (ADDV x (NEGV y)) -> (SUBV x y)
610 (SUBV x x) -> (MOVVconst [0])
611 (SUBV (MOVVconst [0]) x) -> (NEGV x)
612 (AND x x) -> x
613 (OR x x) -> x
614 (XOR x x) -> (MOVVconst [0])
615
616 // remove redundant *const ops
617 (ADDVconst [0] x) -> x
618 (SUBVconst [0] x) -> x
619 (ANDconst [0] _) -> (MOVVconst [0])
620 (ANDconst [-1] x) -> x
621 (ORconst [0] x) -> x
622 (ORconst [-1] _) -> (MOVVconst [-1])
623 (XORconst [0] x) -> x
624 (XORconst [-1] x) -> (NORconst [0] x)
625
626 // generic constant folding
627 (ADDVconst [c] (MOVVconst [d])) -> (MOVVconst [c+d])
628 (ADDVconst [c] (ADDVconst [d] x)) && is32Bit(c+d) -> (ADDVconst [c+d] x)
629 (ADDVconst [c] (SUBVconst [d] x)) && is32Bit(c-d) -> (ADDVconst [c-d] x)
630 (SUBVconst [c] (MOVVconst [d])) -> (MOVVconst [d-c])
631 (SUBVconst [c] (SUBVconst [d] x)) && is32Bit(-c-d) -> (ADDVconst [-c-d] x)
632 (SUBVconst [c] (ADDVconst [d] x)) && is32Bit(-c+d) -> (ADDVconst [-c+d] x)
633 (SLLVconst [c] (MOVVconst [d])) -> (MOVVconst [d<<uint64(c)])
634 (SRLVconst [c] (MOVVconst [d])) -> (MOVVconst [int64(uint64(d)>>uint64(c))])
635 (SRAVconst [c] (MOVVconst [d])) -> (MOVVconst [d>>uint64(c)])
636 (Select1 (MULVU (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [c*d])
637 (Select1 (DIVV (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [c/d])
638 (Select1 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [int64(uint64(c)/uint64(d))])
639 (Select0 (DIVV (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [c%d]) // mod
640 (Select0 (DIVVU (MOVVconst [c]) (MOVVconst [d]))) -> (MOVVconst [int64(uint64(c)%uint64(d))]) // mod
641 (ANDconst [c] (MOVVconst [d])) -> (MOVVconst [c&d])
642 (ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
643 (ORconst [c] (MOVVconst [d])) -> (MOVVconst [c|d])
644 (ORconst [c] (ORconst [d] x)) && is32Bit(c|d) -> (ORconst [c|d] x)
645 (XORconst [c] (MOVVconst [d])) -> (MOVVconst [c^d])
646 (XORconst [c] (XORconst [d] x)) && is32Bit(c^d) -> (XORconst [c^d] x)
647 (NORconst [c] (MOVVconst [d])) -> (MOVVconst [^(c|d)])
648 (NEGV (MOVVconst [c])) -> (MOVVconst [-c])
649 (MOVBreg (MOVVconst [c])) -> (MOVVconst [int64(int8(c))])
650 (MOVBUreg (MOVVconst [c])) -> (MOVVconst [int64(uint8(c))])
651 (MOVHreg (MOVVconst [c])) -> (MOVVconst [int64(int16(c))])
652 (MOVHUreg (MOVVconst [c])) -> (MOVVconst [int64(uint16(c))])
653 (MOVWreg (MOVVconst [c])) -> (MOVVconst [int64(int32(c))])
654 (MOVWUreg (MOVVconst [c])) -> (MOVVconst [int64(uint32(c))])
655 (MOVVreg (MOVVconst [c])) -> (MOVVconst [c])
656 (LoweredAtomicStore32 ptr (MOVVconst [0]) mem) -> (LoweredAtomicStorezero32 ptr mem)
657 (LoweredAtomicStore64 ptr (MOVVconst [0]) mem) -> (LoweredAtomicStorezero64 ptr mem)
658 (LoweredAtomicAdd32 ptr (MOVVconst [c]) mem) && is32Bit(c) -> (LoweredAtomicAddconst32 [c] ptr mem)
659 (LoweredAtomicAdd64 ptr (MOVVconst [c]) mem) && is32Bit(c) -> (LoweredAtomicAddconst64 [c] ptr mem)
660
661 // constant comparisons
662 (SGTconst [c] (MOVVconst [d])) && c>d -> (MOVVconst [1])
663 (SGTconst [c] (MOVVconst [d])) && c<=d -> (MOVVconst [0])
664 (SGTUconst [c] (MOVVconst [d])) && uint64(c)>uint64(d) -> (MOVVconst [1])
665 (SGTUconst [c] (MOVVconst [d])) && uint64(c)<=uint64(d) -> (MOVVconst [0])
666
667 // other known comparisons
668 (SGTconst [c] (MOVBreg _)) && 0x7f < c -> (MOVVconst [1])
669 (SGTconst [c] (MOVBreg _)) && c <= -0x80 -> (MOVVconst [0])
670 (SGTconst [c] (MOVBUreg _)) && 0xff < c -> (MOVVconst [1])
671 (SGTconst [c] (MOVBUreg _)) && c < 0 -> (MOVVconst [0])
672 (SGTUconst [c] (MOVBUreg _)) && 0xff < uint64(c) -> (MOVVconst [1])
673 (SGTconst [c] (MOVHreg _)) && 0x7fff < c -> (MOVVconst [1])
674 (SGTconst [c] (MOVHreg _)) && c <= -0x8000 -> (MOVVconst [0])
675 (SGTconst [c] (MOVHUreg _)) && 0xffff < c -> (MOVVconst [1])
676 (SGTconst [c] (MOVHUreg _)) && c < 0 -> (MOVVconst [0])
677 (SGTUconst [c] (MOVHUreg _)) && 0xffff < uint64(c) -> (MOVVconst [1])
678 (SGTconst [c] (MOVWUreg _)) && c < 0 -> (MOVVconst [0])
679 (SGTconst [c] (ANDconst [m] _)) && 0 <= m && m < c -> (MOVVconst [1])
680 (SGTUconst [c] (ANDconst [m] _)) && uint64(m) < uint64(c) -> (MOVVconst [1])
681 (SGTconst [c] (SRLVconst _ [d])) && 0 <= c && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) -> (MOVVconst [1])
682 (SGTUconst [c] (SRLVconst _ [d])) && 0 < d && d <= 63 && 0xffffffffffffffff>>uint64(d) < uint64(c) -> (MOVVconst [1])
683
684 // absorb constants into branches
685 (EQ (MOVVconst [0]) yes no) -> (First nil yes no)
686 (EQ (MOVVconst [c]) yes no) && c != 0 -> (First nil no yes)
687 (NE (MOVVconst [0]) yes no) -> (First nil no yes)
688 (NE (MOVVconst [c]) yes no) && c != 0 -> (First nil yes no)
689 (LTZ (MOVVconst [c]) yes no) && c < 0 -> (First nil yes no)
690 (LTZ (MOVVconst [c]) yes no) && c >= 0 -> (First nil no yes)
691 (LEZ (MOVVconst [c]) yes no) && c <= 0 -> (First nil yes no)
692 (LEZ (MOVVconst [c]) yes no) && c > 0 -> (First nil no yes)
693 (GTZ (MOVVconst [c]) yes no) && c > 0 -> (First nil yes no)
694 (GTZ (MOVVconst [c]) yes no) && c <= 0 -> (First nil no yes)
695 (GEZ (MOVVconst [c]) yes no) && c >= 0 -> (First nil yes no)
696 (GEZ (MOVVconst [c]) yes no) && c < 0 -> (First nil no yes)
View as plain text