...

Text file src/pkg/cmd/compile/internal/ssa/gen/ARM.rules

     1	// Copyright 2016 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	(Add(Ptr|32|16|8) x y) -> (ADD x y)
     6	(Add(32|64)F x y) -> (ADD(F|D) x y)
     7	(Add32carry x y) -> (ADDS x y)
     8	(Add32withcarry x y c) -> (ADC x y c)
     9	
    10	(Sub(Ptr|32|16|8) x y) -> (SUB x y)
    11	(Sub(32|64)F x y) -> (SUB(F|D) x y)
    12	(Sub32carry x y) -> (SUBS x y)
    13	(Sub32withcarry x y c) -> (SBC x y c)
    14	
    15	(Mul(32|16|8) x y) -> (MUL x y)
    16	(Mul(32|64)F x y) -> (MUL(F|D) x y)
    17	(Hmul(32|32u) x y) -> (HMU(L|LU) x y)
    18	(Mul32uhilo x y) -> (MULLU x y)
    19	
    20	(Div32 x y) ->
    21		(SUB (XOR <typ.UInt32>                                                        // negate the result if one operand is negative
    22			(Select0 <typ.UInt32> (CALLudiv
    23				(SUB <typ.UInt32> (XOR x <typ.UInt32> (Signmask x)) (Signmask x))   // negate x if negative
    24				(SUB <typ.UInt32> (XOR y <typ.UInt32> (Signmask y)) (Signmask y)))) // negate y if negative
    25			(Signmask (XOR <typ.UInt32> x y))) (Signmask (XOR <typ.UInt32> x y)))
    26	(Div32u x y) -> (Select0 <typ.UInt32> (CALLudiv x y))
    27	(Div16 x y) -> (Div32 (SignExt16to32 x) (SignExt16to32 y))
    28	(Div16u x y) -> (Div32u (ZeroExt16to32 x) (ZeroExt16to32 y))
    29	(Div8 x y) -> (Div32 (SignExt8to32 x) (SignExt8to32 y))
    30	(Div8u x y) -> (Div32u (ZeroExt8to32 x) (ZeroExt8to32 y))
    31	(Div(32|64)F x y) -> (DIV(F|D) x y)
    32	
    33	(Mod32 x y) ->
    34		(SUB (XOR <typ.UInt32>                                                        // negate the result if x is negative
    35			(Select1 <typ.UInt32> (CALLudiv
    36				(SUB <typ.UInt32> (XOR <typ.UInt32> x (Signmask x)) (Signmask x))   // negate x if negative
    37				(SUB <typ.UInt32> (XOR <typ.UInt32> y (Signmask y)) (Signmask y)))) // negate y if negative
    38			(Signmask x)) (Signmask x))
    39	(Mod32u x y) -> (Select1 <typ.UInt32> (CALLudiv x y))
    40	(Mod16 x y) -> (Mod32 (SignExt16to32 x) (SignExt16to32 y))
    41	(Mod16u x y) -> (Mod32u (ZeroExt16to32 x) (ZeroExt16to32 y))
    42	(Mod8 x y) -> (Mod32 (SignExt8to32 x) (SignExt8to32 y))
    43	(Mod8u x y) -> (Mod32u (ZeroExt8to32 x) (ZeroExt8to32 y))
    44	
    45	// (x + y) / 2 with x>=y -> (x - y) / 2 + y
    46	(Avg32u <t> x y) -> (ADD (SRLconst <t> (SUB <t> x y) [1]) y)
    47	
    48	(And(32|16|8) x y) -> (AND x y)
    49	(Or(32|16|8) x y) -> (OR x y)
    50	(Xor(32|16|8) x y) -> (XOR x y)
    51	
    52	// unary ops
    53	(Neg(32|16|8) x) -> (RSBconst [0] x)
    54	(Neg(32|64)F x) -> (NEG(F|D) x)
    55	
    56	(Com(32|16|8) x) -> (MVN x)
    57	
    58	(Sqrt x) -> (SQRTD x)
    59	
    60	// TODO: optimize this for ARMv5 and ARMv6
    61	(Ctz32NonZero x) -> (Ctz32 x)
    62	(Ctz16NonZero x) -> (Ctz32 x)
    63	(Ctz8NonZero x) -> (Ctz32 x)
    64	
    65	// count trailing zero for ARMv5 and ARMv6
    66	// 32 - CLZ(x&-x - 1)
    67	(Ctz32 <t> x) && objabi.GOARM<=6 ->
    68		(RSBconst [32] (CLZ <t> (SUBconst <t> (AND <t> x (RSBconst <t> [0] x)) [1])))
    69	(Ctz16 <t> x) && objabi.GOARM<=6 ->
    70		(RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x10000] x))) [1])))
    71	(Ctz8 <t> x) && objabi.GOARM<=6 ->
    72		(RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x100] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x100] x))) [1])))
    73	
    74	// count trailing zero for ARMv7
    75	(Ctz32 <t> x) && objabi.GOARM==7 -> (CLZ <t> (RBIT <t> x))
    76	(Ctz16 <t> x) && objabi.GOARM==7 -> (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
    77	(Ctz8 <t> x) && objabi.GOARM==7 -> (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
    78	
    79	// bit length
    80	(BitLen32 <t> x) -> (RSBconst [32] (CLZ <t> x))
    81	
    82	// byte swap for ARMv5
    83	// let (a, b, c, d) be the bytes of x from high to low
    84	// t1 = x right rotate 16 bits -- (c,   d,   a,   b  )
    85	// t2 = x ^ t1                 -- (a^c, b^d, a^c, b^d)
    86	// t3 = t2 &^ 0xff0000         -- (a^c, 0,   a^c, b^d)
    87	// t4 = t3 >> 8                -- (0,   a^c, 0,   a^c)
    88	// t5 = x right rotate 8 bits  -- (d,   a,   b,   c  )
    89	// result = t4 ^ t5            -- (d,   c,   b,   a  )
    90	// using shifted ops this can be done in 4 instructions.
    91	(Bswap32 <t> x) && objabi.GOARM==5 ->
    92		(XOR <t>
    93			(SRLconst <t> (BICconst <t> (XOR <t> x (SRRconst <t> [16] x)) [0xff0000]) [8])
    94			(SRRconst <t> x [8]))
    95	
    96	// byte swap for ARMv6 and above
    97	(Bswap32 x) && objabi.GOARM>=6 -> (REV x)
    98	
    99	// boolean ops -- booleans are represented with 0=false, 1=true
   100	(AndB x y) -> (AND x y)
   101	(OrB x y) -> (OR x y)
   102	(EqB x y) -> (XORconst [1] (XOR <typ.Bool> x y))
   103	(NeqB x y) -> (XOR x y)
   104	(Not x) -> (XORconst [1] x)
   105	
   106	// shifts
   107	// hardware instruction uses only the low byte of the shift
   108	// we compare to 256 to ensure Go semantics for large shifts
   109	(Lsh32x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
   110	(Lsh32x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
   111	(Lsh32x8  x y) -> (SLL x (ZeroExt8to32 y))
   112	
   113	(Lsh16x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
   114	(Lsh16x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
   115	(Lsh16x8  x y) -> (SLL x (ZeroExt8to32 y))
   116	
   117	(Lsh8x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
   118	(Lsh8x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
   119	(Lsh8x8  x y) -> (SLL x (ZeroExt8to32 y))
   120	
   121	(Rsh32Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> x y) (CMPconst [256] y) [0])
   122	(Rsh32Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
   123	(Rsh32Ux8  x y) -> (SRL x (ZeroExt8to32 y))
   124	
   125	(Rsh16Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) y) (CMPconst [256] y) [0])
   126	(Rsh16Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
   127	(Rsh16Ux8  x y) -> (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
   128	
   129	(Rsh8Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) y) (CMPconst [256] y) [0])
   130	(Rsh8Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
   131	(Rsh8Ux8  x y) -> (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
   132	
   133	(Rsh32x32 x y) -> (SRAcond x y (CMPconst [256] y))
   134	(Rsh32x16 x y) -> (SRAcond x (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
   135	(Rsh32x8  x y) -> (SRA x (ZeroExt8to32 y))
   136	
   137	(Rsh16x32 x y) -> (SRAcond (SignExt16to32 x) y (CMPconst [256] y))
   138	(Rsh16x16 x y) -> (SRAcond (SignExt16to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
   139	(Rsh16x8  x y) -> (SRA (SignExt16to32 x) (ZeroExt8to32 y))
   140	
   141	(Rsh8x32 x y) -> (SRAcond (SignExt8to32 x) y (CMPconst [256] y))
   142	(Rsh8x16 x y) -> (SRAcond (SignExt8to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
   143	(Rsh8x8  x y) -> (SRA (SignExt8to32 x) (ZeroExt8to32 y))
   144	
   145	// constant shifts
   146	// generic opt rewrites all constant shifts to shift by Const64
   147	(Lsh32x64 x (Const64 [c])) && uint64(c) < 32 -> (SLLconst x [c])
   148	(Rsh32x64 x (Const64 [c])) && uint64(c) < 32 -> (SRAconst x [c])
   149	(Rsh32Ux64 x (Const64 [c])) && uint64(c) < 32 -> (SRLconst x [c])
   150	(Lsh16x64 x (Const64 [c])) && uint64(c) < 16 -> (SLLconst x [c])
   151	(Rsh16x64 x (Const64 [c])) && uint64(c) < 16 -> (SRAconst (SLLconst <typ.UInt32> x [16]) [c+16])
   152	(Rsh16Ux64 x (Const64 [c])) && uint64(c) < 16 -> (SRLconst (SLLconst <typ.UInt32> x [16]) [c+16])
   153	(Lsh8x64 x (Const64 [c])) && uint64(c) < 8 -> (SLLconst x [c])
   154	(Rsh8x64 x (Const64 [c])) && uint64(c) < 8 -> (SRAconst (SLLconst <typ.UInt32> x [24]) [c+24])
   155	(Rsh8Ux64 x (Const64 [c])) && uint64(c) < 8 -> (SRLconst (SLLconst <typ.UInt32> x [24]) [c+24])
   156	
   157	// large constant shifts
   158	(Lsh32x64 _ (Const64 [c])) && uint64(c) >= 32 -> (Const32 [0])
   159	(Rsh32Ux64 _ (Const64 [c])) && uint64(c) >= 32 -> (Const32 [0])
   160	(Lsh16x64 _ (Const64 [c])) && uint64(c) >= 16 -> (Const16 [0])
   161	(Rsh16Ux64 _ (Const64 [c])) && uint64(c) >= 16 -> (Const16 [0])
   162	(Lsh8x64 _ (Const64 [c])) && uint64(c) >= 8 -> (Const8 [0])
   163	(Rsh8Ux64 _ (Const64 [c])) && uint64(c) >= 8 -> (Const8 [0])
   164	
   165	// large constant signed right shift, we leave the sign bit
   166	(Rsh32x64 x (Const64 [c])) && uint64(c) >= 32 -> (SRAconst x [31])
   167	(Rsh16x64 x (Const64 [c])) && uint64(c) >= 16 -> (SRAconst (SLLconst <typ.UInt32> x [16]) [31])
   168	(Rsh8x64 x (Const64 [c])) && uint64(c) >= 8 -> (SRAconst (SLLconst <typ.UInt32> x [24]) [31])
   169	
   170	// constants
   171	(Const8 [val]) -> (MOVWconst [val])
   172	(Const16 [val]) -> (MOVWconst [val])
   173	(Const32 [val]) -> (MOVWconst [val])
   174	(Const32F [val]) -> (MOVFconst [val])
   175	(Const64F [val]) -> (MOVDconst [val])
   176	(ConstNil) -> (MOVWconst [0])
   177	(ConstBool [b]) -> (MOVWconst [b])
   178	
   179	// truncations
   180	// Because we ignore high parts of registers, truncates are just copies.
   181	(Trunc16to8 x) -> x
   182	(Trunc32to8 x) -> x
   183	(Trunc32to16 x) -> x
   184	
   185	// Zero-/Sign-extensions
   186	(ZeroExt8to16 x) -> (MOVBUreg x)
   187	(ZeroExt8to32 x) -> (MOVBUreg x)
   188	(ZeroExt16to32 x) -> (MOVHUreg x)
   189	
   190	(SignExt8to16 x) -> (MOVBreg x)
   191	(SignExt8to32 x) -> (MOVBreg x)
   192	(SignExt16to32 x) -> (MOVHreg x)
   193	
   194	(Signmask x) -> (SRAconst x [31])
   195	(Zeromask x) -> (SRAconst (RSBshiftRL <typ.Int32> x x [1]) [31]) // sign bit of uint32(x)>>1 - x
   196	(Slicemask <t> x) -> (SRAconst (RSBconst <t> [0] x) [31])
   197	
   198	// float <-> int conversion
   199	(Cvt32to32F x) -> (MOVWF x)
   200	(Cvt32to64F x) -> (MOVWD x)
   201	(Cvt32Uto32F x) -> (MOVWUF x)
   202	(Cvt32Uto64F x) -> (MOVWUD x)
   203	(Cvt32Fto32 x) -> (MOVFW x)
   204	(Cvt64Fto32 x) -> (MOVDW x)
   205	(Cvt32Fto32U x) -> (MOVFWU x)
   206	(Cvt64Fto32U x) -> (MOVDWU x)
   207	(Cvt32Fto64F x) -> (MOVFD x)
   208	(Cvt64Fto32F x) -> (MOVDF x)
   209	
   210	(Round(32|64)F x) -> x
   211	
   212	// comparisons
   213	(Eq8 x y)  -> (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
   214	(Eq16 x y) -> (Equal (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
   215	(Eq32 x y) -> (Equal (CMP x y))
   216	(EqPtr x y) -> (Equal (CMP x y))
   217	(Eq(32|64)F x y) -> (Equal (CMP(F|D) x y))
   218	
   219	(Neq8 x y)  -> (NotEqual (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
   220	(Neq16 x y) -> (NotEqual (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
   221	(Neq32 x y) -> (NotEqual (CMP x y))
   222	(NeqPtr x y) -> (NotEqual (CMP x y))
   223	(Neq(32|64)F x y) -> (NotEqual (CMP(F|D) x y))
   224	
   225	(Less8 x y)  -> (LessThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
   226	(Less16 x y) -> (LessThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
   227	(Less32 x y) -> (LessThan (CMP x y))
   228	(Less(32|64)F x y) -> (GreaterThan (CMP(F|D) y x)) // reverse operands to work around NaN
   229	
   230	(Less8U x y)  -> (LessThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
   231	(Less16U x y) -> (LessThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
   232	(Less32U x y) -> (LessThanU (CMP x y))
   233	
   234	(Leq8 x y)  -> (LessEqual (CMP (SignExt8to32 x) (SignExt8to32 y)))
   235	(Leq16 x y) -> (LessEqual (CMP (SignExt16to32 x) (SignExt16to32 y)))
   236	(Leq32 x y) -> (LessEqual (CMP x y))
   237	(Leq(32|64)F x y) -> (GreaterEqual (CMP(F|D) y x)) // reverse operands to work around NaN
   238	
   239	(Leq8U x y)  -> (LessEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
   240	(Leq16U x y) -> (LessEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
   241	(Leq32U x y) -> (LessEqualU (CMP x y))
   242	
   243	(Greater8 x y)  -> (GreaterThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
   244	(Greater16 x y) -> (GreaterThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
   245	(Greater32 x y) -> (GreaterThan (CMP x y))
   246	(Greater(32|64)F x y) -> (GreaterThan (CMP(F|D) x y))
   247	
   248	(Greater8U x y)  -> (GreaterThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
   249	(Greater16U x y) -> (GreaterThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
   250	(Greater32U x y) -> (GreaterThanU (CMP x y))
   251	
   252	(Geq8 x y)  -> (GreaterEqual (CMP (SignExt8to32 x) (SignExt8to32 y)))
   253	(Geq16 x y) -> (GreaterEqual (CMP (SignExt16to32 x) (SignExt16to32 y)))
   254	(Geq32 x y) -> (GreaterEqual (CMP x y))
   255	(Geq(32|64)F x y) -> (GreaterEqual (CMP(F|D) x y))
   256	
   257	(Geq8U x y)  -> (GreaterEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
   258	(Geq16U x y) -> (GreaterEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
   259	(Geq32U x y) -> (GreaterEqualU (CMP x y))
   260	
   261	(OffPtr [off] ptr:(SP)) -> (MOVWaddr [off] ptr)
   262	(OffPtr [off] ptr) -> (ADDconst [off] ptr)
   263	
   264	(Addr {sym} base) -> (MOVWaddr {sym} base)
   265	(LocalAddr {sym} base _) -> (MOVWaddr {sym} base)
   266	
   267	// loads
   268	(Load <t> ptr mem) && t.IsBoolean() -> (MOVBUload ptr mem)
   269	(Load <t> ptr mem) && (is8BitInt(t) && isSigned(t)) -> (MOVBload ptr mem)
   270	(Load <t> ptr mem) && (is8BitInt(t) && !isSigned(t)) -> (MOVBUload ptr mem)
   271	(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
   272	(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
   273	(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t)) -> (MOVWload ptr mem)
   274	(Load <t> ptr mem) && is32BitFloat(t) -> (MOVFload ptr mem)
   275	(Load <t> ptr mem) && is64BitFloat(t) -> (MOVDload ptr mem)
   276	
   277	// stores
   278	(Store {t} ptr val mem) && t.(*types.Type).Size() == 1 -> (MOVBstore ptr val mem)
   279	(Store {t} ptr val mem) && t.(*types.Type).Size() == 2 -> (MOVHstore ptr val mem)
   280	(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
   281	(Store {t} ptr val mem) && t.(*types.Type).Size() == 4 && is32BitFloat(val.Type) -> (MOVFstore ptr val mem)
   282	(Store {t} ptr val mem) && t.(*types.Type).Size() == 8 && is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
   283	
   284	// zero instructions
   285	(Zero [0] _ mem) -> mem
   286	(Zero [1] ptr mem) -> (MOVBstore ptr (MOVWconst [0]) mem)
   287	(Zero [2] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
   288		(MOVHstore ptr (MOVWconst [0]) mem)
   289	(Zero [2] ptr mem) ->
   290		(MOVBstore [1] ptr (MOVWconst [0])
   291			(MOVBstore [0] ptr (MOVWconst [0]) mem))
   292	(Zero [4] {t} ptr mem) && t.(*types.Type).Alignment()%4 == 0 ->
   293		(MOVWstore ptr (MOVWconst [0]) mem)
   294	(Zero [4] {t} ptr mem) && t.(*types.Type).Alignment()%2 == 0 ->
   295		(MOVHstore [2] ptr (MOVWconst [0])
   296			(MOVHstore [0] ptr (MOVWconst [0]) mem))
   297	(Zero [4] ptr mem) ->
   298		(MOVBstore [3] ptr (MOVWconst [0])
   299			(MOVBstore [2] ptr (MOVWconst [0])
   300				(MOVBstore [1] ptr (MOVWconst [0])
   301					(MOVBstore [0] ptr (MOVWconst [0]) mem))))
   302	
   303	(Zero [3] ptr mem) ->
   304		(MOVBstore [2] ptr (MOVWconst [0])
   305			(MOVBstore [1] ptr (MOVWconst [0])
   306				(MOVBstore [0] ptr (MOVWconst [0]) mem)))
   307	
   308	// Medium zeroing uses a duff device
   309	// 4 and 128 are magic constants, see runtime/mkduff.go
   310	(Zero [s] {t} ptr mem)
   311		&& s%4 == 0 && s > 4 && s <= 512
   312		&& t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice ->
   313		(DUFFZERO [4 * (128 - s/4)] ptr (MOVWconst [0]) mem)
   314	
   315	// Large zeroing uses a loop
   316	(Zero [s] {t} ptr mem)
   317		&& (s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0 ->
   318		(LoweredZero [t.(*types.Type).Alignment()]
   319			ptr
   320			(ADDconst <ptr.Type> ptr [s-moveSize(t.(*types.Type).Alignment(), config)])
   321			(MOVWconst [0])
   322			mem)
   323	
   324	// moves
   325	(Move [0] _ _ mem) -> mem
   326	(Move [1] dst src mem) -> (MOVBstore dst (MOVBUload src mem) mem)
   327	(Move [2] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
   328		(MOVHstore dst (MOVHUload src mem) mem)
   329	(Move [2] dst src mem) ->
   330		(MOVBstore [1] dst (MOVBUload [1] src mem)
   331			(MOVBstore dst (MOVBUload src mem) mem))
   332	(Move [4] {t} dst src mem) && t.(*types.Type).Alignment()%4 == 0 ->
   333		(MOVWstore dst (MOVWload src mem) mem)
   334	(Move [4] {t} dst src mem) && t.(*types.Type).Alignment()%2 == 0 ->
   335		(MOVHstore [2] dst (MOVHUload [2] src mem)
   336			(MOVHstore dst (MOVHUload src mem) mem))
   337	(Move [4] dst src mem) ->
   338		(MOVBstore [3] dst (MOVBUload [3] src mem)
   339			(MOVBstore [2] dst (MOVBUload [2] src mem)
   340				(MOVBstore [1] dst (MOVBUload [1] src mem)
   341					(MOVBstore dst (MOVBUload src mem) mem))))
   342	
   343	(Move [3] dst src mem) ->
   344		(MOVBstore [2] dst (MOVBUload [2] src mem)
   345			(MOVBstore [1] dst (MOVBUload [1] src mem)
   346				(MOVBstore dst (MOVBUload src mem) mem)))
   347	
   348	// Medium move uses a duff device
   349	// 8 and 128 are magic constants, see runtime/mkduff.go
   350	(Move [s] {t} dst src mem)
   351		&& s%4 == 0 && s > 4 && s <= 512
   352		&& t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice ->
   353		(DUFFCOPY [8 * (128 - s/4)] dst src mem)
   354	
   355	// Large move uses a loop
   356	(Move [s] {t} dst src mem)
   357		&& (s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0 ->
   358		(LoweredMove [t.(*types.Type).Alignment()]
   359			dst
   360			src
   361			(ADDconst <src.Type> src [s-moveSize(t.(*types.Type).Alignment(), config)])
   362			mem)
   363	
   364	// calls
   365	(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
   366	(ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem)
   367	(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
   368	
   369	// checks
   370	(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
   371	(IsNonNil ptr) -> (NotEqual (CMPconst [0] ptr))
   372	(IsInBounds idx len) -> (LessThanU (CMP idx len))
   373	(IsSliceInBounds idx len) -> (LessEqualU (CMP idx len))
   374	
   375	// pseudo-ops
   376	(GetClosurePtr) -> (LoweredGetClosurePtr)
   377	(GetCallerSP) -> (LoweredGetCallerSP)
   378	(GetCallerPC) -> (LoweredGetCallerPC)
   379	
   380	// Absorb pseudo-ops into blocks.
   381	(If (Equal cc) yes no) -> (EQ cc yes no)
   382	(If (NotEqual cc) yes no) -> (NE cc yes no)
   383	(If (LessThan cc) yes no) -> (LT cc yes no)
   384	(If (LessThanU cc) yes no) -> (ULT cc yes no)
   385	(If (LessEqual cc) yes no) -> (LE cc yes no)
   386	(If (LessEqualU cc) yes no) -> (ULE cc yes no)
   387	(If (GreaterThan cc) yes no) -> (GT cc yes no)
   388	(If (GreaterThanU cc) yes no) -> (UGT cc yes no)
   389	(If (GreaterEqual cc) yes no) -> (GE cc yes no)
   390	(If (GreaterEqualU cc) yes no) -> (UGE cc yes no)
   391	
   392	(If cond yes no) -> (NE (CMPconst [0] cond) yes no)
   393	
   394	// Absorb boolean tests into block
   395	(NE (CMPconst [0] (Equal cc)) yes no) -> (EQ cc yes no)
   396	(NE (CMPconst [0] (NotEqual cc)) yes no) -> (NE cc yes no)
   397	(NE (CMPconst [0] (LessThan cc)) yes no) -> (LT cc yes no)
   398	(NE (CMPconst [0] (LessThanU cc)) yes no) -> (ULT cc yes no)
   399	(NE (CMPconst [0] (LessEqual cc)) yes no) -> (LE cc yes no)
   400	(NE (CMPconst [0] (LessEqualU cc)) yes no) -> (ULE cc yes no)
   401	(NE (CMPconst [0] (GreaterThan cc)) yes no) -> (GT cc yes no)
   402	(NE (CMPconst [0] (GreaterThanU cc)) yes no) -> (UGT cc yes no)
   403	(NE (CMPconst [0] (GreaterEqual cc)) yes no) -> (GE cc yes no)
   404	(NE (CMPconst [0] (GreaterEqualU cc)) yes no) -> (UGE cc yes no)
   405	
   406	// Write barrier.
   407	(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
   408	
   409	(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 -> (LoweredPanicBoundsA [kind] x y mem)
   410	(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 -> (LoweredPanicBoundsB [kind] x y mem)
   411	(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 -> (LoweredPanicBoundsC [kind] x y mem)
   412	
   413	(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 0 -> (LoweredPanicExtendA [kind] hi lo y mem)
   414	(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 1 -> (LoweredPanicExtendB [kind] hi lo y mem)
   415	(PanicExtend [kind] hi lo y mem) && boundsABI(kind) == 2 -> (LoweredPanicExtendC [kind] hi lo y mem)
   416	
   417	// Optimizations
   418	
   419	// fold offset into address
   420	(ADDconst [off1] (MOVWaddr [off2] {sym} ptr)) -> (MOVWaddr [off1+off2] {sym} ptr)
   421	(SUBconst [off1] (MOVWaddr [off2] {sym} ptr)) -> (MOVWaddr [off2-off1] {sym} ptr)
   422	
   423	// fold address into load/store
   424	(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBload [off1+off2] {sym} ptr mem)
   425	(MOVBload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVBload [off1-off2] {sym} ptr mem)
   426	(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBUload [off1+off2] {sym} ptr mem)
   427	(MOVBUload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVBUload [off1-off2] {sym} ptr mem)
   428	(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVHload [off1+off2] {sym} ptr mem)
   429	(MOVHload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVHload [off1-off2] {sym} ptr mem)
   430	(MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVHUload [off1+off2] {sym} ptr mem)
   431	(MOVHUload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVHUload [off1-off2] {sym} ptr mem)
   432	(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVWload [off1+off2] {sym} ptr mem)
   433	(MOVWload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVWload [off1-off2] {sym} ptr mem)
   434	(MOVFload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVFload [off1+off2] {sym} ptr mem)
   435	(MOVFload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVFload [off1-off2] {sym} ptr mem)
   436	(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVDload [off1+off2] {sym} ptr mem)
   437	(MOVDload [off1] {sym} (SUBconst [off2] ptr) mem) -> (MOVDload [off1-off2] {sym} ptr mem)
   438	
   439	(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVBstore [off1+off2] {sym} ptr val mem)
   440	(MOVBstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVBstore [off1-off2] {sym} ptr val mem)
   441	(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVHstore [off1+off2] {sym} ptr val mem)
   442	(MOVHstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVHstore [off1-off2] {sym} ptr val mem)
   443	(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVWstore [off1+off2] {sym} ptr val mem)
   444	(MOVWstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVWstore [off1-off2] {sym} ptr val mem)
   445	(MOVFstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVFstore [off1+off2] {sym} ptr val mem)
   446	(MOVFstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVFstore [off1-off2] {sym} ptr val mem)
   447	(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVDstore [off1+off2] {sym} ptr val mem)
   448	(MOVDstore [off1] {sym} (SUBconst [off2] ptr) val mem) -> (MOVDstore [off1-off2] {sym} ptr val mem)
   449	
   450	(MOVBload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   451		(MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   452	(MOVBUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   453		(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   454	(MOVHload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   455		(MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   456	(MOVHUload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   457		(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   458	(MOVWload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   459		(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   460	(MOVFload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   461		(MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   462	(MOVDload [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
   463		(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
   464	
   465	(MOVBstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   466		(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   467	(MOVHstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   468		(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   469	(MOVWstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   470		(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   471	(MOVFstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   472		(MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   473	(MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
   474		(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
   475	
   476	// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
   477	(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBreg x)
   478	(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
   479	(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHreg x)
   480	(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
   481	(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
   482	
   483	(MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
   484	(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
   485	
   486	(MOVWloadidx ptr idx (MOVWstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> x
   487	(MOVWloadshiftLL ptr idx [c] (MOVWstoreshiftLL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
   488	(MOVWloadshiftRL ptr idx [c] (MOVWstoreshiftRL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
   489	(MOVWloadshiftRA ptr idx [c] (MOVWstoreshiftRA ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
   490	(MOVBUloadidx ptr idx (MOVBstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
   491	(MOVBloadidx ptr idx (MOVBstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> (MOVBreg x)
   492	(MOVHUloadidx ptr idx (MOVHstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
   493	(MOVHloadidx ptr idx (MOVHstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> (MOVHreg x)
   494	
   495	// fold constant into arithmatic ops
   496	(ADD x (MOVWconst [c])) -> (ADDconst [c] x)
   497	(SUB (MOVWconst [c]) x) -> (RSBconst [c] x)
   498	(SUB x (MOVWconst [c])) -> (SUBconst [c] x)
   499	(RSB (MOVWconst [c]) x) -> (SUBconst [c] x)
   500	(RSB x (MOVWconst [c])) -> (RSBconst [c] x)
   501	
   502	(ADDS x (MOVWconst [c])) -> (ADDSconst [c] x)
   503	(SUBS x (MOVWconst [c])) -> (SUBSconst [c] x)
   504	
   505	(ADC (MOVWconst [c]) x flags) -> (ADCconst [c] x flags)
   506	(ADC x (MOVWconst [c]) flags) -> (ADCconst [c] x flags)
   507	(SBC (MOVWconst [c]) x flags) -> (RSCconst [c] x flags)
   508	(SBC x (MOVWconst [c]) flags) -> (SBCconst [c] x flags)
   509	
   510	(AND x (MOVWconst [c])) -> (ANDconst [c] x)
   511	(OR  x (MOVWconst [c])) -> (ORconst [c] x)
   512	(XOR x (MOVWconst [c])) -> (XORconst [c] x)
   513	(BIC x (MOVWconst [c])) -> (BICconst [c] x)
   514	
   515	(SLL x (MOVWconst [c])) -> (SLLconst x [c&31]) // Note: I don't think we ever generate bad constant shifts (i.e. c>=32)
   516	(SRL x (MOVWconst [c])) -> (SRLconst x [c&31])
   517	(SRA x (MOVWconst [c])) -> (SRAconst x [c&31])
   518	
   519	(CMP x (MOVWconst [c])) -> (CMPconst [c] x)
   520	(CMP (MOVWconst [c]) x) -> (InvertFlags (CMPconst [c] x))
   521	(CMN x (MOVWconst [c])) -> (CMNconst [c] x)
   522	(TST x (MOVWconst [c])) -> (TSTconst [c] x)
   523	(TEQ x (MOVWconst [c])) -> (TEQconst [c] x)
   524	
   525	// don't extend after proper load
   526	// MOVWreg instruction is not emitted if src and dst registers are same, but it ensures the type.
   527	(MOVBreg x:(MOVBload _ _)) -> (MOVWreg x)
   528	(MOVBUreg x:(MOVBUload _ _)) -> (MOVWreg x)
   529	(MOVHreg x:(MOVBload _ _)) -> (MOVWreg x)
   530	(MOVHreg x:(MOVBUload _ _)) -> (MOVWreg x)
   531	(MOVHreg x:(MOVHload _ _)) -> (MOVWreg x)
   532	(MOVHUreg x:(MOVBUload _ _)) -> (MOVWreg x)
   533	(MOVHUreg x:(MOVHUload _ _)) -> (MOVWreg x)
   534	
   535	// fold extensions and ANDs together
   536	(MOVBUreg (ANDconst [c] x)) -> (ANDconst [c&0xff] x)
   537	(MOVHUreg (ANDconst [c] x)) -> (ANDconst [c&0xffff] x)
   538	(MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 -> (ANDconst [c&0x7f] x)
   539	(MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 -> (ANDconst [c&0x7fff] x)
   540	
   541	// fold double extensions
   542	(MOVBreg x:(MOVBreg _)) -> (MOVWreg x)
   543	(MOVBUreg x:(MOVBUreg _)) -> (MOVWreg x)
   544	(MOVHreg x:(MOVBreg _)) -> (MOVWreg x)
   545	(MOVHreg x:(MOVBUreg _)) -> (MOVWreg x)
   546	(MOVHreg x:(MOVHreg _)) -> (MOVWreg x)
   547	(MOVHUreg x:(MOVBUreg _)) -> (MOVWreg x)
   548	(MOVHUreg x:(MOVHUreg _)) -> (MOVWreg x)
   549	
   550	// don't extend before store
   551	(MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   552	(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   553	(MOVBstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   554	(MOVBstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
   555	(MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   556	(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
   557	
   558	// if a register move has only 1 use, just use the same register without emitting instruction
   559	// MOVWnop doesn't emit instruction, only for ensuring the type.
   560	(MOVWreg x) && x.Uses == 1 -> (MOVWnop x)
   561	
   562	// mul by constant
   563	(MUL x (MOVWconst [c])) && int32(c) == -1 -> (RSBconst [0] x)
   564	(MUL _ (MOVWconst [0])) -> (MOVWconst [0])
   565	(MUL x (MOVWconst [1])) -> x
   566	(MUL x (MOVWconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
   567	(MUL x (MOVWconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)])
   568	(MUL x (MOVWconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSBshiftLL x x [log2(c+1)])
   569	(MUL x (MOVWconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
   570	(MUL x (MOVWconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
   571	(MUL x (MOVWconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (RSBshiftLL <x.Type> x x [3]))
   572	(MUL x (MOVWconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
   573	
   574	(MULA x (MOVWconst [c]) a) && int32(c) == -1 -> (SUB a x)
   575	(MULA _ (MOVWconst [0]) a) -> a
   576	(MULA x (MOVWconst [1]) a) -> (ADD x a)
   577	(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a)
   578	(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADD (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
   579	(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADD (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
   580	(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)
   581	(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)
   582	(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)
   583	(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)
   584	
   585	(MULA (MOVWconst [c]) x a) && int32(c) == -1 -> (SUB a x)
   586	(MULA (MOVWconst [0]) _ a) -> a
   587	(MULA (MOVWconst [1]) x a) -> (ADD x a)
   588	(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a)
   589	(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADD (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
   590	(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADD (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
   591	(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)
   592	(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)
   593	(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)
   594	(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)
   595	
   596	(MULS x (MOVWconst [c]) a) && int32(c) == -1 -> (ADD a x)
   597	(MULS _ (MOVWconst [0]) a) -> a
   598	(MULS x (MOVWconst [1]) a) -> (RSB x a)
   599	(MULS x (MOVWconst [c]) a) && isPowerOfTwo(c) -> (RSB (SLLconst <x.Type> [log2(c)] x) a)
   600	(MULS x (MOVWconst [c]) a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (RSB (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
   601	(MULS x (MOVWconst [c]) a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSB (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
   602	(MULS x (MOVWconst [c]) a) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) a)
   603	(MULS x (MOVWconst [c]) a) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) a)
   604	(MULS x (MOVWconst [c]) a) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/7)] (RSBshiftLL <x.Type> x x [3])) a)
   605	(MULS x (MOVWconst [c]) a) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) a)
   606	
   607	(MULS (MOVWconst [c]) x a) && int32(c) == -1 -> (ADD a x)
   608	(MULS (MOVWconst [0]) _ a) -> a
   609	(MULS (MOVWconst [1]) x a) -> (RSB x a)
   610	(MULS (MOVWconst [c]) x a) && isPowerOfTwo(c) -> (RSB (SLLconst <x.Type> [log2(c)] x) a)
   611	(MULS (MOVWconst [c]) x a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (RSB (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
   612	(MULS (MOVWconst [c]) x a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSB (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
   613	(MULS (MOVWconst [c]) x a) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) a)
   614	(MULS (MOVWconst [c]) x a) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) a)
   615	(MULS (MOVWconst [c]) x a) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/7)] (RSBshiftLL <x.Type> x x [3])) a)
   616	(MULS (MOVWconst [c]) x a) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (RSB (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) a)
   617	
   618	// div by constant
   619	(Select0 (CALLudiv x (MOVWconst [1]))) -> x
   620	(Select1 (CALLudiv _ (MOVWconst [1]))) -> (MOVWconst [0])
   621	(Select0 (CALLudiv x (MOVWconst [c]))) && isPowerOfTwo(c) -> (SRLconst [log2(c)] x)
   622	(Select1 (CALLudiv x (MOVWconst [c]))) && isPowerOfTwo(c) -> (ANDconst [c-1] x)
   623	
   624	// constant comparisons
   625	(CMPconst (MOVWconst [x]) [y]) && int32(x)==int32(y) -> (FlagEQ)
   626	(CMPconst (MOVWconst [x]) [y]) && int32(x)<int32(y) && uint32(x)<uint32(y) -> (FlagLT_ULT)
   627	(CMPconst (MOVWconst [x]) [y]) && int32(x)<int32(y) && uint32(x)>uint32(y) -> (FlagLT_UGT)
   628	(CMPconst (MOVWconst [x]) [y]) && int32(x)>int32(y) && uint32(x)<uint32(y) -> (FlagGT_ULT)
   629	(CMPconst (MOVWconst [x]) [y]) && int32(x)>int32(y) && uint32(x)>uint32(y) -> (FlagGT_UGT)
   630	(CMNconst (MOVWconst [x]) [y]) && int32(x)==int32(-y) -> (FlagEQ)
   631	(CMNconst (MOVWconst [x]) [y]) && int32(x)<int32(-y) && uint32(x)<uint32(-y) -> (FlagLT_ULT)
   632	(CMNconst (MOVWconst [x]) [y]) && int32(x)<int32(-y) && uint32(x)>uint32(-y) -> (FlagLT_UGT)
   633	(CMNconst (MOVWconst [x]) [y]) && int32(x)>int32(-y) && uint32(x)<uint32(-y) -> (FlagGT_ULT)
   634	(CMNconst (MOVWconst [x]) [y]) && int32(x)>int32(-y) && uint32(x)>uint32(-y) -> (FlagGT_UGT)
   635	(TSTconst (MOVWconst [x]) [y]) && int32(x&y)==0 -> (FlagEQ)
   636	(TSTconst (MOVWconst [x]) [y]) && int32(x&y)<0 -> (FlagLT_UGT)
   637	(TSTconst (MOVWconst [x]) [y]) && int32(x&y)>0 -> (FlagGT_UGT)
   638	(TEQconst (MOVWconst [x]) [y]) && int32(x^y)==0 -> (FlagEQ)
   639	(TEQconst (MOVWconst [x]) [y]) && int32(x^y)<0 -> (FlagLT_UGT)
   640	(TEQconst (MOVWconst [x]) [y]) && int32(x^y)>0 -> (FlagGT_UGT)
   641	
   642	// other known comparisons
   643	(CMPconst (MOVBUreg _) [c]) && 0xff < c -> (FlagLT_ULT)
   644	(CMPconst (MOVHUreg _) [c]) && 0xffff < c -> (FlagLT_ULT)
   645	(CMPconst (ANDconst _ [m]) [n]) && 0 <= int32(m) && int32(m) < int32(n) -> (FlagLT_ULT)
   646	(CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n) -> (FlagLT_ULT)
   647	
   648	// absorb flag constants into branches
   649	(EQ (FlagEQ) yes no) -> (First nil yes no)
   650	(EQ (FlagLT_ULT) yes no) -> (First nil no yes)
   651	(EQ (FlagLT_UGT) yes no) -> (First nil no yes)
   652	(EQ (FlagGT_ULT) yes no) -> (First nil no yes)
   653	(EQ (FlagGT_UGT) yes no) -> (First nil no yes)
   654	
   655	(NE (FlagEQ) yes no) -> (First nil no yes)
   656	(NE (FlagLT_ULT) yes no) -> (First nil yes no)
   657	(NE (FlagLT_UGT) yes no) -> (First nil yes no)
   658	(NE (FlagGT_ULT) yes no) -> (First nil yes no)
   659	(NE (FlagGT_UGT) yes no) -> (First nil yes no)
   660	
   661	(LT (FlagEQ) yes no) -> (First nil no yes)
   662	(LT (FlagLT_ULT) yes no) -> (First nil yes no)
   663	(LT (FlagLT_UGT) yes no) -> (First nil yes no)
   664	(LT (FlagGT_ULT) yes no) -> (First nil no yes)
   665	(LT (FlagGT_UGT) yes no) -> (First nil no yes)
   666	
   667	(LE (FlagEQ) yes no) -> (First nil yes no)
   668	(LE (FlagLT_ULT) yes no) -> (First nil yes no)
   669	(LE (FlagLT_UGT) yes no) -> (First nil yes no)
   670	(LE (FlagGT_ULT) yes no) -> (First nil no yes)
   671	(LE (FlagGT_UGT) yes no) -> (First nil no yes)
   672	
   673	(GT (FlagEQ) yes no) -> (First nil no yes)
   674	(GT (FlagLT_ULT) yes no) -> (First nil no yes)
   675	(GT (FlagLT_UGT) yes no) -> (First nil no yes)
   676	(GT (FlagGT_ULT) yes no) -> (First nil yes no)
   677	(GT (FlagGT_UGT) yes no) -> (First nil yes no)
   678	
   679	(GE (FlagEQ) yes no) -> (First nil yes no)
   680	(GE (FlagLT_ULT) yes no) -> (First nil no yes)
   681	(GE (FlagLT_UGT) yes no) -> (First nil no yes)
   682	(GE (FlagGT_ULT) yes no) -> (First nil yes no)
   683	(GE (FlagGT_UGT) yes no) -> (First nil yes no)
   684	
   685	(ULT (FlagEQ) yes no) -> (First nil no yes)
   686	(ULT (FlagLT_ULT) yes no) -> (First nil yes no)
   687	(ULT (FlagLT_UGT) yes no) -> (First nil no yes)
   688	(ULT (FlagGT_ULT) yes no) -> (First nil yes no)
   689	(ULT (FlagGT_UGT) yes no) -> (First nil no yes)
   690	
   691	(ULE (FlagEQ) yes no) -> (First nil yes no)
   692	(ULE (FlagLT_ULT) yes no) -> (First nil yes no)
   693	(ULE (FlagLT_UGT) yes no) -> (First nil no yes)
   694	(ULE (FlagGT_ULT) yes no) -> (First nil yes no)
   695	(ULE (FlagGT_UGT) yes no) -> (First nil no yes)
   696	
   697	(UGT (FlagEQ) yes no) -> (First nil no yes)
   698	(UGT (FlagLT_ULT) yes no) -> (First nil no yes)
   699	(UGT (FlagLT_UGT) yes no) -> (First nil yes no)
   700	(UGT (FlagGT_ULT) yes no) -> (First nil no yes)
   701	(UGT (FlagGT_UGT) yes no) -> (First nil yes no)
   702	
   703	(UGE (FlagEQ) yes no) -> (First nil yes no)
   704	(UGE (FlagLT_ULT) yes no) -> (First nil no yes)
   705	(UGE (FlagLT_UGT) yes no) -> (First nil yes no)
   706	(UGE (FlagGT_ULT) yes no) -> (First nil no yes)
   707	(UGE (FlagGT_UGT) yes no) -> (First nil yes no)
   708	
   709	// absorb InvertFlags into branches
   710	(LT (InvertFlags cmp) yes no) -> (GT cmp yes no)
   711	(GT (InvertFlags cmp) yes no) -> (LT cmp yes no)
   712	(LE (InvertFlags cmp) yes no) -> (GE cmp yes no)
   713	(GE (InvertFlags cmp) yes no) -> (LE cmp yes no)
   714	(ULT (InvertFlags cmp) yes no) -> (UGT cmp yes no)
   715	(UGT (InvertFlags cmp) yes no) -> (ULT cmp yes no)
   716	(ULE (InvertFlags cmp) yes no) -> (UGE cmp yes no)
   717	(UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no)
   718	(EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no)
   719	(NE (InvertFlags cmp) yes no) -> (NE cmp yes no)
   720	
   721	// absorb flag constants into boolean values
   722	(Equal (FlagEQ)) -> (MOVWconst [1])
   723	(Equal (FlagLT_ULT)) -> (MOVWconst [0])
   724	(Equal (FlagLT_UGT)) -> (MOVWconst [0])
   725	(Equal (FlagGT_ULT)) -> (MOVWconst [0])
   726	(Equal (FlagGT_UGT)) -> (MOVWconst [0])
   727	
   728	(NotEqual (FlagEQ)) -> (MOVWconst [0])
   729	(NotEqual (FlagLT_ULT)) -> (MOVWconst [1])
   730	(NotEqual (FlagLT_UGT)) -> (MOVWconst [1])
   731	(NotEqual (FlagGT_ULT)) -> (MOVWconst [1])
   732	(NotEqual (FlagGT_UGT)) -> (MOVWconst [1])
   733	
   734	(LessThan (FlagEQ)) -> (MOVWconst [0])
   735	(LessThan (FlagLT_ULT)) -> (MOVWconst [1])
   736	(LessThan (FlagLT_UGT)) -> (MOVWconst [1])
   737	(LessThan (FlagGT_ULT)) -> (MOVWconst [0])
   738	(LessThan (FlagGT_UGT)) -> (MOVWconst [0])
   739	
   740	(LessThanU (FlagEQ)) -> (MOVWconst [0])
   741	(LessThanU (FlagLT_ULT)) -> (MOVWconst [1])
   742	(LessThanU (FlagLT_UGT)) -> (MOVWconst [0])
   743	(LessThanU (FlagGT_ULT)) -> (MOVWconst [1])
   744	(LessThanU (FlagGT_UGT)) -> (MOVWconst [0])
   745	
   746	(LessEqual (FlagEQ)) -> (MOVWconst [1])
   747	(LessEqual (FlagLT_ULT)) -> (MOVWconst [1])
   748	(LessEqual (FlagLT_UGT)) -> (MOVWconst [1])
   749	(LessEqual (FlagGT_ULT)) -> (MOVWconst [0])
   750	(LessEqual (FlagGT_UGT)) -> (MOVWconst [0])
   751	
   752	(LessEqualU (FlagEQ)) -> (MOVWconst [1])
   753	(LessEqualU (FlagLT_ULT)) -> (MOVWconst [1])
   754	(LessEqualU (FlagLT_UGT)) -> (MOVWconst [0])
   755	(LessEqualU (FlagGT_ULT)) -> (MOVWconst [1])
   756	(LessEqualU (FlagGT_UGT)) -> (MOVWconst [0])
   757	
   758	(GreaterThan (FlagEQ)) -> (MOVWconst [0])
   759	(GreaterThan (FlagLT_ULT)) -> (MOVWconst [0])
   760	(GreaterThan (FlagLT_UGT)) -> (MOVWconst [0])
   761	(GreaterThan (FlagGT_ULT)) -> (MOVWconst [1])
   762	(GreaterThan (FlagGT_UGT)) -> (MOVWconst [1])
   763	
   764	(GreaterThanU (FlagEQ)) -> (MOVWconst [0])
   765	(GreaterThanU (FlagLT_ULT)) -> (MOVWconst [0])
   766	(GreaterThanU (FlagLT_UGT)) -> (MOVWconst [1])
   767	(GreaterThanU (FlagGT_ULT)) -> (MOVWconst [0])
   768	(GreaterThanU (FlagGT_UGT)) -> (MOVWconst [1])
   769	
   770	(GreaterEqual (FlagEQ)) -> (MOVWconst [1])
   771	(GreaterEqual (FlagLT_ULT)) -> (MOVWconst [0])
   772	(GreaterEqual (FlagLT_UGT)) -> (MOVWconst [0])
   773	(GreaterEqual (FlagGT_ULT)) -> (MOVWconst [1])
   774	(GreaterEqual (FlagGT_UGT)) -> (MOVWconst [1])
   775	
   776	(GreaterEqualU (FlagEQ)) -> (MOVWconst [1])
   777	(GreaterEqualU (FlagLT_ULT)) -> (MOVWconst [0])
   778	(GreaterEqualU (FlagLT_UGT)) -> (MOVWconst [1])
   779	(GreaterEqualU (FlagGT_ULT)) -> (MOVWconst [0])
   780	(GreaterEqualU (FlagGT_UGT)) -> (MOVWconst [1])
   781	
   782	// absorb InvertFlags into boolean values
   783	(Equal (InvertFlags x)) -> (Equal x)
   784	(NotEqual (InvertFlags x)) -> (NotEqual x)
   785	(LessThan (InvertFlags x)) -> (GreaterThan x)
   786	(LessThanU (InvertFlags x)) -> (GreaterThanU x)
   787	(GreaterThan (InvertFlags x)) -> (LessThan x)
   788	(GreaterThanU (InvertFlags x)) -> (LessThanU x)
   789	(LessEqual (InvertFlags x)) -> (GreaterEqual x)
   790	(LessEqualU (InvertFlags x)) -> (GreaterEqualU x)
   791	(GreaterEqual (InvertFlags x)) -> (LessEqual x)
   792	(GreaterEqualU (InvertFlags x)) -> (LessEqualU x)
   793	
   794	// absorb flag constants into conditional instructions
   795	(CMOVWLSconst _ (FlagEQ) [c]) -> (MOVWconst [c])
   796	(CMOVWLSconst _ (FlagLT_ULT) [c]) -> (MOVWconst [c])
   797	(CMOVWLSconst x (FlagLT_UGT)) -> x
   798	(CMOVWLSconst _ (FlagGT_ULT) [c]) -> (MOVWconst [c])
   799	(CMOVWLSconst x (FlagGT_UGT)) -> x
   800	
   801	(CMOVWHSconst _ (FlagEQ) [c]) -> (MOVWconst [c])
   802	(CMOVWHSconst x (FlagLT_ULT)) -> x
   803	(CMOVWHSconst _ (FlagLT_UGT) [c]) -> (MOVWconst [c])
   804	(CMOVWHSconst x (FlagGT_ULT)) -> x
   805	(CMOVWHSconst _ (FlagGT_UGT) [c]) -> (MOVWconst [c])
   806	
   807	(CMOVWLSconst x (InvertFlags flags) [c]) -> (CMOVWHSconst x flags [c])
   808	(CMOVWHSconst x (InvertFlags flags) [c]) -> (CMOVWLSconst x flags [c])
   809	
   810	(SRAcond x _ (FlagEQ)) -> (SRAconst x [31])
   811	(SRAcond x y (FlagLT_ULT)) -> (SRA x y)
   812	(SRAcond x _ (FlagLT_UGT)) -> (SRAconst x [31])
   813	(SRAcond x y (FlagGT_ULT)) -> (SRA x y)
   814	(SRAcond x _ (FlagGT_UGT)) -> (SRAconst x [31])
   815	
   816	// remove redundant *const ops
   817	(ADDconst [0] x) -> x
   818	(SUBconst [0] x) -> x
   819	(ANDconst [0] _) -> (MOVWconst [0])
   820	(ANDconst [c] x) && int32(c)==-1 -> x
   821	(ORconst [0] x) -> x
   822	(ORconst [c] _) && int32(c)==-1 -> (MOVWconst [-1])
   823	(XORconst [0] x) -> x
   824	(BICconst [0] x) -> x
   825	(BICconst [c] _) && int32(c)==-1 -> (MOVWconst [0])
   826	
   827	// generic constant folding
   828	(ADDconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) -> (SUBconst [int64(int32(-c))] x)
   829	(SUBconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) -> (ADDconst [int64(int32(-c))] x)
   830	(ANDconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c)) -> (BICconst [int64(int32(^uint32(c)))] x)
   831	(BICconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c)) -> (ANDconst [int64(int32(^uint32(c)))] x)
   832	(ADDconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff -> (SUBconst [int64(int32(-c))] x)
   833	(SUBconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff -> (ANDconst [int64(int32(-c))] x)
   834	(ANDconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff -> (BICconst [int64(int32(^uint32(c)))] x)
   835	(BICconst [c] x) && objabi.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff -> (ANDconst [int64(int32(^uint32(c)))] x)
   836	(ADDconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(c+d))])
   837	(ADDconst [c] (ADDconst [d] x)) -> (ADDconst [int64(int32(c+d))] x)
   838	(ADDconst [c] (SUBconst [d] x)) -> (ADDconst [int64(int32(c-d))] x)
   839	(ADDconst [c] (RSBconst [d] x)) -> (RSBconst [int64(int32(c+d))] x)
   840	(ADCconst [c] (ADDconst [d] x) flags) -> (ADCconst [int64(int32(c+d))] x flags)
   841	(ADCconst [c] (SUBconst [d] x) flags) -> (ADCconst [int64(int32(c-d))] x flags)
   842	(SUBconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(d-c))])
   843	(SUBconst [c] (SUBconst [d] x)) -> (ADDconst [int64(int32(-c-d))] x)
   844	(SUBconst [c] (ADDconst [d] x)) -> (ADDconst [int64(int32(-c+d))] x)
   845	(SUBconst [c] (RSBconst [d] x)) -> (RSBconst [int64(int32(-c+d))] x)
   846	(SBCconst [c] (ADDconst [d] x) flags) -> (SBCconst [int64(int32(c-d))] x flags)
   847	(SBCconst [c] (SUBconst [d] x) flags) -> (SBCconst [int64(int32(c+d))] x flags)
   848	(RSBconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(c-d))])
   849	(RSBconst [c] (RSBconst [d] x)) -> (ADDconst [int64(int32(c-d))] x)
   850	(RSBconst [c] (ADDconst [d] x)) -> (RSBconst [int64(int32(c-d))] x)
   851	(RSBconst [c] (SUBconst [d] x)) -> (RSBconst [int64(int32(c+d))] x)
   852	(RSCconst [c] (ADDconst [d] x) flags) -> (RSCconst [int64(int32(c-d))] x flags)
   853	(RSCconst [c] (SUBconst [d] x) flags) -> (RSCconst [int64(int32(c+d))] x flags)
   854	(SLLconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(uint32(d)<<uint64(c)))])
   855	(SRLconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(uint32(d)>>uint64(c)))])
   856	(SRAconst [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(d)>>uint64(c))])
   857	(MUL (MOVWconst [c]) (MOVWconst [d])) -> (MOVWconst [int64(int32(c*d))])
   858	(MULA (MOVWconst [c]) (MOVWconst [d]) a) -> (ADDconst [int64(int32(c*d))] a)
   859	(MULS (MOVWconst [c]) (MOVWconst [d]) a) -> (SUBconst [int64(int32(c*d))] a)
   860	(Select0 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) -> (MOVWconst [int64(int32(uint32(c)/uint32(d)))])
   861	(Select1 (CALLudiv (MOVWconst [c]) (MOVWconst [d]))) -> (MOVWconst [int64(int32(uint32(c)%uint32(d)))])
   862	(ANDconst [c] (MOVWconst [d])) -> (MOVWconst [c&d])
   863	(ANDconst [c] (ANDconst [d] x)) -> (ANDconst [c&d] x)
   864	(ORconst [c] (MOVWconst [d])) -> (MOVWconst [c|d])
   865	(ORconst [c] (ORconst [d] x)) -> (ORconst [c|d] x)
   866	(XORconst [c] (MOVWconst [d])) -> (MOVWconst [c^d])
   867	(XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
   868	(BICconst [c] (MOVWconst [d])) -> (MOVWconst [d&^c])
   869	(BICconst [c] (BICconst [d] x)) -> (BICconst [int64(int32(c|d))] x)
   870	(MVN (MOVWconst [c])) -> (MOVWconst [^c])
   871	(MOVBreg (MOVWconst [c])) -> (MOVWconst [int64(int8(c))])
   872	(MOVBUreg (MOVWconst [c])) -> (MOVWconst [int64(uint8(c))])
   873	(MOVHreg (MOVWconst [c])) -> (MOVWconst [int64(int16(c))])
   874	(MOVHUreg (MOVWconst [c])) -> (MOVWconst [int64(uint16(c))])
   875	(MOVWreg (MOVWconst [c])) -> (MOVWconst [c])
   876	// BFX: Width = c >> 8, LSB = c & 0xff, result = d << (32 - Width - LSB) >> (32 - Width)
   877	(BFX [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8)))])
   878	(BFXU [c] (MOVWconst [d])) -> (MOVWconst [int64(int32(uint32(d)<<(32-uint32(c&0xff)-uint32(c>>8))>>(32-uint32(c>>8))))])
   879	
   880	// absorb shifts into ops
   881	(ADD x (SLLconst [c] y)) -> (ADDshiftLL x y [c])
   882	(ADD x (SRLconst [c] y)) -> (ADDshiftRL x y [c])
   883	(ADD x (SRAconst [c] y)) -> (ADDshiftRA x y [c])
   884	(ADD x (SLL y z)) -> (ADDshiftLLreg x y z)
   885	(ADD x (SRL y z)) -> (ADDshiftRLreg x y z)
   886	(ADD x (SRA y z)) -> (ADDshiftRAreg x y z)
   887	(ADC x (SLLconst [c] y) flags) -> (ADCshiftLL x y [c] flags)
   888	(ADC (SLLconst [c] y) x flags) -> (ADCshiftLL x y [c] flags)
   889	(ADC x (SRLconst [c] y) flags) -> (ADCshiftRL x y [c] flags)
   890	(ADC (SRLconst [c] y) x flags) -> (ADCshiftRL x y [c] flags)
   891	(ADC x (SRAconst [c] y) flags) -> (ADCshiftRA x y [c] flags)
   892	(ADC (SRAconst [c] y) x flags) -> (ADCshiftRA x y [c] flags)
   893	(ADC x (SLL y z) flags) -> (ADCshiftLLreg x y z flags)
   894	(ADC (SLL y z) x flags) -> (ADCshiftLLreg x y z flags)
   895	(ADC x (SRL y z) flags) -> (ADCshiftRLreg x y z flags)
   896	(ADC (SRL y z) x flags) -> (ADCshiftRLreg x y z flags)
   897	(ADC x (SRA y z) flags) -> (ADCshiftRAreg x y z flags)
   898	(ADC (SRA y z) x flags) -> (ADCshiftRAreg x y z flags)
   899	(ADDS x (SLLconst [c] y)) -> (ADDSshiftLL x y [c])
   900	(ADDS x (SRLconst [c] y)) -> (ADDSshiftRL x y [c])
   901	(ADDS x (SRAconst [c] y)) -> (ADDSshiftRA x y [c])
   902	(ADDS x (SLL y z)) -> (ADDSshiftLLreg x y z)
   903	(ADDS x (SRL y z)) -> (ADDSshiftRLreg x y z)
   904	(ADDS x (SRA y z)) -> (ADDSshiftRAreg x y z)
   905	(SUB x (SLLconst [c] y)) -> (SUBshiftLL x y [c])
   906	(SUB (SLLconst [c] y) x) -> (RSBshiftLL x y [c])
   907	(SUB x (SRLconst [c] y)) -> (SUBshiftRL x y [c])
   908	(SUB (SRLconst [c] y) x) -> (RSBshiftRL x y [c])
   909	(SUB x (SRAconst [c] y)) -> (SUBshiftRA x y [c])
   910	(SUB (SRAconst [c] y) x) -> (RSBshiftRA x y [c])
   911	(SUB x (SLL y z)) -> (SUBshiftLLreg x y z)
   912	(SUB (SLL y z) x) -> (RSBshiftLLreg x y z)
   913	(SUB x (SRL y z)) -> (SUBshiftRLreg x y z)
   914	(SUB (SRL y z) x) -> (RSBshiftRLreg x y z)
   915	(SUB x (SRA y z)) -> (SUBshiftRAreg x y z)
   916	(SUB (SRA y z) x) -> (RSBshiftRAreg x y z)
   917	(SBC x (SLLconst [c] y) flags) -> (SBCshiftLL x y [c] flags)
   918	(SBC (SLLconst [c] y) x flags) -> (RSCshiftLL x y [c] flags)
   919	(SBC x (SRLconst [c] y) flags) -> (SBCshiftRL x y [c] flags)
   920	(SBC (SRLconst [c] y) x flags) -> (RSCshiftRL x y [c] flags)
   921	(SBC x (SRAconst [c] y) flags) -> (SBCshiftRA x y [c] flags)
   922	(SBC (SRAconst [c] y) x flags) -> (RSCshiftRA x y [c] flags)
   923	(SBC x (SLL y z) flags) -> (SBCshiftLLreg x y z flags)
   924	(SBC (SLL y z) x flags) -> (RSCshiftLLreg x y z flags)
   925	(SBC x (SRL y z) flags) -> (SBCshiftRLreg x y z flags)
   926	(SBC (SRL y z) x flags) -> (RSCshiftRLreg x y z flags)
   927	(SBC x (SRA y z) flags) -> (SBCshiftRAreg x y z flags)
   928	(SBC (SRA y z) x flags) -> (RSCshiftRAreg x y z flags)
   929	(SUBS x (SLLconst [c] y)) -> (SUBSshiftLL x y [c])
   930	(SUBS (SLLconst [c] y) x) -> (RSBSshiftLL x y [c])
   931	(SUBS x (SRLconst [c] y)) -> (SUBSshiftRL x y [c])
   932	(SUBS (SRLconst [c] y) x) -> (RSBSshiftRL x y [c])
   933	(SUBS x (SRAconst [c] y)) -> (SUBSshiftRA x y [c])
   934	(SUBS (SRAconst [c] y) x) -> (RSBSshiftRA x y [c])
   935	(SUBS x (SLL y z)) -> (SUBSshiftLLreg x y z)
   936	(SUBS (SLL y z) x) -> (RSBSshiftLLreg x y z)
   937	(SUBS x (SRL y z)) -> (SUBSshiftRLreg x y z)
   938	(SUBS (SRL y z) x) -> (RSBSshiftRLreg x y z)
   939	(SUBS x (SRA y z)) -> (SUBSshiftRAreg x y z)
   940	(SUBS (SRA y z) x) -> (RSBSshiftRAreg x y z)
   941	(RSB x (SLLconst [c] y)) -> (RSBshiftLL x y [c])
   942	(RSB (SLLconst [c] y) x) -> (SUBshiftLL x y [c])
   943	(RSB x (SRLconst [c] y)) -> (RSBshiftRL x y [c])
   944	(RSB (SRLconst [c] y) x) -> (SUBshiftRL x y [c])
   945	(RSB x (SRAconst [c] y)) -> (RSBshiftRA x y [c])
   946	(RSB (SRAconst [c] y) x) -> (SUBshiftRA x y [c])
   947	(RSB x (SLL y z)) -> (RSBshiftLLreg x y z)
   948	(RSB (SLL y z) x) -> (SUBshiftLLreg x y z)
   949	(RSB x (SRL y z)) -> (RSBshiftRLreg x y z)
   950	(RSB (SRL y z) x) -> (SUBshiftRLreg x y z)
   951	(RSB x (SRA y z)) -> (RSBshiftRAreg x y z)
   952	(RSB (SRA y z) x) -> (SUBshiftRAreg x y z)
   953	(AND x (SLLconst [c] y)) -> (ANDshiftLL x y [c])
   954	(AND x (SRLconst [c] y)) -> (ANDshiftRL x y [c])
   955	(AND x (SRAconst [c] y)) -> (ANDshiftRA x y [c])
   956	(AND x (SLL y z)) -> (ANDshiftLLreg x y z)
   957	(AND x (SRL y z)) -> (ANDshiftRLreg x y z)
   958	(AND x (SRA y z)) -> (ANDshiftRAreg x y z)
   959	(OR x (SLLconst [c] y)) -> (ORshiftLL x y [c])
   960	(OR x (SRLconst [c] y)) -> (ORshiftRL x y [c])
   961	(OR x (SRAconst [c] y)) -> (ORshiftRA x y [c])
   962	(OR x (SLL y z)) -> (ORshiftLLreg x y z)
   963	(OR x (SRL y z)) -> (ORshiftRLreg x y z)
   964	(OR x (SRA y z)) -> (ORshiftRAreg x y z)
   965	(XOR x (SLLconst [c] y)) -> (XORshiftLL x y [c])
   966	(XOR x (SRLconst [c] y)) -> (XORshiftRL x y [c])
   967	(XOR x (SRAconst [c] y)) -> (XORshiftRA x y [c])
   968	(XOR x (SRRconst [c] y)) -> (XORshiftRR x y [c])
   969	(XOR x (SLL y z)) -> (XORshiftLLreg x y z)
   970	(XOR x (SRL y z)) -> (XORshiftRLreg x y z)
   971	(XOR x (SRA y z)) -> (XORshiftRAreg x y z)
   972	(BIC x (SLLconst [c] y)) -> (BICshiftLL x y [c])
   973	(BIC x (SRLconst [c] y)) -> (BICshiftRL x y [c])
   974	(BIC x (SRAconst [c] y)) -> (BICshiftRA x y [c])
   975	(BIC x (SLL y z)) -> (BICshiftLLreg x y z)
   976	(BIC x (SRL y z)) -> (BICshiftRLreg x y z)
   977	(BIC x (SRA y z)) -> (BICshiftRAreg x y z)
   978	(MVN (SLLconst [c] x)) -> (MVNshiftLL x [c])
   979	(MVN (SRLconst [c] x)) -> (MVNshiftRL x [c])
   980	(MVN (SRAconst [c] x)) -> (MVNshiftRA x [c])
   981	(MVN (SLL x y)) -> (MVNshiftLLreg x y)
   982	(MVN (SRL x y)) -> (MVNshiftRLreg x y)
   983	(MVN (SRA x y)) -> (MVNshiftRAreg x y)
   984	
   985	(CMP x (SLLconst [c] y)) -> (CMPshiftLL x y [c])
   986	(CMP (SLLconst [c] y) x) -> (InvertFlags (CMPshiftLL x y [c]))
   987	(CMP x (SRLconst [c] y)) -> (CMPshiftRL x y [c])
   988	(CMP (SRLconst [c] y) x) -> (InvertFlags (CMPshiftRL x y [c]))
   989	(CMP x (SRAconst [c] y)) -> (CMPshiftRA x y [c])
   990	(CMP (SRAconst [c] y) x) -> (InvertFlags (CMPshiftRA x y [c]))
   991	(CMP x (SLL y z)) -> (CMPshiftLLreg x y z)
   992	(CMP (SLL y z) x) -> (InvertFlags (CMPshiftLLreg x y z))
   993	(CMP x (SRL y z)) -> (CMPshiftRLreg x y z)
   994	(CMP (SRL y z) x) -> (InvertFlags (CMPshiftRLreg x y z))
   995	(CMP x (SRA y z)) -> (CMPshiftRAreg x y z)
   996	(CMP (SRA y z) x) -> (InvertFlags (CMPshiftRAreg x y z))
   997	(TST x (SLLconst [c] y)) -> (TSTshiftLL x y [c])
   998	(TST x (SRLconst [c] y)) -> (TSTshiftRL x y [c])
   999	(TST x (SRAconst [c] y)) -> (TSTshiftRA x y [c])
  1000	(TST x (SLL y z)) -> (TSTshiftLLreg x y z)
  1001	(TST x (SRL y z)) -> (TSTshiftRLreg x y z)
  1002	(TST x (SRA y z)) -> (TSTshiftRAreg x y z)
  1003	(TEQ x (SLLconst [c] y)) -> (TEQshiftLL x y [c])
  1004	(TEQ x (SRLconst [c] y)) -> (TEQshiftRL x y [c])
  1005	(TEQ x (SRAconst [c] y)) -> (TEQshiftRA x y [c])
  1006	(TEQ x (SLL y z)) -> (TEQshiftLLreg x y z)
  1007	(TEQ x (SRL y z)) -> (TEQshiftRLreg x y z)
  1008	(TEQ x (SRA y z)) -> (TEQshiftRAreg x y z)
  1009	(CMN x (SLLconst [c] y)) -> (CMNshiftLL x y [c])
  1010	(CMN x (SRLconst [c] y)) -> (CMNshiftRL x y [c])
  1011	(CMN x (SRAconst [c] y)) -> (CMNshiftRA x y [c])
  1012	(CMN x (SLL y z)) -> (CMNshiftLLreg x y z)
  1013	(CMN x (SRL y z)) -> (CMNshiftRLreg x y z)
  1014	(CMN x (SRA y z)) -> (CMNshiftRAreg x y z)
  1015	
  1016	// prefer *const ops to *shift ops
  1017	(ADDshiftLL (MOVWconst [c]) x [d]) -> (ADDconst [c] (SLLconst <x.Type> x [d]))
  1018	(ADDshiftRL (MOVWconst [c]) x [d]) -> (ADDconst [c] (SRLconst <x.Type> x [d]))
  1019	(ADDshiftRA (MOVWconst [c]) x [d]) -> (ADDconst [c] (SRAconst <x.Type> x [d]))
  1020	(ADCshiftLL (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SLLconst <x.Type> x [d]) flags)
  1021	(ADCshiftRL (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SRLconst <x.Type> x [d]) flags)
  1022	(ADCshiftRA (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SRAconst <x.Type> x [d]) flags)
  1023	(ADDSshiftLL (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SLLconst <x.Type> x [d]))
  1024	(ADDSshiftRL (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SRLconst <x.Type> x [d]))
  1025	(ADDSshiftRA (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SRAconst <x.Type> x [d]))
  1026	(SUBshiftLL (MOVWconst [c]) x [d]) -> (RSBconst [c] (SLLconst <x.Type> x [d]))
  1027	(SUBshiftRL (MOVWconst [c]) x [d]) -> (RSBconst [c] (SRLconst <x.Type> x [d]))
  1028	(SUBshiftRA (MOVWconst [c]) x [d]) -> (RSBconst [c] (SRAconst <x.Type> x [d]))
  1029	(SBCshiftLL (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SLLconst <x.Type> x [d]) flags)
  1030	(SBCshiftRL (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SRLconst <x.Type> x [d]) flags)
  1031	(SBCshiftRA (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SRAconst <x.Type> x [d]) flags)
  1032	(SUBSshiftLL (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SLLconst <x.Type> x [d]))
  1033	(SUBSshiftRL (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SRLconst <x.Type> x [d]))
  1034	(SUBSshiftRA (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SRAconst <x.Type> x [d]))
  1035	(RSBshiftLL (MOVWconst [c]) x [d]) -> (SUBconst [c] (SLLconst <x.Type> x [d]))
  1036	(RSBshiftRL (MOVWconst [c]) x [d]) -> (SUBconst [c] (SRLconst <x.Type> x [d]))
  1037	(RSBshiftRA (MOVWconst [c]) x [d]) -> (SUBconst [c] (SRAconst <x.Type> x [d]))
  1038	(RSCshiftLL (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SLLconst <x.Type> x [d]) flags)
  1039	(RSCshiftRL (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SRLconst <x.Type> x [d]) flags)
  1040	(RSCshiftRA (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SRAconst <x.Type> x [d]) flags)
  1041	(RSBSshiftLL (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SLLconst <x.Type> x [d]))
  1042	(RSBSshiftRL (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SRLconst <x.Type> x [d]))
  1043	(RSBSshiftRA (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SRAconst <x.Type> x [d]))
  1044	(ANDshiftLL (MOVWconst [c]) x [d]) -> (ANDconst [c] (SLLconst <x.Type> x [d]))
  1045	(ANDshiftRL (MOVWconst [c]) x [d]) -> (ANDconst [c] (SRLconst <x.Type> x [d]))
  1046	(ANDshiftRA (MOVWconst [c]) x [d]) -> (ANDconst [c] (SRAconst <x.Type> x [d]))
  1047	(ORshiftLL (MOVWconst [c]) x [d]) -> (ORconst [c] (SLLconst <x.Type> x [d]))
  1048	(ORshiftRL (MOVWconst [c]) x [d]) -> (ORconst [c] (SRLconst <x.Type> x [d]))
  1049	(ORshiftRA (MOVWconst [c]) x [d]) -> (ORconst [c] (SRAconst <x.Type> x [d]))
  1050	(XORshiftLL (MOVWconst [c]) x [d]) -> (XORconst [c] (SLLconst <x.Type> x [d]))
  1051	(XORshiftRL (MOVWconst [c]) x [d]) -> (XORconst [c] (SRLconst <x.Type> x [d]))
  1052	(XORshiftRA (MOVWconst [c]) x [d]) -> (XORconst [c] (SRAconst <x.Type> x [d]))
  1053	(XORshiftRR (MOVWconst [c]) x [d]) -> (XORconst [c] (SRRconst <x.Type> x [d]))
  1054	(CMPshiftLL (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
  1055	(CMPshiftRL (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
  1056	(CMPshiftRA (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
  1057	(TSTshiftLL (MOVWconst [c]) x [d]) -> (TSTconst [c] (SLLconst <x.Type> x [d]))
  1058	(TSTshiftRL (MOVWconst [c]) x [d]) -> (TSTconst [c] (SRLconst <x.Type> x [d]))
  1059	(TSTshiftRA (MOVWconst [c]) x [d]) -> (TSTconst [c] (SRAconst <x.Type> x [d]))
  1060	(TEQshiftLL (MOVWconst [c]) x [d]) -> (TEQconst [c] (SLLconst <x.Type> x [d]))
  1061	(TEQshiftRL (MOVWconst [c]) x [d]) -> (TEQconst [c] (SRLconst <x.Type> x [d]))
  1062	(TEQshiftRA (MOVWconst [c]) x [d]) -> (TEQconst [c] (SRAconst <x.Type> x [d]))
  1063	(CMNshiftLL (MOVWconst [c]) x [d]) -> (CMNconst [c] (SLLconst <x.Type> x [d]))
  1064	(CMNshiftRL (MOVWconst [c]) x [d]) -> (CMNconst [c] (SRLconst <x.Type> x [d]))
  1065	(CMNshiftRA (MOVWconst [c]) x [d]) -> (CMNconst [c] (SRAconst <x.Type> x [d]))
  1066	
  1067	(ADDshiftLLreg (MOVWconst [c]) x y) -> (ADDconst [c] (SLL <x.Type> x y))
  1068	(ADDshiftRLreg (MOVWconst [c]) x y) -> (ADDconst [c] (SRL <x.Type> x y))
  1069	(ADDshiftRAreg (MOVWconst [c]) x y) -> (ADDconst [c] (SRA <x.Type> x y))
  1070	(ADCshiftLLreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SLL <x.Type> x y) flags)
  1071	(ADCshiftRLreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SRL <x.Type> x y) flags)
  1072	(ADCshiftRAreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SRA <x.Type> x y) flags)
  1073	(ADDSshiftLLreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SLL <x.Type> x y))
  1074	(ADDSshiftRLreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SRL <x.Type> x y))
  1075	(ADDSshiftRAreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SRA <x.Type> x y))
  1076	(SUBshiftLLreg (MOVWconst [c]) x y) -> (RSBconst [c] (SLL <x.Type> x y))
  1077	(SUBshiftRLreg (MOVWconst [c]) x y) -> (RSBconst [c] (SRL <x.Type> x y))
  1078	(SUBshiftRAreg (MOVWconst [c]) x y) -> (RSBconst [c] (SRA <x.Type> x y))
  1079	(SBCshiftLLreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SLL <x.Type> x y) flags)
  1080	(SBCshiftRLreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SRL <x.Type> x y) flags)
  1081	(SBCshiftRAreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SRA <x.Type> x y) flags)
  1082	(SUBSshiftLLreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SLL <x.Type> x y))
  1083	(SUBSshiftRLreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SRL <x.Type> x y))
  1084	(SUBSshiftRAreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SRA <x.Type> x y))
  1085	(RSBshiftLLreg (MOVWconst [c]) x y) -> (SUBconst [c] (SLL <x.Type> x y))
  1086	(RSBshiftRLreg (MOVWconst [c]) x y) -> (SUBconst [c] (SRL <x.Type> x y))
  1087	(RSBshiftRAreg (MOVWconst [c]) x y) -> (SUBconst [c] (SRA <x.Type> x y))
  1088	(RSCshiftLLreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SLL <x.Type> x y) flags)
  1089	(RSCshiftRLreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SRL <x.Type> x y) flags)
  1090	(RSCshiftRAreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SRA <x.Type> x y) flags)
  1091	(RSBSshiftLLreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SLL <x.Type> x y))
  1092	(RSBSshiftRLreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SRL <x.Type> x y))
  1093	(RSBSshiftRAreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SRA <x.Type> x y))
  1094	(ANDshiftLLreg (MOVWconst [c]) x y) -> (ANDconst [c] (SLL <x.Type> x y))
  1095	(ANDshiftRLreg (MOVWconst [c]) x y) -> (ANDconst [c] (SRL <x.Type> x y))
  1096	(ANDshiftRAreg (MOVWconst [c]) x y) -> (ANDconst [c] (SRA <x.Type> x y))
  1097	(ORshiftLLreg (MOVWconst [c]) x y) -> (ORconst [c] (SLL <x.Type> x y))
  1098	(ORshiftRLreg (MOVWconst [c]) x y) -> (ORconst [c] (SRL <x.Type> x y))
  1099	(ORshiftRAreg (MOVWconst [c]) x y) -> (ORconst [c] (SRA <x.Type> x y))
  1100	(XORshiftLLreg (MOVWconst [c]) x y) -> (XORconst [c] (SLL <x.Type> x y))
  1101	(XORshiftRLreg (MOVWconst [c]) x y) -> (XORconst [c] (SRL <x.Type> x y))
  1102	(XORshiftRAreg (MOVWconst [c]) x y) -> (XORconst [c] (SRA <x.Type> x y))
  1103	(CMPshiftLLreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SLL <x.Type> x y)))
  1104	(CMPshiftRLreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SRL <x.Type> x y)))
  1105	(CMPshiftRAreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SRA <x.Type> x y)))
  1106	(TSTshiftLLreg (MOVWconst [c]) x y) -> (TSTconst [c] (SLL <x.Type> x y))
  1107	(TSTshiftRLreg (MOVWconst [c]) x y) -> (TSTconst [c] (SRL <x.Type> x y))
  1108	(TSTshiftRAreg (MOVWconst [c]) x y) -> (TSTconst [c] (SRA <x.Type> x y))
  1109	(TEQshiftLLreg (MOVWconst [c]) x y) -> (TEQconst [c] (SLL <x.Type> x y))
  1110	(TEQshiftRLreg (MOVWconst [c]) x y) -> (TEQconst [c] (SRL <x.Type> x y))
  1111	(TEQshiftRAreg (MOVWconst [c]) x y) -> (TEQconst [c] (SRA <x.Type> x y))
  1112	(CMNshiftLLreg (MOVWconst [c]) x y) -> (CMNconst [c] (SLL <x.Type> x y))
  1113	(CMNshiftRLreg (MOVWconst [c]) x y) -> (CMNconst [c] (SRL <x.Type> x y))
  1114	(CMNshiftRAreg (MOVWconst [c]) x y) -> (CMNconst [c] (SRA <x.Type> x y))
  1115	
  1116	// constant folding in *shift ops
  1117	(ADDshiftLL x (MOVWconst [c]) [d]) -> (ADDconst x [int64(int32(uint32(c)<<uint64(d)))])
  1118	(ADDshiftRL x (MOVWconst [c]) [d]) -> (ADDconst x [int64(int32(uint32(c)>>uint64(d)))])
  1119	(ADDshiftRA x (MOVWconst [c]) [d]) -> (ADDconst x [int64(int32(c)>>uint64(d))])
  1120	(ADCshiftLL x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(int32(uint32(c)<<uint64(d)))] flags)
  1121	(ADCshiftRL x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(int32(uint32(c)>>uint64(d)))] flags)
  1122	(ADCshiftRA x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(int32(c)>>uint64(d))] flags)
  1123	(ADDSshiftLL x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(int32(uint32(c)<<uint64(d)))])
  1124	(ADDSshiftRL x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(int32(uint32(c)>>uint64(d)))])
  1125	(ADDSshiftRA x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(int32(c)>>uint64(d))])
  1126	(SUBshiftLL x (MOVWconst [c]) [d]) -> (SUBconst x [int64(int32(uint32(c)<<uint64(d)))])
  1127	(SUBshiftRL x (MOVWconst [c]) [d]) -> (SUBconst x [int64(int32(uint32(c)>>uint64(d)))])
  1128	(SUBshiftRA x (MOVWconst [c]) [d]) -> (SUBconst x [int64(int32(c)>>uint64(d))])
  1129	(SBCshiftLL x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(int32(uint32(c)<<uint64(d)))] flags)
  1130	(SBCshiftRL x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(int32(uint32(c)>>uint64(d)))] flags)
  1131	(SBCshiftRA x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(int32(c)>>uint64(d))] flags)
  1132	(SUBSshiftLL x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(int32(uint32(c)<<uint64(d)))])
  1133	(SUBSshiftRL x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(int32(uint32(c)>>uint64(d)))])
  1134	(SUBSshiftRA x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(int32(c)>>uint64(d))])
  1135	(RSBshiftLL x (MOVWconst [c]) [d]) -> (RSBconst x [int64(int32(uint32(c)<<uint64(d)))])
  1136	(RSBshiftRL x (MOVWconst [c]) [d]) -> (RSBconst x [int64(int32(uint32(c)>>uint64(d)))])
  1137	(RSBshiftRA x (MOVWconst [c]) [d]) -> (RSBconst x [int64(int32(c)>>uint64(d))])
  1138	(RSCshiftLL x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(int32(uint32(c)<<uint64(d)))] flags)
  1139	(RSCshiftRL x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(int32(uint32(c)>>uint64(d)))] flags)
  1140	(RSCshiftRA x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(int32(c)>>uint64(d))] flags)
  1141	(RSBSshiftLL x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(int32(uint32(c)<<uint64(d)))])
  1142	(RSBSshiftRL x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(int32(uint32(c)>>uint64(d)))])
  1143	(RSBSshiftRA x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(int32(c)>>uint64(d))])
  1144	(ANDshiftLL x (MOVWconst [c]) [d]) -> (ANDconst x [int64(int32(uint32(c)<<uint64(d)))])
  1145	(ANDshiftRL x (MOVWconst [c]) [d]) -> (ANDconst x [int64(int32(uint32(c)>>uint64(d)))])
  1146	(ANDshiftRA x (MOVWconst [c]) [d]) -> (ANDconst x [int64(int32(c)>>uint64(d))])
  1147	(ORshiftLL x (MOVWconst [c]) [d]) -> (ORconst x [int64(int32(uint32(c)<<uint64(d)))])
  1148	(ORshiftRL x (MOVWconst [c]) [d]) -> (ORconst x [int64(int32(uint32(c)>>uint64(d)))])
  1149	(ORshiftRA x (MOVWconst [c]) [d]) -> (ORconst x [int64(int32(c)>>uint64(d))])
  1150	(XORshiftLL x (MOVWconst [c]) [d]) -> (XORconst x [int64(int32(uint32(c)<<uint64(d)))])
  1151	(XORshiftRL x (MOVWconst [c]) [d]) -> (XORconst x [int64(int32(uint32(c)>>uint64(d)))])
  1152	(XORshiftRA x (MOVWconst [c]) [d]) -> (XORconst x [int64(int32(c)>>uint64(d))])
  1153	(XORshiftRR x (MOVWconst [c]) [d]) -> (XORconst x [int64(int32(uint32(c)>>uint64(d)|uint32(c)<<uint64(32-d)))])
  1154	(BICshiftLL x (MOVWconst [c]) [d]) -> (BICconst x [int64(int32(uint32(c)<<uint64(d)))])
  1155	(BICshiftRL x (MOVWconst [c]) [d]) -> (BICconst x [int64(int32(uint32(c)>>uint64(d)))])
  1156	(BICshiftRA x (MOVWconst [c]) [d]) -> (BICconst x [int64(int32(c)>>uint64(d))])
  1157	(MVNshiftLL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)<<uint64(d))])
  1158	(MVNshiftRL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)>>uint64(d))])
  1159	(MVNshiftRA (MOVWconst [c]) [d]) -> (MOVWconst [^int64(int32(c)>>uint64(d))])
  1160	(CMPshiftLL x (MOVWconst [c]) [d]) -> (CMPconst x [int64(int32(uint32(c)<<uint64(d)))])
  1161	(CMPshiftRL x (MOVWconst [c]) [d]) -> (CMPconst x [int64(int32(uint32(c)>>uint64(d)))])
  1162	(CMPshiftRA x (MOVWconst [c]) [d]) -> (CMPconst x [int64(int32(c)>>uint64(d))])
  1163	(TSTshiftLL x (MOVWconst [c]) [d]) -> (TSTconst x [int64(int32(uint32(c)<<uint64(d)))])
  1164	(TSTshiftRL x (MOVWconst [c]) [d]) -> (TSTconst x [int64(int32(uint32(c)>>uint64(d)))])
  1165	(TSTshiftRA x (MOVWconst [c]) [d]) -> (TSTconst x [int64(int32(c)>>uint64(d))])
  1166	(TEQshiftLL x (MOVWconst [c]) [d]) -> (TEQconst x [int64(int32(uint32(c)<<uint64(d)))])
  1167	(TEQshiftRL x (MOVWconst [c]) [d]) -> (TEQconst x [int64(int32(uint32(c)>>uint64(d)))])
  1168	(TEQshiftRA x (MOVWconst [c]) [d]) -> (TEQconst x [int64(int32(c)>>uint64(d))])
  1169	(CMNshiftLL x (MOVWconst [c]) [d]) -> (CMNconst x [int64(int32(uint32(c)<<uint64(d)))])
  1170	(CMNshiftRL x (MOVWconst [c]) [d]) -> (CMNconst x [int64(int32(uint32(c)>>uint64(d)))])
  1171	(CMNshiftRA x (MOVWconst [c]) [d]) -> (CMNconst x [int64(int32(c)>>uint64(d))])
  1172	
  1173	(ADDshiftLLreg x y (MOVWconst [c])) -> (ADDshiftLL x y [c])
  1174	(ADDshiftRLreg x y (MOVWconst [c])) -> (ADDshiftRL x y [c])
  1175	(ADDshiftRAreg x y (MOVWconst [c])) -> (ADDshiftRA x y [c])
  1176	(ADCshiftLLreg x y (MOVWconst [c]) flags) -> (ADCshiftLL x y [c] flags)
  1177	(ADCshiftRLreg x y (MOVWconst [c]) flags) -> (ADCshiftRL x y [c] flags)
  1178	(ADCshiftRAreg x y (MOVWconst [c]) flags) -> (ADCshiftRA x y [c] flags)
  1179	(ADDSshiftLLreg x y (MOVWconst [c])) -> (ADDSshiftLL x y [c])
  1180	(ADDSshiftRLreg x y (MOVWconst [c])) -> (ADDSshiftRL x y [c])
  1181	(ADDSshiftRAreg x y (MOVWconst [c])) -> (ADDSshiftRA x y [c])
  1182	(SUBshiftLLreg x y (MOVWconst [c])) -> (SUBshiftLL x y [c])
  1183	(SUBshiftRLreg x y (MOVWconst [c])) -> (SUBshiftRL x y [c])
  1184	(SUBshiftRAreg x y (MOVWconst [c])) -> (SUBshiftRA x y [c])
  1185	(SBCshiftLLreg x y (MOVWconst [c]) flags) -> (SBCshiftLL x y [c] flags)
  1186	(SBCshiftRLreg x y (MOVWconst [c]) flags) -> (SBCshiftRL x y [c] flags)
  1187	(SBCshiftRAreg x y (MOVWconst [c]) flags) -> (SBCshiftRA x y [c] flags)
  1188	(SUBSshiftLLreg x y (MOVWconst [c])) -> (SUBSshiftLL x y [c])
  1189	(SUBSshiftRLreg x y (MOVWconst [c])) -> (SUBSshiftRL x y [c])
  1190	(SUBSshiftRAreg x y (MOVWconst [c])) -> (SUBSshiftRA x y [c])
  1191	(RSBshiftLLreg x y (MOVWconst [c])) -> (RSBshiftLL x y [c])
  1192	(RSBshiftRLreg x y (MOVWconst [c])) -> (RSBshiftRL x y [c])
  1193	(RSBshiftRAreg x y (MOVWconst [c])) -> (RSBshiftRA x y [c])
  1194	(RSCshiftLLreg x y (MOVWconst [c]) flags) -> (RSCshiftLL x y [c] flags)
  1195	(RSCshiftRLreg x y (MOVWconst [c]) flags) -> (RSCshiftRL x y [c] flags)
  1196	(RSCshiftRAreg x y (MOVWconst [c]) flags) -> (RSCshiftRA x y [c] flags)
  1197	(RSBSshiftLLreg x y (MOVWconst [c])) -> (RSBSshiftLL x y [c])
  1198	(RSBSshiftRLreg x y (MOVWconst [c])) -> (RSBSshiftRL x y [c])
  1199	(RSBSshiftRAreg x y (MOVWconst [c])) -> (RSBSshiftRA x y [c])
  1200	(ANDshiftLLreg x y (MOVWconst [c])) -> (ANDshiftLL x y [c])
  1201	(ANDshiftRLreg x y (MOVWconst [c])) -> (ANDshiftRL x y [c])
  1202	(ANDshiftRAreg x y (MOVWconst [c])) -> (ANDshiftRA x y [c])
  1203	(ORshiftLLreg x y (MOVWconst [c])) -> (ORshiftLL x y [c])
  1204	(ORshiftRLreg x y (MOVWconst [c])) -> (ORshiftRL x y [c])
  1205	(ORshiftRAreg x y (MOVWconst [c])) -> (ORshiftRA x y [c])
  1206	(XORshiftLLreg x y (MOVWconst [c])) -> (XORshiftLL x y [c])
  1207	(XORshiftRLreg x y (MOVWconst [c])) -> (XORshiftRL x y [c])
  1208	(XORshiftRAreg x y (MOVWconst [c])) -> (XORshiftRA x y [c])
  1209	(BICshiftLLreg x y (MOVWconst [c])) -> (BICshiftLL x y [c])
  1210	(BICshiftRLreg x y (MOVWconst [c])) -> (BICshiftRL x y [c])
  1211	(BICshiftRAreg x y (MOVWconst [c])) -> (BICshiftRA x y [c])
  1212	(MVNshiftLLreg x (MOVWconst [c])) -> (MVNshiftLL x [c])
  1213	(MVNshiftRLreg x (MOVWconst [c])) -> (MVNshiftRL x [c])
  1214	(MVNshiftRAreg x (MOVWconst [c])) -> (MVNshiftRA x [c])
  1215	(CMPshiftLLreg x y (MOVWconst [c])) -> (CMPshiftLL x y [c])
  1216	(CMPshiftRLreg x y (MOVWconst [c])) -> (CMPshiftRL x y [c])
  1217	(CMPshiftRAreg x y (MOVWconst [c])) -> (CMPshiftRA x y [c])
  1218	(TSTshiftLLreg x y (MOVWconst [c])) -> (TSTshiftLL x y [c])
  1219	(TSTshiftRLreg x y (MOVWconst [c])) -> (TSTshiftRL x y [c])
  1220	(TSTshiftRAreg x y (MOVWconst [c])) -> (TSTshiftRA x y [c])
  1221	(TEQshiftLLreg x y (MOVWconst [c])) -> (TEQshiftLL x y [c])
  1222	(TEQshiftRLreg x y (MOVWconst [c])) -> (TEQshiftRL x y [c])
  1223	(TEQshiftRAreg x y (MOVWconst [c])) -> (TEQshiftRA x y [c])
  1224	(CMNshiftLLreg x y (MOVWconst [c])) -> (CMNshiftLL x y [c])
  1225	(CMNshiftRLreg x y (MOVWconst [c])) -> (CMNshiftRL x y [c])
  1226	(CMNshiftRAreg x y (MOVWconst [c])) -> (CMNshiftRA x y [c])
  1227	
  1228	// Generate rotates
  1229	(ADDshiftLL [c] (SRLconst x [32-c]) x) -> (SRRconst [32-c] x)
  1230	( ORshiftLL [c] (SRLconst x [32-c]) x) -> (SRRconst [32-c] x)
  1231	(XORshiftLL [c] (SRLconst x [32-c]) x) -> (SRRconst [32-c] x)
  1232	(ADDshiftRL [c] (SLLconst x [32-c]) x) -> (SRRconst [   c] x)
  1233	( ORshiftRL [c] (SLLconst x [32-c]) x) -> (SRRconst [   c] x)
  1234	(XORshiftRL [c] (SLLconst x [32-c]) x) -> (SRRconst [   c] x)
  1235	
  1236	(RotateLeft32 x (MOVWconst [c])) -> (SRRconst [-c&31] x)
  1237	(RotateLeft16 <t> x (MOVWconst [c])) -> (Or16 (Lsh16x32 <t> x (MOVWconst [c&15])) (Rsh16Ux32 <t> x (MOVWconst [-c&15])))
  1238	(RotateLeft8 <t> x (MOVWconst [c])) -> (Or8 (Lsh8x32 <t> x (MOVWconst [c&7])) (Rsh8Ux32 <t> x (MOVWconst [-c&7])))
  1239	
  1240	// ((x>>8) | (x<<8)) -> (REV16 x), the type of x is uint16, "|" can also be "^" or "+".
  1241	// UBFX instruction is supported by ARMv6T2, ARMv7 and above versions, REV16 is supported by
  1242	// ARMv6 and above versions. So for ARMv6, we need to match SLLconst, SRLconst and ORshiftLL.
  1243	((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (BFXU <typ.UInt16> [armBFAuxInt(8, 8)] x) x) -> (REV16 x)
  1244	((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x) && objabi.GOARM>=6 -> (REV16 x)
  1245	
  1246	// use indexed loads and stores
  1247	(MOVWload [0] {sym} (ADD ptr idx) mem) && sym == nil && !config.nacl -> (MOVWloadidx ptr idx mem)
  1248	(MOVWstore [0] {sym} (ADD ptr idx) val mem) && sym == nil && !config.nacl -> (MOVWstoreidx ptr idx val mem)
  1249	(MOVWload [0] {sym} (ADDshiftLL ptr idx [c]) mem) && sym == nil && !config.nacl -> (MOVWloadshiftLL ptr idx [c] mem)
  1250	(MOVWload [0] {sym} (ADDshiftRL ptr idx [c]) mem) && sym == nil && !config.nacl -> (MOVWloadshiftRL ptr idx [c] mem)
  1251	(MOVWload [0] {sym} (ADDshiftRA ptr idx [c]) mem) && sym == nil && !config.nacl -> (MOVWloadshiftRA ptr idx [c] mem)
  1252	(MOVWstore [0] {sym} (ADDshiftLL ptr idx [c]) val mem) && sym == nil && !config.nacl -> (MOVWstoreshiftLL ptr idx [c] val mem)
  1253	(MOVWstore [0] {sym} (ADDshiftRL ptr idx [c]) val mem) && sym == nil && !config.nacl -> (MOVWstoreshiftRL ptr idx [c] val mem)
  1254	(MOVWstore [0] {sym} (ADDshiftRA ptr idx [c]) val mem) && sym == nil && !config.nacl -> (MOVWstoreshiftRA ptr idx [c] val mem)
  1255	(MOVBUload [0] {sym} (ADD ptr idx) mem) && sym == nil && !config.nacl -> (MOVBUloadidx ptr idx mem)
  1256	(MOVBload [0] {sym} (ADD ptr idx) mem) && sym == nil && !config.nacl -> (MOVBloadidx ptr idx mem)
  1257	(MOVBstore [0] {sym} (ADD ptr idx) val mem) && sym == nil && !config.nacl -> (MOVBstoreidx ptr idx val mem)
  1258	(MOVHUload [0] {sym} (ADD ptr idx) mem) && sym == nil && !config.nacl -> (MOVHUloadidx ptr idx mem)
  1259	(MOVHload [0] {sym} (ADD ptr idx) mem) && sym == nil && !config.nacl -> (MOVHloadidx ptr idx mem)
  1260	(MOVHstore [0] {sym} (ADD ptr idx) val mem) && sym == nil && !config.nacl -> (MOVHstoreidx ptr idx val mem)
  1261	
  1262	// constant folding in indexed loads and stores
  1263	(MOVWloadidx ptr (MOVWconst [c]) mem) -> (MOVWload [c] ptr mem)
  1264	(MOVWloadidx (MOVWconst [c]) ptr mem) -> (MOVWload [c] ptr mem)
  1265	(MOVBloadidx ptr (MOVWconst [c]) mem) -> (MOVBload [c] ptr mem)
  1266	(MOVBloadidx (MOVWconst [c]) ptr mem) -> (MOVBload [c] ptr mem)
  1267	(MOVBUloadidx ptr (MOVWconst [c]) mem) -> (MOVBUload [c] ptr mem)
  1268	(MOVBUloadidx (MOVWconst [c]) ptr mem) -> (MOVBUload [c] ptr mem)
  1269	(MOVHUloadidx ptr (MOVWconst [c]) mem) -> (MOVHUload [c] ptr mem)
  1270	(MOVHUloadidx (MOVWconst [c]) ptr mem) -> (MOVHUload [c] ptr mem)
  1271	(MOVHloadidx ptr (MOVWconst [c]) mem) -> (MOVHload [c] ptr mem)
  1272	(MOVHloadidx (MOVWconst [c]) ptr mem) -> (MOVHload [c] ptr mem)
  1273	
  1274	(MOVWstoreidx ptr (MOVWconst [c]) val mem) -> (MOVWstore [c] ptr val mem)
  1275	(MOVWstoreidx (MOVWconst [c]) ptr val mem) -> (MOVWstore [c] ptr val mem)
  1276	(MOVBstoreidx ptr (MOVWconst [c]) val mem) -> (MOVBstore [c] ptr val mem)
  1277	(MOVBstoreidx (MOVWconst [c]) ptr val mem) -> (MOVBstore [c] ptr val mem)
  1278	(MOVHstoreidx ptr (MOVWconst [c]) val mem) -> (MOVHstore [c] ptr val mem)
  1279	(MOVHstoreidx (MOVWconst [c]) ptr val mem) -> (MOVHstore [c] ptr val mem)
  1280	
  1281	(MOVWloadidx ptr (SLLconst idx [c]) mem) -> (MOVWloadshiftLL ptr idx [c] mem)
  1282	(MOVWloadidx (SLLconst idx [c]) ptr mem) -> (MOVWloadshiftLL ptr idx [c] mem)
  1283	(MOVWloadidx ptr (SRLconst idx [c]) mem) -> (MOVWloadshiftRL ptr idx [c] mem)
  1284	(MOVWloadidx (SRLconst idx [c]) ptr mem) -> (MOVWloadshiftRL ptr idx [c] mem)
  1285	(MOVWloadidx ptr (SRAconst idx [c]) mem) -> (MOVWloadshiftRA ptr idx [c] mem)
  1286	(MOVWloadidx (SRAconst idx [c]) ptr mem) -> (MOVWloadshiftRA ptr idx [c] mem)
  1287	
  1288	(MOVWstoreidx ptr (SLLconst idx [c]) val mem) -> (MOVWstoreshiftLL ptr idx [c] val mem)
  1289	(MOVWstoreidx (SLLconst idx [c]) ptr val mem) -> (MOVWstoreshiftLL ptr idx [c] val mem)
  1290	(MOVWstoreidx ptr (SRLconst idx [c]) val mem) -> (MOVWstoreshiftRL ptr idx [c] val mem)
  1291	(MOVWstoreidx (SRLconst idx [c]) ptr val mem) -> (MOVWstoreshiftRL ptr idx [c] val mem)
  1292	(MOVWstoreidx ptr (SRAconst idx [c]) val mem) -> (MOVWstoreshiftRA ptr idx [c] val mem)
  1293	(MOVWstoreidx (SRAconst idx [c]) ptr val mem) -> (MOVWstoreshiftRA ptr idx [c] val mem)
  1294	
  1295	(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)<<uint64(d))] ptr mem)
  1296	(MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)>>uint64(d))] ptr mem)
  1297	(MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(int32(c)>>uint64(d))] ptr mem)
  1298	
  1299	(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)<<uint64(d))] ptr val mem)
  1300	(MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)>>uint64(d))] ptr val mem)
  1301	(MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(int32(c)>>uint64(d))] ptr val mem)
  1302	
  1303	// generic simplifications
  1304	(ADD x (RSBconst [0] y)) -> (SUB x y)
  1305	(ADD <t> (RSBconst [c] x) (RSBconst [d] y)) -> (RSBconst [c+d] (ADD <t> x y))
  1306	(SUB x x) -> (MOVWconst [0])
  1307	(RSB x x) -> (MOVWconst [0])
  1308	(AND x x) -> x
  1309	(OR x x) -> x
  1310	(XOR x x) -> (MOVWconst [0])
  1311	(BIC x x) -> (MOVWconst [0])
  1312	
  1313	(ADD (MUL x y) a) -> (MULA x y a)
  1314	(SUB a (MUL x y)) && objabi.GOARM == 7 -> (MULS x y a)
  1315	(RSB (MUL x y) a) && objabi.GOARM == 7 -> (MULS x y a)
  1316	
  1317	(NEGF (MULF x y)) && objabi.GOARM >= 6 -> (NMULF x y)
  1318	(NEGD (MULD x y)) && objabi.GOARM >= 6 -> (NMULD x y)
  1319	(MULF (NEGF x) y) && objabi.GOARM >= 6 -> (NMULF x y)
  1320	(MULD (NEGD x) y) && objabi.GOARM >= 6 -> (NMULD x y)
  1321	(NMULF (NEGF x) y) -> (MULF x y)
  1322	(NMULD (NEGD x) y) -> (MULD x y)
  1323	
  1324	// the result will overwrite the addend, since they are in the same register
  1325	(ADDF a (MULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULAF a x y)
  1326	(ADDF a (NMULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULSF a x y)
  1327	(ADDD a (MULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULAD a x y)
  1328	(ADDD a (NMULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULSD a x y)
  1329	(SUBF a (MULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULSF a x y)
  1330	(SUBF a (NMULF x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULAF a x y)
  1331	(SUBD a (MULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULSD a x y)
  1332	(SUBD a (NMULD x y)) && a.Uses == 1 && objabi.GOARM >= 6 -> (MULAD a x y)
  1333	
  1334	(AND x (MVN y)) -> (BIC x y)
  1335	
  1336	// simplification with *shift ops
  1337	(SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1338	(SUBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1339	(SUBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1340	(RSBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1341	(RSBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1342	(RSBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1343	(ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
  1344	(ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
  1345	(ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
  1346	(ORshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
  1347	(ORshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
  1348	(ORshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
  1349	(XORshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1350	(XORshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1351	(XORshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1352	(BICshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1353	(BICshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1354	(BICshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
  1355	(AND x (MVNshiftLL y [c])) -> (BICshiftLL x y [c])
  1356	(AND x (MVNshiftRL y [c])) -> (BICshiftRL x y [c])
  1357	(AND x (MVNshiftRA y [c])) -> (BICshiftRA x y [c])
  1358	
  1359	// floating point optimizations
  1360	(CMPF x (MOVFconst [0])) -> (CMPF0 x)
  1361	(CMPD x (MOVDconst [0])) -> (CMPD0 x)
  1362	
  1363	// bit extraction
  1364	(SRAconst (SLLconst x [c]) [d]) && objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 -> (BFX [(d-c)|(32-d)<<8] x)
  1365	(SRLconst (SLLconst x [c]) [d]) && objabi.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 -> (BFXU [(d-c)|(32-d)<<8] x)
  1366	
  1367	// comparison simplification
  1368	(CMP x (RSBconst [0] y)) -> (CMN x y)
  1369	(CMN x (RSBconst [0] y)) -> (CMP x y)
  1370	(EQ (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (EQ (CMP x y) yes no)
  1371	(EQ (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (EQ (CMP a (MUL <x.Type> x y)) yes no)
  1372	(EQ (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (EQ (CMPconst [c] x) yes no)
  1373	(EQ (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (EQ (CMPshiftLL x y [c]) yes no)
  1374	(EQ (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (EQ (CMPshiftRL x y [c]) yes no)
  1375	(EQ (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (EQ (CMPshiftRA x y [c]) yes no)
  1376	(EQ (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (EQ (CMPshiftLLreg x y z) yes no)
  1377	(EQ (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (EQ (CMPshiftRLreg x y z) yes no)
  1378	(EQ (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (EQ (CMPshiftRAreg x y z) yes no)
  1379	(NE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (NE (CMP x y) yes no)
  1380	(NE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (NE (CMP a (MUL <x.Type> x y)) yes no)
  1381	(NE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (NE (CMPconst [c] x) yes no)
  1382	(NE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (NE (CMPshiftLL x y [c]) yes no)
  1383	(NE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (NE (CMPshiftRL x y [c]) yes no)
  1384	(NE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (NE (CMPshiftRA x y [c]) yes no)
  1385	(NE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (CMPshiftLLreg x y z) yes no)
  1386	(NE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (CMPshiftRLreg x y z) yes no)
  1387	(NE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (CMPshiftRAreg x y z) yes no)
  1388	(EQ (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (EQ (CMN x y) yes no)
  1389	(EQ (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (EQ (CMN a (MUL <x.Type> x y)) yes no)
  1390	(EQ (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (EQ (CMNconst [c] x) yes no)
  1391	(EQ (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (EQ (CMNshiftLL x y [c]) yes no)
  1392	(EQ (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (EQ (CMNshiftRL x y [c]) yes no)
  1393	(EQ (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (EQ (CMNshiftRA x y [c]) yes no)
  1394	(EQ (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (EQ (CMNshiftLLreg x y z) yes no)
  1395	(EQ (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (EQ (CMNshiftRLreg x y z) yes no)
  1396	(EQ (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (EQ (CMNshiftRAreg x y z) yes no)
  1397	(NE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (NE (CMN x y) yes no)
  1398	(NE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (NE (CMN a (MUL <x.Type> x y)) yes no)
  1399	(NE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (NE (CMNconst [c] x) yes no)
  1400	(NE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (NE (CMNshiftLL x y [c]) yes no)
  1401	(NE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (NE (CMNshiftRL x y [c]) yes no)
  1402	(NE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (NE (CMNshiftRA x y [c]) yes no)
  1403	(NE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (CMNshiftLLreg x y z) yes no)
  1404	(NE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (CMNshiftRLreg x y z) yes no)
  1405	(NE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (CMNshiftRAreg x y z) yes no)
  1406	(EQ (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (EQ (TST x y) yes no)
  1407	(EQ (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (EQ (TSTconst [c] x) yes no)
  1408	(EQ (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (EQ (TSTshiftLL x y [c]) yes no)
  1409	(EQ (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (EQ (TSTshiftRL x y [c]) yes no)
  1410	(EQ (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (EQ (TSTshiftRA x y [c]) yes no)
  1411	(EQ (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (EQ (TSTshiftLLreg x y z) yes no)
  1412	(EQ (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (EQ (TSTshiftRLreg x y z) yes no)
  1413	(EQ (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (EQ (TSTshiftRAreg x y z) yes no)
  1414	(NE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (NE (TST x y) yes no)
  1415	(NE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (NE (TSTconst [c] x) yes no)
  1416	(NE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (NE (TSTshiftLL x y [c]) yes no)
  1417	(NE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (NE (TSTshiftRL x y [c]) yes no)
  1418	(NE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (NE (TSTshiftRA x y [c]) yes no)
  1419	(NE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TSTshiftLLreg x y z) yes no)
  1420	(NE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TSTshiftRLreg x y z) yes no)
  1421	(NE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TSTshiftRAreg x y z) yes no)
  1422	(EQ (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (EQ (TEQ x y) yes no)
  1423	(EQ (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (EQ (TEQconst [c] x) yes no)
  1424	(EQ (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (EQ (TEQshiftLL x y [c]) yes no)
  1425	(EQ (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (EQ (TEQshiftRL x y [c]) yes no)
  1426	(EQ (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (EQ (TEQshiftRA x y [c]) yes no)
  1427	(EQ (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (EQ (TEQshiftLLreg x y z) yes no)
  1428	(EQ (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (EQ (TEQshiftRLreg x y z) yes no)
  1429	(EQ (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (EQ (TEQshiftRAreg x y z) yes no)
  1430	(NE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (NE (TEQ x y) yes no)
  1431	(NE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (NE (TEQconst [c] x) yes no)
  1432	(NE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (NE (TEQshiftLL x y [c]) yes no)
  1433	(NE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (NE (TEQshiftRL x y [c]) yes no)
  1434	(NE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (NE (TEQshiftRA x y [c]) yes no)
  1435	(NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftLLreg x y z) yes no)
  1436	(NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRLreg x y z) yes no)
  1437	(NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRAreg x y z) yes no)
  1438	(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LT (CMP x y) yes no)
  1439	(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LT (CMP a (MUL <x.Type> x y)) yes no)
  1440	(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LT (CMPconst [c] x) yes no)
  1441	(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftLL x y [c]) yes no)
  1442	(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRL x y [c]) yes no)
  1443	(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRA x y [c]) yes no)
  1444	(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftLLreg x y z) yes no)
  1445	(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRLreg x y z) yes no)
  1446	(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRAreg x y z) yes no)
  1447	(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LE (CMP x y) yes no)
  1448	(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LE (CMP a (MUL <x.Type> x y)) yes no)
  1449	(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LE (CMPconst [c] x) yes no)
  1450	(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftLL x y [c]) yes no)
  1451	(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRL x y [c]) yes no)
  1452	(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRA x y [c]) yes no)
  1453	(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftLLreg x y z) yes no)
  1454	(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRLreg x y z) yes no)
  1455	(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRAreg x y z) yes no)
  1456	(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LT (CMN x y) yes no)
  1457	(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LT (CMN a (MUL <x.Type> x y)) yes no)
  1458	(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LT (CMNconst [c] x) yes no)
  1459	(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftLL x y [c]) yes no)
  1460	(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRL x y [c]) yes no)
  1461	(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRA x y [c]) yes no)
  1462	(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftLLreg x y z) yes no)
  1463	(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRLreg x y z) yes no)
  1464	(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRAreg x y z) yes no)
  1465	(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LE (CMN x y) yes no)
  1466	(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LE (CMN a (MUL <x.Type> x y)) yes no)
  1467	(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1  -> (LE (CMNconst [c] x) yes no)
  1468	(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftLL x y [c]) yes no)
  1469	(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRL x y [c]) yes no)
  1470	(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRA x y [c]) yes no)
  1471	(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftLLreg x y z) yes no)
  1472	(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRLreg x y z) yes no)
  1473	(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRAreg x y z) yes no)
  1474	(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no)
  1475	(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no)
  1476	(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no)
  1477	(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftRL x y [c]) yes no)
  1478	(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftRA x y [c]) yes no)
  1479	(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftLLreg x y z) yes no)
  1480	(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftRLreg x y z) yes no)
  1481	(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (TSTshiftRAreg x y z) yes no)
  1482	(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LE (TST x y) yes no)
  1483	(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LE (TSTconst [c] x) yes no)
  1484	(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftLL x y [c]) yes no)
  1485	(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftRL x y [c]) yes no)
  1486	(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (TSTshiftRA x y [c]) yes no)
  1487	(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftLLreg x y z) yes no)
  1488	(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftRLreg x y z) yes no)
  1489	(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TSTshiftRAreg x y z) yes no)
  1490	(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LT (TEQ x y) yes no)
  1491	(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (LT (TEQconst [c] x) yes no)
  1492	(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftLL x y [c]) yes no)
  1493	(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftRL x y [c]) yes no)
  1494	(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (TEQshiftRA x y [c]) yes no)
  1495	(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftLLreg x y z) yes no)
  1496	(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftRLreg x y z) yes no)
  1497	(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (TEQshiftRAreg x y z) yes no)
  1498	(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (LE (TEQ x y) yes no)
  1499	(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1  -> (LE (TEQconst [c] x) yes no)
  1500	(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftLL x y [c]) yes no)
  1501	(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftRL x y [c]) yes no)
  1502	(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (TEQshiftRA x y [c]) yes no)
  1503	(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no)
  1504	(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no)
  1505	(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no)
  1506	(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GT (CMP x y) yes no)
  1507	(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GT (CMP a (MUL <x.Type> x y)) yes no)
  1508	(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GT (CMPconst [c] x) yes no)
  1509	(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftLL x y [c]) yes no)
  1510	(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRL x y [c]) yes no)
  1511	(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRA x y [c]) yes no)
  1512	(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftLLreg x y z) yes no)
  1513	(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRLreg x y z) yes no)
  1514	(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRAreg x y z) yes no)
  1515	(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GE (CMP x y) yes no)
  1516	(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GE (CMP a (MUL <x.Type> x y)) yes no)
  1517	(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GE (CMPconst [c] x) yes no)
  1518	(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftLL x y [c]) yes no)
  1519	(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRL x y [c]) yes no)
  1520	(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRA x y [c]) yes no)
  1521	(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftLLreg x y z) yes no)
  1522	(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRLreg x y z) yes no)
  1523	(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRAreg x y z) yes no)
  1524	(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GT (CMN x y) yes no)
  1525	(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GT (CMNconst [c] x) yes no)
  1526	(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftLL x y [c]) yes no)
  1527	(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRL x y [c]) yes no)
  1528	(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRA x y [c]) yes no)
  1529	(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftLLreg x y z) yes no)
  1530	(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRLreg x y z) yes no)
  1531	(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRAreg x y z) yes no)
  1532	(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GE (CMN x y) yes no)
  1533	(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GE (CMN a (MUL <x.Type> x y)) yes no)
  1534	(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GE (CMNconst [c] x) yes no)
  1535	(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftLL x y [c]) yes no)
  1536	(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRL x y [c]) yes no)
  1537	(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRA x y [c]) yes no)
  1538	(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftLLreg x y z) yes no)
  1539	(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRLreg x y z) yes no)
  1540	(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRAreg x y z) yes no)
  1541	(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no)
  1542	(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GT (CMN a (MUL <x.Type> x y)) yes no)
  1543	(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no)
  1544	(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no)
  1545	(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no)
  1546	(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRA x y [c]) yes no)
  1547	(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftLLreg x y z) yes no)
  1548	(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftRLreg x y z) yes no)
  1549	(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (TSTshiftRAreg x y z) yes no)
  1550	(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GE (TST x y) yes no)
  1551	(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GE (TSTconst [c] x) yes no)
  1552	(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftLL x y [c]) yes no)
  1553	(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftRL x y [c]) yes no)
  1554	(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (TSTshiftRA x y [c]) yes no)
  1555	(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftLLreg x y z) yes no)
  1556	(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftRLreg x y z) yes no)
  1557	(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TSTshiftRAreg x y z) yes no)
  1558	(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GT (TEQ x y) yes no)
  1559	(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GT (TEQconst [c] x) yes no)
  1560	(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftLL x y [c]) yes no)
  1561	(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftRL x y [c]) yes no)
  1562	(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (TEQshiftRA x y [c]) yes no)
  1563	(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftLLreg x y z) yes no)
  1564	(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftRLreg x y z) yes no)
  1565	(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (TEQshiftRAreg x y z) yes no)
  1566	(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 -> (GE (TEQ x y) yes no)
  1567	(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 -> (GE (TEQconst [c] x) yes no)
  1568	(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftLL x y [c]) yes no)
  1569	(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftRL x y [c]) yes no)
  1570	(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (TEQshiftRA x y [c]) yes no)
  1571	(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftLLreg x y z) yes no)
  1572	(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRLreg x y z) yes no)
  1573	(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRAreg x y z) yes no)
  1574	
  1575	(MOVBUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read8(sym, off))])
  1576	(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read16(sym, off, config.BigEndian))])
  1577	(MOVWload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(int32(read32(sym, off, config.BigEndian)))])

View as plain text