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

View as plain text