Text file src/pkg/cmd/compile/internal/ssa/gen/ARM64.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 (AddPtr x y) -> (ADD x y)
6 (Add64 x y) -> (ADD x y)
7 (Add32 x y) -> (ADD x y)
8 (Add16 x y) -> (ADD x y)
9 (Add8 x y) -> (ADD x y)
10 (Add32F x y) -> (FADDS x y)
11 (Add64F x y) -> (FADDD x y)
12
13 (SubPtr x y) -> (SUB x y)
14 (Sub64 x y) -> (SUB x y)
15 (Sub32 x y) -> (SUB x y)
16 (Sub16 x y) -> (SUB x y)
17 (Sub8 x y) -> (SUB x y)
18 (Sub32F x y) -> (FSUBS x y)
19 (Sub64F x y) -> (FSUBD x y)
20
21 (Mul64 x y) -> (MUL x y)
22 (Mul32 x y) -> (MULW x y)
23 (Mul16 x y) -> (MULW x y)
24 (Mul8 x y) -> (MULW x y)
25 (Mul32F x y) -> (FMULS x y)
26 (Mul64F x y) -> (FMULD x y)
27
28 (Hmul64 x y) -> (MULH x y)
29 (Hmul64u x y) -> (UMULH x y)
30 (Hmul32 x y) -> (SRAconst (MULL <typ.Int64> x y) [32])
31 (Hmul32u x y) -> (SRAconst (UMULL <typ.UInt64> x y) [32])
32 (Mul64uhilo x y) -> (LoweredMuluhilo x y)
33
34 (Div64 x y) -> (DIV x y)
35 (Div64u x y) -> (UDIV x y)
36 (Div32 x y) -> (DIVW x y)
37 (Div32u x y) -> (UDIVW x y)
38 (Div16 x y) -> (DIVW (SignExt16to32 x) (SignExt16to32 y))
39 (Div16u x y) -> (UDIVW (ZeroExt16to32 x) (ZeroExt16to32 y))
40 (Div8 x y) -> (DIVW (SignExt8to32 x) (SignExt8to32 y))
41 (Div8u x y) -> (UDIVW (ZeroExt8to32 x) (ZeroExt8to32 y))
42 (Div32F x y) -> (FDIVS x y)
43 (Div64F x y) -> (FDIVD x y)
44
45 (Mod64 x y) -> (MOD x y)
46 (Mod64u x y) -> (UMOD x y)
47 (Mod32 x y) -> (MODW x y)
48 (Mod32u x y) -> (UMODW x y)
49 (Mod16 x y) -> (MODW (SignExt16to32 x) (SignExt16to32 y))
50 (Mod16u x y) -> (UMODW (ZeroExt16to32 x) (ZeroExt16to32 y))
51 (Mod8 x y) -> (MODW (SignExt8to32 x) (SignExt8to32 y))
52 (Mod8u x y) -> (UMODW (ZeroExt8to32 x) (ZeroExt8to32 y))
53
54 // (x + y) / 2 with x>=y -> (x - y) / 2 + y
55 (Avg64u <t> x y) -> (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
56
57 (And64 x y) -> (AND x y)
58 (And32 x y) -> (AND x y)
59 (And16 x y) -> (AND x y)
60 (And8 x y) -> (AND x y)
61
62 (Or64 x y) -> (OR x y)
63 (Or32 x y) -> (OR x y)
64 (Or16 x y) -> (OR x y)
65 (Or8 x y) -> (OR x y)
66
67 (Xor64 x y) -> (XOR x y)
68 (Xor32 x y) -> (XOR x y)
69 (Xor16 x y) -> (XOR x y)
70 (Xor8 x y) -> (XOR x y)
71
72 // unary ops
73 (Neg64 x) -> (NEG x)
74 (Neg32 x) -> (NEG x)
75 (Neg16 x) -> (NEG x)
76 (Neg8 x) -> (NEG x)
77 (Neg32F x) -> (FNEGS x)
78 (Neg64F x) -> (FNEGD x)
79
80 (Com64 x) -> (MVN x)
81 (Com32 x) -> (MVN x)
82 (Com16 x) -> (MVN x)
83 (Com8 x) -> (MVN x)
84
85 // math package intrinsics
86 (Abs x) -> (FABSD x)
87 (Sqrt x) -> (FSQRTD x)
88 (Ceil x) -> (FRINTPD x)
89 (Floor x) -> (FRINTMD x)
90 (Round x) -> (FRINTAD x)
91 (RoundToEven x) -> (FRINTND x)
92 (Trunc x) -> (FRINTZD x)
93
94 // lowering rotates
95 (RotateLeft8 <t> x (MOVDconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
96 (RotateLeft16 <t> x (MOVDconst [c])) -> (Or16 (Lsh16x64 <t> x (MOVDconst [c&15])) (Rsh16Ux64 <t> x (MOVDconst [-c&15])))
97 (RotateLeft32 x y) -> (RORW x (NEG <y.Type> y))
98 (RotateLeft64 x y) -> (ROR x (NEG <y.Type> y))
99
100 (Ctz64NonZero x) -> (Ctz64 x)
101 (Ctz32NonZero x) -> (Ctz32 x)
102 (Ctz16NonZero x) -> (Ctz32 x)
103 (Ctz8NonZero x) -> (Ctz32 x)
104
105 (Ctz64 <t> x) -> (CLZ (RBIT <t> x))
106 (Ctz32 <t> x) -> (CLZW (RBITW <t> x))
107 (Ctz16 <t> x) -> (CLZW <t> (RBITW <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
108 (Ctz8 <t> x) -> (CLZW <t> (RBITW <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
109
110 (PopCount64 <t> x) -> (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> x))))
111 (PopCount32 <t> x) -> (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> (ZeroExt32to64 x)))))
112 (PopCount16 <t> x) -> (FMOVDfpgp <t> (VUADDLV <typ.Float64> (VCNT <typ.Float64> (FMOVDgpfp <typ.Float64> (ZeroExt16to64 x)))))
113
114 // Load args directly into the register class where it will be used.
115 (FMOVDgpfp <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
116 (FMOVDfpgp <t> (Arg [off] {sym})) -> @b.Func.Entry (Arg <t> [off] {sym})
117
118 // Similarly for stores, if we see a store after FPR <-> GPR move, then redirect store to use the other register set.
119 (MOVDstore [off] {sym} ptr (FMOVDfpgp val) mem) -> (FMOVDstore [off] {sym} ptr val mem)
120 (FMOVDstore [off] {sym} ptr (FMOVDgpfp val) mem) -> (MOVDstore [off] {sym} ptr val mem)
121 (MOVWstore [off] {sym} ptr (FMOVSfpgp val) mem) -> (FMOVSstore [off] {sym} ptr val mem)
122 (FMOVSstore [off] {sym} ptr (FMOVSgpfp val) mem) -> (MOVWstore [off] {sym} ptr val mem)
123
124 // float <-> int register moves, with no conversion.
125 // These come up when compiling math.{Float64bits, Float64frombits, Float32bits, Float32frombits}.
126 (MOVDload [off] {sym} ptr (FMOVDstore [off] {sym} ptr val _)) -> (FMOVDfpgp val)
127 (FMOVDload [off] {sym} ptr (MOVDstore [off] {sym} ptr val _)) -> (FMOVDgpfp val)
128 (MOVWUload [off] {sym} ptr (FMOVSstore [off] {sym} ptr val _)) -> (FMOVSfpgp val)
129 (FMOVSload [off] {sym} ptr (MOVWstore [off] {sym} ptr val _)) -> (FMOVSgpfp val)
130
131 (BitLen64 x) -> (SUB (MOVDconst [64]) (CLZ <typ.Int> x))
132 (BitLen32 x) -> (SUB (MOVDconst [32]) (CLZW <typ.Int> x))
133
134 (Bswap64 x) -> (REV x)
135 (Bswap32 x) -> (REVW x)
136
137 (BitRev64 x) -> (RBIT x)
138 (BitRev32 x) -> (RBITW x)
139 (BitRev16 x) -> (SRLconst [48] (RBIT <typ.UInt64> x))
140 (BitRev8 x) -> (SRLconst [56] (RBIT <typ.UInt64> x))
141
142 // In fact, UMOD will be translated into UREM instruction, and UREM is originally translated into
143 // UDIV and MSUB instructions. But if there is already an identical UDIV instruction just before or
144 // after UREM (case like quo, rem := z/y, z%y), then the second UDIV instruction becomes redundant.
145 // The purpose of this rule is to have this extra UDIV instruction removed in CSE pass.
146 (UMOD <typ.UInt64> x y) -> (MSUB <typ.UInt64> x y (UDIV <typ.UInt64> x y))
147 (UMODW <typ.UInt32> x y) -> (MSUBW <typ.UInt32> x y (UDIVW <typ.UInt32> x y))
148
149 // 64-bit addition with carry.
150 (Select0 (Add64carry x y c)) -> (Select0 <typ.UInt64> (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] c))))
151 (Select1 (Add64carry x y c)) -> (ADCzerocarry <typ.UInt64> (Select1 <types.TypeFlags> (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] c)))))
152
153 // 64-bit subtraction with borrowing.
154 (Select0 (Sub64borrow x y bo)) -> (Select0 <typ.UInt64> (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags bo))))
155 (Select1 (Sub64borrow x y bo)) -> (NEG <typ.UInt64> (NGCzerocarry <typ.UInt64> (Select1 <types.TypeFlags> (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags bo))))))
156
157 // boolean ops -- booleans are represented with 0=false, 1=true
158 (AndB x y) -> (AND x y)
159 (OrB x y) -> (OR x y)
160 (EqB x y) -> (XOR (MOVDconst [1]) (XOR <typ.Bool> x y))
161 (NeqB x y) -> (XOR x y)
162 (Not x) -> (XOR (MOVDconst [1]) x)
163
164 // shifts
165 // hardware instruction uses only the low 6 bits of the shift
166 // we compare to 64 to ensure Go semantics for large shifts
167 // Rules about rotates with non-const shift are based on the following rules,
168 // if the following rules change, please also modify the rules based on them.
169 (Lsh64x64 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
170 (Lsh64x32 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
171 (Lsh64x16 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
172 (Lsh64x8 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
173
174 (Lsh32x64 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
175 (Lsh32x32 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
176 (Lsh32x16 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
177 (Lsh32x8 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
178
179 (Lsh16x64 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
180 (Lsh16x32 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
181 (Lsh16x16 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
182 (Lsh16x8 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
183
184 (Lsh8x64 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
185 (Lsh8x32 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
186 (Lsh8x16 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
187 (Lsh8x8 <t> x y) -> (CSEL {OpARM64LessThanU} (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
188
189 (Rsh64Ux64 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> x y) (Const64 <t> [0]) (CMPconst [64] y))
190 (Rsh64Ux32 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
191 (Rsh64Ux16 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
192 (Rsh64Ux8 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
193
194 (Rsh32Ux64 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt32to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
195 (Rsh32Ux32 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt32to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
196 (Rsh32Ux16 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt32to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
197 (Rsh32Ux8 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt32to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
198
199 (Rsh16Ux64 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt16to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
200 (Rsh16Ux32 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt16to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
201 (Rsh16Ux16 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt16to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
202 (Rsh16Ux8 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt16to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
203
204 (Rsh8Ux64 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt8to64 x) y) (Const64 <t> [0]) (CMPconst [64] y))
205 (Rsh8Ux32 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt8to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y)))
206 (Rsh8Ux16 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt8to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y)))
207 (Rsh8Ux8 <t> x y) -> (CSEL {OpARM64LessThanU} (SRL <t> (ZeroExt8to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y)))
208
209 (Rsh64x64 x y) -> (SRA x (CSEL {OpARM64LessThanU} <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
210 (Rsh64x32 x y) -> (SRA x (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
211 (Rsh64x16 x y) -> (SRA x (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
212 (Rsh64x8 x y) -> (SRA x (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
213
214 (Rsh32x64 x y) -> (SRA (SignExt32to64 x) (CSEL {OpARM64LessThanU} <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
215 (Rsh32x32 x y) -> (SRA (SignExt32to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
216 (Rsh32x16 x y) -> (SRA (SignExt32to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
217 (Rsh32x8 x y) -> (SRA (SignExt32to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
218
219 (Rsh16x64 x y) -> (SRA (SignExt16to64 x) (CSEL {OpARM64LessThanU} <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
220 (Rsh16x32 x y) -> (SRA (SignExt16to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
221 (Rsh16x16 x y) -> (SRA (SignExt16to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
222 (Rsh16x8 x y) -> (SRA (SignExt16to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
223
224 (Rsh8x64 x y) -> (SRA (SignExt8to64 x) (CSEL {OpARM64LessThanU} <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y)))
225 (Rsh8x32 x y) -> (SRA (SignExt8to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y))))
226 (Rsh8x16 x y) -> (SRA (SignExt8to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y))))
227 (Rsh8x8 x y) -> (SRA (SignExt8to64 x) (CSEL {OpARM64LessThanU} <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y))))
228
229 // constants
230 (Const64 [val]) -> (MOVDconst [val])
231 (Const32 [val]) -> (MOVDconst [val])
232 (Const16 [val]) -> (MOVDconst [val])
233 (Const8 [val]) -> (MOVDconst [val])
234 (Const32F [val]) -> (FMOVSconst [val])
235 (Const64F [val]) -> (FMOVDconst [val])
236 (ConstNil) -> (MOVDconst [0])
237 (ConstBool [b]) -> (MOVDconst [b])
238
239 (Slicemask <t> x) -> (SRAconst (NEG <t> x) [63])
240
241 // truncations
242 // Because we ignore high parts of registers, truncates are just copies.
243 (Trunc16to8 x) -> x
244 (Trunc32to8 x) -> x
245 (Trunc32to16 x) -> x
246 (Trunc64to8 x) -> x
247 (Trunc64to16 x) -> x
248 (Trunc64to32 x) -> x
249
250 // Zero-/Sign-extensions
251 (ZeroExt8to16 x) -> (MOVBUreg x)
252 (ZeroExt8to32 x) -> (MOVBUreg x)
253 (ZeroExt16to32 x) -> (MOVHUreg x)
254 (ZeroExt8to64 x) -> (MOVBUreg x)
255 (ZeroExt16to64 x) -> (MOVHUreg x)
256 (ZeroExt32to64 x) -> (MOVWUreg x)
257
258 (SignExt8to16 x) -> (MOVBreg x)
259 (SignExt8to32 x) -> (MOVBreg x)
260 (SignExt16to32 x) -> (MOVHreg x)
261 (SignExt8to64 x) -> (MOVBreg x)
262 (SignExt16to64 x) -> (MOVHreg x)
263 (SignExt32to64 x) -> (MOVWreg x)
264
265 // float <-> int conversion
266 (Cvt32to32F x) -> (SCVTFWS x)
267 (Cvt32to64F x) -> (SCVTFWD x)
268 (Cvt64to32F x) -> (SCVTFS x)
269 (Cvt64to64F x) -> (SCVTFD x)
270 (Cvt32Uto32F x) -> (UCVTFWS x)
271 (Cvt32Uto64F x) -> (UCVTFWD x)
272 (Cvt64Uto32F x) -> (UCVTFS x)
273 (Cvt64Uto64F x) -> (UCVTFD x)
274 (Cvt32Fto32 x) -> (FCVTZSSW x)
275 (Cvt64Fto32 x) -> (FCVTZSDW x)
276 (Cvt32Fto64 x) -> (FCVTZSS x)
277 (Cvt64Fto64 x) -> (FCVTZSD x)
278 (Cvt32Fto32U x) -> (FCVTZUSW x)
279 (Cvt64Fto32U x) -> (FCVTZUDW x)
280 (Cvt32Fto64U x) -> (FCVTZUS x)
281 (Cvt64Fto64U x) -> (FCVTZUD x)
282 (Cvt32Fto64F x) -> (FCVTSD x)
283 (Cvt64Fto32F x) -> (FCVTDS x)
284
285 (Round32F x) -> (LoweredRound32F x)
286 (Round64F x) -> (LoweredRound64F x)
287
288 // comparisons
289 (Eq8 x y) -> (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
290 (Eq16 x y) -> (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
291 (Eq32 x y) -> (Equal (CMPW x y))
292 (Eq64 x y) -> (Equal (CMP x y))
293 (EqPtr x y) -> (Equal (CMP x y))
294 (Eq32F x y) -> (Equal (FCMPS x y))
295 (Eq64F x y) -> (Equal (FCMPD x y))
296
297 (Neq8 x y) -> (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
298 (Neq16 x y) -> (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
299 (Neq32 x y) -> (NotEqual (CMPW x y))
300 (Neq64 x y) -> (NotEqual (CMP x y))
301 (NeqPtr x y) -> (NotEqual (CMP x y))
302 (Neq32F x y) -> (NotEqual (FCMPS x y))
303 (Neq64F x y) -> (NotEqual (FCMPD x y))
304
305 (Less8 x y) -> (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
306 (Less16 x y) -> (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
307 (Less32 x y) -> (LessThan (CMPW x y))
308 (Less64 x y) -> (LessThan (CMP x y))
309
310 // Set condition flags for floating-point comparisons "x < y"
311 // and "x <= y". Because if either or both of the operands are
312 // NaNs, all three of (x < y), (x == y) and (x > y) are false,
313 // and ARM Manual says FCMP instruction sets PSTATE.<N,Z,C,V>
314 // of this case to (0, 0, 1, 1).
315 (Less32F x y) -> (LessThanF (FCMPS x y))
316 (Less64F x y) -> (LessThanF (FCMPD x y))
317
318 (Less8U x y) -> (LessThanU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
319 (Less16U x y) -> (LessThanU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
320 (Less32U x y) -> (LessThanU (CMPW x y))
321 (Less64U x y) -> (LessThanU (CMP x y))
322
323 (Leq8 x y) -> (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
324 (Leq16 x y) -> (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
325 (Leq32 x y) -> (LessEqual (CMPW x y))
326 (Leq64 x y) -> (LessEqual (CMP x y))
327
328 // Refer to the comments for op Less64F above.
329 (Leq32F x y) -> (LessEqualF (FCMPS x y))
330 (Leq64F x y) -> (LessEqualF (FCMPD x y))
331
332 (Leq8U x y) -> (LessEqualU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
333 (Leq16U x y) -> (LessEqualU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
334 (Leq32U x y) -> (LessEqualU (CMPW x y))
335 (Leq64U x y) -> (LessEqualU (CMP x y))
336
337 (Greater8 x y) -> (GreaterThan (CMPW (SignExt8to32 x) (SignExt8to32 y)))
338 (Greater16 x y) -> (GreaterThan (CMPW (SignExt16to32 x) (SignExt16to32 y)))
339 (Greater32 x y) -> (GreaterThan (CMPW x y))
340 (Greater64 x y) -> (GreaterThan (CMP x y))
341 (Greater32F x y) -> (GreaterThanF (FCMPS x y))
342 (Greater64F x y) -> (GreaterThanF (FCMPD x y))
343
344 (Greater8U x y) -> (GreaterThanU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
345 (Greater16U x y) -> (GreaterThanU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
346 (Greater32U x y) -> (GreaterThanU (CMPW x y))
347 (Greater64U x y) -> (GreaterThanU (CMP x y))
348
349 (Geq8 x y) -> (GreaterEqual (CMPW (SignExt8to32 x) (SignExt8to32 y)))
350 (Geq16 x y) -> (GreaterEqual (CMPW (SignExt16to32 x) (SignExt16to32 y)))
351 (Geq32 x y) -> (GreaterEqual (CMPW x y))
352 (Geq64 x y) -> (GreaterEqual (CMP x y))
353 (Geq32F x y) -> (GreaterEqualF (FCMPS x y))
354 (Geq64F x y) -> (GreaterEqualF (FCMPD x y))
355
356 (Geq8U x y) -> (GreaterEqualU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y)))
357 (Geq16U x y) -> (GreaterEqualU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y)))
358 (Geq32U x y) -> (GreaterEqualU (CMPW x y))
359 (Geq64U x y) -> (GreaterEqualU (CMP x y))
360
361 // Optimize comparision between a floating-point value and 0.0 with "FCMP $(0.0), Fn"
362 (FCMPS x (FMOVSconst [0])) -> (FCMPS0 x)
363 (FCMPS (FMOVSconst [0]) x) -> (InvertFlags (FCMPS0 x))
364 (FCMPD x (FMOVDconst [0])) -> (FCMPD0 x)
365 (FCMPD (FMOVDconst [0]) x) -> (InvertFlags (FCMPD0 x))
366
367 // CSEL needs a flag-generating argument. Synthesize a CMPW if necessary.
368 (CondSelect x y boolval) && flagArg(boolval) != nil -> (CSEL {boolval.Op} x y flagArg(boolval))
369 (CondSelect x y boolval) && flagArg(boolval) == nil -> (CSEL {OpARM64NotEqual} x y (CMPWconst [0] boolval))
370
371 (OffPtr [off] ptr:(SP)) -> (MOVDaddr [off] ptr)
372 (OffPtr [off] ptr) -> (ADDconst [off] ptr)
373
374 (Addr {sym} base) -> (MOVDaddr {sym} base)
375 (LocalAddr {sym} base _) -> (MOVDaddr {sym} base)
376
377 // loads
378 (Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem)
379 (Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem)
380 (Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem)
381 (Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
382 (Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
383 (Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) -> (MOVWload ptr mem)
384 (Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) -> (MOVWUload ptr mem)
385 (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
386 (Load <t> ptr mem) && is32BitFloat(t) -> (FMOVSload ptr mem)
387 (Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
388
389 // stores
390 (Store {t} ptr val mem) && t.(*types.Type).Size() == 1 -> (MOVBstore ptr val mem)
391 (Store {t} ptr val mem) && t.(*types.Type).Size() == 2 -> (MOVHstore ptr val mem)
392 (Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
393 (Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && !is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
394 (Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && is32BitFloat(val.Type) -> (FMOVSstore ptr val mem)
395 (Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && is64BitFloat(val.Type) -> (FMOVDstore ptr val mem)
396
397 // zeroing
398 (Zero [0] _ mem) -> mem
399 (Zero [1] ptr mem) -> (MOVBstore ptr (MOVDconst [0]) mem)
400 (Zero [2] ptr mem) -> (MOVHstore ptr (MOVDconst [0]) mem)
401 (Zero [4] ptr mem) -> (MOVWstore ptr (MOVDconst [0]) mem)
402 (Zero [8] ptr mem) -> (MOVDstore ptr (MOVDconst [0]) mem)
403
404 (Zero [3] ptr mem) ->
405 (MOVBstore [2] ptr (MOVDconst [0])
406 (MOVHstore ptr (MOVDconst [0]) mem))
407 (Zero [5] ptr mem) ->
408 (MOVBstore [4] ptr (MOVDconst [0])
409 (MOVWstore ptr (MOVDconst [0]) mem))
410 (Zero [6] ptr mem) ->
411 (MOVHstore [4] ptr (MOVDconst [0])
412 (MOVWstore ptr (MOVDconst [0]) mem))
413 (Zero [7] ptr mem) ->
414 (MOVBstore [6] ptr (MOVDconst [0])
415 (MOVHstore [4] ptr (MOVDconst [0])
416 (MOVWstore ptr (MOVDconst [0]) mem)))
417 (Zero [9] ptr mem) ->
418 (MOVBstore [8] ptr (MOVDconst [0])
419 (MOVDstore ptr (MOVDconst [0]) mem))
420 (Zero [10] ptr mem) ->
421 (MOVHstore [8] ptr (MOVDconst [0])
422 (MOVDstore ptr (MOVDconst [0]) mem))
423 (Zero [11] ptr mem) ->
424 (MOVBstore [10] ptr (MOVDconst [0])
425 (MOVHstore [8] ptr (MOVDconst [0])
426 (MOVDstore ptr (MOVDconst [0]) mem)))
427 (Zero [12] ptr mem) ->
428 (MOVWstore [8] ptr (MOVDconst [0])
429 (MOVDstore ptr (MOVDconst [0]) mem))
430 (Zero [13] ptr mem) ->
431 (MOVBstore [12] ptr (MOVDconst [0])
432 (MOVWstore [8] ptr (MOVDconst [0])
433 (MOVDstore ptr (MOVDconst [0]) mem)))
434 (Zero [14] ptr mem) ->
435 (MOVHstore [12] ptr (MOVDconst [0])
436 (MOVWstore [8] ptr (MOVDconst [0])
437 (MOVDstore ptr (MOVDconst [0]) mem)))
438 (Zero [15] ptr mem) ->
439 (MOVBstore [14] ptr (MOVDconst [0])
440 (MOVHstore [12] ptr (MOVDconst [0])
441 (MOVWstore [8] ptr (MOVDconst [0])
442 (MOVDstore ptr (MOVDconst [0]) mem))))
443 (Zero [16] ptr mem) ->
444 (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)
445
446 (Zero [32] ptr mem) ->
447 (STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
448 (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))
449
450 (Zero [48] ptr mem) ->
451 (STP [32] ptr (MOVDconst [0]) (MOVDconst [0])
452 (STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
453 (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)))
454
455 (Zero [64] ptr mem) ->
456 (STP [48] ptr (MOVDconst [0]) (MOVDconst [0])
457 (STP [32] ptr (MOVDconst [0]) (MOVDconst [0])
458 (STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
459 (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))))
460
461 // strip off fractional word zeroing
462 (Zero [s] ptr mem) && s%16 != 0 && s%16 <= 8 && s > 16 ->
463 (Zero [8]
464 (OffPtr <ptr.Type> ptr [s-8])
465 (Zero [s-s%16] ptr mem))
466 (Zero [s] ptr mem) && s%16 != 0 && s%16 > 8 && s > 16 ->
467 (Zero [16]
468 (OffPtr <ptr.Type> ptr [s-16])
469 (Zero [s-s%16] ptr mem))
470
471 // medium zeroing uses a duff device
472 // 4, 16, and 64 are magic constants, see runtime/mkduff.go
473 (Zero [s] ptr mem)
474 && s%16 == 0 && s > 64 && s <= 16*64
475 && !config.noDuffDevice ->
476 (DUFFZERO [4 * (64 - s/16)] ptr mem)
477
478 // large zeroing uses a loop
479 (Zero [s] ptr mem)
480 && s%16 == 0 && (s > 16*64 || config.noDuffDevice) ->
481 (LoweredZero
482 ptr
483 (ADDconst <ptr.Type> [s-16] ptr)
484 mem)
485
486 // moves
487 (Move [0] _ _ mem) -> mem
488 (Move [1] dst src mem) -> (MOVBstore dst (MOVBUload src mem) mem)
489 (Move [2] dst src mem) -> (MOVHstore dst (MOVHUload src mem) mem)
490 (Move [4] dst src mem) -> (MOVWstore dst (MOVWUload src mem) mem)
491 (Move [8] dst src mem) -> (MOVDstore dst (MOVDload src mem) mem)
492
493 (Move [3] dst src mem) ->
494 (MOVBstore [2] dst (MOVBUload [2] src mem)
495 (MOVHstore dst (MOVHUload src mem) mem))
496 (Move [5] dst src mem) ->
497 (MOVBstore [4] dst (MOVBUload [4] src mem)
498 (MOVWstore dst (MOVWUload src mem) mem))
499 (Move [6] dst src mem) ->
500 (MOVHstore [4] dst (MOVHUload [4] src mem)
501 (MOVWstore dst (MOVWUload src mem) mem))
502 (Move [7] dst src mem) ->
503 (MOVBstore [6] dst (MOVBUload [6] src mem)
504 (MOVHstore [4] dst (MOVHUload [4] src mem)
505 (MOVWstore dst (MOVWUload src mem) mem)))
506 (Move [12] dst src mem) ->
507 (MOVWstore [8] dst (MOVWUload [8] src mem)
508 (MOVDstore dst (MOVDload src mem) mem))
509 (Move [16] dst src mem) ->
510 (MOVDstore [8] dst (MOVDload [8] src mem)
511 (MOVDstore dst (MOVDload src mem) mem))
512 (Move [24] dst src mem) ->
513 (MOVDstore [16] dst (MOVDload [16] src mem)
514 (MOVDstore [8] dst (MOVDload [8] src mem)
515 (MOVDstore dst (MOVDload src mem) mem)))
516
517 // strip off fractional word move
518 (Move [s] dst src mem) && s%8 != 0 && s > 8 ->
519 (Move [s%8]
520 (OffPtr <dst.Type> dst [s-s%8])
521 (OffPtr <src.Type> src [s-s%8])
522 (Move [s-s%8] dst src mem))
523
524 // medium move uses a duff device
525 (Move [s] dst src mem)
526 && s > 32 && s <= 16*64 && s%16 == 8
527 && !config.noDuffDevice ->
528 (MOVDstore [s-8] dst (MOVDload [s-8] src mem)
529 (DUFFCOPY <types.TypeMem> [8*(64-(s-8)/16)] dst src mem))
530 (Move [s] dst src mem)
531 && s > 32 && s <= 16*64 && s%16 == 0
532 && !config.noDuffDevice ->
533 (DUFFCOPY [8 * (64 - s/16)] dst src mem)
534 // 8 is the number of bytes to encode:
535 //
536 // LDP.P 16(R16), (R26, R27)
537 // STP.P (R26, R27), 16(R17)
538 //
539 // 64 is number of these blocks. See runtime/duff_arm64.s:duffcopy
540
541 // large move uses a loop
542 (Move [s] dst src mem)
543 && s > 24 && s%8 == 0 ->
544 (LoweredMove
545 dst
546 src
547 (ADDconst <src.Type> src [s-8])
548 mem)
549
550 // calls
551 (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
552 (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
553 (InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
554
555 // checks
556 (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
557 (IsNonNil ptr) -> (NotEqual (CMPconst [0] ptr))
558 (IsInBounds idx len) -> (LessThanU (CMP idx len))
559 (IsSliceInBounds idx len) -> (LessEqualU (CMP idx len))
560
561 // pseudo-ops
562 (GetClosurePtr) -> (LoweredGetClosurePtr)
563 (GetCallerSP) -> (LoweredGetCallerSP)
564 (GetCallerPC) -> (LoweredGetCallerPC)
565
566 // Absorb pseudo-ops into blocks.
567 (If (Equal cc) yes no) -> (EQ cc yes no)
568 (If (NotEqual cc) yes no) -> (NE cc yes no)
569 (If (LessThan cc) yes no) -> (LT cc yes no)
570 (If (LessThanU cc) yes no) -> (ULT cc yes no)
571 (If (LessEqual cc) yes no) -> (LE cc yes no)
572 (If (LessEqualU cc) yes no) -> (ULE cc yes no)
573 (If (GreaterThan cc) yes no) -> (GT cc yes no)
574 (If (GreaterThanU cc) yes no) -> (UGT cc yes no)
575 (If (GreaterEqual cc) yes no) -> (GE cc yes no)
576 (If (GreaterEqualU cc) yes no) -> (UGE cc yes no)
577 (If (LessThanF cc) yes no) -> (FLT cc yes no)
578 (If (LessEqualF cc) yes no) -> (FLE cc yes no)
579 (If (GreaterThanF cc) yes no) -> (FGT cc yes no)
580 (If (GreaterEqualF cc) yes no) -> (FGE cc yes no)
581
582 (If cond yes no) -> (NZ cond yes no)
583
584 // atomic intrinsics
585 // Note: these ops do not accept offset.
586 (AtomicLoad8 ptr mem) -> (LDARB ptr mem)
587 (AtomicLoad32 ptr mem) -> (LDARW ptr mem)
588 (AtomicLoad64 ptr mem) -> (LDAR ptr mem)
589 (AtomicLoadPtr ptr mem) -> (LDAR ptr mem)
590
591 (AtomicStore32 ptr val mem) -> (STLRW ptr val mem)
592 (AtomicStore64 ptr val mem) -> (STLR ptr val mem)
593 (AtomicStorePtrNoWB ptr val mem) -> (STLR ptr val mem)
594
595 (AtomicExchange32 ptr val mem) -> (LoweredAtomicExchange32 ptr val mem)
596 (AtomicExchange64 ptr val mem) -> (LoweredAtomicExchange64 ptr val mem)
597
598 (AtomicAdd32 ptr val mem) -> (LoweredAtomicAdd32 ptr val mem)
599 (AtomicAdd64 ptr val mem) -> (LoweredAtomicAdd64 ptr val mem)
600
601 (AtomicCompareAndSwap32 ptr old new_ mem) -> (LoweredAtomicCas32 ptr old new_ mem)
602 (AtomicCompareAndSwap64 ptr old new_ mem) -> (LoweredAtomicCas64 ptr old new_ mem)
603
604 // Currently the updated value is not used, but we need a register to temporarily hold it.
605 (AtomicAnd8 ptr val mem) -> (Select1 (LoweredAtomicAnd8 ptr val mem))
606 (AtomicOr8 ptr val mem) -> (Select1 (LoweredAtomicOr8 ptr val mem))
607
608 (AtomicAdd32Variant ptr val mem) -> (LoweredAtomicAdd32Variant ptr val mem)
609 (AtomicAdd64Variant ptr val mem) -> (LoweredAtomicAdd64Variant ptr val mem)
610
611 // Write barrier.
612 (WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
613
614 (PanicBounds [kind] x y mem) && boundsABI(kind) == 0 -> (LoweredPanicBoundsA [kind] x y mem)
615 (PanicBounds [kind] x y mem) && boundsABI(kind) == 1 -> (LoweredPanicBoundsB [kind] x y mem)
616 (PanicBounds [kind] x y mem) && boundsABI(kind) == 2 -> (LoweredPanicBoundsC [kind] x y mem)
617
618 // Optimizations
619
620 // Absorb boolean tests into block
621 (NZ (Equal cc) yes no) -> (EQ cc yes no)
622 (NZ (NotEqual cc) yes no) -> (NE cc yes no)
623 (NZ (LessThan cc) yes no) -> (LT cc yes no)
624 (NZ (LessThanU cc) yes no) -> (ULT cc yes no)
625 (NZ (LessEqual cc) yes no) -> (LE cc yes no)
626 (NZ (LessEqualU cc) yes no) -> (ULE cc yes no)
627 (NZ (GreaterThan cc) yes no) -> (GT cc yes no)
628 (NZ (GreaterThanU cc) yes no) -> (UGT cc yes no)
629 (NZ (GreaterEqual cc) yes no) -> (GE cc yes no)
630 (NZ (GreaterEqualU cc) yes no) -> (UGE cc yes no)
631 (NZ (LessThanF cc) yes no) -> (FLT cc yes no)
632 (NZ (LessEqualF cc) yes no) -> (FLE cc yes no)
633 (NZ (GreaterThanF cc) yes no) -> (FGT cc yes no)
634 (NZ (GreaterEqualF cc) yes no) -> (FGE cc yes no)
635
636 (EQ (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (EQ (TSTWconst [c] y) yes no)
637 (NE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (NE (TSTWconst [c] y) yes no)
638 (LT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (LT (TSTWconst [c] y) yes no)
639 (LE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (LE (TSTWconst [c] y) yes no)
640 (GT (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (GT (TSTWconst [c] y) yes no)
641 (GE (CMPWconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (GE (TSTWconst [c] y) yes no)
642
643 (EQ (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (EQ (TST x y) yes no)
644 (NE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (NE (TST x y) yes no)
645 (LT (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (LT (TST x y) yes no)
646 (LE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (LE (TST x y) yes no)
647 (GT (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (GT (TST x y) yes no)
648 (GE (CMPconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (GE (TST x y) yes no)
649
650 (EQ (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (EQ (TSTW x y) yes no)
651 (NE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (NE (TSTW x y) yes no)
652 (LT (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (LT (TSTW x y) yes no)
653 (LE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (LE (TSTW x y) yes no)
654 (GT (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (GT (TSTW x y) yes no)
655 (GE (CMPWconst [0] z:(AND x y)) yes no) && z.Uses == 1 -> (GE (TSTW x y) yes no)
656
657 (EQ (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (EQ (TSTconst [c] y) yes no)
658 (NE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (NE (TSTconst [c] y) yes no)
659 (LT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (LT (TSTconst [c] y) yes no)
660 (LE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (LE (TSTconst [c] y) yes no)
661 (GT (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (GT (TSTconst [c] y) yes no)
662 (GE (CMPconst [0] x:(ANDconst [c] y)) yes no) && x.Uses == 1 -> (GE (TSTconst [c] y) yes no)
663
664 (EQ (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (EQ (CMNconst [c] y) yes no)
665 (NE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (NE (CMNconst [c] y) yes no)
666 (LT (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LT (CMNconst [c] y) yes no)
667 (LE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LE (CMNconst [c] y) yes no)
668 (GT (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GT (CMNconst [c] y) yes no)
669 (GE (CMPconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GE (CMNconst [c] y) yes no)
670
671 (EQ (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (EQ (CMNWconst [c] y) yes no)
672 (NE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (NE (CMNWconst [c] y) yes no)
673 (LT (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LT (CMNWconst [c] y) yes no)
674 (LE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (LE (CMNWconst [c] y) yes no)
675 (GT (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GT (CMNWconst [c] y) yes no)
676 (GE (CMPWconst [0] x:(ADDconst [c] y)) yes no) && x.Uses == 1 -> (GE (CMNWconst [c] y) yes no)
677
678 (EQ (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (EQ (CMN x y) yes no)
679 (NE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (NE (CMN x y) yes no)
680 (LT (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LT (CMN x y) yes no)
681 (LE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LE (CMN x y) yes no)
682 (GT (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GT (CMN x y) yes no)
683 (GE (CMPconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GE (CMN x y) yes no)
684
685 (EQ (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (EQ (CMNW x y) yes no)
686 (NE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (NE (CMNW x y) yes no)
687 (LT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LT (CMNW x y) yes no)
688 (LE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (LE (CMNW x y) yes no)
689 (GT (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GT (CMNW x y) yes no)
690 (GE (CMPWconst [0] z:(ADD x y)) yes no) && z.Uses == 1 -> (GE (CMNW x y) yes no)
691
692 (EQ (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (EQ (CMN x y) yes no)
693 (NE (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (NE (CMN x y) yes no)
694 (LT (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (LT (CMN x y) yes no)
695 (LE (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (LE (CMN x y) yes no)
696 (GT (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (GT (CMN x y) yes no)
697 (GE (CMP x z:(NEG y)) yes no) && z.Uses == 1 -> (GE (CMN x y) yes no)
698
699 (EQ (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (EQ (CMNW x y) yes no)
700 (NE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (NE (CMNW x y) yes no)
701 (LT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (LT (CMNW x y) yes no)
702 (LE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (LE (CMNW x y) yes no)
703 (GT (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (GT (CMNW x y) yes no)
704 (GE (CMPW x z:(NEG y)) yes no) && z.Uses == 1 -> (GE (CMNW x y) yes no)
705
706 (EQ (CMPconst [0] x) yes no) -> (Z x yes no)
707 (NE (CMPconst [0] x) yes no) -> (NZ x yes no)
708 (EQ (CMPWconst [0] x) yes no) -> (ZW x yes no)
709 (NE (CMPWconst [0] x) yes no) -> (NZW x yes no)
710
711 (EQ (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 -> (EQ (CMN a (MUL <x.Type> x y)) yes no)
712 (NE (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 -> (NE (CMN a (MUL <x.Type> x y)) yes no)
713 (LT (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 -> (LT (CMN a (MUL <x.Type> x y)) yes no)
714 (LE (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 -> (LE (CMN a (MUL <x.Type> x y)) yes no)
715 (GT (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 -> (GT (CMN a (MUL <x.Type> x y)) yes no)
716 (GE (CMPconst [0] z:(MADD a x y)) yes no) && z.Uses==1 -> (GE (CMN a (MUL <x.Type> x y)) yes no)
717
718 (EQ (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 -> (EQ (CMP a (MUL <x.Type> x y)) yes no)
719 (NE (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 -> (NE (CMP a (MUL <x.Type> x y)) yes no)
720 (LE (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 -> (LE (CMP a (MUL <x.Type> x y)) yes no)
721 (LT (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 -> (LT (CMP a (MUL <x.Type> x y)) yes no)
722 (GE (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 -> (GE (CMP a (MUL <x.Type> x y)) yes no)
723 (GT (CMPconst [0] z:(MSUB a x y)) yes no) && z.Uses==1 -> (GT (CMP a (MUL <x.Type> x y)) yes no)
724
725 (EQ (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 -> (EQ (CMNW a (MULW <x.Type> x y)) yes no)
726 (NE (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 -> (NE (CMNW a (MULW <x.Type> x y)) yes no)
727 (LE (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 -> (LE (CMNW a (MULW <x.Type> x y)) yes no)
728 (LT (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 -> (LT (CMNW a (MULW <x.Type> x y)) yes no)
729 (GE (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 -> (GE (CMNW a (MULW <x.Type> x y)) yes no)
730 (GT (CMPWconst [0] z:(MADDW a x y)) yes no) && z.Uses==1 -> (GT (CMNW a (MULW <x.Type> x y)) yes no)
731
732 (EQ (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 -> (EQ (CMPW a (MULW <x.Type> x y)) yes no)
733 (NE (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 -> (NE (CMPW a (MULW <x.Type> x y)) yes no)
734 (LE (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 -> (LE (CMPW a (MULW <x.Type> x y)) yes no)
735 (LT (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 -> (LT (CMPW a (MULW <x.Type> x y)) yes no)
736 (GE (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 -> (GE (CMPW a (MULW <x.Type> x y)) yes no)
737 (GT (CMPWconst [0] z:(MSUBW a x y)) yes no) && z.Uses==1 -> (GT (CMPW a (MULW <x.Type> x y)) yes no)
738
739 // Absorb bit-tests into block
740 (Z (ANDconst [c] x) yes no) && oneBit(c) -> (TBZ {ntz(c)} x yes no)
741 (NZ (ANDconst [c] x) yes no) && oneBit(c) -> (TBNZ {ntz(c)} x yes no)
742 (ZW (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBZ {ntz(int64(uint32(c)))} x yes no)
743 (NZW (ANDconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBNZ {ntz(int64(uint32(c)))} x yes no)
744 (EQ (TSTconst [c] x) yes no) && oneBit(c) -> (TBZ {ntz(c)} x yes no)
745 (NE (TSTconst [c] x) yes no) && oneBit(c) -> (TBNZ {ntz(c)} x yes no)
746 (EQ (TSTWconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBZ {ntz(int64(uint32(c)))} x yes no)
747 (NE (TSTWconst [c] x) yes no) && oneBit(int64(uint32(c))) -> (TBNZ {ntz(int64(uint32(c)))} x yes no)
748
749 // Test sign-bit for signed comparisons against zero
750 (GE (CMPWconst [0] x) yes no) -> (TBZ {int64(31)} x yes no)
751 (GE (CMPconst [0] x) yes no) -> (TBZ {int64(63)} x yes no)
752 (LT (CMPWconst [0] x) yes no) -> (TBNZ {int64(31)} x yes no)
753 (LT (CMPconst [0] x) yes no) -> (TBNZ {int64(63)} x yes no)
754
755 // fold offset into address
756 (ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr)
757
758 // fold address into load/store
759 (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
760 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
761 (MOVBload [off1+off2] {sym} ptr mem)
762 (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
763 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
764 (MOVBUload [off1+off2] {sym} ptr mem)
765 (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
766 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
767 (MOVHload [off1+off2] {sym} ptr mem)
768 (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
769 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
770 (MOVHUload [off1+off2] {sym} ptr mem)
771 (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
772 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
773 (MOVWload [off1+off2] {sym} ptr mem)
774 (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
775 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
776 (MOVWUload [off1+off2] {sym} ptr mem)
777 (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
778 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
779 (MOVDload [off1+off2] {sym} ptr mem)
780 (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
781 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
782 (FMOVSload [off1+off2] {sym} ptr mem)
783 (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
784 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
785 (FMOVDload [off1+off2] {sym} ptr mem)
786
787 // register indexed load
788 (MOVDload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVDloadidx ptr idx mem)
789 (MOVWUload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVWUloadidx ptr idx mem)
790 (MOVWload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVWloadidx ptr idx mem)
791 (MOVHUload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVHUloadidx ptr idx mem)
792 (MOVHload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVHloadidx ptr idx mem)
793 (MOVBUload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVBUloadidx ptr idx mem)
794 (MOVBload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVBloadidx ptr idx mem)
795 (FMOVSload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (FMOVSloadidx ptr idx mem)
796 (FMOVDload [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (FMOVDloadidx ptr idx mem)
797 (MOVDloadidx ptr (MOVDconst [c]) mem) -> (MOVDload [c] ptr mem)
798 (MOVDloadidx (MOVDconst [c]) ptr mem) -> (MOVDload [c] ptr mem)
799 (MOVWUloadidx ptr (MOVDconst [c]) mem) -> (MOVWUload [c] ptr mem)
800 (MOVWUloadidx (MOVDconst [c]) ptr mem) -> (MOVWUload [c] ptr mem)
801 (MOVWloadidx ptr (MOVDconst [c]) mem) -> (MOVWload [c] ptr mem)
802 (MOVWloadidx (MOVDconst [c]) ptr mem) -> (MOVWload [c] ptr mem)
803 (MOVHUloadidx ptr (MOVDconst [c]) mem) -> (MOVHUload [c] ptr mem)
804 (MOVHUloadidx (MOVDconst [c]) ptr mem) -> (MOVHUload [c] ptr mem)
805 (MOVHloadidx ptr (MOVDconst [c]) mem) -> (MOVHload [c] ptr mem)
806 (MOVHloadidx (MOVDconst [c]) ptr mem) -> (MOVHload [c] ptr mem)
807 (MOVBUloadidx ptr (MOVDconst [c]) mem) -> (MOVBUload [c] ptr mem)
808 (MOVBUloadidx (MOVDconst [c]) ptr mem) -> (MOVBUload [c] ptr mem)
809 (MOVBloadidx ptr (MOVDconst [c]) mem) -> (MOVBload [c] ptr mem)
810 (MOVBloadidx (MOVDconst [c]) ptr mem) -> (MOVBload [c] ptr mem)
811 (FMOVSloadidx ptr (MOVDconst [c]) mem) -> (FMOVSload [c] ptr mem)
812 (FMOVSloadidx (MOVDconst [c]) ptr mem) -> (FMOVSload [c] ptr mem)
813 (FMOVDloadidx ptr (MOVDconst [c]) mem) -> (FMOVDload [c] ptr mem)
814 (FMOVDloadidx (MOVDconst [c]) ptr mem) -> (FMOVDload [c] ptr mem)
815
816 // shifted register indexed load
817 (MOVDload [off] {sym} (ADDshiftLL [3] ptr idx) mem) && off == 0 && sym == nil -> (MOVDloadidx8 ptr idx mem)
818 (MOVWUload [off] {sym} (ADDshiftLL [2] ptr idx) mem) && off == 0 && sym == nil -> (MOVWUloadidx4 ptr idx mem)
819 (MOVWload [off] {sym} (ADDshiftLL [2] ptr idx) mem) && off == 0 && sym == nil -> (MOVWloadidx4 ptr idx mem)
820 (MOVHUload [off] {sym} (ADDshiftLL [1] ptr idx) mem) && off == 0 && sym == nil -> (MOVHUloadidx2 ptr idx mem)
821 (MOVHload [off] {sym} (ADDshiftLL [1] ptr idx) mem) && off == 0 && sym == nil -> (MOVHloadidx2 ptr idx mem)
822 (MOVDloadidx ptr (SLLconst [3] idx) mem) -> (MOVDloadidx8 ptr idx mem)
823 (MOVWloadidx ptr (SLLconst [2] idx) mem) -> (MOVWloadidx4 ptr idx mem)
824 (MOVWUloadidx ptr (SLLconst [2] idx) mem) -> (MOVWUloadidx4 ptr idx mem)
825 (MOVHloadidx ptr (SLLconst [1] idx) mem) -> (MOVHloadidx2 ptr idx mem)
826 (MOVHUloadidx ptr (SLLconst [1] idx) mem) -> (MOVHUloadidx2 ptr idx mem)
827 (MOVHloadidx ptr (ADD idx idx) mem) -> (MOVHloadidx2 ptr idx mem)
828 (MOVHUloadidx ptr (ADD idx idx) mem) -> (MOVHUloadidx2 ptr idx mem)
829 (MOVDloadidx (SLLconst [3] idx) ptr mem) -> (MOVDloadidx8 ptr idx mem)
830 (MOVWloadidx (SLLconst [2] idx) ptr mem) -> (MOVWloadidx4 ptr idx mem)
831 (MOVWUloadidx (SLLconst [2] idx) ptr mem) -> (MOVWUloadidx4 ptr idx mem)
832 (MOVHloadidx (ADD idx idx) ptr mem) -> (MOVHloadidx2 ptr idx mem)
833 (MOVHUloadidx (ADD idx idx) ptr mem) -> (MOVHUloadidx2 ptr idx mem)
834 (MOVDloadidx8 ptr (MOVDconst [c]) mem) -> (MOVDload [c<<3] ptr mem)
835 (MOVWUloadidx4 ptr (MOVDconst [c]) mem) -> (MOVWUload [c<<2] ptr mem)
836 (MOVWloadidx4 ptr (MOVDconst [c]) mem) -> (MOVWload [c<<2] ptr mem)
837 (MOVHUloadidx2 ptr (MOVDconst [c]) mem) -> (MOVHUload [c<<1] ptr mem)
838 (MOVHloadidx2 ptr (MOVDconst [c]) mem) -> (MOVHload [c<<1] ptr mem)
839
840 (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2)
841 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
842 (MOVBstore [off1+off2] {sym} ptr val mem)
843 (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2)
844 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
845 (MOVHstore [off1+off2] {sym} ptr val mem)
846 (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2)
847 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
848 (MOVWstore [off1+off2] {sym} ptr val mem)
849 (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2)
850 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
851 (MOVDstore [off1+off2] {sym} ptr val mem)
852 (STP [off1] {sym} (ADDconst [off2] ptr) val1 val2 mem) && is32Bit(off1+off2)
853 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
854 (STP [off1+off2] {sym} ptr val1 val2 mem)
855 (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2)
856 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
857 (FMOVSstore [off1+off2] {sym} ptr val mem)
858 (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2)
859 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
860 (FMOVDstore [off1+off2] {sym} ptr val mem)
861 (MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
862 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
863 (MOVBstorezero [off1+off2] {sym} ptr mem)
864 (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
865 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
866 (MOVHstorezero [off1+off2] {sym} ptr mem)
867 (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
868 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
869 (MOVWstorezero [off1+off2] {sym} ptr mem)
870 (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
871 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
872 (MOVDstorezero [off1+off2] {sym} ptr mem)
873 (MOVQstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2)
874 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
875 (MOVQstorezero [off1+off2] {sym} ptr mem)
876
877 // register indexed store
878 (MOVDstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil -> (MOVDstoreidx ptr idx val mem)
879 (MOVWstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil -> (MOVWstoreidx ptr idx val mem)
880 (MOVHstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil -> (MOVHstoreidx ptr idx val mem)
881 (MOVBstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil -> (MOVBstoreidx ptr idx val mem)
882 (FMOVDstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil -> (FMOVDstoreidx ptr idx val mem)
883 (FMOVSstore [off] {sym} (ADD ptr idx) val mem) && off == 0 && sym == nil -> (FMOVSstoreidx ptr idx val mem)
884 (MOVDstoreidx ptr (MOVDconst [c]) val mem) -> (MOVDstore [c] ptr val mem)
885 (MOVDstoreidx (MOVDconst [c]) idx val mem) -> (MOVDstore [c] idx val mem)
886 (MOVWstoreidx ptr (MOVDconst [c]) val mem) -> (MOVWstore [c] ptr val mem)
887 (MOVWstoreidx (MOVDconst [c]) idx val mem) -> (MOVWstore [c] idx val mem)
888 (MOVHstoreidx ptr (MOVDconst [c]) val mem) -> (MOVHstore [c] ptr val mem)
889 (MOVHstoreidx (MOVDconst [c]) idx val mem) -> (MOVHstore [c] idx val mem)
890 (MOVBstoreidx ptr (MOVDconst [c]) val mem) -> (MOVBstore [c] ptr val mem)
891 (MOVBstoreidx (MOVDconst [c]) idx val mem) -> (MOVBstore [c] idx val mem)
892 (FMOVDstoreidx ptr (MOVDconst [c]) val mem) -> (FMOVDstore [c] ptr val mem)
893 (FMOVDstoreidx (MOVDconst [c]) idx val mem) -> (FMOVDstore [c] idx val mem)
894 (FMOVSstoreidx ptr (MOVDconst [c]) val mem) -> (FMOVSstore [c] ptr val mem)
895 (FMOVSstoreidx (MOVDconst [c]) idx val mem) -> (FMOVSstore [c] idx val mem)
896
897 // shifted register indexed store
898 (MOVDstore [off] {sym} (ADDshiftLL [3] ptr idx) val mem) && off == 0 && sym == nil -> (MOVDstoreidx8 ptr idx val mem)
899 (MOVWstore [off] {sym} (ADDshiftLL [2] ptr idx) val mem) && off == 0 && sym == nil -> (MOVWstoreidx4 ptr idx val mem)
900 (MOVHstore [off] {sym} (ADDshiftLL [1] ptr idx) val mem) && off == 0 && sym == nil -> (MOVHstoreidx2 ptr idx val mem)
901 (MOVDstoreidx ptr (SLLconst [3] idx) val mem) -> (MOVDstoreidx8 ptr idx val mem)
902 (MOVWstoreidx ptr (SLLconst [2] idx) val mem) -> (MOVWstoreidx4 ptr idx val mem)
903 (MOVHstoreidx ptr (SLLconst [1] idx) val mem) -> (MOVHstoreidx2 ptr idx val mem)
904 (MOVHstoreidx ptr (ADD idx idx) val mem) -> (MOVHstoreidx2 ptr idx val mem)
905 (MOVDstoreidx (SLLconst [3] idx) ptr val mem) -> (MOVDstoreidx8 ptr idx val mem)
906 (MOVWstoreidx (SLLconst [2] idx) ptr val mem) -> (MOVWstoreidx4 ptr idx val mem)
907 (MOVHstoreidx (SLLconst [1] idx) ptr val mem) -> (MOVHstoreidx2 ptr idx val mem)
908 (MOVHstoreidx (ADD idx idx) ptr val mem) -> (MOVHstoreidx2 ptr idx val mem)
909 (MOVDstoreidx8 ptr (MOVDconst [c]) val mem) -> (MOVDstore [c<<3] ptr val mem)
910 (MOVWstoreidx4 ptr (MOVDconst [c]) val mem) -> (MOVWstore [c<<2] ptr val mem)
911 (MOVHstoreidx2 ptr (MOVDconst [c]) val mem) -> (MOVHstore [c<<1] ptr val mem)
912
913 (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
914 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
915 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
916 (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
917 (MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
918 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
919 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
920 (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
921 (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
922 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
923 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
924 (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
925 (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
926 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
927 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
928 (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
929 (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
930 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
931 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
932 (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
933 (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
934 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
935 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
936 (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
937 (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
938 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
939 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
940 (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
941 (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
942 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
943 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
944 (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
945 (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
946 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
947 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
948 (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
949
950 (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
951 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
952 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
953 (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
954 (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
955 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
956 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
957 (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
958 (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
959 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
960 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
961 (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
962 (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
963 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
964 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
965 (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
966 (STP [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val1 val2 mem)
967 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
968 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
969 (STP [off1+off2] {mergeSym(sym1,sym2)} ptr val1 val2 mem)
970 (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
971 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
972 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
973 (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
974 (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
975 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
976 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
977 (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
978 (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
979 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
980 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
981 (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
982 (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
983 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
984 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
985 (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
986 (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
987 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
988 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
989 (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
990 (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
991 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
992 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
993 (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
994 (MOVQstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
995 && canMergeSym(sym1,sym2) && is32Bit(off1+off2)
996 && (ptr.Op != OpSB || !config.ctxt.Flag_shared) ->
997 (MOVQstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
998
999 // store zero
1000 (MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem)
1001 (MOVHstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVHstorezero [off] {sym} ptr mem)
1002 (MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem)
1003 (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem)
1004 (STP [off] {sym} ptr (MOVDconst [0]) (MOVDconst [0]) mem) -> (MOVQstorezero [off] {sym} ptr mem)
1005
1006 // register indexed store zero
1007 (MOVDstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVDstorezeroidx ptr idx mem)
1008 (MOVWstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVWstorezeroidx ptr idx mem)
1009 (MOVHstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVHstorezeroidx ptr idx mem)
1010 (MOVBstorezero [off] {sym} (ADD ptr idx) mem) && off == 0 && sym == nil -> (MOVBstorezeroidx ptr idx mem)
1011 (MOVDstoreidx ptr idx (MOVDconst [0]) mem) -> (MOVDstorezeroidx ptr idx mem)
1012 (MOVWstoreidx ptr idx (MOVDconst [0]) mem) -> (MOVWstorezeroidx ptr idx mem)
1013 (MOVHstoreidx ptr idx (MOVDconst [0]) mem) -> (MOVHstorezeroidx ptr idx mem)
1014 (MOVBstoreidx ptr idx (MOVDconst [0]) mem) -> (MOVBstorezeroidx ptr idx mem)
1015 (MOVDstorezeroidx ptr (MOVDconst [c]) mem) -> (MOVDstorezero [c] ptr mem)
1016 (MOVDstorezeroidx (MOVDconst [c]) idx mem) -> (MOVDstorezero [c] idx mem)
1017 (MOVWstorezeroidx ptr (MOVDconst [c]) mem) -> (MOVWstorezero [c] ptr mem)
1018 (MOVWstorezeroidx (MOVDconst [c]) idx mem) -> (MOVWstorezero [c] idx mem)
1019 (MOVHstorezeroidx ptr (MOVDconst [c]) mem) -> (MOVHstorezero [c] ptr mem)
1020 (MOVHstorezeroidx (MOVDconst [c]) idx mem) -> (MOVHstorezero [c] idx mem)
1021 (MOVBstorezeroidx ptr (MOVDconst [c]) mem) -> (MOVBstorezero [c] ptr mem)
1022 (MOVBstorezeroidx (MOVDconst [c]) idx mem) -> (MOVBstorezero [c] idx mem)
1023
1024 // shifted register indexed store zero
1025 (MOVDstorezero [off] {sym} (ADDshiftLL [3] ptr idx) mem) && off == 0 && sym == nil -> (MOVDstorezeroidx8 ptr idx mem)
1026 (MOVWstorezero [off] {sym} (ADDshiftLL [2] ptr idx) mem) && off == 0 && sym == nil -> (MOVWstorezeroidx4 ptr idx mem)
1027 (MOVHstorezero [off] {sym} (ADDshiftLL [1] ptr idx) mem) && off == 0 && sym == nil -> (MOVHstorezeroidx2 ptr idx mem)
1028 (MOVDstorezeroidx ptr (SLLconst [3] idx) mem) -> (MOVDstorezeroidx8 ptr idx mem)
1029 (MOVWstorezeroidx ptr (SLLconst [2] idx) mem) -> (MOVWstorezeroidx4 ptr idx mem)
1030 (MOVHstorezeroidx ptr (SLLconst [1] idx) mem) -> (MOVHstorezeroidx2 ptr idx mem)
1031 (MOVHstorezeroidx ptr (ADD idx idx) mem) -> (MOVHstorezeroidx2 ptr idx mem)
1032 (MOVDstorezeroidx (SLLconst [3] idx) ptr mem) -> (MOVDstorezeroidx8 ptr idx mem)
1033 (MOVWstorezeroidx (SLLconst [2] idx) ptr mem) -> (MOVWstorezeroidx4 ptr idx mem)
1034 (MOVHstorezeroidx (SLLconst [1] idx) ptr mem) -> (MOVHstorezeroidx2 ptr idx mem)
1035 (MOVHstorezeroidx (ADD idx idx) ptr mem) -> (MOVHstorezeroidx2 ptr idx mem)
1036 (MOVDstoreidx8 ptr idx (MOVDconst [0]) mem) -> (MOVDstorezeroidx8 ptr idx mem)
1037 (MOVWstoreidx4 ptr idx (MOVDconst [0]) mem) -> (MOVWstorezeroidx4 ptr idx mem)
1038 (MOVHstoreidx2 ptr idx (MOVDconst [0]) mem) -> (MOVHstorezeroidx2 ptr idx mem)
1039 (MOVDstorezeroidx8 ptr (MOVDconst [c]) mem) -> (MOVDstorezero [c<<3] ptr mem)
1040 (MOVWstorezeroidx4 ptr (MOVDconst [c]) mem) -> (MOVWstorezero [c<<2] ptr mem)
1041 (MOVHstorezeroidx2 ptr (MOVDconst [c]) mem) -> (MOVHstorezero [c<<1] ptr mem)
1042
1043 // replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
1044 // these seem to have bad interaction with other rules, resulting in slower code
1045 //(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBreg x)
1046 //(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
1047 //(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHreg x)
1048 //(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
1049 //(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWreg x)
1050 //(MOVWUload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWUreg x)
1051 //(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
1052 //(FMOVSload [off] {sym} ptr (FMOVSstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
1053 //(FMOVDload [off] {sym} ptr (FMOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
1054
1055 (MOVBload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1056 (MOVBUload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1057 (MOVHload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1058 (MOVHUload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1059 (MOVWload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1060 (MOVWUload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1061 (MOVDload [off] {sym} ptr (MOVDstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0])
1062
1063 (MOVBloadidx ptr idx (MOVBstorezeroidx ptr2 idx2 _))
1064 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1065 (MOVBUloadidx ptr idx (MOVBstorezeroidx ptr2 idx2 _))
1066 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1067 (MOVHloadidx ptr idx (MOVHstorezeroidx ptr2 idx2 _))
1068 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1069 (MOVHUloadidx ptr idx (MOVHstorezeroidx ptr2 idx2 _))
1070 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1071 (MOVWloadidx ptr idx (MOVWstorezeroidx ptr2 idx2 _))
1072 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1073 (MOVWUloadidx ptr idx (MOVWstorezeroidx ptr2 idx2 _))
1074 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1075 (MOVDloadidx ptr idx (MOVDstorezeroidx ptr2 idx2 _))
1076 && (isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) || isSamePtr(ptr, idx2) && isSamePtr(idx, ptr2)) -> (MOVDconst [0])
1077
1078 (MOVHloadidx2 ptr idx (MOVHstorezeroidx2 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) -> (MOVDconst [0])
1079 (MOVHUloadidx2 ptr idx (MOVHstorezeroidx2 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) -> (MOVDconst [0])
1080 (MOVWloadidx4 ptr idx (MOVWstorezeroidx4 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) -> (MOVDconst [0])
1081 (MOVWUloadidx4 ptr idx (MOVWstorezeroidx4 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) -> (MOVDconst [0])
1082 (MOVDloadidx8 ptr idx (MOVDstorezeroidx8 ptr2 idx2 _)) && isSamePtr(ptr, ptr2) && isSamePtr(idx, idx2) -> (MOVDconst [0])
1083
1084 // don't extend after proper load
1085 (MOVBreg x:(MOVBload _ _)) -> (MOVDreg x)
1086 (MOVBUreg x:(MOVBUload _ _)) -> (MOVDreg x)
1087 (MOVHreg x:(MOVBload _ _)) -> (MOVDreg x)
1088 (MOVHreg x:(MOVBUload _ _)) -> (MOVDreg x)
1089 (MOVHreg x:(MOVHload _ _)) -> (MOVDreg x)
1090 (MOVHUreg x:(MOVBUload _ _)) -> (MOVDreg x)
1091 (MOVHUreg x:(MOVHUload _ _)) -> (MOVDreg x)
1092 (MOVWreg x:(MOVBload _ _)) -> (MOVDreg x)
1093 (MOVWreg x:(MOVBUload _ _)) -> (MOVDreg x)
1094 (MOVWreg x:(MOVHload _ _)) -> (MOVDreg x)
1095 (MOVWreg x:(MOVHUload _ _)) -> (MOVDreg x)
1096 (MOVWreg x:(MOVWload _ _)) -> (MOVDreg x)
1097 (MOVWUreg x:(MOVBUload _ _)) -> (MOVDreg x)
1098 (MOVWUreg x:(MOVHUload _ _)) -> (MOVDreg x)
1099 (MOVWUreg x:(MOVWUload _ _)) -> (MOVDreg x)
1100 (MOVBreg x:(MOVBloadidx _ _ _)) -> (MOVDreg x)
1101 (MOVBUreg x:(MOVBUloadidx _ _ _)) -> (MOVDreg x)
1102 (MOVHreg x:(MOVBloadidx _ _ _)) -> (MOVDreg x)
1103 (MOVHreg x:(MOVBUloadidx _ _ _)) -> (MOVDreg x)
1104 (MOVHreg x:(MOVHloadidx _ _ _)) -> (MOVDreg x)
1105 (MOVHUreg x:(MOVBUloadidx _ _ _)) -> (MOVDreg x)
1106 (MOVHUreg x:(MOVHUloadidx _ _ _)) -> (MOVDreg x)
1107 (MOVWreg x:(MOVBloadidx _ _ _)) -> (MOVDreg x)
1108 (MOVWreg x:(MOVBUloadidx _ _ _)) -> (MOVDreg x)
1109 (MOVWreg x:(MOVHloadidx _ _ _)) -> (MOVDreg x)
1110 (MOVWreg x:(MOVHUloadidx _ _ _)) -> (MOVDreg x)
1111 (MOVWreg x:(MOVWloadidx _ _ _)) -> (MOVDreg x)
1112 (MOVWUreg x:(MOVBUloadidx _ _ _)) -> (MOVDreg x)
1113 (MOVWUreg x:(MOVHUloadidx _ _ _)) -> (MOVDreg x)
1114 (MOVWUreg x:(MOVWUloadidx _ _ _)) -> (MOVDreg x)
1115 (MOVHreg x:(MOVHloadidx2 _ _ _)) -> (MOVDreg x)
1116 (MOVHUreg x:(MOVHUloadidx2 _ _ _)) -> (MOVDreg x)
1117 (MOVWreg x:(MOVHloadidx2 _ _ _)) -> (MOVDreg x)
1118 (MOVWreg x:(MOVHUloadidx2 _ _ _)) -> (MOVDreg x)
1119 (MOVWreg x:(MOVWloadidx4 _ _ _)) -> (MOVDreg x)
1120 (MOVWUreg x:(MOVHUloadidx2 _ _ _)) -> (MOVDreg x)
1121 (MOVWUreg x:(MOVWUloadidx4 _ _ _)) -> (MOVDreg x)
1122
1123 // fold double extensions
1124 (MOVBreg x:(MOVBreg _)) -> (MOVDreg x)
1125 (MOVBUreg x:(MOVBUreg _)) -> (MOVDreg x)
1126 (MOVHreg x:(MOVBreg _)) -> (MOVDreg x)
1127 (MOVHreg x:(MOVBUreg _)) -> (MOVDreg x)
1128 (MOVHreg x:(MOVHreg _)) -> (MOVDreg x)
1129 (MOVHUreg x:(MOVBUreg _)) -> (MOVDreg x)
1130 (MOVHUreg x:(MOVHUreg _)) -> (MOVDreg x)
1131 (MOVWreg x:(MOVBreg _)) -> (MOVDreg x)
1132 (MOVWreg x:(MOVBUreg _)) -> (MOVDreg x)
1133 (MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
1134 (MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
1135 (MOVWreg x:(MOVWreg _)) -> (MOVDreg x)
1136 (MOVWUreg x:(MOVBUreg _)) -> (MOVDreg x)
1137 (MOVWUreg x:(MOVHUreg _)) -> (MOVDreg x)
1138 (MOVWUreg x:(MOVWUreg _)) -> (MOVDreg x)
1139
1140 // don't extend before store
1141 (MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
1142 (MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
1143 (MOVBstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
1144 (MOVBstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
1145 (MOVBstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
1146 (MOVBstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
1147 (MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
1148 (MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
1149 (MOVHstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
1150 (MOVHstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
1151 (MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
1152 (MOVWstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
1153 (MOVBstoreidx ptr idx (MOVBreg x) mem) -> (MOVBstoreidx ptr idx x mem)
1154 (MOVBstoreidx ptr idx (MOVBUreg x) mem) -> (MOVBstoreidx ptr idx x mem)
1155 (MOVBstoreidx ptr idx (MOVHreg x) mem) -> (MOVBstoreidx ptr idx x mem)
1156 (MOVBstoreidx ptr idx (MOVHUreg x) mem) -> (MOVBstoreidx ptr idx x mem)
1157 (MOVBstoreidx ptr idx (MOVWreg x) mem) -> (MOVBstoreidx ptr idx x mem)
1158 (MOVBstoreidx ptr idx (MOVWUreg x) mem) -> (MOVBstoreidx ptr idx x mem)
1159 (MOVHstoreidx ptr idx (MOVHreg x) mem) -> (MOVHstoreidx ptr idx x mem)
1160 (MOVHstoreidx ptr idx (MOVHUreg x) mem) -> (MOVHstoreidx ptr idx x mem)
1161 (MOVHstoreidx ptr idx (MOVWreg x) mem) -> (MOVHstoreidx ptr idx x mem)
1162 (MOVHstoreidx ptr idx (MOVWUreg x) mem) -> (MOVHstoreidx ptr idx x mem)
1163 (MOVWstoreidx ptr idx (MOVWreg x) mem) -> (MOVWstoreidx ptr idx x mem)
1164 (MOVWstoreidx ptr idx (MOVWUreg x) mem) -> (MOVWstoreidx ptr idx x mem)
1165 (MOVHstoreidx2 ptr idx (MOVHreg x) mem) -> (MOVHstoreidx2 ptr idx x mem)
1166 (MOVHstoreidx2 ptr idx (MOVHUreg x) mem) -> (MOVHstoreidx2 ptr idx x mem)
1167 (MOVHstoreidx2 ptr idx (MOVWreg x) mem) -> (MOVHstoreidx2 ptr idx x mem)
1168 (MOVHstoreidx2 ptr idx (MOVWUreg x) mem) -> (MOVHstoreidx2 ptr idx x mem)
1169 (MOVWstoreidx4 ptr idx (MOVWreg x) mem) -> (MOVWstoreidx4 ptr idx x mem)
1170 (MOVWstoreidx4 ptr idx (MOVWUreg x) mem) -> (MOVWstoreidx4 ptr idx x mem)
1171
1172 // if a register move has only 1 use, just use the same register without emitting instruction
1173 // MOVDnop doesn't emit instruction, only for ensuring the type.
1174 (MOVDreg x) && x.Uses == 1 -> (MOVDnop x)
1175
1176 // fold constant into arithmatic ops
1177 (ADD x (MOVDconst [c])) -> (ADDconst [c] x)
1178 (SUB x (MOVDconst [c])) -> (SUBconst [c] x)
1179 (AND x (MOVDconst [c])) -> (ANDconst [c] x)
1180 (OR x (MOVDconst [c])) -> (ORconst [c] x)
1181 (XOR x (MOVDconst [c])) -> (XORconst [c] x)
1182 (TST x (MOVDconst [c])) -> (TSTconst [c] x)
1183 (TSTW x (MOVDconst [c])) -> (TSTWconst [c] x)
1184 (CMN x (MOVDconst [c])) -> (CMNconst [c] x)
1185 (CMNW x (MOVDconst [c])) -> (CMNWconst [c] x)
1186 (BIC x (MOVDconst [c])) -> (ANDconst [^c] x)
1187 (EON x (MOVDconst [c])) -> (XORconst [^c] x)
1188 (ORN x (MOVDconst [c])) -> (ORconst [^c] x)
1189
1190 (SLL x (MOVDconst [c])) -> (SLLconst x [c&63]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=64)
1191 (SRL x (MOVDconst [c])) -> (SRLconst x [c&63])
1192 (SRA x (MOVDconst [c])) -> (SRAconst x [c&63])
1193
1194 (CMP x (MOVDconst [c])) -> (CMPconst [c] x)
1195 (CMP (MOVDconst [c]) x) -> (InvertFlags (CMPconst [c] x))
1196 (CMPW x (MOVDconst [c])) -> (CMPWconst [int64(int32(c))] x)
1197 (CMPW (MOVDconst [c]) x) -> (InvertFlags (CMPWconst [int64(int32(c))] x))
1198
1199 // mul-neg -> mneg
1200 (NEG (MUL x y)) -> (MNEG x y)
1201 (NEG (MULW x y)) -> (MNEGW x y)
1202 (MUL (NEG x) y) -> (MNEG x y)
1203 (MULW (NEG x) y) -> (MNEGW x y)
1204
1205 // madd/msub
1206 (ADD a l:(MUL x y)) && l.Uses==1 && clobber(l) -> (MADD a x y)
1207 (SUB a l:(MUL x y)) && l.Uses==1 && clobber(l) -> (MSUB a x y)
1208 (ADD a l:(MNEG x y)) && l.Uses==1 && clobber(l) -> (MSUB a x y)
1209 (SUB a l:(MNEG x y)) && l.Uses==1 && clobber(l) -> (MADD a x y)
1210
1211 (ADD a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MADDW a x y)
1212 (SUB a l:(MULW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MSUBW a x y)
1213 (ADD a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MSUBW a x y)
1214 (SUB a l:(MNEGW x y)) && a.Type.Size() != 8 && l.Uses==1 && clobber(l) -> (MADDW a x y)
1215
1216 // optimize ADCSflags, SBCSflags and friends
1217 (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (ADCzerocarry <typ.UInt64> c)))) -> (ADCSflags x y c)
1218 (ADCSflags x y (Select1 <types.TypeFlags> (ADDSconstflags [-1] (MOVDconst [0])))) -> (ADDSflags x y)
1219 (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags (NEG <typ.UInt64> (NGCzerocarry <typ.UInt64> bo))))) -> (SBCSflags x y bo)
1220 (SBCSflags x y (Select1 <types.TypeFlags> (NEGSflags (MOVDconst [0])))) -> (SUBSflags x y)
1221
1222 // mul by constant
1223 (MUL x (MOVDconst [-1])) -> (NEG x)
1224 (MUL _ (MOVDconst [0])) -> (MOVDconst [0])
1225 (MUL x (MOVDconst [1])) -> x
1226 (MUL x (MOVDconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
1227 (MUL x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 -> (ADDshiftLL x x [log2(c-1)])
1228 (MUL x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 -> (ADDshiftLL (NEG <x.Type> x) x [log2(c+1)])
1229 (MUL x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
1230 (MUL x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
1231 (MUL x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SLLconst [log2(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3]))
1232 (MUL x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
1233
1234 (MULW x (MOVDconst [c])) && int32(c)==-1 -> (NEG x)
1235 (MULW _ (MOVDconst [c])) && int32(c)==0 -> (MOVDconst [0])
1236 (MULW x (MOVDconst [c])) && int32(c)==1 -> x
1237 (MULW x (MOVDconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
1238 (MULW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)])
1239 (MULW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADDshiftLL (NEG <x.Type> x) x [log2(c+1)])
1240 (MULW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
1241 (MULW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
1242 (MULW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3]))
1243 (MULW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
1244
1245 // mneg by constant
1246 (MNEG x (MOVDconst [-1])) -> x
1247 (MNEG _ (MOVDconst [0])) -> (MOVDconst [0])
1248 (MNEG x (MOVDconst [1])) -> (NEG x)
1249 (MNEG x (MOVDconst [c])) && isPowerOfTwo(c) -> (NEG (SLLconst <x.Type> [log2(c)] x))
1250 (MNEG x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 -> (NEG (ADDshiftLL <x.Type> x x [log2(c-1)]))
1251 (MNEG x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 -> (NEG (ADDshiftLL <x.Type> (NEG <x.Type> x) x [log2(c+1)]))
1252 (MNEG x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SLLconst <x.Type> [log2(c/3)] (SUBshiftLL <x.Type> x x [2]))
1253 (MNEG x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (NEG (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])))
1254 (MNEG x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SLLconst <x.Type> [log2(c/7)] (SUBshiftLL <x.Type> x x [3]))
1255 (MNEG x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (NEG (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])))
1256
1257 (MNEGW x (MOVDconst [c])) && int32(c)==-1 -> x
1258 (MNEGW _ (MOVDconst [c])) && int32(c)==0 -> (MOVDconst [0])
1259 (MNEGW x (MOVDconst [c])) && int32(c)==1 -> (NEG x)
1260 (MNEGW x (MOVDconst [c])) && isPowerOfTwo(c) -> (NEG (SLLconst <x.Type> [log2(c)] x))
1261 (MNEGW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (NEG (ADDshiftLL <x.Type> x x [log2(c-1)]))
1262 (MNEGW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (NEG (ADDshiftLL <x.Type> (NEG <x.Type> x) x [log2(c+1)]))
1263 (MNEGW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst <x.Type> [log2(c/3)] (SUBshiftLL <x.Type> x x [2]))
1264 (MNEGW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (NEG (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])))
1265 (MNEGW x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst <x.Type> [log2(c/7)] (SUBshiftLL <x.Type> x x [3]))
1266 (MNEGW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (NEG (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])))
1267
1268 (MADD a x (MOVDconst [-1])) -> (SUB a x)
1269 (MADD a _ (MOVDconst [0])) -> a
1270 (MADD a x (MOVDconst [1])) -> (ADD a x)
1271 (MADD a x (MOVDconst [c])) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
1272 (MADD a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1273 (MADD a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1274 (MADD a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1275 (MADD a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1276 (MADD a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1277 (MADD a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1278
1279 (MADD a (MOVDconst [-1]) x) -> (SUB a x)
1280 (MADD a (MOVDconst [0]) _) -> a
1281 (MADD a (MOVDconst [1]) x) -> (ADD a x)
1282 (MADD a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
1283 (MADD a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1284 (MADD a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1285 (MADD a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1286 (MADD a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1287 (MADD a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1288 (MADD a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1289
1290 (MADDW a x (MOVDconst [c])) && int32(c)==-1 -> (SUB a x)
1291 (MADDW a _ (MOVDconst [c])) && int32(c)==0 -> a
1292 (MADDW a x (MOVDconst [c])) && int32(c)==1 -> (ADD a x)
1293 (MADDW a x (MOVDconst [c])) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
1294 (MADDW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1295 (MADDW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1296 (MADDW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1297 (MADDW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1298 (MADDW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1299 (MADDW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1300
1301 (MADDW a (MOVDconst [c]) x) && int32(c)==-1 -> (SUB a x)
1302 (MADDW a (MOVDconst [c]) _) && int32(c)==0 -> a
1303 (MADDW a (MOVDconst [c]) x) && int32(c)==1 -> (ADD a x)
1304 (MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (ADDshiftLL a x [log2(c)])
1305 (MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 -> (ADD a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1306 (MADDW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 -> (SUB a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1307 (MADDW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1308 (MADDW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1309 (MADDW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SUBshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1310 (MADDW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADDshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1311
1312 (MSUB a x (MOVDconst [-1])) -> (ADD a x)
1313 (MSUB a _ (MOVDconst [0])) -> a
1314 (MSUB a x (MOVDconst [1])) -> (SUB a x)
1315 (MSUB a x (MOVDconst [c])) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
1316 (MSUB a x (MOVDconst [c])) && isPowerOfTwo(c-1) && c>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1317 (MSUB a x (MOVDconst [c])) && isPowerOfTwo(c+1) && c>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1318 (MSUB a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1319 (MSUB a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1320 (MSUB a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1321 (MSUB a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1322
1323 (MSUB a (MOVDconst [-1]) x) -> (ADD a x)
1324 (MSUB a (MOVDconst [0]) _) -> a
1325 (MSUB a (MOVDconst [1]) x) -> (SUB a x)
1326 (MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
1327 (MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1328 (MSUB a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1329 (MSUB a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1330 (MSUB a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1331 (MSUB a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1332 (MSUB a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1333
1334 (MSUBW a x (MOVDconst [c])) && int32(c)==-1 -> (ADD a x)
1335 (MSUBW a _ (MOVDconst [c])) && int32(c)==0 -> a
1336 (MSUBW a x (MOVDconst [c])) && int32(c)==1 -> (SUB a x)
1337 (MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
1338 (MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c)>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1339 (MSUBW a x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c)>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1340 (MSUBW a x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1341 (MSUBW a x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1342 (MSUBW a x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1343 (MSUBW a x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1344
1345 (MSUBW a (MOVDconst [c]) x) && int32(c)==-1 -> (ADD a x)
1346 (MSUBW a (MOVDconst [c]) _) && int32(c)==0 -> a
1347 (MSUBW a (MOVDconst [c]) x) && int32(c)==1 -> (SUB a x)
1348 (MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SUBshiftLL a x [log2(c)])
1349 (MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c)>=3 -> (SUB a (ADDshiftLL <x.Type> x x [log2(c-1)]))
1350 (MSUBW a (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c)>=7 -> (ADD a (SUBshiftLL <x.Type> x x [log2(c+1)]))
1351 (MSUBW a (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [2]) [log2(c/3)])
1352 (MSUBW a (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [2]) [log2(c/5)])
1353 (MSUBW a (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADDshiftLL a (SUBshiftLL <x.Type> x x [3]) [log2(c/7)])
1354 (MSUBW a (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SUBshiftLL a (ADDshiftLL <x.Type> x x [3]) [log2(c/9)])
1355
1356 // div by constant
1357 (UDIV x (MOVDconst [1])) -> x
1358 (UDIV x (MOVDconst [c])) && isPowerOfTwo(c) -> (SRLconst [log2(c)] x)
1359 (UDIVW x (MOVDconst [c])) && uint32(c)==1 -> x
1360 (UDIVW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) -> (SRLconst [log2(c)] x)
1361 (UMOD _ (MOVDconst [1])) -> (MOVDconst [0])
1362 (UMOD x (MOVDconst [c])) && isPowerOfTwo(c) -> (ANDconst [c-1] x)
1363 (UMODW _ (MOVDconst [c])) && uint32(c)==1 -> (MOVDconst [0])
1364 (UMODW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) -> (ANDconst [c-1] x)
1365
1366 // generic simplifications
1367 (ADD x (NEG y)) -> (SUB x y)
1368 (SUB x x) -> (MOVDconst [0])
1369 (AND x x) -> x
1370 (OR x x) -> x
1371 (XOR x x) -> (MOVDconst [0])
1372 (BIC x x) -> (MOVDconst [0])
1373 (EON x x) -> (MOVDconst [-1])
1374 (ORN x x) -> (MOVDconst [-1])
1375 (AND x (MVN y)) -> (BIC x y)
1376 (XOR x (MVN y)) -> (EON x y)
1377 (OR x (MVN y)) -> (ORN x y)
1378 (CSEL {cc} x (MOVDconst [0]) flag) -> (CSEL0 {cc} x flag)
1379 (CSEL {cc} (MOVDconst [0]) y flag) -> (CSEL0 {arm64Negate(cc.(Op))} y flag)
1380 (SUB x (SUB y z)) -> (SUB (ADD <v.Type> x z) y)
1381 (SUB (SUB x y) z) -> (SUB x (ADD <y.Type> y z))
1382
1383 // remove redundant *const ops
1384 (ADDconst [0] x) -> x
1385 (SUBconst [0] x) -> x
1386 (ANDconst [0] _) -> (MOVDconst [0])
1387 (ANDconst [-1] x) -> x
1388 (ORconst [0] x) -> x
1389 (ORconst [-1] _) -> (MOVDconst [-1])
1390 (XORconst [0] x) -> x
1391 (XORconst [-1] x) -> (MVN x)
1392
1393 // generic constant folding
1394 (ADDconst [c] (MOVDconst [d])) -> (MOVDconst [c+d])
1395 (ADDconst [c] (ADDconst [d] x)) -> (ADDconst [c+d] x)
1396 (ADDconst [c] (SUBconst [d] x)) -> (ADDconst [c-d] x)
1397 (SUBconst [c] (MOVDconst [d])) -> (MOVDconst [d-c])
1398 (SUBconst [c] (SUBconst [d] x)) -> (ADDconst [-c-d] x)
1399 (SUBconst [c] (ADDconst [d] x)) -> (ADDconst [-c+d] x)
1400 (SLLconst [c] (MOVDconst [d])) -> (MOVDconst [d<<uint64(c)])
1401 (SRLconst [c] (MOVDconst [d])) -> (MOVDconst [int64(uint64(d)>>uint64(c))])
1402 (SRAconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)])
1403 (MUL (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c*d])
1404 (MULW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)*int32(d))])
1405 (MNEG (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [-c*d])
1406 (MNEGW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [-int64(int32(c)*int32(d))])
1407 (MADD (MOVDconst [c]) x y) -> (ADDconst [c] (MUL <x.Type> x y))
1408 (MADDW (MOVDconst [c]) x y) -> (ADDconst [c] (MULW <x.Type> x y))
1409 (MSUB (MOVDconst [c]) x y) -> (ADDconst [c] (MNEG <x.Type> x y))
1410 (MSUBW (MOVDconst [c]) x y) -> (ADDconst [c] (MNEGW <x.Type> x y))
1411 (MADD a (MOVDconst [c]) (MOVDconst [d])) -> (ADDconst [c*d] a)
1412 (MADDW a (MOVDconst [c]) (MOVDconst [d])) -> (ADDconst [int64(int32(c)*int32(d))] a)
1413 (MSUB a (MOVDconst [c]) (MOVDconst [d])) -> (SUBconst [c*d] a)
1414 (MSUBW a (MOVDconst [c]) (MOVDconst [d])) -> (SUBconst [int64(int32(c)*int32(d))] a)
1415 (DIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c/d])
1416 (UDIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)/uint64(d))])
1417 (DIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)/int32(d))])
1418 (UDIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint32(c)/uint32(d))])
1419 (MOD (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c%d])
1420 (UMOD (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)%uint64(d))])
1421 (MODW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)%int32(d))])
1422 (UMODW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint32(c)%uint32(d))])
1423 (ANDconst [c] (MOVDconst [d])) -> (MOVDconst [c&d])
1424 (ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
1425 (ANDconst [c] (MOVWUreg x)) -> (ANDconst [c&(1<<32-1)] x)
1426 (ANDconst [c] (MOVHUreg x)) -> (ANDconst [c&(1<<16-1)] x)
1427 (ANDconst [c] (MOVBUreg x)) -> (ANDconst [c&(1<<8-1)] x)
1428 (MOVWUreg (ANDconst [c] x)) -> (ANDconst [c&(1<<32-1)] x)
1429 (MOVHUreg (ANDconst [c] x)) -> (ANDconst [c&(1<<16-1)] x)
1430 (MOVBUreg (ANDconst [c] x)) -> (ANDconst [c&(1<<8-1)] x)
1431 (ORconst [c] (MOVDconst [d])) -> (MOVDconst [c|d])
1432 (ORconst [c] (ORconst [d] x)) -> (ORconst [c|d] x)
1433 (XORconst [c] (MOVDconst [d])) -> (MOVDconst [c^d])
1434 (XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
1435 (MVN (MOVDconst [c])) -> (MOVDconst [^c])
1436 (NEG (MOVDconst [c])) -> (MOVDconst [-c])
1437 (MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))])
1438 (MOVBUreg (MOVDconst [c])) -> (MOVDconst [int64(uint8(c))])
1439 (MOVHreg (MOVDconst [c])) -> (MOVDconst [int64(int16(c))])
1440 (MOVHUreg (MOVDconst [c])) -> (MOVDconst [int64(uint16(c))])
1441 (MOVWreg (MOVDconst [c])) -> (MOVDconst [int64(int32(c))])
1442 (MOVWUreg (MOVDconst [c])) -> (MOVDconst [int64(uint32(c))])
1443 (MOVDreg (MOVDconst [c])) -> (MOVDconst [c])
1444
1445 // constant comparisons
1446 (CMPconst (MOVDconst [x]) [y]) && x==y -> (FlagEQ)
1447 (CMPconst (MOVDconst [x]) [y]) && x<y && uint64(x)<uint64(y) -> (FlagLT_ULT)
1448 (CMPconst (MOVDconst [x]) [y]) && x<y && uint64(x)>uint64(y) -> (FlagLT_UGT)
1449 (CMPconst (MOVDconst [x]) [y]) && x>y && uint64(x)<uint64(y) -> (FlagGT_ULT)
1450 (CMPconst (MOVDconst [x]) [y]) && x>y && uint64(x)>uint64(y) -> (FlagGT_UGT)
1451 (CMPWconst (MOVDconst [x]) [y]) && int32(x)==int32(y) -> (FlagEQ)
1452 (CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y) && uint32(x)<uint32(y) -> (FlagLT_ULT)
1453 (CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y) && uint32(x)>uint32(y) -> (FlagLT_UGT)
1454 (CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y) && uint32(x)<uint32(y) -> (FlagGT_ULT)
1455 (CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y) && uint32(x)>uint32(y) -> (FlagGT_UGT)
1456 (TSTconst (MOVDconst [x]) [y]) && int64(x&y)==0 -> (FlagEQ)
1457 (TSTconst (MOVDconst [x]) [y]) && int64(x&y)<0 -> (FlagLT_UGT)
1458 (TSTconst (MOVDconst [x]) [y]) && int64(x&y)>0 -> (FlagGT_UGT)
1459 (TSTWconst (MOVDconst [x]) [y]) && int32(x&y)==0 -> (FlagEQ)
1460 (TSTWconst (MOVDconst [x]) [y]) && int32(x&y)<0 -> (FlagLT_UGT)
1461 (TSTWconst (MOVDconst [x]) [y]) && int32(x&y)>0 -> (FlagGT_UGT)
1462 (CMNconst (MOVDconst [x]) [y]) && int64(x)==int64(-y) -> (FlagEQ)
1463 (CMNconst (MOVDconst [x]) [y]) && int64(x)<int64(-y) && uint64(x)<uint64(-y) -> (FlagLT_ULT)
1464 (CMNconst (MOVDconst [x]) [y]) && int64(x)<int64(-y) && uint64(x)>uint64(-y) -> (FlagLT_UGT)
1465 (CMNconst (MOVDconst [x]) [y]) && int64(x)>int64(-y) && uint64(x)<uint64(-y) -> (FlagGT_ULT)
1466 (CMNconst (MOVDconst [x]) [y]) && int64(x)>int64(-y) && uint64(x)>uint64(-y) -> (FlagGT_UGT)
1467 (CMNWconst (MOVDconst [x]) [y]) && int32(x)==int32(-y) -> (FlagEQ)
1468 (CMNWconst (MOVDconst [x]) [y]) && int32(x)<int32(-y) && uint32(x)<uint32(-y) -> (FlagLT_ULT)
1469 (CMNWconst (MOVDconst [x]) [y]) && int32(x)<int32(-y) && uint32(x)>uint32(-y) -> (FlagLT_UGT)
1470 (CMNWconst (MOVDconst [x]) [y]) && int32(x)>int32(-y) && uint32(x)<uint32(-y) -> (FlagGT_ULT)
1471 (CMNWconst (MOVDconst [x]) [y]) && int32(x)>int32(-y) && uint32(x)>uint32(-y) -> (FlagGT_UGT)
1472
1473
1474 // other known comparisons
1475 (CMPconst (MOVBUreg _) [c]) && 0xff < c -> (FlagLT_ULT)
1476 (CMPconst (MOVHUreg _) [c]) && 0xffff < c -> (FlagLT_ULT)
1477 (CMPconst (MOVWUreg _) [c]) && 0xffffffff < c -> (FlagLT_ULT)
1478 (CMPconst (ANDconst _ [m]) [n]) && 0 <= m && m < n -> (FlagLT_ULT)
1479 (CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 63 && (1<<uint64(64-c)) <= uint64(n) -> (FlagLT_ULT)
1480 (CMPWconst (MOVBUreg _) [c]) && 0xff < int32(c) -> (FlagLT_ULT)
1481 (CMPWconst (MOVHUreg _) [c]) && 0xffff < int32(c) -> (FlagLT_ULT)
1482
1483 // absorb flag constants into branches
1484 (EQ (FlagEQ) yes no) -> (First nil yes no)
1485 (EQ (FlagLT_ULT) yes no) -> (First nil no yes)
1486 (EQ (FlagLT_UGT) yes no) -> (First nil no yes)
1487 (EQ (FlagGT_ULT) yes no) -> (First nil no yes)
1488 (EQ (FlagGT_UGT) yes no) -> (First nil no yes)
1489
1490 (NE (FlagEQ) yes no) -> (First nil no yes)
1491 (NE (FlagLT_ULT) yes no) -> (First nil yes no)
1492 (NE (FlagLT_UGT) yes no) -> (First nil yes no)
1493 (NE (FlagGT_ULT) yes no) -> (First nil yes no)
1494 (NE (FlagGT_UGT) yes no) -> (First nil yes no)
1495
1496 (LT (FlagEQ) yes no) -> (First nil no yes)
1497 (LT (FlagLT_ULT) yes no) -> (First nil yes no)
1498 (LT (FlagLT_UGT) yes no) -> (First nil yes no)
1499 (LT (FlagGT_ULT) yes no) -> (First nil no yes)
1500 (LT (FlagGT_UGT) yes no) -> (First nil no yes)
1501
1502 (LE (FlagEQ) yes no) -> (First nil yes no)
1503 (LE (FlagLT_ULT) yes no) -> (First nil yes no)
1504 (LE (FlagLT_UGT) yes no) -> (First nil yes no)
1505 (LE (FlagGT_ULT) yes no) -> (First nil no yes)
1506 (LE (FlagGT_UGT) yes no) -> (First nil no yes)
1507
1508 (GT (FlagEQ) yes no) -> (First nil no yes)
1509 (GT (FlagLT_ULT) yes no) -> (First nil no yes)
1510 (GT (FlagLT_UGT) yes no) -> (First nil no yes)
1511 (GT (FlagGT_ULT) yes no) -> (First nil yes no)
1512 (GT (FlagGT_UGT) yes no) -> (First nil yes no)
1513
1514 (GE (FlagEQ) yes no) -> (First nil yes no)
1515 (GE (FlagLT_ULT) yes no) -> (First nil no yes)
1516 (GE (FlagLT_UGT) yes no) -> (First nil no yes)
1517 (GE (FlagGT_ULT) yes no) -> (First nil yes no)
1518 (GE (FlagGT_UGT) yes no) -> (First nil yes no)
1519
1520 (ULT (FlagEQ) yes no) -> (First nil no yes)
1521 (ULT (FlagLT_ULT) yes no) -> (First nil yes no)
1522 (ULT (FlagLT_UGT) yes no) -> (First nil no yes)
1523 (ULT (FlagGT_ULT) yes no) -> (First nil yes no)
1524 (ULT (FlagGT_UGT) yes no) -> (First nil no yes)
1525
1526 (ULE (FlagEQ) yes no) -> (First nil yes no)
1527 (ULE (FlagLT_ULT) yes no) -> (First nil yes no)
1528 (ULE (FlagLT_UGT) yes no) -> (First nil no yes)
1529 (ULE (FlagGT_ULT) yes no) -> (First nil yes no)
1530 (ULE (FlagGT_UGT) yes no) -> (First nil no yes)
1531
1532 (UGT (FlagEQ) yes no) -> (First nil no yes)
1533 (UGT (FlagLT_ULT) yes no) -> (First nil no yes)
1534 (UGT (FlagLT_UGT) yes no) -> (First nil yes no)
1535 (UGT (FlagGT_ULT) yes no) -> (First nil no yes)
1536 (UGT (FlagGT_UGT) yes no) -> (First nil yes no)
1537
1538 (UGE (FlagEQ) yes no) -> (First nil yes no)
1539 (UGE (FlagLT_ULT) yes no) -> (First nil no yes)
1540 (UGE (FlagLT_UGT) yes no) -> (First nil yes no)
1541 (UGE (FlagGT_ULT) yes no) -> (First nil no yes)
1542 (UGE (FlagGT_UGT) yes no) -> (First nil yes no)
1543
1544 (Z (MOVDconst [0]) yes no) -> (First nil yes no)
1545 (Z (MOVDconst [c]) yes no) && c != 0 -> (First nil no yes)
1546 (NZ (MOVDconst [0]) yes no) -> (First nil no yes)
1547 (NZ (MOVDconst [c]) yes no) && c != 0 -> (First nil yes no)
1548 (ZW (MOVDconst [c]) yes no) && int32(c) == 0 -> (First nil yes no)
1549 (ZW (MOVDconst [c]) yes no) && int32(c) != 0 -> (First nil no yes)
1550 (NZW (MOVDconst [c]) yes no) && int32(c) == 0 -> (First nil no yes)
1551 (NZW (MOVDconst [c]) yes no) && int32(c) != 0 -> (First nil yes no)
1552
1553 // absorb InvertFlags into branches
1554 (LT (InvertFlags cmp) yes no) -> (GT cmp yes no)
1555 (GT (InvertFlags cmp) yes no) -> (LT cmp yes no)
1556 (LE (InvertFlags cmp) yes no) -> (GE cmp yes no)
1557 (GE (InvertFlags cmp) yes no) -> (LE cmp yes no)
1558 (ULT (InvertFlags cmp) yes no) -> (UGT cmp yes no)
1559 (UGT (InvertFlags cmp) yes no) -> (ULT cmp yes no)
1560 (ULE (InvertFlags cmp) yes no) -> (UGE cmp yes no)
1561 (UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no)
1562 (EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no)
1563 (NE (InvertFlags cmp) yes no) -> (NE cmp yes no)
1564 (FLT (InvertFlags cmp) yes no) -> (FGT cmp yes no)
1565 (FGT (InvertFlags cmp) yes no) -> (FLT cmp yes no)
1566 (FLE (InvertFlags cmp) yes no) -> (FGE cmp yes no)
1567 (FGE (InvertFlags cmp) yes no) -> (FLE cmp yes no)
1568
1569 // absorb InvertFlags into CSEL(0)
1570 (CSEL {cc} x y (InvertFlags cmp)) -> (CSEL {arm64Invert(cc.(Op))} x y cmp)
1571 (CSEL0 {cc} x (InvertFlags cmp)) -> (CSEL0 {arm64Invert(cc.(Op))} x cmp)
1572
1573 // absorb flag constants into boolean values
1574 (Equal (FlagEQ)) -> (MOVDconst [1])
1575 (Equal (FlagLT_ULT)) -> (MOVDconst [0])
1576 (Equal (FlagLT_UGT)) -> (MOVDconst [0])
1577 (Equal (FlagGT_ULT)) -> (MOVDconst [0])
1578 (Equal (FlagGT_UGT)) -> (MOVDconst [0])
1579
1580 (NotEqual (FlagEQ)) -> (MOVDconst [0])
1581 (NotEqual (FlagLT_ULT)) -> (MOVDconst [1])
1582 (NotEqual (FlagLT_UGT)) -> (MOVDconst [1])
1583 (NotEqual (FlagGT_ULT)) -> (MOVDconst [1])
1584 (NotEqual (FlagGT_UGT)) -> (MOVDconst [1])
1585
1586 (LessThan (FlagEQ)) -> (MOVDconst [0])
1587 (LessThan (FlagLT_ULT)) -> (MOVDconst [1])
1588 (LessThan (FlagLT_UGT)) -> (MOVDconst [1])
1589 (LessThan (FlagGT_ULT)) -> (MOVDconst [0])
1590 (LessThan (FlagGT_UGT)) -> (MOVDconst [0])
1591
1592 (LessThanU (FlagEQ)) -> (MOVDconst [0])
1593 (LessThanU (FlagLT_ULT)) -> (MOVDconst [1])
1594 (LessThanU (FlagLT_UGT)) -> (MOVDconst [0])
1595 (LessThanU (FlagGT_ULT)) -> (MOVDconst [1])
1596 (LessThanU (FlagGT_UGT)) -> (MOVDconst [0])
1597
1598 (LessEqual (FlagEQ)) -> (MOVDconst [1])
1599 (LessEqual (FlagLT_ULT)) -> (MOVDconst [1])
1600 (LessEqual (FlagLT_UGT)) -> (MOVDconst [1])
1601 (LessEqual (FlagGT_ULT)) -> (MOVDconst [0])
1602 (LessEqual (FlagGT_UGT)) -> (MOVDconst [0])
1603
1604 (LessEqualU (FlagEQ)) -> (MOVDconst [1])
1605 (LessEqualU (FlagLT_ULT)) -> (MOVDconst [1])
1606 (LessEqualU (FlagLT_UGT)) -> (MOVDconst [0])
1607 (LessEqualU (FlagGT_ULT)) -> (MOVDconst [1])
1608 (LessEqualU (FlagGT_UGT)) -> (MOVDconst [0])
1609
1610 (GreaterThan (FlagEQ)) -> (MOVDconst [0])
1611 (GreaterThan (FlagLT_ULT)) -> (MOVDconst [0])
1612 (GreaterThan (FlagLT_UGT)) -> (MOVDconst [0])
1613 (GreaterThan (FlagGT_ULT)) -> (MOVDconst [1])
1614 (GreaterThan (FlagGT_UGT)) -> (MOVDconst [1])
1615
1616 (GreaterThanU (FlagEQ)) -> (MOVDconst [0])
1617 (GreaterThanU (FlagLT_ULT)) -> (MOVDconst [0])
1618 (GreaterThanU (FlagLT_UGT)) -> (MOVDconst [1])
1619 (GreaterThanU (FlagGT_ULT)) -> (MOVDconst [0])
1620 (GreaterThanU (FlagGT_UGT)) -> (MOVDconst [1])
1621
1622 (GreaterEqual (FlagEQ)) -> (MOVDconst [1])
1623 (GreaterEqual (FlagLT_ULT)) -> (MOVDconst [0])
1624 (GreaterEqual (FlagLT_UGT)) -> (MOVDconst [0])
1625 (GreaterEqual (FlagGT_ULT)) -> (MOVDconst [1])
1626 (GreaterEqual (FlagGT_UGT)) -> (MOVDconst [1])
1627
1628 (GreaterEqualU (FlagEQ)) -> (MOVDconst [1])
1629 (GreaterEqualU (FlagLT_ULT)) -> (MOVDconst [0])
1630 (GreaterEqualU (FlagLT_UGT)) -> (MOVDconst [1])
1631 (GreaterEqualU (FlagGT_ULT)) -> (MOVDconst [0])
1632 (GreaterEqualU (FlagGT_UGT)) -> (MOVDconst [1])
1633
1634 // absorb InvertFlags into boolean values
1635 (Equal (InvertFlags x)) -> (Equal x)
1636 (NotEqual (InvertFlags x)) -> (NotEqual x)
1637 (LessThan (InvertFlags x)) -> (GreaterThan x)
1638 (LessThanU (InvertFlags x)) -> (GreaterThanU x)
1639 (GreaterThan (InvertFlags x)) -> (LessThan x)
1640 (GreaterThanU (InvertFlags x)) -> (LessThanU x)
1641 (LessEqual (InvertFlags x)) -> (GreaterEqual x)
1642 (LessEqualU (InvertFlags x)) -> (GreaterEqualU x)
1643 (GreaterEqual (InvertFlags x)) -> (LessEqual x)
1644 (GreaterEqualU (InvertFlags x)) -> (LessEqualU x)
1645 (LessThanF (InvertFlags x)) -> (GreaterThanF x)
1646 (LessEqualF (InvertFlags x)) -> (GreaterEqualF x)
1647 (GreaterThanF (InvertFlags x)) -> (LessThanF x)
1648 (GreaterEqualF (InvertFlags x)) -> (LessEqualF x)
1649
1650 // Boolean-generating instructions always
1651 // zero upper bit of the register; no need to zero-extend
1652 (MOVBUreg x) && x.Type.IsBoolean() -> (MOVDreg x)
1653
1654 // absorb flag constants into conditional instructions
1655 (CSEL {cc} x _ flag) && ccARM64Eval(cc, flag) > 0 -> x
1656 (CSEL {cc} _ y flag) && ccARM64Eval(cc, flag) < 0 -> y
1657 (CSEL0 {cc} x flag) && ccARM64Eval(cc, flag) > 0 -> x
1658 (CSEL0 {cc} _ flag) && ccARM64Eval(cc, flag) < 0 -> (MOVDconst [0])
1659
1660 // absorb flags back into boolean CSEL
1661 (CSEL {cc} x y (CMPWconst [0] boolval)) && cc.(Op) == OpARM64NotEqual && flagArg(boolval) != nil ->
1662 (CSEL {boolval.Op} x y flagArg(boolval))
1663 (CSEL {cc} x y (CMPWconst [0] boolval)) && cc.(Op) == OpARM64Equal && flagArg(boolval) != nil ->
1664 (CSEL {arm64Negate(boolval.Op)} x y flagArg(boolval))
1665 (CSEL0 {cc} x (CMPWconst [0] boolval)) && cc.(Op) == OpARM64NotEqual && flagArg(boolval) != nil ->
1666 (CSEL0 {boolval.Op} x flagArg(boolval))
1667 (CSEL0 {cc} x (CMPWconst [0] boolval)) && cc.(Op) == OpARM64Equal && flagArg(boolval) != nil ->
1668 (CSEL0 {arm64Negate(boolval.Op)} x flagArg(boolval))
1669
1670 // absorb shifts into ops
1671 (NEG x:(SLLconst [c] y)) && clobberIfDead(x) -> (NEGshiftLL [c] y)
1672 (NEG x:(SRLconst [c] y)) && clobberIfDead(x) -> (NEGshiftRL [c] y)
1673 (NEG x:(SRAconst [c] y)) && clobberIfDead(x) -> (NEGshiftRA [c] y)
1674 (MVN x:(SLLconst [c] y)) && clobberIfDead(x) -> (MVNshiftLL [c] y)
1675 (MVN x:(SRLconst [c] y)) && clobberIfDead(x) -> (MVNshiftRL [c] y)
1676 (MVN x:(SRAconst [c] y)) && clobberIfDead(x) -> (MVNshiftRA [c] y)
1677 (ADD x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ADDshiftLL x0 y [c])
1678 (ADD x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ADDshiftRL x0 y [c])
1679 (ADD x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ADDshiftRA x0 y [c])
1680 (SUB x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (SUBshiftLL x0 y [c])
1681 (SUB x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (SUBshiftRL x0 y [c])
1682 (SUB x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (SUBshiftRA x0 y [c])
1683 (AND x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ANDshiftLL x0 y [c])
1684 (AND x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ANDshiftRL x0 y [c])
1685 (AND x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ANDshiftRA x0 y [c])
1686 (OR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ORshiftLL x0 y [c]) // useful for combined load
1687 (OR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ORshiftRL x0 y [c])
1688 (OR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ORshiftRA x0 y [c])
1689 (XOR x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (XORshiftLL x0 y [c])
1690 (XOR x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (XORshiftRL x0 y [c])
1691 (XOR x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (XORshiftRA x0 y [c])
1692 (BIC x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (BICshiftLL x0 y [c])
1693 (BIC x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (BICshiftRL x0 y [c])
1694 (BIC x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (BICshiftRA x0 y [c])
1695 (ORN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (ORNshiftLL x0 y [c])
1696 (ORN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (ORNshiftRL x0 y [c])
1697 (ORN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (ORNshiftRA x0 y [c])
1698 (EON x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (EONshiftLL x0 y [c])
1699 (EON x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (EONshiftRL x0 y [c])
1700 (EON x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (EONshiftRA x0 y [c])
1701 (CMP x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (CMPshiftLL x0 y [c])
1702 (CMP x0:(SLLconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftLL x1 y [c]))
1703 (CMP x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (CMPshiftRL x0 y [c])
1704 (CMP x0:(SRLconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftRL x1 y [c]))
1705 (CMP x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (CMPshiftRA x0 y [c])
1706 (CMP x0:(SRAconst [c] y) x1) && clobberIfDead(x0) -> (InvertFlags (CMPshiftRA x1 y [c]))
1707 (CMN x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (CMNshiftLL x0 y [c])
1708 (CMN x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (CMNshiftRL x0 y [c])
1709 (CMN x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (CMNshiftRA x0 y [c])
1710 (TST x0 x1:(SLLconst [c] y)) && clobberIfDead(x1) -> (TSTshiftLL x0 y [c])
1711 (TST x0 x1:(SRLconst [c] y)) && clobberIfDead(x1) -> (TSTshiftRL x0 y [c])
1712 (TST x0 x1:(SRAconst [c] y)) && clobberIfDead(x1) -> (TSTshiftRA x0 y [c])
1713
1714 // prefer *const ops to *shift ops
1715 (ADDshiftLL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SLLconst <x.Type> x [d]))
1716 (ADDshiftRL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SRLconst <x.Type> x [d]))
1717 (ADDshiftRA (MOVDconst [c]) x [d]) -> (ADDconst [c] (SRAconst <x.Type> x [d]))
1718 (ANDshiftLL (MOVDconst [c]) x [d]) -> (ANDconst [c] (SLLconst <x.Type> x [d]))
1719 (ANDshiftRL (MOVDconst [c]) x [d]) -> (ANDconst [c] (SRLconst <x.Type> x [d]))
1720 (ANDshiftRA (MOVDconst [c]) x [d]) -> (ANDconst [c] (SRAconst <x.Type> x [d]))
1721 (ORshiftLL (MOVDconst [c]) x [d]) -> (ORconst [c] (SLLconst <x.Type> x [d]))
1722 (ORshiftRL (MOVDconst [c]) x [d]) -> (ORconst [c] (SRLconst <x.Type> x [d]))
1723 (ORshiftRA (MOVDconst [c]) x [d]) -> (ORconst [c] (SRAconst <x.Type> x [d]))
1724 (XORshiftLL (MOVDconst [c]) x [d]) -> (XORconst [c] (SLLconst <x.Type> x [d]))
1725 (XORshiftRL (MOVDconst [c]) x [d]) -> (XORconst [c] (SRLconst <x.Type> x [d]))
1726 (XORshiftRA (MOVDconst [c]) x [d]) -> (XORconst [c] (SRAconst <x.Type> x [d]))
1727 (CMPshiftLL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
1728 (CMPshiftRL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
1729 (CMPshiftRA (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
1730 (CMNshiftLL (MOVDconst [c]) x [d]) -> (CMNconst [c] (SLLconst <x.Type> x [d]))
1731 (CMNshiftRL (MOVDconst [c]) x [d]) -> (CMNconst [c] (SRLconst <x.Type> x [d]))
1732 (CMNshiftRA (MOVDconst [c]) x [d]) -> (CMNconst [c] (SRAconst <x.Type> x [d]))
1733 (TSTshiftLL (MOVDconst [c]) x [d]) -> (TSTconst [c] (SLLconst <x.Type> x [d]))
1734 (TSTshiftRL (MOVDconst [c]) x [d]) -> (TSTconst [c] (SRLconst <x.Type> x [d]))
1735 (TSTshiftRA (MOVDconst [c]) x [d]) -> (TSTconst [c] (SRAconst <x.Type> x [d]))
1736
1737 // constant folding in *shift ops
1738 (MVNshiftLL (MOVDconst [c]) [d]) -> (MOVDconst [^int64(uint64(c)<<uint64(d))])
1739 (MVNshiftRL (MOVDconst [c]) [d]) -> (MOVDconst [^int64(uint64(c)>>uint64(d))])
1740 (MVNshiftRA (MOVDconst [c]) [d]) -> (MOVDconst [^(c>>uint64(d))])
1741 (NEGshiftLL (MOVDconst [c]) [d]) -> (MOVDconst [-int64(uint64(c)<<uint64(d))])
1742 (NEGshiftRL (MOVDconst [c]) [d]) -> (MOVDconst [-int64(uint64(c)>>uint64(d))])
1743 (NEGshiftRA (MOVDconst [c]) [d]) -> (MOVDconst [-(c>>uint64(d))])
1744 (ADDshiftLL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)<<uint64(d))])
1745 (ADDshiftRL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)>>uint64(d))])
1746 (ADDshiftRA x (MOVDconst [c]) [d]) -> (ADDconst x [c>>uint64(d)])
1747 (SUBshiftLL x (MOVDconst [c]) [d]) -> (SUBconst x [int64(uint64(c)<<uint64(d))])
1748 (SUBshiftRL x (MOVDconst [c]) [d]) -> (SUBconst x [int64(uint64(c)>>uint64(d))])
1749 (SUBshiftRA x (MOVDconst [c]) [d]) -> (SUBconst x [c>>uint64(d)])
1750 (ANDshiftLL x (MOVDconst [c]) [d]) -> (ANDconst x [int64(uint64(c)<<uint64(d))])
1751 (ANDshiftRL x (MOVDconst [c]) [d]) -> (ANDconst x [int64(uint64(c)>>uint64(d))])
1752 (ANDshiftRA x (MOVDconst [c]) [d]) -> (ANDconst x [c>>uint64(d)])
1753 (ORshiftLL x (MOVDconst [c]) [d]) -> (ORconst x [int64(uint64(c)<<uint64(d))])
1754 (ORshiftRL x (MOVDconst [c]) [d]) -> (ORconst x [int64(uint64(c)>>uint64(d))])
1755 (ORshiftRA x (MOVDconst [c]) [d]) -> (ORconst x [c>>uint64(d)])
1756 (XORshiftLL x (MOVDconst [c]) [d]) -> (XORconst x [int64(uint64(c)<<uint64(d))])
1757 (XORshiftRL x (MOVDconst [c]) [d]) -> (XORconst x [int64(uint64(c)>>uint64(d))])
1758 (XORshiftRA x (MOVDconst [c]) [d]) -> (XORconst x [c>>uint64(d)])
1759 (BICshiftLL x (MOVDconst [c]) [d]) -> (ANDconst x [^int64(uint64(c)<<uint64(d))])
1760 (BICshiftRL x (MOVDconst [c]) [d]) -> (ANDconst x [^int64(uint64(c)>>uint64(d))])
1761 (BICshiftRA x (MOVDconst [c]) [d]) -> (ANDconst x [^(c>>uint64(d))])
1762 (ORNshiftLL x (MOVDconst [c]) [d]) -> (ORconst x [^int64(uint64(c)<<uint64(d))])
1763 (ORNshiftRL x (MOVDconst [c]) [d]) -> (ORconst x [^int64(uint64(c)>>uint64(d))])
1764 (ORNshiftRA x (MOVDconst [c]) [d]) -> (ORconst x [^(c>>uint64(d))])
1765 (EONshiftLL x (MOVDconst [c]) [d]) -> (XORconst x [^int64(uint64(c)<<uint64(d))])
1766 (EONshiftRL x (MOVDconst [c]) [d]) -> (XORconst x [^int64(uint64(c)>>uint64(d))])
1767 (EONshiftRA x (MOVDconst [c]) [d]) -> (XORconst x [^(c>>uint64(d))])
1768 (CMPshiftLL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)<<uint64(d))])
1769 (CMPshiftRL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)>>uint64(d))])
1770 (CMPshiftRA x (MOVDconst [c]) [d]) -> (CMPconst x [c>>uint64(d)])
1771 (CMNshiftLL x (MOVDconst [c]) [d]) -> (CMNconst x [int64(uint64(c)<<uint64(d))])
1772 (CMNshiftRL x (MOVDconst [c]) [d]) -> (CMNconst x [int64(uint64(c)>>uint64(d))])
1773 (CMNshiftRA x (MOVDconst [c]) [d]) -> (CMNconst x [c>>uint64(d)])
1774 (TSTshiftLL x (MOVDconst [c]) [d]) -> (TSTconst x [int64(uint64(c)<<uint64(d))])
1775 (TSTshiftRL x (MOVDconst [c]) [d]) -> (TSTconst x [int64(uint64(c)>>uint64(d))])
1776 (TSTshiftRA x (MOVDconst [c]) [d]) -> (TSTconst x [c>>uint64(d)])
1777
1778 // simplification with *shift ops
1779 (SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0])
1780 (SUBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [0])
1781 (SUBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [0])
1782 (ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
1783 (ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
1784 (ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
1785 (ORshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
1786 (ORshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
1787 (ORshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
1788 (XORshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0])
1789 (XORshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [0])
1790 (XORshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [0])
1791 (BICshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0])
1792 (BICshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [0])
1793 (BICshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [0])
1794 (EONshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [-1])
1795 (EONshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [-1])
1796 (EONshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [-1])
1797 (ORNshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [-1])
1798 (ORNshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [-1])
1799 (ORNshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [-1])
1800
1801 // Generate rotates with const shift
1802 (ADDshiftLL [c] (SRLconst x [64-c]) x) -> (RORconst [64-c] x)
1803 ( ORshiftLL [c] (SRLconst x [64-c]) x) -> (RORconst [64-c] x)
1804 (XORshiftLL [c] (SRLconst x [64-c]) x) -> (RORconst [64-c] x)
1805 (ADDshiftRL [c] (SLLconst x [64-c]) x) -> (RORconst [ c] x)
1806 ( ORshiftRL [c] (SLLconst x [64-c]) x) -> (RORconst [ c] x)
1807 (XORshiftRL [c] (SLLconst x [64-c]) x) -> (RORconst [ c] x)
1808
1809 (ADDshiftLL <t> [c] (UBFX [bfc] x) x) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
1810 -> (RORWconst [32-c] x)
1811 ( ORshiftLL <t> [c] (UBFX [bfc] x) x) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
1812 -> (RORWconst [32-c] x)
1813 (XORshiftLL <t> [c] (UBFX [bfc] x) x) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
1814 -> (RORWconst [32-c] x)
1815 (ADDshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [c] x)
1816 ( ORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [c] x)
1817 (XORshiftRL <t> [c] (SLLconst x [32-c]) (MOVWUreg x)) && c < 32 && t.Size() == 4 -> (RORWconst [c] x)
1818
1819 (RORconst [c] (RORconst [d] x)) -> (RORconst [(c+d)&63] x)
1820 (RORWconst [c] (RORWconst [d] x)) -> (RORWconst [(c+d)&31] x)
1821
1822 // Generate rotates with non-const shift.
1823 // These rules match the Go source code like
1824 // y &= 63
1825 // x << y | x >> (64-y)
1826 // "|" can also be "^" or "+".
1827 // As arm64 does not have a ROL instruction, so ROL(x, y) is replaced by ROR(x, -y).
1828 ((ADD|OR|XOR) (SLL x (ANDconst <t> [63] y))
1829 (CSEL0 <typ.UInt64> {cc} (SRL <typ.UInt64> x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))
1830 (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))))) && cc.(Op) == OpARM64LessThanU
1831 -> (ROR x (NEG <t> y))
1832 ((ADD|OR|XOR) (SRL <typ.UInt64> x (ANDconst <t> [63] y))
1833 (CSEL0 <typ.UInt64> {cc} (SLL x (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y)))
1834 (CMPconst [64] (SUB <t> (MOVDconst [64]) (ANDconst <t> [63] y))))) && cc.(Op) == OpARM64LessThanU
1835 -> (ROR x y)
1836
1837 // These rules match the Go source code like
1838 // y &= 31
1839 // x << y | x >> (32-y)
1840 // "|" can also be "^" or "+".
1841 // As arm64 does not have a ROLW instruction, so ROLW(x, y) is replaced by RORW(x, -y).
1842 ((ADD|OR|XOR) (SLL x (ANDconst <t> [31] y))
1843 (CSEL0 <typ.UInt32> {cc} (SRL <typ.UInt32> (MOVWUreg x) (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))
1844 (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))))) && cc.(Op) == OpARM64LessThanU
1845 -> (RORW x (NEG <t> y))
1846 ((ADD|OR|XOR) (SRL <typ.UInt32> (MOVWUreg x) (ANDconst <t> [31] y))
1847 (CSEL0 <typ.UInt32> {cc} (SLL x (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y)))
1848 (CMPconst [64] (SUB <t> (MOVDconst [32]) (ANDconst <t> [31] y))))) && cc.(Op) == OpARM64LessThanU
1849 -> (RORW x y)
1850
1851 // ((x>>8) | (x<<8)) -> (REV16W x), the type of x is uint16, "|" can also be "^" or "+".
1852 ((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (UBFX <typ.UInt16> [armBFAuxInt(8, 8)] x) x) -> (REV16W x)
1853
1854 // Extract from reg pair
1855 (ADDshiftLL [c] (SRLconst x [64-c]) x2) -> (EXTRconst [64-c] x2 x)
1856 ( ORshiftLL [c] (SRLconst x [64-c]) x2) -> (EXTRconst [64-c] x2 x)
1857 (XORshiftLL [c] (SRLconst x [64-c]) x2) -> (EXTRconst [64-c] x2 x)
1858
1859 (ADDshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
1860 -> (EXTRWconst [32-c] x2 x)
1861 ( ORshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
1862 -> (EXTRWconst [32-c] x2 x)
1863 (XORshiftLL <t> [c] (UBFX [bfc] x) x2) && c < 32 && t.Size() == 4 && bfc == armBFAuxInt(32-c, c)
1864 -> (EXTRWconst [32-c] x2 x)
1865
1866 // Generic rules rewrite certain AND to a pair of shifts.
1867 // However, on ARM64 the bitmask can fit into an instruction.
1868 // Rewrite it back to AND.
1869 (SRLconst [c] (SLLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [1<<uint(64-c)-1] x) // mask out high bits
1870 (SLLconst [c] (SRLconst [c] x)) && 0 < c && c < 64 -> (ANDconst [^(1<<uint(c)-1)] x) // mask out low bits
1871
1872 // Special case setting bit as 1. An example is math.Copysign(c,-1)
1873 (ORconst [c1] (ANDconst [c2] x)) && c2|c1 == ^0 -> (ORconst [c1] x)
1874
1875 // bitfield ops
1876
1877 // sbfiz
1878 // (x << lc) >> rc
1879 (SRAconst [rc] (SLLconst [lc] x)) && lc > rc -> (SBFIZ [armBFAuxInt(lc-rc, 64-lc)] x)
1880 (MOVWreg (SLLconst [lc] x)) && lc < 32 -> (SBFIZ [armBFAuxInt(lc, 32-lc)] x)
1881 (MOVHreg (SLLconst [lc] x)) && lc < 16 -> (SBFIZ [armBFAuxInt(lc, 16-lc)] x)
1882 (MOVBreg (SLLconst [lc] x)) && lc < 8 -> (SBFIZ [armBFAuxInt(lc, 8-lc)] x)
1883
1884 // sbfx
1885 // (x << lc) >> rc
1886 (SRAconst [rc] (SLLconst [lc] x)) && lc <= rc -> (SBFX [armBFAuxInt(rc-lc, 64-rc)] x)
1887 (SRAconst [rc] (MOVWreg x)) && rc < 32 -> (SBFX [armBFAuxInt(rc, 32-rc)] x)
1888 (SRAconst [rc] (MOVHreg x)) && rc < 16 -> (SBFX [armBFAuxInt(rc, 16-rc)] x)
1889 (SRAconst [rc] (MOVBreg x)) && rc < 8 -> (SBFX [armBFAuxInt(rc, 8-rc)] x)
1890
1891 // sbfiz/sbfx combinations: merge shifts into bitfield ops
1892 (SRAconst [sc] (SBFIZ [bfc] x)) && sc < getARM64BFlsb(bfc)
1893 -> (SBFIZ [armBFAuxInt(getARM64BFlsb(bfc)-sc, getARM64BFwidth(bfc))] x)
1894 (SRAconst [sc] (SBFIZ [bfc] x)) && sc >= getARM64BFlsb(bfc)
1895 && sc < getARM64BFlsb(bfc)+getARM64BFwidth(bfc)
1896 -> (SBFX [armBFAuxInt(sc-getARM64BFlsb(bfc), getARM64BFlsb(bfc)+getARM64BFwidth(bfc)-sc)] x)
1897
1898 // ubfiz
1899 // (x & ac) << sc
1900 (SLLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, 0)
1901 -> (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x)
1902 (SLLconst [sc] (MOVWUreg x)) && isARM64BFMask(sc, 1<<32-1, 0) -> (UBFIZ [armBFAuxInt(sc, 32)] x)
1903 (SLLconst [sc] (MOVHUreg x)) && isARM64BFMask(sc, 1<<16-1, 0) -> (UBFIZ [armBFAuxInt(sc, 16)] x)
1904 (SLLconst [sc] (MOVBUreg x)) && isARM64BFMask(sc, 1<<8-1, 0) -> (UBFIZ [armBFAuxInt(sc, 8)] x)
1905 // (x << sc) & ac
1906 (ANDconst [ac] (SLLconst [sc] x)) && isARM64BFMask(sc, ac, sc)
1907 -> (UBFIZ [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
1908 (MOVWUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<32-1, sc)
1909 -> (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x)
1910 (MOVHUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<16-1, sc)
1911 -> (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x)
1912 (MOVBUreg (SLLconst [sc] x)) && isARM64BFMask(sc, 1<<8-1, sc)
1913 -> (UBFIZ [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x)
1914 // (x << lc) >> rc
1915 (SRLconst [rc] (SLLconst [lc] x)) && lc > rc -> (UBFIZ [armBFAuxInt(lc-rc, 64-lc)] x)
1916
1917 // ubfx
1918 // (x >> sc) & ac
1919 (ANDconst [ac] (SRLconst [sc] x)) && isARM64BFMask(sc, ac, 0)
1920 -> (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, 0))] x)
1921 (MOVWUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<32-1, 0) -> (UBFX [armBFAuxInt(sc, 32)] x)
1922 (MOVHUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<16-1, 0) -> (UBFX [armBFAuxInt(sc, 16)] x)
1923 (MOVBUreg (SRLconst [sc] x)) && isARM64BFMask(sc, 1<<8-1, 0) -> (UBFX [armBFAuxInt(sc, 8)] x)
1924 // (x & ac) >> sc
1925 (SRLconst [sc] (ANDconst [ac] x)) && isARM64BFMask(sc, ac, sc)
1926 -> (UBFX [armBFAuxInt(sc, arm64BFWidth(ac, sc))] x)
1927 (SRLconst [sc] (MOVWUreg x)) && isARM64BFMask(sc, 1<<32-1, sc)
1928 -> (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<32-1, sc))] x)
1929 (SRLconst [sc] (MOVHUreg x)) && isARM64BFMask(sc, 1<<16-1, sc)
1930 -> (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<16-1, sc))] x)
1931 (SRLconst [sc] (MOVBUreg x)) && isARM64BFMask(sc, 1<<8-1, sc)
1932 -> (UBFX [armBFAuxInt(sc, arm64BFWidth(1<<8-1, sc))] x)
1933 // (x << lc) >> rc
1934 (SRLconst [rc] (SLLconst [lc] x)) && lc < rc -> (UBFX [armBFAuxInt(rc-lc, 64-rc)] x)
1935
1936 // ubfiz/ubfx combinations: merge shifts into bitfield ops
1937 (SRLconst [sc] (UBFX [bfc] x)) && sc < getARM64BFwidth(bfc)
1938 -> (UBFX [armBFAuxInt(getARM64BFlsb(bfc)+sc, getARM64BFwidth(bfc)-sc)] x)
1939 (UBFX [bfc] (SRLconst [sc] x)) && sc+getARM64BFwidth(bfc)+getARM64BFlsb(bfc) < 64
1940 -> (UBFX [armBFAuxInt(getARM64BFlsb(bfc)+sc, getARM64BFwidth(bfc))] x)
1941 (SLLconst [sc] (UBFIZ [bfc] x)) && sc+getARM64BFwidth(bfc)+getARM64BFlsb(bfc) < 64
1942 -> (UBFIZ [armBFAuxInt(getARM64BFlsb(bfc)+sc, getARM64BFwidth(bfc))] x)
1943 (UBFIZ [bfc] (SLLconst [sc] x)) && sc < getARM64BFwidth(bfc)
1944 -> (UBFIZ [armBFAuxInt(getARM64BFlsb(bfc)+sc, getARM64BFwidth(bfc)-sc)] x)
1945 // ((x << c1) >> c2) >> c3
1946 (SRLconst [sc] (UBFIZ [bfc] x)) && sc == getARM64BFlsb(bfc)
1947 -> (ANDconst [1<<uint(getARM64BFwidth(bfc))-1] x)
1948 (SRLconst [sc] (UBFIZ [bfc] x)) && sc < getARM64BFlsb(bfc)
1949 -> (UBFIZ [armBFAuxInt(getARM64BFlsb(bfc)-sc, getARM64BFwidth(bfc))] x)
1950 (SRLconst [sc] (UBFIZ [bfc] x)) && sc > getARM64BFlsb(bfc)
1951 && sc < getARM64BFlsb(bfc)+getARM64BFwidth(bfc)
1952 -> (UBFX [armBFAuxInt(sc-getARM64BFlsb(bfc), getARM64BFlsb(bfc)+getARM64BFwidth(bfc)-sc)] x)
1953 // ((x << c1) << c2) >> c3
1954 (UBFX [bfc] (SLLconst [sc] x)) && sc == getARM64BFlsb(bfc)
1955 -> (ANDconst [1<<uint(getARM64BFwidth(bfc))-1] x)
1956 (UBFX [bfc] (SLLconst [sc] x)) && sc < getARM64BFlsb(bfc)
1957 -> (UBFX [armBFAuxInt(getARM64BFlsb(bfc)-sc, getARM64BFwidth(bfc))] x)
1958 (UBFX [bfc] (SLLconst [sc] x)) && sc > getARM64BFlsb(bfc)
1959 && sc < getARM64BFlsb(bfc)+getARM64BFwidth(bfc)
1960 -> (UBFIZ [armBFAuxInt(sc-getARM64BFlsb(bfc), getARM64BFlsb(bfc)+getARM64BFwidth(bfc)-sc)] x)
1961
1962 // bfi
1963 (OR (UBFIZ [bfc] x) (ANDconst [ac] y))
1964 && ac == ^((1<<uint(getARM64BFwidth(bfc))-1) << uint(getARM64BFlsb(bfc)))
1965 -> (BFI [bfc] y x)
1966 (ORshiftRL [rc] (ANDconst [ac] x) (SLLconst [lc] y))
1967 && lc > rc && ac == ^((1<<uint(64-lc)-1) << uint64(lc-rc))
1968 -> (BFI [armBFAuxInt(lc-rc, 64-lc)] x y)
1969 // bfxil
1970 (OR (UBFX [bfc] x) (ANDconst [ac] y)) && ac == ^(1<<uint(getARM64BFwidth(bfc))-1)
1971 -> (BFXIL [bfc] y x)
1972 (ORshiftLL [sc] (UBFX [bfc] x) (SRLconst [sc] y)) && sc == getARM64BFwidth(bfc)
1973 -> (BFXIL [bfc] y x)
1974
1975 // do combined loads
1976 // little endian loads
1977 // b[0] | b[1]<<8 -> load 16-bit
1978 (ORshiftLL <t> [8]
1979 y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem))
1980 y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
1981 && i1 == i0+1
1982 && x0.Uses == 1 && x1.Uses == 1
1983 && y0.Uses == 1 && y1.Uses == 1
1984 && mergePoint(b,x0,x1) != nil
1985 && clobber(x0) && clobber(x1)
1986 && clobber(y0) && clobber(y1)
1987 -> @mergePoint(b,x0,x1) (MOVHUload <t> {s} (OffPtr <p.Type> [i0] p) mem)
1988 (ORshiftLL <t> [8]
1989 y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem))
1990 y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
1991 && s == nil
1992 && x0.Uses == 1 && x1.Uses == 1
1993 && y0.Uses == 1 && y1.Uses == 1
1994 && mergePoint(b,x0,x1) != nil
1995 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
1996 && clobber(x0) && clobber(x1)
1997 && clobber(y0) && clobber(y1)
1998 -> @mergePoint(b,x0,x1) (MOVHUloadidx <t> ptr0 idx0 mem)
1999 (ORshiftLL <t> [8]
2000 y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem))
2001 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2002 && x0.Uses == 1 && x1.Uses == 1
2003 && y0.Uses == 1 && y1.Uses == 1
2004 && mergePoint(b,x0,x1) != nil
2005 && clobber(x0) && clobber(x1)
2006 && clobber(y0) && clobber(y1)
2007 -> @mergePoint(b,x0,x1) (MOVHUloadidx <t> ptr idx mem)
2008
2009 // b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 -> load 32-bit
2010 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2011 x0:(MOVHUload [i0] {s} p mem)
2012 y1:(MOVDnop x1:(MOVBUload [i2] {s} p mem)))
2013 y2:(MOVDnop x2:(MOVBUload [i3] {s} p mem)))
2014 && i2 == i0+2
2015 && i3 == i0+3
2016 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2017 && y1.Uses == 1 && y2.Uses == 1
2018 && o0.Uses == 1
2019 && mergePoint(b,x0,x1,x2) != nil
2020 && clobber(x0) && clobber(x1) && clobber(x2)
2021 && clobber(y1) && clobber(y2)
2022 && clobber(o0)
2023 -> @mergePoint(b,x0,x1,x2) (MOVWUload <t> {s} (OffPtr <p.Type> [i0] p) mem)
2024 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2025 x0:(MOVHUloadidx ptr0 idx0 mem)
2026 y1:(MOVDnop x1:(MOVBUload [2] {s} p1:(ADD ptr1 idx1) mem)))
2027 y2:(MOVDnop x2:(MOVBUload [3] {s} p mem)))
2028 && s == nil
2029 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2030 && y1.Uses == 1 && y2.Uses == 1
2031 && o0.Uses == 1
2032 && mergePoint(b,x0,x1,x2) != nil
2033 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2034 && isSamePtr(p1, p)
2035 && clobber(x0) && clobber(x1) && clobber(x2)
2036 && clobber(y1) && clobber(y2)
2037 && clobber(o0)
2038 -> @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr0 idx0 mem)
2039 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2040 x0:(MOVHUloadidx ptr idx mem)
2041 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
2042 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
2043 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2044 && y1.Uses == 1 && y2.Uses == 1
2045 && o0.Uses == 1
2046 && mergePoint(b,x0,x1,x2) != nil
2047 && clobber(x0) && clobber(x1) && clobber(x2)
2048 && clobber(y1) && clobber(y2)
2049 && clobber(o0)
2050 -> @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr idx mem)
2051 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2052 x0:(MOVHUloadidx2 ptr0 idx0 mem)
2053 y1:(MOVDnop x1:(MOVBUload [2] {s} p1:(ADDshiftLL [1] ptr1 idx1) mem)))
2054 y2:(MOVDnop x2:(MOVBUload [3] {s} p mem)))
2055 && s == nil
2056 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2057 && y1.Uses == 1 && y2.Uses == 1
2058 && o0.Uses == 1
2059 && mergePoint(b,x0,x1,x2) != nil
2060 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2061 && isSamePtr(p1, p)
2062 && clobber(x0) && clobber(x1) && clobber(x2)
2063 && clobber(y1) && clobber(y2)
2064 && clobber(o0)
2065 -> @mergePoint(b,x0,x1,x2) (MOVWUloadidx <t> ptr0 (SLLconst <idx0.Type> [1] idx0) mem)
2066
2067 // b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 | b[4]<<32 | b[5]<<40 | b[6]<<48 | b[7]<<56 -> load 64-bit
2068 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2069 x0:(MOVWUload [i0] {s} p mem)
2070 y1:(MOVDnop x1:(MOVBUload [i4] {s} p mem)))
2071 y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem)))
2072 y3:(MOVDnop x3:(MOVBUload [i6] {s} p mem)))
2073 y4:(MOVDnop x4:(MOVBUload [i7] {s} p mem)))
2074 && i4 == i0+4
2075 && i5 == i0+5
2076 && i6 == i0+6
2077 && i7 == i0+7
2078 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2079 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2080 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2081 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2082 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2083 && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2084 && clobber(o0) && clobber(o1) && clobber(o2)
2085 -> @mergePoint(b,x0,x1,x2,x3,x4) (MOVDload <t> {s} (OffPtr <p.Type> [i0] p) mem)
2086 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2087 x0:(MOVWUloadidx ptr0 idx0 mem)
2088 y1:(MOVDnop x1:(MOVBUload [4] {s} p1:(ADD ptr1 idx1) mem)))
2089 y2:(MOVDnop x2:(MOVBUload [5] {s} p mem)))
2090 y3:(MOVDnop x3:(MOVBUload [6] {s} p mem)))
2091 y4:(MOVDnop x4:(MOVBUload [7] {s} p mem)))
2092 && s == nil
2093 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2094 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2095 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2096 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2097 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2098 && isSamePtr(p1, p)
2099 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2100 && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2101 && clobber(o0) && clobber(o1) && clobber(o2)
2102 -> @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr0 idx0 mem)
2103 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2104 x0:(MOVWUloadidx4 ptr0 idx0 mem)
2105 y1:(MOVDnop x1:(MOVBUload [4] {s} p1:(ADDshiftLL [2] ptr1 idx1) mem)))
2106 y2:(MOVDnop x2:(MOVBUload [5] {s} p mem)))
2107 y3:(MOVDnop x3:(MOVBUload [6] {s} p mem)))
2108 y4:(MOVDnop x4:(MOVBUload [7] {s} p mem)))
2109 && s == nil
2110 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2111 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2112 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2113 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2114 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2115 && isSamePtr(p1, p)
2116 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2117 && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2118 && clobber(o0) && clobber(o1) && clobber(o2)
2119 -> @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr0 (SLLconst <idx0.Type> [2] idx0) mem)
2120 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2121 x0:(MOVWUloadidx ptr idx mem)
2122 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [4] idx) mem)))
2123 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [5] idx) mem)))
2124 y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [6] idx) mem)))
2125 y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
2126 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2127 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2128 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2129 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2130 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2131 && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2132 && clobber(o0) && clobber(o1) && clobber(o2)
2133 -> @mergePoint(b,x0,x1,x2,x3,x4) (MOVDloadidx <t> ptr idx mem)
2134
2135 // b[3]<<24 | b[2]<<16 | b[1]<<8 | b[0] -> load 32-bit
2136 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
2137 y0:(MOVDnop x0:(MOVBUload [i3] {s} p mem)))
2138 y1:(MOVDnop x1:(MOVBUload [i2] {s} p mem)))
2139 y2:(MOVDnop x2:(MOVBUload [i1] {s} p mem)))
2140 y3:(MOVDnop x3:(MOVBUload [i0] {s} p mem)))
2141 && i1 == i0+1
2142 && i2 == i0+2
2143 && i3 == i0+3
2144 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2145 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2146 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
2147 && mergePoint(b,x0,x1,x2,x3) != nil
2148 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2149 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2150 && clobber(o0) && clobber(o1) && clobber(s0)
2151 -> @mergePoint(b,x0,x1,x2,x3) (MOVWUload <t> {s} (OffPtr <p.Type> [i0] p) mem)
2152 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
2153 y0:(MOVDnop x0:(MOVBUload [3] {s} p mem)))
2154 y1:(MOVDnop x1:(MOVBUload [2] {s} p mem)))
2155 y2:(MOVDnop x2:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
2156 y3:(MOVDnop x3:(MOVBUloadidx ptr0 idx0 mem)))
2157 && s == nil
2158 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2159 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2160 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
2161 && mergePoint(b,x0,x1,x2,x3) != nil
2162 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2163 && isSamePtr(p1, p)
2164 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2165 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2166 && clobber(o0) && clobber(o1) && clobber(s0)
2167 -> @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr0 idx0 mem)
2168 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
2169 y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
2170 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
2171 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2172 y3:(MOVDnop x3:(MOVBUloadidx ptr idx mem)))
2173 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2174 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2175 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
2176 && mergePoint(b,x0,x1,x2,x3) != nil
2177 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2178 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2179 && clobber(o0) && clobber(o1) && clobber(s0)
2180 -> @mergePoint(b,x0,x1,x2,x3) (MOVWUloadidx <t> ptr idx mem)
2181
2182 // b[7]<<56 | b[6]<<48 | b[5]<<40 | b[4]<<32 | b[3]<<24 | b[2]<<16 | b[1]<<8 | b[0] -> load 64-bit
2183 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
2184 y0:(MOVDnop x0:(MOVBUload [i7] {s} p mem)))
2185 y1:(MOVDnop x1:(MOVBUload [i6] {s} p mem)))
2186 y2:(MOVDnop x2:(MOVBUload [i5] {s} p mem)))
2187 y3:(MOVDnop x3:(MOVBUload [i4] {s} p mem)))
2188 y4:(MOVDnop x4:(MOVBUload [i3] {s} p mem)))
2189 y5:(MOVDnop x5:(MOVBUload [i2] {s} p mem)))
2190 y6:(MOVDnop x6:(MOVBUload [i1] {s} p mem)))
2191 y7:(MOVDnop x7:(MOVBUload [i0] {s} p mem)))
2192 && i1 == i0+1
2193 && i2 == i0+2
2194 && i3 == i0+3
2195 && i4 == i0+4
2196 && i5 == i0+5
2197 && i6 == i0+6
2198 && i7 == i0+7
2199 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2200 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
2201 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2202 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
2203 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
2204 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
2205 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
2206 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2207 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7)
2208 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2209 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7)
2210 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3)
2211 && clobber(o4) && clobber(o5) && clobber(s0)
2212 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDload <t> {s} (OffPtr <p.Type> [i0] p) mem)
2213 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
2214 y0:(MOVDnop x0:(MOVBUload [7] {s} p mem)))
2215 y1:(MOVDnop x1:(MOVBUload [6] {s} p mem)))
2216 y2:(MOVDnop x2:(MOVBUload [5] {s} p mem)))
2217 y3:(MOVDnop x3:(MOVBUload [4] {s} p mem)))
2218 y4:(MOVDnop x4:(MOVBUload [3] {s} p mem)))
2219 y5:(MOVDnop x5:(MOVBUload [2] {s} p mem)))
2220 y6:(MOVDnop x6:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
2221 y7:(MOVDnop x7:(MOVBUloadidx ptr0 idx0 mem)))
2222 && s == nil
2223 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2224 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
2225 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2226 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
2227 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
2228 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
2229 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
2230 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2231 && isSamePtr(p1, p)
2232 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2233 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7)
2234 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2235 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7)
2236 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3)
2237 && clobber(o4) && clobber(o5) && clobber(s0)
2238 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDloadidx <t> ptr0 idx0 mem)
2239 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
2240 y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
2241 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [6] idx) mem)))
2242 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [5] idx) mem)))
2243 y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [4] idx) mem)))
2244 y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
2245 y5:(MOVDnop x5:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
2246 y6:(MOVDnop x6:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2247 y7:(MOVDnop x7:(MOVBUloadidx ptr idx mem)))
2248 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2249 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
2250 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2251 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
2252 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
2253 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
2254 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
2255 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2256 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7)
2257 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2258 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7)
2259 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3)
2260 && clobber(o4) && clobber(o5) && clobber(s0)
2261 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (MOVDloadidx <t> ptr idx mem)
2262
2263 // big endian loads
2264 // b[1] | b[0]<<8 -> load 16-bit, reverse
2265 (ORshiftLL <t> [8]
2266 y0:(MOVDnop x0:(MOVBUload [i1] {s} p mem))
2267 y1:(MOVDnop x1:(MOVBUload [i0] {s} p mem)))
2268 && i1 == i0+1
2269 && x0.Uses == 1 && x1.Uses == 1
2270 && y0.Uses == 1 && y1.Uses == 1
2271 && mergePoint(b,x0,x1) != nil
2272 && clobber(x0) && clobber(x1)
2273 && clobber(y0) && clobber(y1)
2274 -> @mergePoint(b,x0,x1) (REV16W <t> (MOVHUload <t> [i0] {s} p mem))
2275 (ORshiftLL <t> [8]
2276 y0:(MOVDnop x0:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem))
2277 y1:(MOVDnop x1:(MOVBUloadidx ptr0 idx0 mem)))
2278 && s == nil
2279 && x0.Uses == 1 && x1.Uses == 1
2280 && y0.Uses == 1 && y1.Uses == 1
2281 && mergePoint(b,x0,x1) != nil
2282 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2283 && clobber(x0) && clobber(x1)
2284 && clobber(y0) && clobber(y1)
2285 -> @mergePoint(b,x0,x1) (REV16W <t> (MOVHUloadidx <t> ptr0 idx0 mem))
2286 (ORshiftLL <t> [8]
2287 y0:(MOVDnop x0:(MOVBUloadidx ptr (ADDconst [1] idx) mem))
2288 y1:(MOVDnop x1:(MOVBUloadidx ptr idx mem)))
2289 && x0.Uses == 1 && x1.Uses == 1
2290 && y0.Uses == 1 && y1.Uses == 1
2291 && mergePoint(b,x0,x1) != nil
2292 && clobber(x0) && clobber(x1)
2293 && clobber(y0) && clobber(y1)
2294 -> @mergePoint(b,x0,x1) (REV16W <t> (MOVHUloadidx <t> ptr idx mem))
2295
2296 // b[3] | b[2]<<8 | b[1]<<16 | b[0]<<24 -> load 32-bit, reverse
2297 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2298 y0:(REV16W x0:(MOVHUload [i2] {s} p mem))
2299 y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
2300 y2:(MOVDnop x2:(MOVBUload [i0] {s} p mem)))
2301 && i1 == i0+1
2302 && i2 == i0+2
2303 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2304 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1
2305 && o0.Uses == 1
2306 && mergePoint(b,x0,x1,x2) != nil
2307 && clobber(x0) && clobber(x1) && clobber(x2)
2308 && clobber(y0) && clobber(y1) && clobber(y2)
2309 && clobber(o0)
2310 -> @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [i0] p) mem))
2311 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2312 y0:(REV16W x0:(MOVHUload [2] {s} p mem))
2313 y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
2314 y2:(MOVDnop x2:(MOVBUloadidx ptr0 idx0 mem)))
2315 && s == nil
2316 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2317 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1
2318 && o0.Uses == 1
2319 && mergePoint(b,x0,x1,x2) != nil
2320 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2321 && isSamePtr(p1, p)
2322 && clobber(x0) && clobber(x1) && clobber(x2)
2323 && clobber(y0) && clobber(y1) && clobber(y2)
2324 && clobber(o0)
2325 -> @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
2326 (ORshiftLL <t> [24] o0:(ORshiftLL [16]
2327 y0:(REV16W x0:(MOVHUloadidx ptr (ADDconst [2] idx) mem))
2328 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2329 y2:(MOVDnop x2:(MOVBUloadidx ptr idx mem)))
2330 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1
2331 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1
2332 && o0.Uses == 1
2333 && mergePoint(b,x0,x1,x2) != nil
2334 && clobber(x0) && clobber(x1) && clobber(x2)
2335 && clobber(y0) && clobber(y1) && clobber(y2)
2336 && clobber(o0)
2337 -> @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
2338
2339 // b[7] | b[6]<<8 | b[5]<<16 | b[4]<<24 | b[3]<<32 | b[2]<<40 | b[1]<<48 | b[0]<<56 -> load 64-bit, reverse
2340 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2341 y0:(REVW x0:(MOVWUload [i4] {s} p mem))
2342 y1:(MOVDnop x1:(MOVBUload [i3] {s} p mem)))
2343 y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem)))
2344 y3:(MOVDnop x3:(MOVBUload [i1] {s} p mem)))
2345 y4:(MOVDnop x4:(MOVBUload [i0] {s} p mem)))
2346 && i1 == i0+1
2347 && i2 == i0+2
2348 && i3 == i0+3
2349 && i4 == i0+4
2350 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2351 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2352 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2353 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2354 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2355 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2356 && clobber(o0) && clobber(o1) && clobber(o2)
2357 -> @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [i0] p) mem))
2358 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2359 y0:(REVW x0:(MOVWUload [4] {s} p mem))
2360 y1:(MOVDnop x1:(MOVBUload [3] {s} p mem)))
2361 y2:(MOVDnop x2:(MOVBUload [2] {s} p mem)))
2362 y3:(MOVDnop x3:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
2363 y4:(MOVDnop x4:(MOVBUloadidx ptr0 idx0 mem)))
2364 && s == nil
2365 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2366 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2367 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2368 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2369 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2370 && isSamePtr(p1, p)
2371 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2372 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2373 && clobber(o0) && clobber(o1) && clobber(o2)
2374 -> @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDloadidx <t> ptr0 idx0 mem))
2375 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32]
2376 y0:(REVW x0:(MOVWUloadidx ptr (ADDconst [4] idx) mem))
2377 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
2378 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
2379 y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2380 y4:(MOVDnop x4:(MOVBUloadidx ptr idx mem)))
2381 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1
2382 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1
2383 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1
2384 && mergePoint(b,x0,x1,x2,x3,x4) != nil
2385 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4)
2386 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4)
2387 && clobber(o0) && clobber(o1) && clobber(o2)
2388 -> @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDloadidx <t> ptr idx mem))
2389
2390 // b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3] -> load 32-bit, reverse
2391 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
2392 y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem)))
2393 y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
2394 y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem)))
2395 y3:(MOVDnop x3:(MOVBUload [i3] {s} p mem)))
2396 && i1 == i0+1
2397 && i2 == i0+2
2398 && i3 == i0+3
2399 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2400 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2401 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
2402 && mergePoint(b,x0,x1,x2,x3) != nil
2403 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2404 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2405 && clobber(o0) && clobber(o1) && clobber(s0)
2406 -> @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [i0] p) mem))
2407 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
2408 y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem)))
2409 y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
2410 y2:(MOVDnop x2:(MOVBUload [2] {s} p mem)))
2411 y3:(MOVDnop x3:(MOVBUload [3] {s} p mem)))
2412 && s == nil
2413 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2414 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2415 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
2416 && mergePoint(b,x0,x1,x2,x3) != nil
2417 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2418 && isSamePtr(p1, p)
2419 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2420 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2421 && clobber(o0) && clobber(o1) && clobber(s0)
2422 -> @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr0 idx0 mem))
2423 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24]
2424 y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem)))
2425 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2426 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
2427 y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
2428 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2429 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2430 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1
2431 && mergePoint(b,x0,x1,x2,x3) != nil
2432 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2433 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2434 && clobber(o0) && clobber(o1) && clobber(s0)
2435 -> @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUloadidx <t> ptr idx mem))
2436
2437 // b[0]<<56 | b[1]<<48 | b[2]<<40 | b[3]<<32 | b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7] -> load 64-bit, reverse
2438 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
2439 y0:(MOVDnop x0:(MOVBUload [i0] {s} p mem)))
2440 y1:(MOVDnop x1:(MOVBUload [i1] {s} p mem)))
2441 y2:(MOVDnop x2:(MOVBUload [i2] {s} p mem)))
2442 y3:(MOVDnop x3:(MOVBUload [i3] {s} p mem)))
2443 y4:(MOVDnop x4:(MOVBUload [i4] {s} p mem)))
2444 y5:(MOVDnop x5:(MOVBUload [i5] {s} p mem)))
2445 y6:(MOVDnop x6:(MOVBUload [i6] {s} p mem)))
2446 y7:(MOVDnop x7:(MOVBUload [i7] {s} p mem)))
2447 && i1 == i0+1
2448 && i2 == i0+2
2449 && i3 == i0+3
2450 && i4 == i0+4
2451 && i5 == i0+5
2452 && i6 == i0+6
2453 && i7 == i0+7
2454 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2455 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
2456 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2457 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
2458 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
2459 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
2460 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
2461 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2462 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7)
2463 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2464 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7)
2465 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3)
2466 && clobber(o4) && clobber(o5) && clobber(s0)
2467 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [i0] p) mem))
2468 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
2469 y0:(MOVDnop x0:(MOVBUloadidx ptr0 idx0 mem)))
2470 y1:(MOVDnop x1:(MOVBUload [1] {s} p1:(ADD ptr1 idx1) mem)))
2471 y2:(MOVDnop x2:(MOVBUload [2] {s} p mem)))
2472 y3:(MOVDnop x3:(MOVBUload [3] {s} p mem)))
2473 y4:(MOVDnop x4:(MOVBUload [4] {s} p mem)))
2474 y5:(MOVDnop x5:(MOVBUload [5] {s} p mem)))
2475 y6:(MOVDnop x6:(MOVBUload [6] {s} p mem)))
2476 y7:(MOVDnop x7:(MOVBUload [7] {s} p mem)))
2477 && s == nil
2478 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2479 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
2480 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2481 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
2482 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
2483 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
2484 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
2485 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2486 && isSamePtr(p1, p)
2487 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2488 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7)
2489 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2490 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7)
2491 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3)
2492 && clobber(o4) && clobber(o5) && clobber(s0)
2493 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDloadidx <t> ptr0 idx0 mem))
2494 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56]
2495 y0:(MOVDnop x0:(MOVBUloadidx ptr idx mem)))
2496 y1:(MOVDnop x1:(MOVBUloadidx ptr (ADDconst [1] idx) mem)))
2497 y2:(MOVDnop x2:(MOVBUloadidx ptr (ADDconst [2] idx) mem)))
2498 y3:(MOVDnop x3:(MOVBUloadidx ptr (ADDconst [3] idx) mem)))
2499 y4:(MOVDnop x4:(MOVBUloadidx ptr (ADDconst [4] idx) mem)))
2500 y5:(MOVDnop x5:(MOVBUloadidx ptr (ADDconst [5] idx) mem)))
2501 y6:(MOVDnop x6:(MOVBUloadidx ptr (ADDconst [6] idx) mem)))
2502 y7:(MOVDnop x7:(MOVBUloadidx ptr (ADDconst [7] idx) mem)))
2503 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1
2504 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1
2505 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1
2506 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1
2507 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1
2508 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1
2509 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil
2510 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3)
2511 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7)
2512 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3)
2513 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7)
2514 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3)
2515 && clobber(o4) && clobber(o5) && clobber(s0)
2516 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDloadidx <t> ptr idx mem))
2517
2518 // Combine zero stores into larger (unaligned) stores.
2519 (MOVBstorezero [i] {s} ptr0 x:(MOVBstorezero [j] {s} ptr1 mem))
2520 && x.Uses == 1
2521 && areAdjacentOffsets(i,j,1)
2522 && is32Bit(min(i,j))
2523 && isSamePtr(ptr0, ptr1)
2524 && clobber(x)
2525 -> (MOVHstorezero [min(i,j)] {s} ptr0 mem)
2526 (MOVBstorezero [1] {s} (ADD ptr0 idx0) x:(MOVBstorezeroidx ptr1 idx1 mem))
2527 && x.Uses == 1
2528 && s == nil
2529 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2530 && clobber(x)
2531 -> (MOVHstorezeroidx ptr1 idx1 mem)
2532 (MOVBstorezeroidx ptr (ADDconst [1] idx) x:(MOVBstorezeroidx ptr idx mem))
2533 && x.Uses == 1
2534 && clobber(x)
2535 -> (MOVHstorezeroidx ptr idx mem)
2536 (MOVHstorezero [i] {s} ptr0 x:(MOVHstorezero [j] {s} ptr1 mem))
2537 && x.Uses == 1
2538 && areAdjacentOffsets(i,j,2)
2539 && is32Bit(min(i,j))
2540 && isSamePtr(ptr0, ptr1)
2541 && clobber(x)
2542 -> (MOVWstorezero [min(i,j)] {s} ptr0 mem)
2543 (MOVHstorezero [2] {s} (ADD ptr0 idx0) x:(MOVHstorezeroidx ptr1 idx1 mem))
2544 && x.Uses == 1
2545 && s == nil
2546 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2547 && clobber(x)
2548 -> (MOVWstorezeroidx ptr1 idx1 mem)
2549 (MOVHstorezeroidx ptr (ADDconst [2] idx) x:(MOVHstorezeroidx ptr idx mem))
2550 && x.Uses == 1
2551 && clobber(x)
2552 -> (MOVWstorezeroidx ptr idx mem)
2553 (MOVHstorezero [2] {s} (ADDshiftLL [1] ptr0 idx0) x:(MOVHstorezeroidx2 ptr1 idx1 mem))
2554 && x.Uses == 1
2555 && s == nil
2556 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2557 && clobber(x)
2558 -> (MOVWstorezeroidx ptr1 (SLLconst <idx1.Type> [1] idx1) mem)
2559 (MOVWstorezero [i] {s} ptr0 x:(MOVWstorezero [j] {s} ptr1 mem))
2560 && x.Uses == 1
2561 && areAdjacentOffsets(i,j,4)
2562 && is32Bit(min(i,j))
2563 && isSamePtr(ptr0, ptr1)
2564 && clobber(x)
2565 -> (MOVDstorezero [min(i,j)] {s} ptr0 mem)
2566 (MOVWstorezero [4] {s} (ADD ptr0 idx0) x:(MOVWstorezeroidx ptr1 idx1 mem))
2567 && x.Uses == 1
2568 && s == nil
2569 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2570 && clobber(x)
2571 -> (MOVDstorezeroidx ptr1 idx1 mem)
2572 (MOVWstorezeroidx ptr (ADDconst [4] idx) x:(MOVWstorezeroidx ptr idx mem))
2573 && x.Uses == 1
2574 && clobber(x)
2575 -> (MOVDstorezeroidx ptr idx mem)
2576 (MOVWstorezero [4] {s} (ADDshiftLL [2] ptr0 idx0) x:(MOVWstorezeroidx4 ptr1 idx1 mem))
2577 && x.Uses == 1
2578 && s == nil
2579 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2580 && clobber(x)
2581 -> (MOVDstorezeroidx ptr1 (SLLconst <idx1.Type> [2] idx1) mem)
2582 (MOVDstorezero [i] {s} ptr0 x:(MOVDstorezero [j] {s} ptr1 mem))
2583 && x.Uses == 1
2584 && areAdjacentOffsets(i,j,8)
2585 && is32Bit(min(i,j))
2586 && isSamePtr(ptr0, ptr1)
2587 && clobber(x)
2588 -> (MOVQstorezero [min(i,j)] {s} ptr0 mem)
2589 (MOVDstorezero [8] {s} p0:(ADD ptr0 idx0) x:(MOVDstorezeroidx ptr1 idx1 mem))
2590 && x.Uses == 1
2591 && s == nil
2592 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2593 && clobber(x)
2594 -> (MOVQstorezero [0] {s} p0 mem)
2595 (MOVDstorezero [8] {s} p0:(ADDshiftLL [3] ptr0 idx0) x:(MOVDstorezeroidx8 ptr1 idx1 mem))
2596 && x.Uses == 1
2597 && s == nil
2598 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2599 && clobber(x)
2600 -> (MOVQstorezero [0] {s} p0 mem)
2601
2602 // Combine stores into larger (unaligned) stores.
2603 (MOVBstore [i] {s} ptr0 (SRLconst [8] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
2604 && x.Uses == 1
2605 && isSamePtr(ptr0, ptr1)
2606 && clobber(x)
2607 -> (MOVHstore [i-1] {s} ptr0 w mem)
2608 (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [8] w) x:(MOVBstoreidx ptr1 idx1 w mem))
2609 && x.Uses == 1
2610 && s == nil
2611 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2612 && clobber(x)
2613 -> (MOVHstoreidx ptr1 idx1 w mem)
2614 (MOVBstoreidx ptr (ADDconst [1] idx) (SRLconst [8] w) x:(MOVBstoreidx ptr idx w mem))
2615 && x.Uses == 1
2616 && clobber(x)
2617 -> (MOVHstoreidx ptr idx w mem)
2618 (MOVBstore [i] {s} ptr0 (UBFX [armBFAuxInt(8, 8)] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
2619 && x.Uses == 1
2620 && isSamePtr(ptr0, ptr1)
2621 && clobber(x)
2622 -> (MOVHstore [i-1] {s} ptr0 w mem)
2623 (MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(8, 8)] w) x:(MOVBstoreidx ptr1 idx1 w mem))
2624 && x.Uses == 1
2625 && s == nil
2626 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2627 && clobber(x)
2628 -> (MOVHstoreidx ptr1 idx1 w mem)
2629 (MOVBstore [i] {s} ptr0 (UBFX [armBFAuxInt(8, 24)] w) x:(MOVBstore [i-1] {s} ptr1 w mem))
2630 && x.Uses == 1
2631 && isSamePtr(ptr0, ptr1)
2632 && clobber(x)
2633 -> (MOVHstore [i-1] {s} ptr0 w mem)
2634 (MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(8, 24)] w) x:(MOVBstoreidx ptr1 idx1 w mem))
2635 && x.Uses == 1
2636 && s == nil
2637 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2638 && clobber(x)
2639 -> (MOVHstoreidx ptr1 idx1 w mem)
2640 (MOVBstore [i] {s} ptr0 (SRLconst [8] (MOVDreg w)) x:(MOVBstore [i-1] {s} ptr1 w mem))
2641 && x.Uses == 1
2642 && isSamePtr(ptr0, ptr1)
2643 && clobber(x)
2644 -> (MOVHstore [i-1] {s} ptr0 w mem)
2645 (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [8] (MOVDreg w)) x:(MOVBstoreidx ptr1 idx1 w mem))
2646 && x.Uses == 1
2647 && s == nil
2648 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2649 && clobber(x)
2650 -> (MOVHstoreidx ptr1 idx1 w mem)
2651 (MOVBstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVBstore [i-1] {s} ptr1 w0:(SRLconst [j-8] w) mem))
2652 && x.Uses == 1
2653 && isSamePtr(ptr0, ptr1)
2654 && clobber(x)
2655 -> (MOVHstore [i-1] {s} ptr0 w0 mem)
2656 (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVBstoreidx ptr1 idx1 w0:(SRLconst [j-8] w) mem))
2657 && x.Uses == 1
2658 && s == nil
2659 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2660 && clobber(x)
2661 -> (MOVHstoreidx ptr1 idx1 w0 mem)
2662 (MOVBstore [i] {s} ptr0 (UBFX [bfc] w) x:(MOVBstore [i-1] {s} ptr1 w0:(UBFX [bfc2] w) mem))
2663 && x.Uses == 1
2664 && isSamePtr(ptr0, ptr1)
2665 && getARM64BFwidth(bfc) == 32 - getARM64BFlsb(bfc)
2666 && getARM64BFwidth(bfc2) == 32 - getARM64BFlsb(bfc2)
2667 && getARM64BFlsb(bfc2) == getARM64BFlsb(bfc) - 8
2668 && clobber(x)
2669 -> (MOVHstore [i-1] {s} ptr0 w0 mem)
2670 (MOVBstore [1] {s} (ADD ptr0 idx0) (UBFX [bfc] w) x:(MOVBstoreidx ptr1 idx1 w0:(UBFX [bfc2] w) mem))
2671 && x.Uses == 1
2672 && s == nil
2673 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2674 && getARM64BFwidth(bfc) == 32 - getARM64BFlsb(bfc)
2675 && getARM64BFwidth(bfc2) == 32 - getARM64BFlsb(bfc2)
2676 && getARM64BFlsb(bfc2) == getARM64BFlsb(bfc) - 8
2677 && clobber(x)
2678 -> (MOVHstoreidx ptr1 idx1 w0 mem)
2679 (MOVBstore [i] {s} ptr0 (SRLconst [j] (MOVDreg w)) x:(MOVBstore [i-1] {s} ptr1 w0:(SRLconst [j-8] (MOVDreg w)) mem))
2680 && x.Uses == 1
2681 && isSamePtr(ptr0, ptr1)
2682 && clobber(x)
2683 -> (MOVHstore [i-1] {s} ptr0 w0 mem)
2684 (MOVBstore [1] {s} (ADD ptr0 idx0) (SRLconst [j] (MOVDreg w)) x:(MOVBstoreidx ptr1 idx1 w0:(SRLconst [j-8] (MOVDreg w)) mem))
2685 && x.Uses == 1
2686 && s == nil
2687 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2688 && clobber(x)
2689 -> (MOVHstoreidx ptr1 idx1 w0 mem)
2690 (MOVHstore [i] {s} ptr0 (SRLconst [16] w) x:(MOVHstore [i-2] {s} ptr1 w mem))
2691 && x.Uses == 1
2692 && isSamePtr(ptr0, ptr1)
2693 && clobber(x)
2694 -> (MOVWstore [i-2] {s} ptr0 w mem)
2695 (MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [16] w) x:(MOVHstoreidx ptr1 idx1 w mem))
2696 && x.Uses == 1
2697 && s == nil
2698 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2699 && clobber(x)
2700 -> (MOVWstoreidx ptr1 idx1 w mem)
2701 (MOVHstoreidx ptr (ADDconst [2] idx) (SRLconst [16] w) x:(MOVHstoreidx ptr idx w mem))
2702 && x.Uses == 1
2703 && clobber(x)
2704 -> (MOVWstoreidx ptr idx w mem)
2705 (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [16] w) x:(MOVHstoreidx2 ptr1 idx1 w mem))
2706 && x.Uses == 1
2707 && s == nil
2708 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2709 && clobber(x)
2710 -> (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
2711 (MOVHstore [i] {s} ptr0 (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstore [i-2] {s} ptr1 w mem))
2712 && x.Uses == 1
2713 && isSamePtr(ptr0, ptr1)
2714 && clobber(x)
2715 -> (MOVWstore [i-2] {s} ptr0 w mem)
2716 (MOVHstore [2] {s} (ADD ptr0 idx0) (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstoreidx ptr1 idx1 w mem))
2717 && x.Uses == 1
2718 && s == nil
2719 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2720 && clobber(x)
2721 -> (MOVWstoreidx ptr1 idx1 w mem)
2722 (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (UBFX [armBFAuxInt(16, 16)] w) x:(MOVHstoreidx2 ptr1 idx1 w mem))
2723 && x.Uses == 1
2724 && s == nil
2725 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2726 && clobber(x)
2727 -> (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
2728 (MOVHstore [i] {s} ptr0 (SRLconst [16] (MOVDreg w)) x:(MOVHstore [i-2] {s} ptr1 w mem))
2729 && x.Uses == 1
2730 && isSamePtr(ptr0, ptr1)
2731 && clobber(x)
2732 -> (MOVWstore [i-2] {s} ptr0 w mem)
2733 (MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [16] (MOVDreg w)) x:(MOVHstoreidx ptr1 idx1 w mem))
2734 && x.Uses == 1
2735 && s == nil
2736 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2737 && clobber(x)
2738 -> (MOVWstoreidx ptr1 idx1 w mem)
2739 (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [16] (MOVDreg w)) x:(MOVHstoreidx2 ptr1 idx1 w mem))
2740 && x.Uses == 1
2741 && s == nil
2742 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2743 && clobber(x)
2744 -> (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w mem)
2745 (MOVHstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVHstore [i-2] {s} ptr1 w0:(SRLconst [j-16] w) mem))
2746 && x.Uses == 1
2747 && isSamePtr(ptr0, ptr1)
2748 && clobber(x)
2749 -> (MOVWstore [i-2] {s} ptr0 w0 mem)
2750 (MOVHstore [2] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVHstoreidx ptr1 idx1 w0:(SRLconst [j-16] w) mem))
2751 && x.Uses == 1
2752 && s == nil
2753 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2754 && clobber(x)
2755 -> (MOVWstoreidx ptr1 idx1 w0 mem)
2756 (MOVHstore [2] {s} (ADDshiftLL [1] ptr0 idx0) (SRLconst [j] w) x:(MOVHstoreidx2 ptr1 idx1 w0:(SRLconst [j-16] w) mem))
2757 && x.Uses == 1
2758 && s == nil
2759 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2760 && clobber(x)
2761 -> (MOVWstoreidx ptr1 (SLLconst <idx1.Type> [1] idx1) w0 mem)
2762 (MOVWstore [i] {s} ptr0 (SRLconst [32] w) x:(MOVWstore [i-4] {s} ptr1 w mem))
2763 && x.Uses == 1
2764 && isSamePtr(ptr0, ptr1)
2765 && clobber(x)
2766 -> (MOVDstore [i-4] {s} ptr0 w mem)
2767 (MOVWstore [4] {s} (ADD ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx ptr1 idx1 w mem))
2768 && x.Uses == 1
2769 && s == nil
2770 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2771 && clobber(x)
2772 -> (MOVDstoreidx ptr1 idx1 w mem)
2773 (MOVWstoreidx ptr (ADDconst [4] idx) (SRLconst [32] w) x:(MOVWstoreidx ptr idx w mem))
2774 && x.Uses == 1
2775 && clobber(x)
2776 -> (MOVDstoreidx ptr idx w mem)
2777 (MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [32] w) x:(MOVWstoreidx4 ptr1 idx1 w mem))
2778 && x.Uses == 1
2779 && s == nil
2780 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2781 && clobber(x)
2782 -> (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w mem)
2783 (MOVWstore [i] {s} ptr0 (SRLconst [j] w) x:(MOVWstore [i-4] {s} ptr1 w0:(SRLconst [j-32] w) mem))
2784 && x.Uses == 1
2785 && isSamePtr(ptr0, ptr1)
2786 && clobber(x)
2787 -> (MOVDstore [i-4] {s} ptr0 w0 mem)
2788 (MOVWstore [4] {s} (ADD ptr0 idx0) (SRLconst [j] w) x:(MOVWstoreidx ptr1 idx1 w0:(SRLconst [j-32] w) mem))
2789 && x.Uses == 1
2790 && s == nil
2791 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2792 && clobber(x)
2793 -> (MOVDstoreidx ptr1 idx1 w0 mem)
2794 (MOVWstore [4] {s} (ADDshiftLL [2] ptr0 idx0) (SRLconst [j] w) x:(MOVWstoreidx4 ptr1 idx1 w0:(SRLconst [j-32] w) mem))
2795 && x.Uses == 1
2796 && s == nil
2797 && isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1)
2798 && clobber(x)
2799 -> (MOVDstoreidx ptr1 (SLLconst <idx1.Type> [2] idx1) w0 mem)
2800 (MOVBstore [i] {s} ptr w
2801 x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] w)
2802 x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] w)
2803 x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] w)
2804 x3:(MOVBstore [i-4] {s} ptr (SRLconst [32] w)
2805 x4:(MOVBstore [i-5] {s} ptr (SRLconst [40] w)
2806 x5:(MOVBstore [i-6] {s} ptr (SRLconst [48] w)
2807 x6:(MOVBstore [i-7] {s} ptr (SRLconst [56] w) mem))))))))
2808 && x0.Uses == 1
2809 && x1.Uses == 1
2810 && x2.Uses == 1
2811 && x3.Uses == 1
2812 && x4.Uses == 1
2813 && x5.Uses == 1
2814 && x6.Uses == 1
2815 && clobber(x0)
2816 && clobber(x1)
2817 && clobber(x2)
2818 && clobber(x3)
2819 && clobber(x4)
2820 && clobber(x5)
2821 && clobber(x6)
2822 -> (MOVDstore [i-7] {s} ptr (REV <w.Type> w) mem)
2823 (MOVBstore [7] {s} p w
2824 x0:(MOVBstore [6] {s} p (SRLconst [8] w)
2825 x1:(MOVBstore [5] {s} p (SRLconst [16] w)
2826 x2:(MOVBstore [4] {s} p (SRLconst [24] w)
2827 x3:(MOVBstore [3] {s} p (SRLconst [32] w)
2828 x4:(MOVBstore [2] {s} p (SRLconst [40] w)
2829 x5:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [48] w)
2830 x6:(MOVBstoreidx ptr0 idx0 (SRLconst [56] w) mem))))))))
2831 && x0.Uses == 1
2832 && x1.Uses == 1
2833 && x2.Uses == 1
2834 && x3.Uses == 1
2835 && x4.Uses == 1
2836 && x5.Uses == 1
2837 && x6.Uses == 1
2838 && s == nil
2839 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2840 && isSamePtr(p1, p)
2841 && clobber(x0)
2842 && clobber(x1)
2843 && clobber(x2)
2844 && clobber(x3)
2845 && clobber(x4)
2846 && clobber(x5)
2847 && clobber(x6)
2848 -> (MOVDstoreidx ptr0 idx0 (REV <w.Type> w) mem)
2849 (MOVBstore [i] {s} ptr w
2850 x0:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 24)] w)
2851 x1:(MOVBstore [i-2] {s} ptr (UBFX [armBFAuxInt(16, 16)] w)
2852 x2:(MOVBstore [i-3] {s} ptr (UBFX [armBFAuxInt(24, 8)] w) mem))))
2853 && x0.Uses == 1
2854 && x1.Uses == 1
2855 && x2.Uses == 1
2856 && clobber(x0)
2857 && clobber(x1)
2858 && clobber(x2)
2859 -> (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
2860 (MOVBstore [3] {s} p w
2861 x0:(MOVBstore [2] {s} p (UBFX [armBFAuxInt(8, 24)] w)
2862 x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (UBFX [armBFAuxInt(16, 16)] w)
2863 x2:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(24, 8)] w) mem))))
2864 && x0.Uses == 1
2865 && x1.Uses == 1
2866 && x2.Uses == 1
2867 && s == nil
2868 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2869 && isSamePtr(p1, p)
2870 && clobber(x0)
2871 && clobber(x1)
2872 && clobber(x2)
2873 -> (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
2874 (MOVBstoreidx ptr (ADDconst [3] idx) w
2875 x0:(MOVBstoreidx ptr (ADDconst [2] idx) (UBFX [armBFAuxInt(8, 24)] w)
2876 x1:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(16, 16)] w)
2877 x2:(MOVBstoreidx ptr idx (UBFX [armBFAuxInt(24, 8)] w) mem))))
2878 && x0.Uses == 1
2879 && x1.Uses == 1
2880 && x2.Uses == 1
2881 && clobber(x0)
2882 && clobber(x1)
2883 && clobber(x2)
2884 -> (MOVWstoreidx ptr idx (REVW <w.Type> w) mem)
2885 (MOVBstoreidx ptr idx w
2886 x0:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(8, 24)] w)
2887 x1:(MOVBstoreidx ptr (ADDconst [2] idx) (UBFX [armBFAuxInt(16, 16)] w)
2888 x2:(MOVBstoreidx ptr (ADDconst [3] idx) (UBFX [armBFAuxInt(24, 8)] w) mem))))
2889 && x0.Uses == 1
2890 && x1.Uses == 1
2891 && x2.Uses == 1
2892 && clobber(x0)
2893 && clobber(x1)
2894 && clobber(x2)
2895 -> (MOVWstoreidx ptr idx w mem)
2896 (MOVBstore [i] {s} ptr w
2897 x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w))
2898 x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] (MOVDreg w))
2899 x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] (MOVDreg w)) mem))))
2900 && x0.Uses == 1
2901 && x1.Uses == 1
2902 && x2.Uses == 1
2903 && clobber(x0)
2904 && clobber(x1)
2905 && clobber(x2)
2906 -> (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
2907 (MOVBstore [3] {s} p w
2908 x0:(MOVBstore [2] {s} p (SRLconst [8] (MOVDreg w))
2909 x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [16] (MOVDreg w))
2910 x2:(MOVBstoreidx ptr0 idx0 (SRLconst [24] (MOVDreg w)) mem))))
2911 && x0.Uses == 1
2912 && x1.Uses == 1
2913 && x2.Uses == 1
2914 && s == nil
2915 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2916 && isSamePtr(p1, p)
2917 && clobber(x0)
2918 && clobber(x1)
2919 && clobber(x2)
2920 -> (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
2921 (MOVBstore [i] {s} ptr w
2922 x0:(MOVBstore [i-1] {s} ptr (SRLconst [8] w)
2923 x1:(MOVBstore [i-2] {s} ptr (SRLconst [16] w)
2924 x2:(MOVBstore [i-3] {s} ptr (SRLconst [24] w) mem))))
2925 && x0.Uses == 1
2926 && x1.Uses == 1
2927 && x2.Uses == 1
2928 && clobber(x0)
2929 && clobber(x1)
2930 && clobber(x2)
2931 -> (MOVWstore [i-3] {s} ptr (REVW <w.Type> w) mem)
2932 (MOVBstore [3] {s} p w
2933 x0:(MOVBstore [2] {s} p (SRLconst [8] w)
2934 x1:(MOVBstore [1] {s} p1:(ADD ptr1 idx1) (SRLconst [16] w)
2935 x2:(MOVBstoreidx ptr0 idx0 (SRLconst [24] w) mem))))
2936 && x0.Uses == 1
2937 && x1.Uses == 1
2938 && x2.Uses == 1
2939 && s == nil
2940 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2941 && isSamePtr(p1, p)
2942 && clobber(x0)
2943 && clobber(x1)
2944 && clobber(x2)
2945 -> (MOVWstoreidx ptr0 idx0 (REVW <w.Type> w) mem)
2946 (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] w) mem))
2947 && x.Uses == 1
2948 && clobber(x)
2949 -> (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
2950 (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] w) mem))
2951 && x.Uses == 1
2952 && s == nil
2953 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2954 && clobber(x)
2955 -> (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
2956 (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 8)] w) mem))
2957 && x.Uses == 1
2958 && clobber(x)
2959 -> (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
2960 (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(8, 8)] w) mem))
2961 && x.Uses == 1
2962 && s == nil
2963 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2964 && clobber(x)
2965 -> (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
2966 (MOVBstoreidx ptr (ADDconst [1] idx) w x:(MOVBstoreidx ptr idx (UBFX [armBFAuxInt(8, 8)] w) mem))
2967 && x.Uses == 1
2968 && clobber(x)
2969 -> (MOVHstoreidx ptr idx (REV16W <w.Type> w) mem)
2970 (MOVBstoreidx ptr idx w x:(MOVBstoreidx ptr (ADDconst [1] idx) (UBFX [armBFAuxInt(8, 8)] w) mem))
2971 && x.Uses == 1
2972 && clobber(x)
2973 -> (MOVHstoreidx ptr idx w mem)
2974 (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w)) mem))
2975 && x.Uses == 1
2976 && clobber(x)
2977 -> (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
2978 (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] (MOVDreg w)) mem))
2979 && x.Uses == 1
2980 && s == nil
2981 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2982 && clobber(x)
2983 -> (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
2984 (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (UBFX [armBFAuxInt(8, 24)] w) mem))
2985 && x.Uses == 1
2986 && clobber(x)
2987 -> (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
2988 (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (UBFX [armBFAuxInt(8, 24)] w) mem))
2989 && x.Uses == 1
2990 && s == nil
2991 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
2992 && clobber(x)
2993 -> (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
2994 (MOVBstore [i] {s} ptr w x:(MOVBstore [i-1] {s} ptr (SRLconst [8] (MOVDreg w)) mem))
2995 && x.Uses == 1
2996 && clobber(x)
2997 -> (MOVHstore [i-1] {s} ptr (REV16W <w.Type> w) mem)
2998 (MOVBstore [1] {s} (ADD ptr1 idx1) w x:(MOVBstoreidx ptr0 idx0 (SRLconst [8] (MOVDreg w)) mem))
2999 && x.Uses == 1
3000 && s == nil
3001 && (isSamePtr(ptr0, ptr1) && isSamePtr(idx0, idx1) || isSamePtr(ptr0, idx1) && isSamePtr(idx0, ptr1))
3002 && clobber(x)
3003 -> (MOVHstoreidx ptr0 idx0 (REV16W <w.Type> w) mem)
3004
3005 // FP simplification
3006 (FNEGS (FMULS x y)) -> (FNMULS x y)
3007 (FNEGD (FMULD x y)) -> (FNMULD x y)
3008 (FMULS (FNEGS x) y) -> (FNMULS x y)
3009 (FMULD (FNEGD x) y) -> (FNMULD x y)
3010 (FNEGS (FNMULS x y)) -> (FMULS x y)
3011 (FNEGD (FNMULD x y)) -> (FMULD x y)
3012 (FNMULS (FNEGS x) y) -> (FMULS x y)
3013 (FNMULD (FNEGD x) y) -> (FMULD x y)
3014 (FADDS a (FMULS x y)) -> (FMADDS a x y)
3015 (FADDD a (FMULD x y)) -> (FMADDD a x y)
3016 (FSUBS a (FMULS x y)) -> (FMSUBS a x y)
3017 (FSUBD a (FMULD x y)) -> (FMSUBD a x y)
3018 (FSUBS (FMULS x y) a) -> (FNMSUBS a x y)
3019 (FSUBD (FMULD x y) a) -> (FNMSUBD a x y)
3020 (FADDS a (FNMULS x y)) -> (FMSUBS a x y)
3021 (FADDD a (FNMULD x y)) -> (FMSUBD a x y)
3022 (FSUBS a (FNMULS x y)) -> (FMADDS a x y)
3023 (FSUBD a (FNMULD x y)) -> (FMADDD a x y)
3024 (FSUBS (FNMULS x y) a) -> (FNMADDS a x y)
3025 (FSUBD (FNMULD x y) a) -> (FNMADDD a x y)
3026
3027 (MOVBUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read8(sym, off))])
3028 (MOVHUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read16(sym, off, config.BigEndian))])
3029 (MOVWUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read32(sym, off, config.BigEndian))])
3030 (MOVDload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read64(sym, off, config.BigEndian))])
View as plain text