github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/compile/internal/ssa/gen/ARM64.rules (about) 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 <config.fe.TypeInt64()> x y) [32]) 31 (Hmul32u x y) -> (SRAconst (UMULL <config.fe.TypeUInt64()> x y) [32]) 32 (Hmul16 x y) -> (SRAconst (MULW <config.fe.TypeInt32()> (SignExt16to32 x) (SignExt16to32 y)) [16]) 33 (Hmul16u x y) -> (SRLconst (MUL <config.fe.TypeUInt32()> (ZeroExt16to32 x) (ZeroExt16to32 y)) [16]) 34 (Hmul8 x y) -> (SRAconst (MULW <config.fe.TypeInt16()> (SignExt8to32 x) (SignExt8to32 y)) [8]) 35 (Hmul8u x y) -> (SRLconst (MUL <config.fe.TypeUInt16()> (ZeroExt8to32 x) (ZeroExt8to32 y)) [8]) 36 37 (Div64 x y) -> (DIV x y) 38 (Div64u x y) -> (UDIV x y) 39 (Div32 x y) -> (DIVW x y) 40 (Div32u x y) -> (UDIVW x y) 41 (Div16 x y) -> (DIVW (SignExt16to32 x) (SignExt16to32 y)) 42 (Div16u x y) -> (UDIVW (ZeroExt16to32 x) (ZeroExt16to32 y)) 43 (Div8 x y) -> (DIVW (SignExt8to32 x) (SignExt8to32 y)) 44 (Div8u x y) -> (UDIVW (ZeroExt8to32 x) (ZeroExt8to32 y)) 45 (Div32F x y) -> (FDIVS x y) 46 (Div64F x y) -> (FDIVD x y) 47 48 (Mod64 x y) -> (MOD x y) 49 (Mod64u x y) -> (UMOD x y) 50 (Mod32 x y) -> (MODW x y) 51 (Mod32u x y) -> (UMODW x y) 52 (Mod16 x y) -> (MODW (SignExt16to32 x) (SignExt16to32 y)) 53 (Mod16u x y) -> (UMODW (ZeroExt16to32 x) (ZeroExt16to32 y)) 54 (Mod8 x y) -> (MODW (SignExt8to32 x) (SignExt8to32 y)) 55 (Mod8u x y) -> (UMODW (ZeroExt8to32 x) (ZeroExt8to32 y)) 56 57 (Avg64u <t> x y) -> (ADD (ADD <t> (SRLconst <t> x [1]) (SRLconst <t> y [1])) (AND <t> (AND <t> x y) (MOVDconst [1]))) 58 59 (And64 x y) -> (AND x y) 60 (And32 x y) -> (AND x y) 61 (And16 x y) -> (AND x y) 62 (And8 x y) -> (AND x y) 63 64 (Or64 x y) -> (OR x y) 65 (Or32 x y) -> (OR x y) 66 (Or16 x y) -> (OR x y) 67 (Or8 x y) -> (OR x y) 68 69 (Xor64 x y) -> (XOR x y) 70 (Xor32 x y) -> (XOR x y) 71 (Xor16 x y) -> (XOR x y) 72 (Xor8 x y) -> (XOR x y) 73 74 // unary ops 75 (Neg64 x) -> (NEG x) 76 (Neg32 x) -> (NEG x) 77 (Neg16 x) -> (NEG x) 78 (Neg8 x) -> (NEG x) 79 (Neg32F x) -> (FNEGS x) 80 (Neg64F x) -> (FNEGD x) 81 82 (Com64 x) -> (MVN x) 83 (Com32 x) -> (MVN x) 84 (Com16 x) -> (MVN x) 85 (Com8 x) -> (MVN x) 86 87 (Sqrt x) -> (FSQRTD x) 88 89 // boolean ops -- booleans are represented with 0=false, 1=true 90 (AndB x y) -> (AND x y) 91 (OrB x y) -> (OR x y) 92 (EqB x y) -> (XOR (MOVDconst [1]) (XOR <config.fe.TypeBool()> x y)) 93 (NeqB x y) -> (XOR x y) 94 (Not x) -> (XOR (MOVDconst [1]) x) 95 96 // constant shifts 97 (Lsh64x64 x (MOVDconst [c])) && uint64(c) < 64 -> (SLLconst x [c]) 98 (Rsh64x64 x (MOVDconst [c])) && uint64(c) < 64 -> (SRAconst x [c]) 99 (Rsh64Ux64 x (MOVDconst [c])) && uint64(c) < 64 -> (SRLconst x [c]) 100 (Lsh32x64 x (MOVDconst [c])) && uint64(c) < 32 -> (SLLconst x [c]) 101 (Rsh32x64 x (MOVDconst [c])) && uint64(c) < 32 -> (SRAconst (SignExt32to64 x) [c]) 102 (Rsh32Ux64 x (MOVDconst [c])) && uint64(c) < 32 -> (SRLconst (ZeroExt32to64 x) [c]) 103 (Lsh16x64 x (MOVDconst [c])) && uint64(c) < 16 -> (SLLconst x [c]) 104 (Rsh16x64 x (MOVDconst [c])) && uint64(c) < 16 -> (SRAconst (SignExt16to64 x) [c]) 105 (Rsh16Ux64 x (MOVDconst [c])) && uint64(c) < 16 -> (SRLconst (ZeroExt16to64 x) [c]) 106 (Lsh8x64 x (MOVDconst [c])) && uint64(c) < 8 -> (SLLconst x [c]) 107 (Rsh8x64 x (MOVDconst [c])) && uint64(c) < 8 -> (SRAconst (SignExt8to64 x) [c]) 108 (Rsh8Ux64 x (MOVDconst [c])) && uint64(c) < 8 -> (SRLconst (ZeroExt8to64 x) [c]) 109 110 // large constant shifts 111 (Lsh64x64 _ (MOVDconst [c])) && uint64(c) >= 64 -> (MOVDconst [0]) 112 (Rsh64Ux64 _ (MOVDconst [c])) && uint64(c) >= 64 -> (MOVDconst [0]) 113 (Lsh32x64 _ (MOVDconst [c])) && uint64(c) >= 32 -> (MOVDconst [0]) 114 (Rsh32Ux64 _ (MOVDconst [c])) && uint64(c) >= 32 -> (MOVDconst [0]) 115 (Lsh16x64 _ (MOVDconst [c])) && uint64(c) >= 16 -> (MOVDconst [0]) 116 (Rsh16Ux64 _ (MOVDconst [c])) && uint64(c) >= 16 -> (MOVDconst [0]) 117 (Lsh8x64 _ (MOVDconst [c])) && uint64(c) >= 8 -> (MOVDconst [0]) 118 (Rsh8Ux64 _ (MOVDconst [c])) && uint64(c) >= 8 -> (MOVDconst [0]) 119 120 // large constant signed right shift, we leave the sign bit 121 (Rsh64x64 x (MOVDconst [c])) && uint64(c) >= 64 -> (SRAconst x [63]) 122 (Rsh32x64 x (MOVDconst [c])) && uint64(c) >= 32 -> (SRAconst (SignExt32to64 x) [63]) 123 (Rsh16x64 x (MOVDconst [c])) && uint64(c) >= 16 -> (SRAconst (SignExt16to64 x) [63]) 124 (Rsh8x64 x (MOVDconst [c])) && uint64(c) >= 8 -> (SRAconst (SignExt8to64 x) [63]) 125 126 // shifts 127 // hardware instruction uses only the low 6 bits of the shift 128 // we compare to 64 to ensure Go semantics for large shifts 129 (Lsh64x64 <t> x y) -> (CSELULT (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y)) 130 (Lsh64x32 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 131 (Lsh64x16 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 132 (Lsh64x8 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 133 134 (Lsh32x64 <t> x y) -> (CSELULT (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y)) 135 (Lsh32x32 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 136 (Lsh32x16 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 137 (Lsh32x8 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 138 139 (Lsh16x64 <t> x y) -> (CSELULT (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y)) 140 (Lsh16x32 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 141 (Lsh16x16 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 142 (Lsh16x8 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 143 144 (Lsh8x64 <t> x y) -> (CSELULT (SLL <t> x y) (Const64 <t> [0]) (CMPconst [64] y)) 145 (Lsh8x32 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 146 (Lsh8x16 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 147 (Lsh8x8 <t> x y) -> (CSELULT (SLL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 148 149 (Rsh64Ux64 <t> x y) -> (CSELULT (SRL <t> x y) (Const64 <t> [0]) (CMPconst [64] y)) 150 (Rsh64Ux32 <t> x y) -> (CSELULT (SRL <t> x (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 151 (Rsh64Ux16 <t> x y) -> (CSELULT (SRL <t> x (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 152 (Rsh64Ux8 <t> x y) -> (CSELULT (SRL <t> x (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 153 154 (Rsh32Ux64 <t> x y) -> (CSELULT (SRL <t> (ZeroExt32to64 x) y) (Const64 <t> [0]) (CMPconst [64] y)) 155 (Rsh32Ux32 <t> x y) -> (CSELULT (SRL <t> (ZeroExt32to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 156 (Rsh32Ux16 <t> x y) -> (CSELULT (SRL <t> (ZeroExt32to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 157 (Rsh32Ux8 <t> x y) -> (CSELULT (SRL <t> (ZeroExt32to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 158 159 (Rsh16Ux64 <t> x y) -> (CSELULT (SRL <t> (ZeroExt16to64 x) y) (Const64 <t> [0]) (CMPconst [64] y)) 160 (Rsh16Ux32 <t> x y) -> (CSELULT (SRL <t> (ZeroExt16to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 161 (Rsh16Ux16 <t> x y) -> (CSELULT (SRL <t> (ZeroExt16to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 162 (Rsh16Ux8 <t> x y) -> (CSELULT (SRL <t> (ZeroExt16to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 163 164 (Rsh8Ux64 <t> x y) -> (CSELULT (SRL <t> (ZeroExt8to64 x) y) (Const64 <t> [0]) (CMPconst [64] y)) 165 (Rsh8Ux32 <t> x y) -> (CSELULT (SRL <t> (ZeroExt8to64 x) (ZeroExt32to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt32to64 y))) 166 (Rsh8Ux16 <t> x y) -> (CSELULT (SRL <t> (ZeroExt8to64 x) (ZeroExt16to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt16to64 y))) 167 (Rsh8Ux8 <t> x y) -> (CSELULT (SRL <t> (ZeroExt8to64 x) (ZeroExt8to64 y)) (Const64 <t> [0]) (CMPconst [64] (ZeroExt8to64 y))) 168 169 (Rsh64x64 x y) -> (SRA x (CSELULT <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y))) 170 (Rsh64x32 x y) -> (SRA x (CSELULT <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y)))) 171 (Rsh64x16 x y) -> (SRA x (CSELULT <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y)))) 172 (Rsh64x8 x y) -> (SRA x (CSELULT <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y)))) 173 174 (Rsh32x64 x y) -> (SRA (SignExt32to64 x) (CSELULT <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y))) 175 (Rsh32x32 x y) -> (SRA (SignExt32to64 x) (CSELULT <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y)))) 176 (Rsh32x16 x y) -> (SRA (SignExt32to64 x) (CSELULT <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y)))) 177 (Rsh32x8 x y) -> (SRA (SignExt32to64 x) (CSELULT <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y)))) 178 179 (Rsh16x64 x y) -> (SRA (SignExt16to64 x) (CSELULT <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y))) 180 (Rsh16x32 x y) -> (SRA (SignExt16to64 x) (CSELULT <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y)))) 181 (Rsh16x16 x y) -> (SRA (SignExt16to64 x) (CSELULT <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y)))) 182 (Rsh16x8 x y) -> (SRA (SignExt16to64 x) (CSELULT <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y)))) 183 184 (Rsh8x64 x y) -> (SRA (SignExt8to64 x) (CSELULT <y.Type> y (Const64 <y.Type> [63]) (CMPconst [64] y))) 185 (Rsh8x32 x y) -> (SRA (SignExt8to64 x) (CSELULT <y.Type> (ZeroExt32to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt32to64 y)))) 186 (Rsh8x16 x y) -> (SRA (SignExt8to64 x) (CSELULT <y.Type> (ZeroExt16to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt16to64 y)))) 187 (Rsh8x8 x y) -> (SRA (SignExt8to64 x) (CSELULT <y.Type> (ZeroExt8to64 y) (Const64 <y.Type> [63]) (CMPconst [64] (ZeroExt8to64 y)))) 188 189 (Lrot64 x [c]) -> (RORconst x [64-c&63]) 190 (Lrot32 x [c]) -> (RORWconst x [32-c&31]) 191 (Lrot16 <t> x [c]) -> (OR (SLLconst <t> x [c&15]) (SRLconst <t> (ZeroExt16to64 x) [16-c&15])) 192 (Lrot8 <t> x [c]) -> (OR (SLLconst <t> x [c&7]) (SRLconst <t> (ZeroExt8to64 x) [8-c&7])) 193 194 // constants 195 (Const64 [val]) -> (MOVDconst [val]) 196 (Const32 [val]) -> (MOVDconst [val]) 197 (Const16 [val]) -> (MOVDconst [val]) 198 (Const8 [val]) -> (MOVDconst [val]) 199 (Const32F [val]) -> (FMOVSconst [val]) 200 (Const64F [val]) -> (FMOVDconst [val]) 201 (ConstNil) -> (MOVDconst [0]) 202 (ConstBool [b]) -> (MOVDconst [b]) 203 204 // truncations 205 // Because we ignore high parts of registers, truncates are just copies. 206 (Trunc16to8 x) -> x 207 (Trunc32to8 x) -> x 208 (Trunc32to16 x) -> x 209 (Trunc64to8 x) -> x 210 (Trunc64to16 x) -> x 211 (Trunc64to32 x) -> x 212 213 // Zero-/Sign-extensions 214 (ZeroExt8to16 x) -> (MOVBUreg x) 215 (ZeroExt8to32 x) -> (MOVBUreg x) 216 (ZeroExt16to32 x) -> (MOVHUreg x) 217 (ZeroExt8to64 x) -> (MOVBUreg x) 218 (ZeroExt16to64 x) -> (MOVHUreg x) 219 (ZeroExt32to64 x) -> (MOVWUreg x) 220 221 (SignExt8to16 x) -> (MOVBreg x) 222 (SignExt8to32 x) -> (MOVBreg x) 223 (SignExt16to32 x) -> (MOVHreg x) 224 (SignExt8to64 x) -> (MOVBreg x) 225 (SignExt16to64 x) -> (MOVHreg x) 226 (SignExt32to64 x) -> (MOVWreg x) 227 228 // float <-> int conversion 229 (Cvt32to32F x) -> (SCVTFWS x) 230 (Cvt32to64F x) -> (SCVTFWD x) 231 (Cvt64to32F x) -> (SCVTFS x) 232 (Cvt64to64F x) -> (SCVTFD x) 233 (Cvt32Uto32F x) -> (UCVTFWS x) 234 (Cvt32Uto64F x) -> (UCVTFWD x) 235 (Cvt64Uto32F x) -> (UCVTFS x) 236 (Cvt64Uto64F x) -> (UCVTFD x) 237 (Cvt32Fto32 x) -> (FCVTZSSW x) 238 (Cvt64Fto32 x) -> (FCVTZSDW x) 239 (Cvt32Fto64 x) -> (FCVTZSS x) 240 (Cvt64Fto64 x) -> (FCVTZSD x) 241 (Cvt32Fto32U x) -> (FCVTZUSW x) 242 (Cvt64Fto32U x) -> (FCVTZUDW x) 243 (Cvt32Fto64U x) -> (FCVTZUS x) 244 (Cvt64Fto64U x) -> (FCVTZUD x) 245 (Cvt32Fto64F x) -> (FCVTSD x) 246 (Cvt64Fto32F x) -> (FCVTDS x) 247 248 // comparisons 249 (Eq8 x y) -> (Equal (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y))) 250 (Eq16 x y) -> (Equal (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y))) 251 (Eq32 x y) -> (Equal (CMPW x y)) 252 (Eq64 x y) -> (Equal (CMP x y)) 253 (EqPtr x y) -> (Equal (CMP x y)) 254 (Eq32F x y) -> (Equal (FCMPS x y)) 255 (Eq64F x y) -> (Equal (FCMPD x y)) 256 257 (Neq8 x y) -> (NotEqual (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y))) 258 (Neq16 x y) -> (NotEqual (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y))) 259 (Neq32 x y) -> (NotEqual (CMPW x y)) 260 (Neq64 x y) -> (NotEqual (CMP x y)) 261 (NeqPtr x y) -> (NotEqual (CMP x y)) 262 (Neq32F x y) -> (NotEqual (FCMPS x y)) 263 (Neq64F x y) -> (NotEqual (FCMPD x y)) 264 265 (Less8 x y) -> (LessThan (CMPW (SignExt8to32 x) (SignExt8to32 y))) 266 (Less16 x y) -> (LessThan (CMPW (SignExt16to32 x) (SignExt16to32 y))) 267 (Less32 x y) -> (LessThan (CMPW x y)) 268 (Less64 x y) -> (LessThan (CMP x y)) 269 (Less32F x y) -> (GreaterThan (FCMPS y x)) // reverse operands to work around NaN 270 (Less64F x y) -> (GreaterThan (FCMPD y x)) // reverse operands to work around NaN 271 272 (Less8U x y) -> (LessThanU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y))) 273 (Less16U x y) -> (LessThanU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y))) 274 (Less32U x y) -> (LessThanU (CMPW x y)) 275 (Less64U x y) -> (LessThanU (CMP x y)) 276 277 (Leq8 x y) -> (LessEqual (CMPW (SignExt8to32 x) (SignExt8to32 y))) 278 (Leq16 x y) -> (LessEqual (CMPW (SignExt16to32 x) (SignExt16to32 y))) 279 (Leq32 x y) -> (LessEqual (CMPW x y)) 280 (Leq64 x y) -> (LessEqual (CMP x y)) 281 (Leq32F x y) -> (GreaterEqual (FCMPS y x)) // reverse operands to work around NaN 282 (Leq64F x y) -> (GreaterEqual (FCMPD y x)) // reverse operands to work around NaN 283 284 (Leq8U x y) -> (LessEqualU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y))) 285 (Leq16U x y) -> (LessEqualU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y))) 286 (Leq32U x y) -> (LessEqualU (CMPW x y)) 287 (Leq64U x y) -> (LessEqualU (CMP x y)) 288 289 (Greater8 x y) -> (GreaterThan (CMPW (SignExt8to32 x) (SignExt8to32 y))) 290 (Greater16 x y) -> (GreaterThan (CMPW (SignExt16to32 x) (SignExt16to32 y))) 291 (Greater32 x y) -> (GreaterThan (CMPW x y)) 292 (Greater64 x y) -> (GreaterThan (CMP x y)) 293 (Greater32F x y) -> (GreaterThan (FCMPS x y)) 294 (Greater64F x y) -> (GreaterThan (FCMPD x y)) 295 296 (Greater8U x y) -> (GreaterThanU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y))) 297 (Greater16U x y) -> (GreaterThanU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y))) 298 (Greater32U x y) -> (GreaterThanU (CMPW x y)) 299 (Greater64U x y) -> (GreaterThanU (CMP x y)) 300 301 (Geq8 x y) -> (GreaterEqual (CMPW (SignExt8to32 x) (SignExt8to32 y))) 302 (Geq16 x y) -> (GreaterEqual (CMPW (SignExt16to32 x) (SignExt16to32 y))) 303 (Geq32 x y) -> (GreaterEqual (CMPW x y)) 304 (Geq64 x y) -> (GreaterEqual (CMP x y)) 305 (Geq32F x y) -> (GreaterEqual (FCMPS x y)) 306 (Geq64F x y) -> (GreaterEqual (FCMPD x y)) 307 308 (Geq8U x y) -> (GreaterEqualU (CMPW (ZeroExt8to32 x) (ZeroExt8to32 y))) 309 (Geq16U x y) -> (GreaterEqualU (CMPW (ZeroExt16to32 x) (ZeroExt16to32 y))) 310 (Geq32U x y) -> (GreaterEqualU (CMPW x y)) 311 (Geq64U x y) -> (GreaterEqualU (CMP x y)) 312 313 (OffPtr [off] ptr:(SP)) -> (MOVDaddr [off] ptr) 314 (OffPtr [off] ptr) -> (ADDconst [off] ptr) 315 316 (Addr {sym} base) -> (MOVDaddr {sym} base) 317 318 // loads 319 (Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem) 320 (Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem) 321 (Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem) 322 (Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem) 323 (Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem) 324 (Load <t> ptr mem) && (is32BitInt(t) && isSigned(t)) -> (MOVWload ptr mem) 325 (Load <t> ptr mem) && (is32BitInt(t) && !isSigned(t)) -> (MOVWUload ptr mem) 326 (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem) 327 (Load <t> ptr mem) && is32BitFloat(t) -> (FMOVSload ptr mem) 328 (Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem) 329 330 // stores 331 (Store [1] ptr val mem) -> (MOVBstore ptr val mem) 332 (Store [2] ptr val mem) -> (MOVHstore ptr val mem) 333 (Store [4] ptr val mem) && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem) 334 (Store [8] ptr val mem) && !is64BitFloat(val.Type) -> (MOVDstore ptr val mem) 335 (Store [4] ptr val mem) && is32BitFloat(val.Type) -> (FMOVSstore ptr val mem) 336 (Store [8] ptr val mem) && is64BitFloat(val.Type) -> (FMOVDstore ptr val mem) 337 338 // zeroing 339 (Zero [s] _ mem) && SizeAndAlign(s).Size() == 0 -> mem 340 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 1 -> (MOVBstore ptr (MOVDconst [0]) mem) 341 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 2 -> (MOVHstore ptr (MOVDconst [0]) mem) 342 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 4 -> (MOVWstore ptr (MOVDconst [0]) mem) 343 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 8 -> (MOVDstore ptr (MOVDconst [0]) mem) 344 345 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 3 -> 346 (MOVBstore [2] ptr (MOVDconst [0]) 347 (MOVHstore ptr (MOVDconst [0]) mem)) 348 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 5 -> 349 (MOVBstore [4] ptr (MOVDconst [0]) 350 (MOVWstore ptr (MOVDconst [0]) mem)) 351 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 6 -> 352 (MOVHstore [4] ptr (MOVDconst [0]) 353 (MOVWstore ptr (MOVDconst [0]) mem)) 354 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 7 -> 355 (MOVBstore [6] ptr (MOVDconst [0]) 356 (MOVHstore [4] ptr (MOVDconst [0]) 357 (MOVWstore ptr (MOVDconst [0]) mem))) 358 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 12 -> 359 (MOVWstore [8] ptr (MOVDconst [0]) 360 (MOVDstore ptr (MOVDconst [0]) mem)) 361 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 16 -> 362 (MOVDstore [8] ptr (MOVDconst [0]) 363 (MOVDstore ptr (MOVDconst [0]) mem)) 364 (Zero [s] ptr mem) && SizeAndAlign(s).Size() == 24 -> 365 (MOVDstore [16] ptr (MOVDconst [0]) 366 (MOVDstore [8] ptr (MOVDconst [0]) 367 (MOVDstore ptr (MOVDconst [0]) mem))) 368 369 // strip off fractional word zeroing 370 (Zero [s] ptr mem) && SizeAndAlign(s).Size()%8 != 0 && SizeAndAlign(s).Size() > 8 -> 371 (Zero [MakeSizeAndAlign(SizeAndAlign(s).Size()%8, 1).Int64()] 372 (OffPtr <ptr.Type> ptr [SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%8]) 373 (Zero [MakeSizeAndAlign(SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%8, 1).Int64()] ptr mem)) 374 375 // medium zeroing uses a duff device 376 // 4, 8, and 128 are magic constants, see runtime/mkduff.go 377 (Zero [s] ptr mem) 378 && SizeAndAlign(s).Size()%8 == 0 && SizeAndAlign(s).Size() > 24 && SizeAndAlign(s).Size() <= 8*128 379 && !config.noDuffDevice -> 380 (DUFFZERO [4 * (128 - int64(SizeAndAlign(s).Size()/8))] ptr mem) 381 382 // large zeroing uses a loop 383 (Zero [s] ptr mem) 384 && SizeAndAlign(s).Size()%8 == 0 && (SizeAndAlign(s).Size() > 8*128 || config.noDuffDevice) -> 385 (LoweredZero 386 ptr 387 (ADDconst <ptr.Type> [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)] ptr) 388 mem) 389 390 // moves 391 (Move [s] _ _ mem) && SizeAndAlign(s).Size() == 0 -> mem 392 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 1 -> (MOVBstore dst (MOVBUload src mem) mem) 393 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 2 -> (MOVHstore dst (MOVHUload src mem) mem) 394 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 4 -> (MOVWstore dst (MOVWUload src mem) mem) 395 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 8 -> (MOVDstore dst (MOVDload src mem) mem) 396 397 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 3 -> 398 (MOVBstore [2] dst (MOVBUload [2] src mem) 399 (MOVHstore dst (MOVHUload src mem) mem)) 400 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 5 -> 401 (MOVBstore [4] dst (MOVBUload [4] src mem) 402 (MOVWstore dst (MOVWUload src mem) mem)) 403 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 6 -> 404 (MOVHstore [4] dst (MOVHUload [4] src mem) 405 (MOVWstore dst (MOVWUload src mem) mem)) 406 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 7 -> 407 (MOVBstore [6] dst (MOVBUload [6] src mem) 408 (MOVHstore [4] dst (MOVHUload [4] src mem) 409 (MOVWstore dst (MOVWUload src mem) mem))) 410 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 12 -> 411 (MOVWstore [8] dst (MOVWUload [8] src mem) 412 (MOVDstore dst (MOVDload src mem) mem)) 413 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 16 -> 414 (MOVDstore [8] dst (MOVDload [8] src mem) 415 (MOVDstore dst (MOVDload src mem) mem)) 416 (Move [s] dst src mem) && SizeAndAlign(s).Size() == 24 -> 417 (MOVDstore [16] dst (MOVDload [16] src mem) 418 (MOVDstore [8] dst (MOVDload [8] src mem) 419 (MOVDstore dst (MOVDload src mem) mem))) 420 421 // strip off fractional word move 422 (Move [s] dst src mem) && SizeAndAlign(s).Size()%8 != 0 && SizeAndAlign(s).Size() > 8 -> 423 (Move [MakeSizeAndAlign(SizeAndAlign(s).Size()%8, 1).Int64()] 424 (OffPtr <dst.Type> dst [SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%8]) 425 (OffPtr <src.Type> src [SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%8]) 426 (Move [MakeSizeAndAlign(SizeAndAlign(s).Size()-SizeAndAlign(s).Size()%8, 1).Int64()] dst src mem)) 427 428 // large move uses a loop 429 // DUFFCOPY is not implemented on ARM64 (TODO) 430 (Move [s] dst src mem) 431 && SizeAndAlign(s).Size() > 24 && SizeAndAlign(s).Size()%8 == 0 -> 432 (LoweredMove 433 dst 434 src 435 (ADDconst <src.Type> src [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)]) 436 mem) 437 438 // calls 439 (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem) 440 (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem) 441 (DeferCall [argwid] mem) -> (CALLdefer [argwid] mem) 442 (GoCall [argwid] mem) -> (CALLgo [argwid] mem) 443 (InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem) 444 445 // checks 446 (NilCheck ptr mem) -> (LoweredNilCheck ptr mem) 447 (IsNonNil ptr) -> (NotEqual (CMPconst [0] ptr)) 448 (IsInBounds idx len) -> (LessThanU (CMP idx len)) 449 (IsSliceInBounds idx len) -> (LessEqualU (CMP idx len)) 450 451 // pseudo-ops 452 (GetClosurePtr) -> (LoweredGetClosurePtr) 453 (Convert x mem) -> (MOVDconvert x mem) 454 455 // Absorb pseudo-ops into blocks. 456 (If (Equal cc) yes no) -> (EQ cc yes no) 457 (If (NotEqual cc) yes no) -> (NE cc yes no) 458 (If (LessThan cc) yes no) -> (LT cc yes no) 459 (If (LessThanU cc) yes no) -> (ULT cc yes no) 460 (If (LessEqual cc) yes no) -> (LE cc yes no) 461 (If (LessEqualU cc) yes no) -> (ULE cc yes no) 462 (If (GreaterThan cc) yes no) -> (GT cc yes no) 463 (If (GreaterThanU cc) yes no) -> (UGT cc yes no) 464 (If (GreaterEqual cc) yes no) -> (GE cc yes no) 465 (If (GreaterEqualU cc) yes no) -> (UGE cc yes no) 466 467 (If cond yes no) -> (NE (CMPconst [0] cond) yes no) 468 469 // Optimizations 470 471 // Absorb boolean tests into block 472 (NE (CMPconst [0] (Equal cc)) yes no) -> (EQ cc yes no) 473 (NE (CMPconst [0] (NotEqual cc)) yes no) -> (NE cc yes no) 474 (NE (CMPconst [0] (LessThan cc)) yes no) -> (LT cc yes no) 475 (NE (CMPconst [0] (LessThanU cc)) yes no) -> (ULT cc yes no) 476 (NE (CMPconst [0] (LessEqual cc)) yes no) -> (LE cc yes no) 477 (NE (CMPconst [0] (LessEqualU cc)) yes no) -> (ULE cc yes no) 478 (NE (CMPconst [0] (GreaterThan cc)) yes no) -> (GT cc yes no) 479 (NE (CMPconst [0] (GreaterThanU cc)) yes no) -> (UGT cc yes no) 480 (NE (CMPconst [0] (GreaterEqual cc)) yes no) -> (GE cc yes no) 481 (NE (CMPconst [0] (GreaterEqualU cc)) yes no) -> (UGE cc yes no) 482 483 // fold offset into address 484 (ADDconst [off1] (MOVDaddr [off2] {sym} ptr)) -> (MOVDaddr [off1+off2] {sym} ptr) 485 486 // fold address into load/store 487 // only small offset (between -256 and 256) or offset that is a multiple of data size 488 // can be encoded in the instructions 489 // since this rewriting takes place before stack allocation, the offset to SP is unknown, 490 // so don't do it for args and locals with unaligned offset 491 (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBload [off1+off2] {sym} ptr mem) 492 (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBUload [off1+off2] {sym} ptr mem) 493 (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) 494 && (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 495 (MOVHload [off1+off2] {sym} ptr mem) 496 (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem) 497 && (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 498 (MOVHUload [off1+off2] {sym} ptr mem) 499 (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) 500 && (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 501 (MOVWload [off1+off2] {sym} ptr mem) 502 (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem) 503 && (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 504 (MOVWUload [off1+off2] {sym} ptr mem) 505 (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) 506 && (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 507 (MOVDload [off1+off2] {sym} ptr mem) 508 (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem) 509 && (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 510 (FMOVSload [off1+off2] {sym} ptr mem) 511 (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem) 512 && (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 513 (FMOVDload [off1+off2] {sym} ptr mem) 514 515 (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVBstore [off1+off2] {sym} ptr val mem) 516 (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) 517 && (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 518 (MOVHstore [off1+off2] {sym} ptr val mem) 519 (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) 520 && (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 521 (MOVWstore [off1+off2] {sym} ptr val mem) 522 (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) 523 && (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 524 (MOVDstore [off1+off2] {sym} ptr val mem) 525 (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem) 526 && (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 527 (FMOVSstore [off1+off2] {sym} ptr val mem) 528 (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) 529 && (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 530 (FMOVDstore [off1+off2] {sym} ptr val mem) 531 (MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBstorezero [off1+off2] {sym} ptr mem) 532 (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem) 533 && (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 534 (MOVHstorezero [off1+off2] {sym} ptr mem) 535 (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem) 536 && (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 537 (MOVWstorezero [off1+off2] {sym} ptr mem) 538 (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem) 539 && (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) -> 540 (MOVDstorezero [off1+off2] {sym} ptr mem) 541 542 (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) -> 543 (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 544 (MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) -> 545 (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 546 (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 547 && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 548 (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 549 (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 550 && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 551 (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 552 (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 553 && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 554 (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 555 (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 556 && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 557 (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 558 (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 559 && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 560 (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 561 (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 562 && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 563 (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 564 (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 565 && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 566 (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 567 568 (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) -> 569 (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) 570 (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) 571 && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 572 (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) 573 (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) 574 && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 575 (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) 576 (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) 577 && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 578 (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) 579 (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) 580 && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 581 (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) 582 (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) 583 && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 584 (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) 585 (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) -> 586 (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 587 (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 588 && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 589 (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 590 (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 591 && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 592 (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 593 (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) 594 && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) -> 595 (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem) 596 597 // store zero 598 (MOVBstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVBstorezero [off] {sym} ptr mem) 599 (MOVHstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVHstorezero [off] {sym} ptr mem) 600 (MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem) 601 (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem) 602 603 // replace load from same location as preceding store with copy 604 // these seem to have bad interaction with other rules, resulting in slower code 605 //(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 606 //(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 607 //(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 608 //(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 609 //(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 610 //(MOVWUload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 611 //(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 612 //(FMOVSload [off] {sym} ptr (FMOVSstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 613 //(FMOVDload [off] {sym} ptr (FMOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x 614 615 (MOVBload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 616 (MOVBUload [off] {sym} ptr (MOVBstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 617 (MOVHload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 618 (MOVHUload [off] {sym} ptr (MOVHstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 619 (MOVWload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 620 (MOVWUload [off] {sym} ptr (MOVWstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 621 (MOVDload [off] {sym} ptr (MOVDstorezero [off2] {sym2} ptr2 _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDconst [0]) 622 623 // don't extend after proper load 624 (MOVBreg x:(MOVBload _ _)) -> (MOVDreg x) 625 (MOVBUreg x:(MOVBUload _ _)) -> (MOVDreg x) 626 (MOVHreg x:(MOVBload _ _)) -> (MOVDreg x) 627 (MOVHreg x:(MOVBUload _ _)) -> (MOVDreg x) 628 (MOVHreg x:(MOVHload _ _)) -> (MOVDreg x) 629 (MOVHUreg x:(MOVBUload _ _)) -> (MOVDreg x) 630 (MOVHUreg x:(MOVHUload _ _)) -> (MOVDreg x) 631 (MOVWreg x:(MOVBload _ _)) -> (MOVDreg x) 632 (MOVWreg x:(MOVBUload _ _)) -> (MOVDreg x) 633 (MOVWreg x:(MOVHload _ _)) -> (MOVDreg x) 634 (MOVWreg x:(MOVHUload _ _)) -> (MOVDreg x) 635 (MOVWreg x:(MOVWload _ _)) -> (MOVDreg x) 636 (MOVWUreg x:(MOVBUload _ _)) -> (MOVDreg x) 637 (MOVWUreg x:(MOVHUload _ _)) -> (MOVDreg x) 638 (MOVWUreg x:(MOVWUload _ _)) -> (MOVDreg x) 639 640 // fold double extensions 641 (MOVBreg x:(MOVBreg _)) -> (MOVDreg x) 642 (MOVBUreg x:(MOVBUreg _)) -> (MOVDreg x) 643 (MOVHreg x:(MOVBreg _)) -> (MOVDreg x) 644 (MOVHreg x:(MOVBUreg _)) -> (MOVDreg x) 645 (MOVHreg x:(MOVHreg _)) -> (MOVDreg x) 646 (MOVHUreg x:(MOVBUreg _)) -> (MOVDreg x) 647 (MOVHUreg x:(MOVHUreg _)) -> (MOVDreg x) 648 (MOVWreg x:(MOVBreg _)) -> (MOVDreg x) 649 (MOVWreg x:(MOVBUreg _)) -> (MOVDreg x) 650 (MOVWreg x:(MOVHreg _)) -> (MOVDreg x) 651 (MOVWreg x:(MOVHreg _)) -> (MOVDreg x) 652 (MOVWreg x:(MOVWreg _)) -> (MOVDreg x) 653 (MOVWUreg x:(MOVBUreg _)) -> (MOVDreg x) 654 (MOVWUreg x:(MOVHUreg _)) -> (MOVDreg x) 655 (MOVWUreg x:(MOVWUreg _)) -> (MOVDreg x) 656 657 // don't extend before store 658 (MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) 659 (MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) 660 (MOVBstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) 661 (MOVBstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) 662 (MOVBstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) 663 (MOVBstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) 664 (MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) 665 (MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) 666 (MOVHstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) 667 (MOVHstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) 668 (MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem) 669 (MOVWstore [off] {sym} ptr (MOVWUreg x) mem) -> (MOVWstore [off] {sym} ptr x mem) 670 671 // if a register move has only 1 use, just use the same register without emitting instruction 672 // MOVDnop doesn't emit instruction, only for ensuring the type. 673 (MOVDreg x) && x.Uses == 1 -> (MOVDnop x) 674 675 // fold constant into arithmatic ops 676 (ADD (MOVDconst [c]) x) -> (ADDconst [c] x) 677 (ADD x (MOVDconst [c])) -> (ADDconst [c] x) 678 (SUB x (MOVDconst [c])) -> (SUBconst [c] x) 679 (AND (MOVDconst [c]) x) -> (ANDconst [c] x) 680 (AND x (MOVDconst [c])) -> (ANDconst [c] x) 681 (OR (MOVDconst [c]) x) -> (ORconst [c] x) 682 (OR x (MOVDconst [c])) -> (ORconst [c] x) 683 (XOR (MOVDconst [c]) x) -> (XORconst [c] x) 684 (XOR x (MOVDconst [c])) -> (XORconst [c] x) 685 (BIC x (MOVDconst [c])) -> (BICconst [c] x) 686 687 (SLL x (MOVDconst [c])) -> (SLLconst x [c&63]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=64) 688 (SRL x (MOVDconst [c])) -> (SRLconst x [c&63]) 689 (SRA x (MOVDconst [c])) -> (SRAconst x [c&63]) 690 691 (CMP x (MOVDconst [c])) -> (CMPconst [c] x) 692 (CMP (MOVDconst [c]) x) -> (InvertFlags (CMPconst [c] x)) 693 (CMPW x (MOVDconst [c])) -> (CMPWconst [int64(int32(c))] x) 694 (CMPW (MOVDconst [c]) x) -> (InvertFlags (CMPWconst [int64(int32(c))] x)) 695 696 // mul by constant 697 (MUL x (MOVDconst [-1])) -> (NEG x) 698 (MUL _ (MOVDconst [0])) -> (MOVDconst [0]) 699 (MUL x (MOVDconst [1])) -> x 700 (MUL x (MOVDconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) 701 (MUL x (MOVDconst [c])) && isPowerOfTwo(c-1) && c >= 3 -> (ADDshiftLL x x [log2(c-1)]) 702 (MUL x (MOVDconst [c])) && isPowerOfTwo(c+1) && c >= 7 -> (ADDshiftLL (NEG <x.Type> x) x [log2(c+1)]) 703 (MUL x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) 704 (MUL x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) 705 (MUL x (MOVDconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) -> (SLLconst [log2(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3])) 706 (MUL x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) 707 708 (MUL (MOVDconst [-1]) x) -> (NEG x) 709 (MUL (MOVDconst [0]) _) -> (MOVDconst [0]) 710 (MUL (MOVDconst [1]) x) -> x 711 (MUL (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) 712 (MUL (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) 713 (MUL (MOVDconst [c]) x) && isPowerOfTwo(c-1) && c >= 3 -> (ADDshiftLL x x [log2(c-1)]) 714 (MUL (MOVDconst [c]) x) && isPowerOfTwo(c+1) && c >= 7 -> (ADDshiftLL (NEG <x.Type> x) x [log2(c+1)]) 715 (MUL (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) 716 (MUL (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) 717 (MUL (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) -> (SLLconst [log2(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3])) 718 (MUL (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) 719 720 (MULW x (MOVDconst [c])) && int32(c)==-1 -> (NEG x) 721 (MULW _ (MOVDconst [c])) && int32(c)==0 -> (MOVDconst [0]) 722 (MULW x (MOVDconst [c])) && int32(c)==1 -> x 723 (MULW x (MOVDconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) 724 (MULW x (MOVDconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)]) 725 (MULW x (MOVDconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADDshiftLL (NEG <x.Type> x) x [log2(c+1)]) 726 (MULW x (MOVDconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) 727 (MULW x (MOVDconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) 728 (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])) 729 (MULW x (MOVDconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) 730 731 (MULW (MOVDconst [c]) x) && int32(c)==-1 -> (NEG x) 732 (MULW (MOVDconst [c]) _) && int32(c)==0 -> (MOVDconst [0]) 733 (MULW (MOVDconst [c]) x) && int32(c)==1 -> x 734 (MULW (MOVDconst [c]) x) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) 735 (MULW (MOVDconst [c]) x) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)]) 736 (MULW (MOVDconst [c]) x) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADDshiftLL (NEG <x.Type> x) x [log2(c+1)]) 737 (MULW (MOVDconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) 738 (MULW (MOVDconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) 739 (MULW (MOVDconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (ADDshiftLL <x.Type> (NEG <x.Type> x) x [3])) 740 (MULW (MOVDconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) 741 742 // div by constant 743 (UDIV x (MOVDconst [1])) -> x 744 (UDIV x (MOVDconst [c])) && isPowerOfTwo(c) -> (SRLconst [log2(c)] x) 745 (UDIVW x (MOVDconst [c])) && uint32(c)==1 -> x 746 (UDIVW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) -> (SRLconst [log2(c)] x) 747 (UMOD _ (MOVDconst [1])) -> (MOVDconst [0]) 748 (UMOD x (MOVDconst [c])) && isPowerOfTwo(c) -> (ANDconst [c-1] x) 749 (UMODW _ (MOVDconst [c])) && uint32(c)==1 -> (MOVDconst [0]) 750 (UMODW x (MOVDconst [c])) && isPowerOfTwo(c) && is32Bit(c) -> (ANDconst [c-1] x) 751 752 // generic simplifications 753 (ADD x (NEG y)) -> (SUB x y) 754 (ADD (NEG y) x) -> (SUB x y) 755 (SUB x x) -> (MOVDconst [0]) 756 (AND x x) -> x 757 (OR x x) -> x 758 (XOR x x) -> (MOVDconst [0]) 759 (BIC x x) -> (MOVDconst [0]) 760 (AND x (MVN y)) -> (BIC x y) 761 (CSELULT x (MOVDconst [0]) flag) -> (CSELULT0 x flag) 762 763 // remove redundant *const ops 764 (ADDconst [0] x) -> x 765 (SUBconst [0] x) -> x 766 (ANDconst [0] _) -> (MOVDconst [0]) 767 (ANDconst [-1] x) -> x 768 (ORconst [0] x) -> x 769 (ORconst [-1] _) -> (MOVDconst [-1]) 770 (XORconst [0] x) -> x 771 (XORconst [-1] x) -> (MVN x) 772 (BICconst [0] x) -> x 773 (BICconst [-1] _) -> (MOVDconst [0]) 774 775 // generic constant folding 776 (ADDconst [c] (MOVDconst [d])) -> (MOVDconst [c+d]) 777 (ADDconst [c] (ADDconst [d] x)) -> (ADDconst [c+d] x) 778 (ADDconst [c] (SUBconst [d] x)) -> (ADDconst [c-d] x) 779 (SUBconst [c] (MOVDconst [d])) -> (MOVDconst [d-c]) 780 (SUBconst [c] (SUBconst [d] x)) -> (ADDconst [-c-d] x) 781 (SUBconst [c] (ADDconst [d] x)) -> (ADDconst [-c+d] x) 782 (SLLconst [c] (MOVDconst [d])) -> (MOVDconst [int64(d)<<uint64(c)]) 783 (SRLconst [c] (MOVDconst [d])) -> (MOVDconst [int64(uint64(d)>>uint64(c))]) 784 (SRAconst [c] (MOVDconst [d])) -> (MOVDconst [int64(d)>>uint64(c)]) 785 (MUL (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [c*d]) 786 (MULW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)*int32(d))]) 787 (DIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(c)/int64(d)]) 788 (UDIV (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)/uint64(d))]) 789 (DIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)/int32(d))]) 790 (UDIVW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint32(c)/uint32(d))]) 791 (MOD (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(c)%int64(d)]) 792 (UMOD (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint64(c)%uint64(d))]) 793 (MODW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(int32(c)%int32(d))]) 794 (UMODW (MOVDconst [c]) (MOVDconst [d])) -> (MOVDconst [int64(uint32(c)%uint32(d))]) 795 (ANDconst [c] (MOVDconst [d])) -> (MOVDconst [c&d]) 796 (ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x) 797 (ORconst [c] (MOVDconst [d])) -> (MOVDconst [c|d]) 798 (ORconst [c] (ORconst [d] x)) -> (ORconst [c|d] x) 799 (XORconst [c] (MOVDconst [d])) -> (MOVDconst [c^d]) 800 (XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x) 801 (BICconst [c] (MOVDconst [d])) -> (MOVDconst [d&^c]) 802 (MVN (MOVDconst [c])) -> (MOVDconst [^c]) 803 (NEG (MOVDconst [c])) -> (MOVDconst [-c]) 804 (MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))]) 805 (MOVBUreg (MOVDconst [c])) -> (MOVDconst [int64(uint8(c))]) 806 (MOVHreg (MOVDconst [c])) -> (MOVDconst [int64(int16(c))]) 807 (MOVHUreg (MOVDconst [c])) -> (MOVDconst [int64(uint16(c))]) 808 (MOVWreg (MOVDconst [c])) -> (MOVDconst [int64(int32(c))]) 809 (MOVWUreg (MOVDconst [c])) -> (MOVDconst [int64(uint32(c))]) 810 (MOVDreg (MOVDconst [c])) -> (MOVDconst [c]) 811 812 // constant comparisons 813 (CMPconst (MOVDconst [x]) [y]) && x==y -> (FlagEQ) 814 (CMPconst (MOVDconst [x]) [y]) && int64(x)<int64(y) && uint64(x)<uint64(y) -> (FlagLT_ULT) 815 (CMPconst (MOVDconst [x]) [y]) && int64(x)<int64(y) && uint64(x)>uint64(y) -> (FlagLT_UGT) 816 (CMPconst (MOVDconst [x]) [y]) && int64(x)>int64(y) && uint64(x)<uint64(y) -> (FlagGT_ULT) 817 (CMPconst (MOVDconst [x]) [y]) && int64(x)>int64(y) && uint64(x)>uint64(y) -> (FlagGT_UGT) 818 (CMPWconst (MOVDconst [x]) [y]) && int32(x)==int32(y) -> (FlagEQ) 819 (CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y) && uint32(x)<uint32(y) -> (FlagLT_ULT) 820 (CMPWconst (MOVDconst [x]) [y]) && int32(x)<int32(y) && uint32(x)>uint32(y) -> (FlagLT_UGT) 821 (CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y) && uint32(x)<uint32(y) -> (FlagGT_ULT) 822 (CMPWconst (MOVDconst [x]) [y]) && int32(x)>int32(y) && uint32(x)>uint32(y) -> (FlagGT_UGT) 823 824 // other known comparisons 825 (CMPconst (MOVBUreg _) [c]) && 0xff < c -> (FlagLT_ULT) 826 (CMPconst (MOVHUreg _) [c]) && 0xffff < c -> (FlagLT_ULT) 827 (CMPconst (MOVWUreg _) [c]) && 0xffffffff < c -> (FlagLT_ULT) 828 (CMPconst (ANDconst _ [m]) [n]) && 0 <= m && m < n -> (FlagLT_ULT) 829 (CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 63 && (1<<uint64(64-c)) <= uint64(n) -> (FlagLT_ULT) 830 (CMPWconst (MOVBUreg _) [c]) && 0xff < int32(c) -> (FlagLT_ULT) 831 (CMPWconst (MOVHUreg _) [c]) && 0xffff < int32(c) -> (FlagLT_ULT) 832 833 // absorb flag constants into branches 834 (EQ (FlagEQ) yes no) -> (First nil yes no) 835 (EQ (FlagLT_ULT) yes no) -> (First nil no yes) 836 (EQ (FlagLT_UGT) yes no) -> (First nil no yes) 837 (EQ (FlagGT_ULT) yes no) -> (First nil no yes) 838 (EQ (FlagGT_UGT) yes no) -> (First nil no yes) 839 840 (NE (FlagEQ) yes no) -> (First nil no yes) 841 (NE (FlagLT_ULT) yes no) -> (First nil yes no) 842 (NE (FlagLT_UGT) yes no) -> (First nil yes no) 843 (NE (FlagGT_ULT) yes no) -> (First nil yes no) 844 (NE (FlagGT_UGT) yes no) -> (First nil yes no) 845 846 (LT (FlagEQ) yes no) -> (First nil no yes) 847 (LT (FlagLT_ULT) yes no) -> (First nil yes no) 848 (LT (FlagLT_UGT) yes no) -> (First nil yes no) 849 (LT (FlagGT_ULT) yes no) -> (First nil no yes) 850 (LT (FlagGT_UGT) yes no) -> (First nil no yes) 851 852 (LE (FlagEQ) yes no) -> (First nil yes no) 853 (LE (FlagLT_ULT) yes no) -> (First nil yes no) 854 (LE (FlagLT_UGT) yes no) -> (First nil yes no) 855 (LE (FlagGT_ULT) yes no) -> (First nil no yes) 856 (LE (FlagGT_UGT) yes no) -> (First nil no yes) 857 858 (GT (FlagEQ) yes no) -> (First nil no yes) 859 (GT (FlagLT_ULT) yes no) -> (First nil no yes) 860 (GT (FlagLT_UGT) yes no) -> (First nil no yes) 861 (GT (FlagGT_ULT) yes no) -> (First nil yes no) 862 (GT (FlagGT_UGT) yes no) -> (First nil yes no) 863 864 (GE (FlagEQ) yes no) -> (First nil yes no) 865 (GE (FlagLT_ULT) yes no) -> (First nil no yes) 866 (GE (FlagLT_UGT) yes no) -> (First nil no yes) 867 (GE (FlagGT_ULT) yes no) -> (First nil yes no) 868 (GE (FlagGT_UGT) yes no) -> (First nil yes no) 869 870 (ULT (FlagEQ) yes no) -> (First nil no yes) 871 (ULT (FlagLT_ULT) yes no) -> (First nil yes no) 872 (ULT (FlagLT_UGT) yes no) -> (First nil no yes) 873 (ULT (FlagGT_ULT) yes no) -> (First nil yes no) 874 (ULT (FlagGT_UGT) yes no) -> (First nil no yes) 875 876 (ULE (FlagEQ) yes no) -> (First nil yes no) 877 (ULE (FlagLT_ULT) yes no) -> (First nil yes no) 878 (ULE (FlagLT_UGT) yes no) -> (First nil no yes) 879 (ULE (FlagGT_ULT) yes no) -> (First nil yes no) 880 (ULE (FlagGT_UGT) yes no) -> (First nil no yes) 881 882 (UGT (FlagEQ) yes no) -> (First nil no yes) 883 (UGT (FlagLT_ULT) yes no) -> (First nil no yes) 884 (UGT (FlagLT_UGT) yes no) -> (First nil yes no) 885 (UGT (FlagGT_ULT) yes no) -> (First nil no yes) 886 (UGT (FlagGT_UGT) yes no) -> (First nil yes no) 887 888 (UGE (FlagEQ) yes no) -> (First nil yes no) 889 (UGE (FlagLT_ULT) yes no) -> (First nil no yes) 890 (UGE (FlagLT_UGT) yes no) -> (First nil yes no) 891 (UGE (FlagGT_ULT) yes no) -> (First nil no yes) 892 (UGE (FlagGT_UGT) yes no) -> (First nil yes no) 893 894 // absorb InvertFlags into branches 895 (LT (InvertFlags cmp) yes no) -> (GT cmp yes no) 896 (GT (InvertFlags cmp) yes no) -> (LT cmp yes no) 897 (LE (InvertFlags cmp) yes no) -> (GE cmp yes no) 898 (GE (InvertFlags cmp) yes no) -> (LE cmp yes no) 899 (ULT (InvertFlags cmp) yes no) -> (UGT cmp yes no) 900 (UGT (InvertFlags cmp) yes no) -> (ULT cmp yes no) 901 (ULE (InvertFlags cmp) yes no) -> (UGE cmp yes no) 902 (UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no) 903 (EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no) 904 (NE (InvertFlags cmp) yes no) -> (NE cmp yes no) 905 906 // absorb flag constants into boolean values 907 (Equal (FlagEQ)) -> (MOVDconst [1]) 908 (Equal (FlagLT_ULT)) -> (MOVDconst [0]) 909 (Equal (FlagLT_UGT)) -> (MOVDconst [0]) 910 (Equal (FlagGT_ULT)) -> (MOVDconst [0]) 911 (Equal (FlagGT_UGT)) -> (MOVDconst [0]) 912 913 (NotEqual (FlagEQ)) -> (MOVDconst [0]) 914 (NotEqual (FlagLT_ULT)) -> (MOVDconst [1]) 915 (NotEqual (FlagLT_UGT)) -> (MOVDconst [1]) 916 (NotEqual (FlagGT_ULT)) -> (MOVDconst [1]) 917 (NotEqual (FlagGT_UGT)) -> (MOVDconst [1]) 918 919 (LessThan (FlagEQ)) -> (MOVDconst [0]) 920 (LessThan (FlagLT_ULT)) -> (MOVDconst [1]) 921 (LessThan (FlagLT_UGT)) -> (MOVDconst [1]) 922 (LessThan (FlagGT_ULT)) -> (MOVDconst [0]) 923 (LessThan (FlagGT_UGT)) -> (MOVDconst [0]) 924 925 (LessThanU (FlagEQ)) -> (MOVDconst [0]) 926 (LessThanU (FlagLT_ULT)) -> (MOVDconst [1]) 927 (LessThanU (FlagLT_UGT)) -> (MOVDconst [0]) 928 (LessThanU (FlagGT_ULT)) -> (MOVDconst [1]) 929 (LessThanU (FlagGT_UGT)) -> (MOVDconst [0]) 930 931 (LessEqual (FlagEQ)) -> (MOVDconst [1]) 932 (LessEqual (FlagLT_ULT)) -> (MOVDconst [1]) 933 (LessEqual (FlagLT_UGT)) -> (MOVDconst [1]) 934 (LessEqual (FlagGT_ULT)) -> (MOVDconst [0]) 935 (LessEqual (FlagGT_UGT)) -> (MOVDconst [0]) 936 937 (LessEqualU (FlagEQ)) -> (MOVDconst [1]) 938 (LessEqualU (FlagLT_ULT)) -> (MOVDconst [1]) 939 (LessEqualU (FlagLT_UGT)) -> (MOVDconst [0]) 940 (LessEqualU (FlagGT_ULT)) -> (MOVDconst [1]) 941 (LessEqualU (FlagGT_UGT)) -> (MOVDconst [0]) 942 943 (GreaterThan (FlagEQ)) -> (MOVDconst [0]) 944 (GreaterThan (FlagLT_ULT)) -> (MOVDconst [0]) 945 (GreaterThan (FlagLT_UGT)) -> (MOVDconst [0]) 946 (GreaterThan (FlagGT_ULT)) -> (MOVDconst [1]) 947 (GreaterThan (FlagGT_UGT)) -> (MOVDconst [1]) 948 949 (GreaterThanU (FlagEQ)) -> (MOVDconst [0]) 950 (GreaterThanU (FlagLT_ULT)) -> (MOVDconst [0]) 951 (GreaterThanU (FlagLT_UGT)) -> (MOVDconst [1]) 952 (GreaterThanU (FlagGT_ULT)) -> (MOVDconst [0]) 953 (GreaterThanU (FlagGT_UGT)) -> (MOVDconst [1]) 954 955 (GreaterEqual (FlagEQ)) -> (MOVDconst [1]) 956 (GreaterEqual (FlagLT_ULT)) -> (MOVDconst [0]) 957 (GreaterEqual (FlagLT_UGT)) -> (MOVDconst [0]) 958 (GreaterEqual (FlagGT_ULT)) -> (MOVDconst [1]) 959 (GreaterEqual (FlagGT_UGT)) -> (MOVDconst [1]) 960 961 (GreaterEqualU (FlagEQ)) -> (MOVDconst [1]) 962 (GreaterEqualU (FlagLT_ULT)) -> (MOVDconst [0]) 963 (GreaterEqualU (FlagLT_UGT)) -> (MOVDconst [1]) 964 (GreaterEqualU (FlagGT_ULT)) -> (MOVDconst [0]) 965 (GreaterEqualU (FlagGT_UGT)) -> (MOVDconst [1]) 966 967 // absorb InvertFlags into boolean values 968 (Equal (InvertFlags x)) -> (Equal x) 969 (NotEqual (InvertFlags x)) -> (NotEqual x) 970 (LessThan (InvertFlags x)) -> (GreaterThan x) 971 (LessThanU (InvertFlags x)) -> (GreaterThanU x) 972 (GreaterThan (InvertFlags x)) -> (LessThan x) 973 (GreaterThanU (InvertFlags x)) -> (LessThanU x) 974 (LessEqual (InvertFlags x)) -> (GreaterEqual x) 975 (LessEqualU (InvertFlags x)) -> (GreaterEqualU x) 976 (GreaterEqual (InvertFlags x)) -> (LessEqual x) 977 (GreaterEqualU (InvertFlags x)) -> (LessEqualU x) 978 979 // absorb flag constants into conditional instructions 980 (CSELULT _ y (FlagEQ)) -> y 981 (CSELULT x _ (FlagLT_ULT)) -> x 982 (CSELULT _ y (FlagLT_UGT)) -> y 983 (CSELULT x _ (FlagGT_ULT)) -> x 984 (CSELULT _ y (FlagGT_UGT)) -> y 985 (CSELULT0 _ (FlagEQ)) -> (MOVDconst [0]) 986 (CSELULT0 x (FlagLT_ULT)) -> x 987 (CSELULT0 _ (FlagLT_UGT)) -> (MOVDconst [0]) 988 (CSELULT0 x (FlagGT_ULT)) -> x 989 (CSELULT0 _ (FlagGT_UGT)) -> (MOVDconst [0]) 990 991 // absorb shifts into ops 992 (ADD x (SLLconst [c] y)) -> (ADDshiftLL x y [c]) 993 (ADD (SLLconst [c] y) x) -> (ADDshiftLL x y [c]) 994 (ADD x (SRLconst [c] y)) -> (ADDshiftRL x y [c]) 995 (ADD (SRLconst [c] y) x) -> (ADDshiftRL x y [c]) 996 (ADD x (SRAconst [c] y)) -> (ADDshiftRA x y [c]) 997 (ADD (SRAconst [c] y) x) -> (ADDshiftRA x y [c]) 998 (SUB x (SLLconst [c] y)) -> (SUBshiftLL x y [c]) 999 (SUB x (SRLconst [c] y)) -> (SUBshiftRL x y [c]) 1000 (SUB x (SRAconst [c] y)) -> (SUBshiftRA x y [c]) 1001 (AND x (SLLconst [c] y)) -> (ANDshiftLL x y [c]) 1002 (AND (SLLconst [c] y) x) -> (ANDshiftLL x y [c]) 1003 (AND x (SRLconst [c] y)) -> (ANDshiftRL x y [c]) 1004 (AND (SRLconst [c] y) x) -> (ANDshiftRL x y [c]) 1005 (AND x (SRAconst [c] y)) -> (ANDshiftRA x y [c]) 1006 (AND (SRAconst [c] y) x) -> (ANDshiftRA x y [c]) 1007 (OR x s:(SLLconst [c] y)) && s.Uses == 1 && clobber(s) -> (ORshiftLL x y [c]) // useful for combined load 1008 (OR s:(SLLconst [c] y) x) && s.Uses == 1 && clobber(s) -> (ORshiftLL x y [c]) 1009 (OR x (SLLconst [c] y)) -> (ORshiftLL x y [c]) 1010 (OR (SLLconst [c] y) x) -> (ORshiftLL x y [c]) 1011 (OR x (SRLconst [c] y)) -> (ORshiftRL x y [c]) 1012 (OR (SRLconst [c] y) x) -> (ORshiftRL x y [c]) 1013 (OR x (SRAconst [c] y)) -> (ORshiftRA x y [c]) 1014 (OR (SRAconst [c] y) x) -> (ORshiftRA x y [c]) 1015 (XOR x (SLLconst [c] y)) -> (XORshiftLL x y [c]) 1016 (XOR (SLLconst [c] y) x) -> (XORshiftLL x y [c]) 1017 (XOR x (SRLconst [c] y)) -> (XORshiftRL x y [c]) 1018 (XOR (SRLconst [c] y) x) -> (XORshiftRL x y [c]) 1019 (XOR x (SRAconst [c] y)) -> (XORshiftRA x y [c]) 1020 (XOR (SRAconst [c] y) x) -> (XORshiftRA x y [c]) 1021 (BIC x (SLLconst [c] y)) -> (BICshiftLL x y [c]) 1022 (BIC x (SRLconst [c] y)) -> (BICshiftRL x y [c]) 1023 (BIC x (SRAconst [c] y)) -> (BICshiftRA x y [c]) 1024 (CMP x (SLLconst [c] y)) -> (CMPshiftLL x y [c]) 1025 (CMP (SLLconst [c] y) x) -> (InvertFlags (CMPshiftLL x y [c])) 1026 (CMP x (SRLconst [c] y)) -> (CMPshiftRL x y [c]) 1027 (CMP (SRLconst [c] y) x) -> (InvertFlags (CMPshiftRL x y [c])) 1028 (CMP x (SRAconst [c] y)) -> (CMPshiftRA x y [c]) 1029 (CMP (SRAconst [c] y) x) -> (InvertFlags (CMPshiftRA x y [c])) 1030 1031 // prefer *const ops to *shift ops 1032 (ADDshiftLL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SLLconst <x.Type> x [d])) 1033 (ADDshiftRL (MOVDconst [c]) x [d]) -> (ADDconst [c] (SRLconst <x.Type> x [d])) 1034 (ADDshiftRA (MOVDconst [c]) x [d]) -> (ADDconst [c] (SRAconst <x.Type> x [d])) 1035 (ANDshiftLL (MOVDconst [c]) x [d]) -> (ANDconst [c] (SLLconst <x.Type> x [d])) 1036 (ANDshiftRL (MOVDconst [c]) x [d]) -> (ANDconst [c] (SRLconst <x.Type> x [d])) 1037 (ANDshiftRA (MOVDconst [c]) x [d]) -> (ANDconst [c] (SRAconst <x.Type> x [d])) 1038 (ORshiftLL (MOVDconst [c]) x [d]) -> (ORconst [c] (SLLconst <x.Type> x [d])) 1039 (ORshiftRL (MOVDconst [c]) x [d]) -> (ORconst [c] (SRLconst <x.Type> x [d])) 1040 (ORshiftRA (MOVDconst [c]) x [d]) -> (ORconst [c] (SRAconst <x.Type> x [d])) 1041 (XORshiftLL (MOVDconst [c]) x [d]) -> (XORconst [c] (SLLconst <x.Type> x [d])) 1042 (XORshiftRL (MOVDconst [c]) x [d]) -> (XORconst [c] (SRLconst <x.Type> x [d])) 1043 (XORshiftRA (MOVDconst [c]) x [d]) -> (XORconst [c] (SRAconst <x.Type> x [d])) 1044 (CMPshiftLL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d]))) 1045 (CMPshiftRL (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d]))) 1046 (CMPshiftRA (MOVDconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d]))) 1047 1048 // constant folding in *shift ops 1049 (ADDshiftLL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)<<uint64(d))]) 1050 (ADDshiftRL x (MOVDconst [c]) [d]) -> (ADDconst x [int64(uint64(c)>>uint64(d))]) 1051 (ADDshiftRA x (MOVDconst [c]) [d]) -> (ADDconst x [int64(int64(c)>>uint64(d))]) 1052 (SUBshiftLL x (MOVDconst [c]) [d]) -> (SUBconst x [int64(uint64(c)<<uint64(d))]) 1053 (SUBshiftRL x (MOVDconst [c]) [d]) -> (SUBconst x [int64(uint64(c)>>uint64(d))]) 1054 (SUBshiftRA x (MOVDconst [c]) [d]) -> (SUBconst x [int64(int64(c)>>uint64(d))]) 1055 (ANDshiftLL x (MOVDconst [c]) [d]) -> (ANDconst x [int64(uint64(c)<<uint64(d))]) 1056 (ANDshiftRL x (MOVDconst [c]) [d]) -> (ANDconst x [int64(uint64(c)>>uint64(d))]) 1057 (ANDshiftRA x (MOVDconst [c]) [d]) -> (ANDconst x [int64(int64(c)>>uint64(d))]) 1058 (ORshiftLL x (MOVDconst [c]) [d]) -> (ORconst x [int64(uint64(c)<<uint64(d))]) 1059 (ORshiftRL x (MOVDconst [c]) [d]) -> (ORconst x [int64(uint64(c)>>uint64(d))]) 1060 (ORshiftRA x (MOVDconst [c]) [d]) -> (ORconst x [int64(int64(c)>>uint64(d))]) 1061 (XORshiftLL x (MOVDconst [c]) [d]) -> (XORconst x [int64(uint64(c)<<uint64(d))]) 1062 (XORshiftRL x (MOVDconst [c]) [d]) -> (XORconst x [int64(uint64(c)>>uint64(d))]) 1063 (XORshiftRA x (MOVDconst [c]) [d]) -> (XORconst x [int64(int64(c)>>uint64(d))]) 1064 (BICshiftLL x (MOVDconst [c]) [d]) -> (BICconst x [int64(uint64(c)<<uint64(d))]) 1065 (BICshiftRL x (MOVDconst [c]) [d]) -> (BICconst x [int64(uint64(c)>>uint64(d))]) 1066 (BICshiftRA x (MOVDconst [c]) [d]) -> (BICconst x [int64(int64(c)>>uint64(d))]) 1067 (CMPshiftLL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)<<uint64(d))]) 1068 (CMPshiftRL x (MOVDconst [c]) [d]) -> (CMPconst x [int64(uint64(c)>>uint64(d))]) 1069 (CMPshiftRA x (MOVDconst [c]) [d]) -> (CMPconst x [int64(int64(c)>>uint64(d))]) 1070 1071 // simplification with *shift ops 1072 (SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1073 (SUBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1074 (SUBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1075 (ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y 1076 (ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y 1077 (ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y 1078 (ORshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y 1079 (ORshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y 1080 (ORshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y 1081 (XORshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1082 (XORshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1083 (XORshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1084 (BICshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1085 (BICshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1086 (BICshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVDconst [0]) 1087 1088 // do combined loads 1089 // little endian loads 1090 // b[0] | b[1]<<8 -> load 16-bit 1091 (ORshiftLL <t> [8] 1092 y0:(MOVDnop x0:(MOVBUload [i] {s} p mem)) 1093 y1:(MOVDnop x1:(MOVBUload [i+1] {s} p mem))) 1094 && x0.Uses == 1 && x1.Uses == 1 1095 && y0.Uses == 1 && y1.Uses == 1 1096 && mergePoint(b,x0,x1) != nil 1097 && clobber(x0) && clobber(x1) 1098 && clobber(y0) && clobber(y1) 1099 -> @mergePoint(b,x0,x1) (MOVHUload <t> {s} (OffPtr <p.Type> [i] p) mem) 1100 1101 // b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24 -> load 32-bit 1102 (ORshiftLL <t> [24] o0:(ORshiftLL [16] 1103 x0:(MOVHUload [i] {s} p mem) 1104 y1:(MOVDnop x1:(MOVBUload [i+2] {s} p mem))) 1105 y2:(MOVDnop x2:(MOVBUload [i+3] {s} p mem))) 1106 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 1107 && y1.Uses == 1 && y2.Uses == 1 1108 && o0.Uses == 1 1109 && mergePoint(b,x0,x1,x2) != nil 1110 && clobber(x0) && clobber(x1) && clobber(x2) 1111 && clobber(y1) && clobber(y2) 1112 && clobber(o0) 1113 -> @mergePoint(b,x0,x1,x2) (MOVWUload <t> {s} (OffPtr <p.Type> [i] p) mem) 1114 1115 // 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 1116 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] 1117 x0:(MOVWUload [i] {s} p mem) 1118 y1:(MOVDnop x1:(MOVBUload [i+4] {s} p mem))) 1119 y2:(MOVDnop x2:(MOVBUload [i+5] {s} p mem))) 1120 y3:(MOVDnop x3:(MOVBUload [i+6] {s} p mem))) 1121 y4:(MOVDnop x4:(MOVBUload [i+7] {s} p mem))) 1122 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 1123 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 1124 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 1125 && mergePoint(b,x0,x1,x2,x3,x4) != nil 1126 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4) 1127 && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4) 1128 && clobber(o0) && clobber(o1) && clobber(o2) 1129 -> @mergePoint(b,x0,x1,x2,x3,x4) (MOVDload <t> {s} (OffPtr <p.Type> [i] p) mem) 1130 1131 // b[3]<<24 | b[2]<<16 | b[1]<<8 | b[0] -> load 32-bit 1132 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] 1133 y0:(MOVDnop x0:(MOVBUload [i] {s} p mem))) 1134 y1:(MOVDnop x1:(MOVBUload [i-1] {s} p mem))) 1135 y2:(MOVDnop x2:(MOVBUload [i-2] {s} p mem))) 1136 y3:(MOVDnop x3:(MOVBUload [i-3] {s} p mem))) 1137 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 1138 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 1139 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 1140 && mergePoint(b,x0,x1,x2,x3) != nil 1141 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) 1142 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) 1143 && clobber(o0) && clobber(o1) && clobber(s0) 1144 -> @mergePoint(b,x0,x1,x2,x3) (MOVWUload <t> {s} (OffPtr <p.Type> [i-3] p) mem) 1145 1146 // 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, reverse 1147 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] 1148 y0:(MOVDnop x0:(MOVBUload [i] {s} p mem))) 1149 y1:(MOVDnop x1:(MOVBUload [i-1] {s} p mem))) 1150 y2:(MOVDnop x2:(MOVBUload [i-2] {s} p mem))) 1151 y3:(MOVDnop x3:(MOVBUload [i-3] {s} p mem))) 1152 y4:(MOVDnop x4:(MOVBUload [i-4] {s} p mem))) 1153 y5:(MOVDnop x5:(MOVBUload [i-5] {s} p mem))) 1154 y6:(MOVDnop x6:(MOVBUload [i-6] {s} p mem))) 1155 y7:(MOVDnop x7:(MOVBUload [i-7] {s} p mem))) 1156 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 1157 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 1158 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 1159 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 1160 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 1161 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 1162 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil 1163 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) 1164 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7) 1165 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) 1166 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7) 1167 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3) 1168 && clobber(o4) && clobber(o5) && clobber(s0) 1169 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [i-7] p) mem)) 1170 1171 // big endian loads 1172 // b[1] | b[0]<<8 -> load 16-bit, reverse 1173 (ORshiftLL <t> [8] 1174 y0:(MOVDnop x0:(MOVBUload [i] {s} p mem)) 1175 y1:(MOVDnop x1:(MOVBUload [i-1] {s} p mem))) 1176 && ((i-1)%2 == 0 || i-1<256 && i-1>-256 && !isArg(s) && !isAuto(s)) 1177 && x0.Uses == 1 && x1.Uses == 1 1178 && y0.Uses == 1 && y1.Uses == 1 1179 && mergePoint(b,x0,x1) != nil 1180 && clobber(x0) && clobber(x1) 1181 && clobber(y0) && clobber(y1) 1182 -> @mergePoint(b,x0,x1) (REV16W <t> (MOVHUload <t> [i-1] {s} p mem)) 1183 1184 // b[3] | b[2]<<8 | b[1]<<16 | b[0]<<24 -> load 32-bit, reverse 1185 (ORshiftLL <t> [24] o0:(ORshiftLL [16] 1186 y0:(REV16W x0:(MOVHUload [i] {s} p mem)) 1187 y1:(MOVDnop x1:(MOVBUload [i-1] {s} p mem))) 1188 y2:(MOVDnop x2:(MOVBUload [i-2] {s} p mem))) 1189 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 1190 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 1191 && o0.Uses == 1 1192 && mergePoint(b,x0,x1,x2) != nil 1193 && clobber(x0) && clobber(x1) && clobber(x2) 1194 && clobber(y0) && clobber(y1) && clobber(y2) 1195 && clobber(o0) 1196 -> @mergePoint(b,x0,x1,x2) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [i-2] p) mem)) 1197 1198 // 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 1199 (ORshiftLL <t> [56] o0:(ORshiftLL [48] o1:(ORshiftLL [40] o2:(ORshiftLL [32] 1200 y0:(REVW x0:(MOVWUload [i] {s} p mem)) 1201 y1:(MOVDnop x1:(MOVBUload [i-1] {s} p mem))) 1202 y2:(MOVDnop x2:(MOVBUload [i-2] {s} p mem))) 1203 y3:(MOVDnop x3:(MOVBUload [i-3] {s} p mem))) 1204 y4:(MOVDnop x4:(MOVBUload [i-4] {s} p mem))) 1205 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 && x4.Uses == 1 1206 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 && y4.Uses == 1 1207 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 1208 && mergePoint(b,x0,x1,x2,x3,x4) != nil 1209 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) && clobber(x4) 1210 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) && clobber(y4) 1211 && clobber(o0) && clobber(o1) && clobber(o2) 1212 -> @mergePoint(b,x0,x1,x2,x3,x4) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [i-4] p) mem)) 1213 1214 // b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3] -> load 32-bit, reverse 1215 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] s0:(SLLconst [24] 1216 y0:(MOVDnop x0:(MOVBUload [i] {s} p mem))) 1217 y1:(MOVDnop x1:(MOVBUload [i+1] {s} p mem))) 1218 y2:(MOVDnop x2:(MOVBUload [i+2] {s} p mem))) 1219 y3:(MOVDnop x3:(MOVBUload [i+3] {s} p mem))) 1220 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 1221 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 1222 && o0.Uses == 1 && o1.Uses == 1 && s0.Uses == 1 1223 && mergePoint(b,x0,x1,x2,x3) != nil 1224 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) 1225 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) 1226 && clobber(o0) && clobber(o1) && clobber(s0) 1227 -> @mergePoint(b,x0,x1,x2,x3) (REVW <t> (MOVWUload <t> {s} (OffPtr <p.Type> [i] p) mem)) 1228 1229 // 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 1230 (OR <t> o0:(ORshiftLL [8] o1:(ORshiftLL [16] o2:(ORshiftLL [24] o3:(ORshiftLL [32] o4:(ORshiftLL [40] o5:(ORshiftLL [48] s0:(SLLconst [56] 1231 y0:(MOVDnop x0:(MOVBUload [i] {s} p mem))) 1232 y1:(MOVDnop x1:(MOVBUload [i+1] {s} p mem))) 1233 y2:(MOVDnop x2:(MOVBUload [i+2] {s} p mem))) 1234 y3:(MOVDnop x3:(MOVBUload [i+3] {s} p mem))) 1235 y4:(MOVDnop x4:(MOVBUload [i+4] {s} p mem))) 1236 y5:(MOVDnop x5:(MOVBUload [i+5] {s} p mem))) 1237 y6:(MOVDnop x6:(MOVBUload [i+6] {s} p mem))) 1238 y7:(MOVDnop x7:(MOVBUload [i+7] {s} p mem))) 1239 && x0.Uses == 1 && x1.Uses == 1 && x2.Uses == 1 && x3.Uses == 1 1240 && x4.Uses == 1 && x5.Uses == 1 && x6.Uses == 1 && x7.Uses == 1 1241 && y0.Uses == 1 && y1.Uses == 1 && y2.Uses == 1 && y3.Uses == 1 1242 && y4.Uses == 1 && y5.Uses == 1 && y6.Uses == 1 && y7.Uses == 1 1243 && o0.Uses == 1 && o1.Uses == 1 && o2.Uses == 1 && o3.Uses == 1 1244 && o4.Uses == 1 && o5.Uses == 1 && s0.Uses == 1 1245 && mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) != nil 1246 && clobber(x0) && clobber(x1) && clobber(x2) && clobber(x3) 1247 && clobber(x4) && clobber(x5) && clobber(x6) && clobber(x7) 1248 && clobber(y0) && clobber(y1) && clobber(y2) && clobber(y3) 1249 && clobber(y4) && clobber(y5) && clobber(y6) && clobber(y7) 1250 && clobber(o0) && clobber(o1) && clobber(o2) && clobber(o3) 1251 && clobber(o4) && clobber(o5) && clobber(s0) 1252 -> @mergePoint(b,x0,x1,x2,x3,x4,x5,x6,x7) (REV <t> (MOVDload <t> {s} (OffPtr <p.Type> [i] p) mem))