github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/ssa/_gen/ARM.rules (about)

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