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