github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/compile/internal/ssa/gen/generic.rules (about)

     1  // Copyright 2015 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  // values are specified using the following format:
     6  // (op <type> [auxint] {aux} arg0 arg1 ...)
     7  // the type, aux, and auxint fields are optional
     8  // on the matching side
     9  //  - the type, aux, and auxint fields must match if they are specified.
    10  //  - the first occurrence of a variable defines that variable.  Subsequent
    11  //    uses must match (be == to) the first use.
    12  //  - v is defined to be the value matched.
    13  //  - an additional conditional can be provided after the match pattern with "&&".
    14  // on the generated side
    15  //  - the type of the top-level expression is the same as the one on the left-hand side.
    16  //  - the type of any subexpressions must be specified explicitly (or
    17  //    be specified in the op's type field).
    18  //  - auxint will be 0 if not specified.
    19  //  - aux will be nil if not specified.
    20  
    21  // blocks are specified using the following format:
    22  // (kind controlvalue succ0 succ1 ...)
    23  // controlvalue must be "nil" or a value expression
    24  // succ* fields must be variables
    25  // For now, the generated successors must be a permutation of the matched successors.
    26  
    27  // constant folding
    28  (Trunc16to8  (Const16 [c]))  -> (Const8   [int64(int8(c))])
    29  (Trunc32to8  (Const32 [c]))  -> (Const8   [int64(int8(c))])
    30  (Trunc32to16 (Const32 [c]))  -> (Const16  [int64(int16(c))])
    31  (Trunc64to8  (Const64 [c]))  -> (Const8   [int64(int8(c))])
    32  (Trunc64to16 (Const64 [c]))  -> (Const16  [int64(int16(c))])
    33  (Trunc64to32 (Const64 [c]))  -> (Const32  [int64(int32(c))])
    34  (Cvt64Fto32F (Const64F [c])) -> (Const32F [f2i(float64(i2f32(c)))])
    35  (Cvt32Fto64F (Const32F [c])) -> (Const64F [c]) // c is already a 64 bit float
    36  
    37  // const negation is currently handled by frontend
    38  //(Neg8 (Const8 [c])) -> (Const8 [-c])
    39  //(Neg16 (Const16 [c])) -> (Const16 [-c])
    40  //(Neg32 (Const32 [c])) -> (Const32 [-c])
    41  //(Neg64 (Const64 [c])) -> (Const64 [-c])
    42  //(Neg32F (Const32F [c])) -> (Const32F [f2i(-i2f(c))])
    43  //(Neg64F (Const64F [c])) -> (Const64F [f2i(-i2f(c))])
    44  
    45  (Add8   (Const8 [c])   (Const8 [d]))   -> (Const8  [int64(int8(c+d))])
    46  (Add16  (Const16 [c])  (Const16 [d]))  -> (Const16 [int64(int16(c+d))])
    47  (Add32  (Const32 [c])  (Const32 [d]))  -> (Const32 [int64(int32(c+d))])
    48  (Add64  (Const64 [c])  (Const64 [d]))  -> (Const64 [c+d])
    49  (Add32F (Const32F [c]) (Const32F [d])) -> 
    50          (Const32F [f2i(float64(i2f32(c) + i2f32(d)))]) // ensure we combine the operands with 32 bit precision
    51  (Add64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) + i2f(d))])
    52  (AddPtr <t> x (Const64 [c])) -> (OffPtr <t> x [c])
    53  
    54  (Sub8   (Const8 [c]) (Const8 [d]))     -> (Const8 [int64(int8(c-d))])
    55  (Sub16  (Const16 [c]) (Const16 [d]))   -> (Const16 [int64(int16(c-d))])
    56  (Sub32  (Const32 [c]) (Const32 [d]))   -> (Const32 [int64(int32(c-d))])
    57  (Sub64  (Const64 [c]) (Const64 [d]))   -> (Const64 [c-d])
    58  (Sub32F (Const32F [c]) (Const32F [d])) -> 
    59          (Const32F [f2i(float64(i2f32(c) - i2f32(d)))])
    60  (Sub64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) - i2f(d))])
    61  
    62  (Mul8   (Const8 [c])   (Const8 [d]))   -> (Const8  [int64(int8(c*d))])
    63  (Mul16  (Const16 [c])  (Const16 [d]))  -> (Const16 [int64(int16(c*d))])
    64  (Mul32  (Const32 [c])  (Const32 [d]))  -> (Const32 [int64(int32(c*d))])
    65  (Mul64  (Const64 [c])  (Const64 [d]))  -> (Const64 [c*d])
    66  (Mul32F (Const32F [c]) (Const32F [d])) -> 
    67          (Const32F [f2i(float64(i2f32(c) * i2f32(d)))])
    68  (Mul64F (Const64F [c]) (Const64F [d])) -> (Const64F [f2i(i2f(c) * i2f(d))])
    69  
    70  (Mod8  (Const8  [c]) (Const8  [d])) && d != 0 -> (Const8  [int64(int8(c % d))])
    71  (Mod16 (Const16 [c]) (Const16 [d])) && d != 0 -> (Const16 [int64(int16(c % d))])
    72  (Mod32 (Const32 [c]) (Const32 [d])) && d != 0 -> (Const32 [int64(int32(c % d))])
    73  (Mod64 (Const64 [c]) (Const64 [d])) && d != 0 -> (Const64 [c % d])
    74  
    75  (Mod8u  (Const8 [c])  (Const8  [d])) && d != 0 -> (Const8  [int64(uint8(c) % uint8(d))])
    76  (Mod16u (Const16 [c]) (Const16 [d])) && d != 0 -> (Const16 [int64(uint16(c) % uint16(d))])
    77  (Mod32u (Const32 [c]) (Const32 [d])) && d != 0 -> (Const32 [int64(uint32(c) % uint32(d))])
    78  (Mod64u (Const64 [c]) (Const64 [d])) && d != 0 -> (Const64 [int64(uint64(c) % uint64(d))])
    79  
    80  (Lsh64x64  (Const64 [c]) (Const64 [d])) -> (Const64 [c << uint64(d)])
    81  (Rsh64x64  (Const64 [c]) (Const64 [d])) -> (Const64 [c >> uint64(d)])
    82  (Rsh64Ux64 (Const64 [c]) (Const64 [d])) -> (Const64 [int64(uint64(c) >> uint64(d))])
    83  (Lsh32x64  (Const32 [c]) (Const64 [d])) -> (Const32 [int64(int32(c) << uint64(d))])
    84  (Rsh32x64  (Const32 [c]) (Const64 [d])) -> (Const32 [int64(int32(c) >> uint64(d))])
    85  (Rsh32Ux64 (Const32 [c]) (Const64 [d])) -> (Const32 [int64(int32(uint32(c) >> uint64(d)))])
    86  (Lsh16x64  (Const16 [c]) (Const64 [d])) -> (Const16 [int64(int16(c) << uint64(d))])
    87  (Rsh16x64  (Const16 [c]) (Const64 [d])) -> (Const16 [int64(int16(c) >> uint64(d))])
    88  (Rsh16Ux64 (Const16 [c]) (Const64 [d])) -> (Const16 [int64(int16(uint16(c) >> uint64(d)))])
    89  (Lsh8x64   (Const8  [c]) (Const64 [d])) -> (Const8  [int64(int8(c) << uint64(d))])
    90  (Rsh8x64   (Const8  [c]) (Const64 [d])) -> (Const8  [int64(int8(c) >> uint64(d))])
    91  (Rsh8Ux64  (Const8  [c]) (Const64 [d])) -> (Const8  [int64(int8(uint8(c) >> uint64(d)))])
    92  
    93  // Fold IsInBounds when the range of the index cannot exceed the limit.
    94  (IsInBounds (ZeroExt8to32  _) (Const32 [c])) && (1 << 8)  <= c -> (ConstBool [1])
    95  (IsInBounds (ZeroExt8to64  _) (Const64 [c])) && (1 << 8)  <= c -> (ConstBool [1])
    96  (IsInBounds (ZeroExt16to32 _) (Const32 [c])) && (1 << 16) <= c -> (ConstBool [1])
    97  (IsInBounds (ZeroExt16to64 _) (Const64 [c])) && (1 << 16) <= c -> (ConstBool [1])
    98  (IsInBounds x x) -> (ConstBool [0])
    99  (IsInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c < d -> (ConstBool [1])
   100  (IsInBounds (And64 (Const64 [c]) _) (Const64 [d])) && 0 <= c && c < d -> (ConstBool [1])
   101  (IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(0 <= c && c < d)])
   102  (IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(0 <= c && c < d)])
   103  // (Mod64u x y) is always between 0 (inclusive) and y (exclusive).
   104  (IsInBounds (Mod32u _ y) y) -> (ConstBool [1])
   105  (IsInBounds (Mod64u _ y) y) -> (ConstBool [1])
   106  
   107  (IsSliceInBounds x x) -> (ConstBool [1])
   108  (IsSliceInBounds (And32 (Const32 [c]) _) (Const32 [d])) && 0 <= c && c <= d -> (ConstBool [1])
   109  (IsSliceInBounds (And64 (Const64 [c]) _) (Const64 [d])) && 0 <= c && c <= d -> (ConstBool [1])
   110  (IsSliceInBounds (Const32 [0]) _) -> (ConstBool [1])
   111  (IsSliceInBounds (Const64 [0]) _) -> (ConstBool [1])
   112  (IsSliceInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(0 <= c && c <= d)])
   113  (IsSliceInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(0 <= c && c <= d)])
   114  (IsSliceInBounds (SliceLen x) (SliceCap x)) -> (ConstBool [1])
   115  
   116  (Eq64 x x) -> (ConstBool [1])
   117  (Eq32 x x) -> (ConstBool [1])
   118  (Eq16 x x) -> (ConstBool [1])
   119  (Eq8  x x) -> (ConstBool [1])
   120  (EqB (ConstBool [c]) (ConstBool [d])) -> (ConstBool [b2i(c == d)])
   121  (EqB (ConstBool [0]) x) -> (Not x)
   122  (EqB (ConstBool [1]) x) -> x
   123  
   124  (Neq64 x x) -> (ConstBool [0])
   125  (Neq32 x x) -> (ConstBool [0])
   126  (Neq16 x x) -> (ConstBool [0])
   127  (Neq8  x x) -> (ConstBool [0])
   128  (NeqB (ConstBool [c]) (ConstBool [d])) -> (ConstBool [b2i(c != d)])
   129  (NeqB (ConstBool [0]) x) -> x
   130  (NeqB (ConstBool [1]) x) -> (Not x)
   131  
   132  (Eq64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x)) -> (Eq64 (Const64 <t> [c-d]) x)
   133  (Eq32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x)) -> (Eq32 (Const32 <t> [int64(int32(c-d))]) x)
   134  (Eq16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x)) -> (Eq16 (Const16 <t> [int64(int16(c-d))]) x)
   135  (Eq8  (Const8  <t> [c]) (Add8  (Const8  <t> [d]) x)) -> (Eq8  (Const8 <t> [int64(int8(c-d))]) x)
   136  
   137  (Neq64 (Const64 <t> [c]) (Add64 (Const64 <t> [d]) x)) -> (Neq64 (Const64 <t> [c-d]) x)
   138  (Neq32 (Const32 <t> [c]) (Add32 (Const32 <t> [d]) x)) -> (Neq32 (Const32 <t> [int64(int32(c-d))]) x)
   139  (Neq16 (Const16 <t> [c]) (Add16 (Const16 <t> [d]) x)) -> (Neq16 (Const16 <t> [int64(int16(c-d))]) x)
   140  (Neq8  (Const8  <t> [c]) (Add8  (Const8  <t> [d]) x)) -> (Neq8 (Const8 <t> [int64(int8(c-d))]) x)
   141  
   142  // canonicalize: swap arguments for commutative operations when one argument is a constant.
   143  (Eq64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Eq64 (Const64 <t> [c]) x)
   144  (Eq32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Eq32 (Const32 <t> [c]) x)
   145  (Eq16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Eq16 (Const16 <t> [c]) x)
   146  (Eq8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (Eq8  (Const8  <t> [c]) x)
   147  
   148  (Neq64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Neq64 (Const64 <t> [c]) x)
   149  (Neq32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Neq32 (Const32 <t> [c]) x)
   150  (Neq16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Neq16 (Const16 <t> [c]) x)
   151  (Neq8  x (Const8 <t>  [c])) && x.Op != OpConst8  -> (Neq8  (Const8  <t> [c]) x)
   152  
   153  // AddPtr is not canonicalized because nilcheck ptr checks the first argument to be non-nil.
   154  (Add64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Add64 (Const64 <t> [c]) x)
   155  (Add32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Add32 (Const32 <t> [c]) x)
   156  (Add16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Add16 (Const16 <t> [c]) x)
   157  (Add8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (Add8  (Const8  <t> [c]) x)
   158  
   159  (Mul64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Mul64 (Const64 <t> [c]) x)
   160  (Mul32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Mul32 (Const32 <t> [c]) x)
   161  (Mul16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Mul16 (Const16 <t> [c]) x)
   162  (Mul8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (Mul8  (Const8  <t> [c]) x)
   163  
   164  (Sub64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Add64 (Const64 <t> [-c]) x)
   165  (Sub32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Add32 (Const32 <t> [int64(int32(-c))]) x)
   166  (Sub16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Add16 (Const16 <t> [int64(int16(-c))]) x)
   167  (Sub8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (Add8  (Const8  <t> [int64(int8(-c))]) x)
   168  
   169  (And64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (And64 (Const64 <t> [c]) x)
   170  (And32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (And32 (Const32 <t> [c]) x)
   171  (And16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (And16 (Const16 <t> [c]) x)
   172  (And8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (And8  (Const8  <t> [c]) x)
   173  
   174  (Or64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Or64 (Const64 <t> [c]) x)
   175  (Or32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Or32 (Const32 <t> [c]) x)
   176  (Or16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Or16 (Const16 <t> [c]) x)
   177  (Or8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (Or8  (Const8  <t> [c]) x)
   178  
   179  (Xor64 x (Const64 <t> [c])) && x.Op != OpConst64 -> (Xor64 (Const64 <t> [c]) x)
   180  (Xor32 x (Const32 <t> [c])) && x.Op != OpConst32 -> (Xor32 (Const32 <t> [c]) x)
   181  (Xor16 x (Const16 <t> [c])) && x.Op != OpConst16 -> (Xor16 (Const16 <t> [c]) x)
   182  (Xor8  x (Const8  <t> [c])) && x.Op != OpConst8  -> (Xor8  (Const8  <t> [c]) x)
   183  
   184  // Distribute multiplication c * (d+x) -> c*d + c*x. Useful for:
   185  // a[i].b = ...; a[i+1].b = ...
   186  (Mul64 (Const64 <t> [c]) (Add64 <t> (Const64 <t> [d]) x)) ->
   187    (Add64 (Const64 <t> [c*d]) (Mul64 <t> (Const64 <t> [c]) x))
   188  (Mul32 (Const32 <t> [c]) (Add32 <t> (Const32 <t> [d]) x)) ->
   189    (Add32 (Const32 <t> [int64(int32(c*d))]) (Mul32 <t> (Const32 <t> [c]) x))
   190  
   191  // rewrite shifts of 8/16/32 bit consts into 64 bit consts to reduce
   192  // the number of the other rewrite rules for const shifts
   193  (Lsh64x32  <t> x (Const32 [c])) -> (Lsh64x64  x (Const64 <t> [int64(uint32(c))]))
   194  (Lsh64x16  <t> x (Const16 [c])) -> (Lsh64x64  x (Const64 <t> [int64(uint16(c))]))
   195  (Lsh64x8   <t> x (Const8  [c])) -> (Lsh64x64  x (Const64 <t> [int64(uint8(c))]))
   196  (Rsh64x32  <t> x (Const32 [c])) -> (Rsh64x64  x (Const64 <t> [int64(uint32(c))]))
   197  (Rsh64x16  <t> x (Const16 [c])) -> (Rsh64x64  x (Const64 <t> [int64(uint16(c))]))
   198  (Rsh64x8   <t> x (Const8  [c])) -> (Rsh64x64  x (Const64 <t> [int64(uint8(c))]))
   199  (Rsh64Ux32 <t> x (Const32 [c])) -> (Rsh64Ux64 x (Const64 <t> [int64(uint32(c))]))
   200  (Rsh64Ux16 <t> x (Const16 [c])) -> (Rsh64Ux64 x (Const64 <t> [int64(uint16(c))]))
   201  (Rsh64Ux8  <t> x (Const8  [c])) -> (Rsh64Ux64 x (Const64 <t> [int64(uint8(c))]))
   202  
   203  (Lsh32x32  <t> x (Const32 [c])) -> (Lsh32x64  x (Const64 <t> [int64(uint32(c))]))
   204  (Lsh32x16  <t> x (Const16 [c])) -> (Lsh32x64  x (Const64 <t> [int64(uint16(c))]))
   205  (Lsh32x8   <t> x (Const8  [c])) -> (Lsh32x64  x (Const64 <t> [int64(uint8(c))]))
   206  (Rsh32x32  <t> x (Const32 [c])) -> (Rsh32x64  x (Const64 <t> [int64(uint32(c))]))
   207  (Rsh32x16  <t> x (Const16 [c])) -> (Rsh32x64  x (Const64 <t> [int64(uint16(c))]))
   208  (Rsh32x8   <t> x (Const8  [c])) -> (Rsh32x64  x (Const64 <t> [int64(uint8(c))]))
   209  (Rsh32Ux32 <t> x (Const32 [c])) -> (Rsh32Ux64 x (Const64 <t> [int64(uint32(c))]))
   210  (Rsh32Ux16 <t> x (Const16 [c])) -> (Rsh32Ux64 x (Const64 <t> [int64(uint16(c))]))
   211  (Rsh32Ux8  <t> x (Const8  [c])) -> (Rsh32Ux64 x (Const64 <t> [int64(uint8(c))]))
   212  
   213  (Lsh16x32  <t> x (Const32 [c])) -> (Lsh16x64  x (Const64 <t> [int64(uint32(c))]))
   214  (Lsh16x16  <t> x (Const16 [c])) -> (Lsh16x64  x (Const64 <t> [int64(uint16(c))]))
   215  (Lsh16x8   <t> x (Const8  [c])) -> (Lsh16x64  x (Const64 <t> [int64(uint8(c))]))
   216  (Rsh16x32  <t> x (Const32 [c])) -> (Rsh16x64  x (Const64 <t> [int64(uint32(c))]))
   217  (Rsh16x16  <t> x (Const16 [c])) -> (Rsh16x64  x (Const64 <t> [int64(uint16(c))]))
   218  (Rsh16x8   <t> x (Const8  [c])) -> (Rsh16x64  x (Const64 <t> [int64(uint8(c))]))
   219  (Rsh16Ux32 <t> x (Const32 [c])) -> (Rsh16Ux64 x (Const64 <t> [int64(uint32(c))]))
   220  (Rsh16Ux16 <t> x (Const16 [c])) -> (Rsh16Ux64 x (Const64 <t> [int64(uint16(c))]))
   221  (Rsh16Ux8  <t> x (Const8  [c])) -> (Rsh16Ux64 x (Const64 <t> [int64(uint8(c))]))
   222  
   223  (Lsh8x32  <t> x (Const32 [c])) -> (Lsh8x64  x (Const64 <t> [int64(uint32(c))]))
   224  (Lsh8x16  <t> x (Const16 [c])) -> (Lsh8x64  x (Const64 <t> [int64(uint16(c))]))
   225  (Lsh8x8   <t> x (Const8  [c])) -> (Lsh8x64  x (Const64 <t> [int64(uint8(c))]))
   226  (Rsh8x32  <t> x (Const32 [c])) -> (Rsh8x64  x (Const64 <t> [int64(uint32(c))]))
   227  (Rsh8x16  <t> x (Const16 [c])) -> (Rsh8x64  x (Const64 <t> [int64(uint16(c))]))
   228  (Rsh8x8   <t> x (Const8  [c])) -> (Rsh8x64  x (Const64 <t> [int64(uint8(c))]))
   229  (Rsh8Ux32 <t> x (Const32 [c])) -> (Rsh8Ux64 x (Const64 <t> [int64(uint32(c))]))
   230  (Rsh8Ux16 <t> x (Const16 [c])) -> (Rsh8Ux64 x (Const64 <t> [int64(uint16(c))]))
   231  (Rsh8Ux8  <t> x (Const8  [c])) -> (Rsh8Ux64 x (Const64 <t> [int64(uint8(c))]))
   232  
   233  // shifts by zero
   234  (Lsh64x64  x (Const64 [0])) -> x
   235  (Rsh64x64  x (Const64 [0])) -> x
   236  (Rsh64Ux64 x (Const64 [0])) -> x
   237  (Lsh32x64  x (Const64 [0])) -> x
   238  (Rsh32x64  x (Const64 [0])) -> x
   239  (Rsh32Ux64 x (Const64 [0])) -> x
   240  (Lsh16x64  x (Const64 [0])) -> x
   241  (Rsh16x64  x (Const64 [0])) -> x
   242  (Rsh16Ux64 x (Const64 [0])) -> x
   243  (Lsh8x64   x (Const64 [0])) -> x
   244  (Rsh8x64   x (Const64 [0])) -> x
   245  (Rsh8Ux64  x (Const64 [0])) -> x
   246  
   247  // zero shifted.
   248  (Lsh64x64  (Const64 [0]) _) -> (Const64 [0])
   249  (Lsh64x32  (Const64 [0]) _) -> (Const64 [0])
   250  (Lsh64x16  (Const64 [0]) _) -> (Const64 [0])
   251  (Lsh64x8  (Const64 [0]) _) -> (Const64 [0])
   252  (Rsh64x64  (Const64 [0]) _) -> (Const64 [0])
   253  (Rsh64x32  (Const64 [0]) _) -> (Const64 [0])
   254  (Rsh64x16  (Const64 [0]) _) -> (Const64 [0])
   255  (Rsh64x8  (Const64 [0]) _) -> (Const64 [0])
   256  (Rsh64Ux64 (Const64 [0]) _) -> (Const64 [0])
   257  (Rsh64Ux32 (Const64 [0]) _) -> (Const64 [0])
   258  (Rsh64Ux16 (Const64 [0]) _) -> (Const64 [0])
   259  (Rsh64Ux8 (Const64 [0]) _) -> (Const64 [0])
   260  (Lsh32x64  (Const32 [0]) _) -> (Const32 [0])
   261  (Lsh32x32  (Const32 [0]) _) -> (Const32 [0])
   262  (Lsh32x16  (Const32 [0]) _) -> (Const32 [0])
   263  (Lsh32x8  (Const32 [0]) _) -> (Const32 [0])
   264  (Rsh32x64  (Const32 [0]) _) -> (Const32 [0])
   265  (Rsh32x32  (Const32 [0]) _) -> (Const32 [0])
   266  (Rsh32x16  (Const32 [0]) _) -> (Const32 [0])
   267  (Rsh32x8  (Const32 [0]) _) -> (Const32 [0])
   268  (Rsh32Ux64 (Const32 [0]) _) -> (Const32 [0])
   269  (Rsh32Ux32 (Const32 [0]) _) -> (Const32 [0])
   270  (Rsh32Ux16 (Const32 [0]) _) -> (Const32 [0])
   271  (Rsh32Ux8 (Const32 [0]) _) -> (Const32 [0])
   272  (Lsh16x64  (Const16 [0]) _) -> (Const16 [0])
   273  (Lsh16x32  (Const16 [0]) _) -> (Const16 [0])
   274  (Lsh16x16  (Const16 [0]) _) -> (Const16 [0])
   275  (Lsh16x8  (Const16 [0]) _) -> (Const16 [0])
   276  (Rsh16x64  (Const16 [0]) _) -> (Const16 [0])
   277  (Rsh16x32  (Const16 [0]) _) -> (Const16 [0])
   278  (Rsh16x16  (Const16 [0]) _) -> (Const16 [0])
   279  (Rsh16x8  (Const16 [0]) _) -> (Const16 [0])
   280  (Rsh16Ux64 (Const16 [0]) _) -> (Const16 [0])
   281  (Rsh16Ux32 (Const16 [0]) _) -> (Const16 [0])
   282  (Rsh16Ux16 (Const16 [0]) _) -> (Const16 [0])
   283  (Rsh16Ux8 (Const16 [0]) _) -> (Const16 [0])
   284  (Lsh8x64   (Const8 [0]) _) -> (Const8  [0])
   285  (Lsh8x32   (Const8 [0]) _) -> (Const8  [0])
   286  (Lsh8x16   (Const8 [0]) _) -> (Const8  [0])
   287  (Lsh8x8   (Const8 [0]) _) -> (Const8  [0])
   288  (Rsh8x64   (Const8 [0]) _) -> (Const8  [0])
   289  (Rsh8x32   (Const8 [0]) _) -> (Const8  [0])
   290  (Rsh8x16   (Const8 [0]) _) -> (Const8  [0])
   291  (Rsh8x8   (Const8 [0]) _) -> (Const8  [0])
   292  (Rsh8Ux64  (Const8 [0]) _) -> (Const8  [0])
   293  (Rsh8Ux32  (Const8 [0]) _) -> (Const8  [0])
   294  (Rsh8Ux16  (Const8 [0]) _) -> (Const8  [0])
   295  (Rsh8Ux8  (Const8 [0]) _) -> (Const8  [0])
   296  
   297  // large left shifts of all values, and right shifts of unsigned values
   298  (Lsh64x64  _ (Const64 [c])) && uint64(c) >= 64 -> (Const64 [0])
   299  (Rsh64Ux64 _ (Const64 [c])) && uint64(c) >= 64 -> (Const64 [0])
   300  (Lsh32x64  _ (Const64 [c])) && uint64(c) >= 32 -> (Const32 [0])
   301  (Rsh32Ux64 _ (Const64 [c])) && uint64(c) >= 32 -> (Const32 [0])
   302  (Lsh16x64  _ (Const64 [c])) && uint64(c) >= 16 -> (Const16 [0])
   303  (Rsh16Ux64 _ (Const64 [c])) && uint64(c) >= 16 -> (Const16 [0])
   304  (Lsh8x64   _ (Const64 [c])) && uint64(c) >= 8  -> (Const8  [0])
   305  (Rsh8Ux64  _ (Const64 [c])) && uint64(c) >= 8  -> (Const8  [0])
   306  
   307  // combine const shifts
   308  (Lsh64x64 <t> (Lsh64x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh64x64 x (Const64 <t> [c+d]))
   309  (Lsh32x64 <t> (Lsh32x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh32x64 x (Const64 <t> [c+d]))
   310  (Lsh16x64 <t> (Lsh16x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh16x64 x (Const64 <t> [c+d]))
   311  (Lsh8x64  <t> (Lsh8x64  x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh8x64  x (Const64 <t> [c+d]))
   312  
   313  (Rsh64x64 <t> (Rsh64x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh64x64 x (Const64 <t> [c+d]))
   314  (Rsh32x64 <t> (Rsh32x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh32x64 x (Const64 <t> [c+d]))
   315  (Rsh16x64 <t> (Rsh16x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh16x64 x (Const64 <t> [c+d]))
   316  (Rsh8x64  <t> (Rsh8x64  x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh8x64  x (Const64 <t> [c+d]))
   317  
   318  (Rsh64Ux64 <t> (Rsh64Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh64Ux64 x (Const64 <t> [c+d]))
   319  (Rsh32Ux64 <t> (Rsh32Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh32Ux64 x (Const64 <t> [c+d]))
   320  (Rsh16Ux64 <t> (Rsh16Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh16Ux64 x (Const64 <t> [c+d]))
   321  (Rsh8Ux64  <t> (Rsh8Ux64  x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh8Ux64  x (Const64 <t> [c+d]))
   322  
   323  // ((x >> c1) << c2) >> c3
   324  (Rsh64Ux64 (Lsh64x64 (Rsh64Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   325    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   326    -> (Rsh64Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   327  (Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   328    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   329    -> (Rsh32Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   330  (Rsh16Ux64 (Lsh16x64 (Rsh16Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   331    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   332    -> (Rsh16Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   333  (Rsh8Ux64 (Lsh8x64 (Rsh8Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   334    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   335    -> (Rsh8Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   336  
   337  // ((x << c1) >> c2) << c3
   338  (Lsh64x64 (Rsh64Ux64 (Lsh64x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   339    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   340    -> (Lsh64x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   341  (Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   342    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   343    -> (Lsh32x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   344  (Lsh16x64 (Rsh16Ux64 (Lsh16x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   345    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   346    -> (Lsh16x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   347  (Lsh8x64 (Rsh8Ux64 (Lsh8x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
   348    && uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
   349    -> (Lsh8x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
   350  
   351  // constant comparisons
   352  (Eq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c == d)])
   353  (Eq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(c == d)])
   354  (Eq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(c == d)])
   355  (Eq8  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(c == d)])
   356  
   357  (Neq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c != d)])
   358  (Neq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(c != d)])
   359  (Neq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(c != d)])
   360  (Neq8  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(c != d)])
   361  
   362  (Greater64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c > d)])
   363  (Greater32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(c > d)])
   364  (Greater16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(c > d)])
   365  (Greater8  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(c > d)])
   366  
   367  (Greater64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) > uint64(d))])
   368  (Greater32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) > uint32(d))])
   369  (Greater16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) > uint16(d))])
   370  (Greater8U  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(uint8(c)  > uint8(d))])
   371  
   372  (Geq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c >= d)])
   373  (Geq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(c >= d)])
   374  (Geq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(c >= d)])
   375  (Geq8  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(c >= d)])
   376  
   377  (Geq64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) >= uint64(d))])
   378  (Geq32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) >= uint32(d))])
   379  (Geq16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) >= uint16(d))])
   380  (Geq8U  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(uint8(c)  >= uint8(d))])
   381  
   382  (Less64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c < d)])
   383  (Less32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(c < d)])
   384  (Less16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(c < d)])
   385  (Less8  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(c < d)])
   386  
   387  (Less64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) < uint64(d))])
   388  (Less32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) < uint32(d))])
   389  (Less16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) < uint16(d))])
   390  (Less8U  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(uint8(c)  < uint8(d))])
   391  
   392  (Leq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c <= d)])
   393  (Leq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(c <= d)])
   394  (Leq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(c <= d)])
   395  (Leq8  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(c <= d)])
   396  
   397  (Leq64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) <= uint64(d))])
   398  (Leq32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) <= uint32(d))])
   399  (Leq16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) <= uint16(d))])
   400  (Leq8U  (Const8  [c]) (Const8  [d])) -> (ConstBool [b2i(uint8(c)  <= uint8(d))])
   401  
   402  // simplifications
   403  (Or64 x x) -> x
   404  (Or32 x x) -> x
   405  (Or16 x x) -> x
   406  (Or8  x x) -> x
   407  (Or64 (Const64 [0]) x) -> x
   408  (Or32 (Const32 [0]) x) -> x
   409  (Or16 (Const16 [0]) x) -> x
   410  (Or8  (Const8  [0]) x) -> x
   411  (Or64 (Const64 [-1]) _) -> (Const64 [-1])
   412  (Or32 (Const32 [-1]) _) -> (Const32 [-1])
   413  (Or16 (Const16 [-1]) _) -> (Const16 [-1])
   414  (Or8  (Const8  [-1]) _) -> (Const8  [-1])
   415  (And64 x x) -> x
   416  (And32 x x) -> x
   417  (And16 x x) -> x
   418  (And8  x x) -> x
   419  (And64 (Const64 [-1]) x) -> x
   420  (And32 (Const32 [-1]) x) -> x
   421  (And16 (Const16 [-1]) x) -> x
   422  (And8  (Const8  [-1]) x) -> x
   423  (And64 (Const64 [0]) _) -> (Const64 [0])
   424  (And32 (Const32 [0]) _) -> (Const32 [0])
   425  (And16 (Const16 [0]) _) -> (Const16 [0])
   426  (And8  (Const8  [0]) _) -> (Const8  [0])
   427  (Xor64 x x) -> (Const64 [0])
   428  (Xor32 x x) -> (Const32 [0])
   429  (Xor16 x x) -> (Const16 [0])
   430  (Xor8  x x) -> (Const8  [0])
   431  (Xor64 (Const64 [0]) x) -> x
   432  (Xor32 (Const32 [0]) x) -> x
   433  (Xor16 (Const16 [0]) x) -> x
   434  (Xor8  (Const8  [0]) x) -> x
   435  (Add64 (Const64 [0]) x) -> x
   436  (Add32 (Const32 [0]) x) -> x
   437  (Add16 (Const16 [0]) x) -> x
   438  (Add8  (Const8  [0]) x) -> x
   439  (Sub64 x x) -> (Const64 [0])
   440  (Sub32 x x) -> (Const32 [0])
   441  (Sub16 x x) -> (Const16 [0])
   442  (Sub8  x x) -> (Const8  [0])
   443  (Mul64 (Const64 [0]) _) -> (Const64 [0])
   444  (Mul32 (Const32 [0]) _) -> (Const32 [0])
   445  (Mul16 (Const16 [0]) _) -> (Const16 [0])
   446  (Mul8  (Const8  [0]) _) -> (Const8  [0])
   447  (Com8  (Com8  x)) -> x
   448  (Com16 (Com16 x)) -> x
   449  (Com32 (Com32 x)) -> x
   450  (Com64 (Com64 x)) -> x
   451  (Neg8  (Sub8  x y)) -> (Sub8  y x)
   452  (Neg16 (Sub16 x y)) -> (Sub16 y x)
   453  (Neg32 (Sub32 x y)) -> (Sub32 y x)
   454  (Neg64 (Sub64 x y)) -> (Sub64 y x)
   455  
   456  (And64 x (And64 x y)) -> (And64 x y)
   457  (And32 x (And32 x y)) -> (And32 x y)
   458  (And16 x (And16 x y)) -> (And16 x y)
   459  (And8  x (And8  x y)) -> (And8  x y)
   460  (And64 x (And64 y x)) -> (And64 x y)
   461  (And32 x (And32 y x)) -> (And32 x y)
   462  (And16 x (And16 y x)) -> (And16 x y)
   463  (And8  x (And8  y x)) -> (And8  x y)
   464  (And64 (And64 x y) x) -> (And64 x y)
   465  (And32 (And32 x y) x) -> (And32 x y)
   466  (And16 (And16 x y) x) -> (And16 x y)
   467  (And8  (And8  x y) x) -> (And8  x y)
   468  (And64 (And64 x y) y) -> (And64 x y)
   469  (And32 (And32 x y) y) -> (And32 x y)
   470  (And16 (And16 x y) y) -> (And16 x y)
   471  (And8  (And8  x y) y) -> (And8  x y)
   472  (Or64 x (Or64 x y)) -> (Or64 x y)
   473  (Or32 x (Or32 x y)) -> (Or32 x y)
   474  (Or16 x (Or16 x y)) -> (Or16 x y)
   475  (Or8  x (Or8  x y)) -> (Or8  x y)
   476  (Or64 x (Or64 y x)) -> (Or64 x y)
   477  (Or32 x (Or32 y x)) -> (Or32 x y)
   478  (Or16 x (Or16 y x)) -> (Or16 x y)
   479  (Or8  x (Or8  y x)) -> (Or8  x y)
   480  (Or64 (Or64 x y) x) -> (Or64 x y)
   481  (Or32 (Or32 x y) x) -> (Or32 x y)
   482  (Or16 (Or16 x y) x) -> (Or16 x y)
   483  (Or8  (Or8  x y) x) -> (Or8  x y)
   484  (Or64 (Or64 x y) y) -> (Or64 x y)
   485  (Or32 (Or32 x y) y) -> (Or32 x y)
   486  (Or16 (Or16 x y) y) -> (Or16 x y)
   487  (Or8  (Or8  x y) y) -> (Or8  x y)
   488  (Xor64 x (Xor64 x y)) -> y
   489  (Xor32 x (Xor32 x y)) -> y
   490  (Xor16 x (Xor16 x y)) -> y
   491  (Xor8  x (Xor8  x y)) -> y
   492  (Xor64 x (Xor64 y x)) -> y
   493  (Xor32 x (Xor32 y x)) -> y
   494  (Xor16 x (Xor16 y x)) -> y
   495  (Xor8  x (Xor8  y x)) -> y
   496  (Xor64 (Xor64 x y) x) -> y
   497  (Xor32 (Xor32 x y) x) -> y
   498  (Xor16 (Xor16 x y) x) -> y
   499  (Xor8  (Xor8  x y) x) -> y
   500  (Xor64 (Xor64 x y) y) -> x
   501  (Xor32 (Xor32 x y) y) -> x
   502  (Xor16 (Xor16 x y) y) -> x
   503  (Xor8  (Xor8  x y) y) -> x
   504  
   505  (Trunc64to8  (And64 (Const64 [y]) x)) && y&0xFF == 0xFF -> (Trunc64to8 x)
   506  (Trunc64to16 (And64 (Const64 [y]) x)) && y&0xFFFF == 0xFFFF -> (Trunc64to16 x)
   507  (Trunc64to32 (And64 (Const64 [y]) x)) && y&0xFFFFFFFF == 0xFFFFFFFF -> (Trunc64to32 x)
   508  (Trunc32to8  (And32 (Const32 [y]) x)) && y&0xFF == 0xFF -> (Trunc32to8 x)
   509  (Trunc32to16 (And32 (Const32 [y]) x)) && y&0xFFFF == 0xFFFF -> (Trunc32to16 x)
   510  (Trunc16to8  (And16 (Const16 [y]) x)) && y&0xFF == 0xFF -> (Trunc16to8 x)
   511  
   512  // Rewrite AND of consts as shifts if possible, slightly faster for 64 bit operands
   513  // leading zeros can be shifted left, then right
   514  (And64 <t> (Const64 [y]) x) && nlz(y) + nto(y) == 64 && nto(y) >= 32
   515    -> (Rsh64Ux64 (Lsh64x64 <t> x (Const64 <t> [nlz(y)])) (Const64 <t> [nlz(y)]))
   516  // trailing zeros can be shifted right, then left
   517  (And64 <t> (Const64 [y]) x) && nlo(y) + ntz(y) == 64 && ntz(y) >= 32
   518    -> (Lsh64x64 (Rsh64Ux64 <t> x (Const64 <t> [ntz(y)])) (Const64 <t> [ntz(y)]))
   519  
   520  // simplifications often used for lengths.  e.g. len(s[i:i+5])==5
   521  (Sub64 (Add64 x y) x) -> y
   522  (Sub64 (Add64 x y) y) -> x
   523  (Sub32 (Add32 x y) x) -> y
   524  (Sub32 (Add32 x y) y) -> x
   525  (Sub16 (Add16 x y) x) -> y
   526  (Sub16 (Add16 x y) y) -> x
   527  (Sub8  (Add8  x y) x) -> y
   528  (Sub8  (Add8  x y) y) -> x
   529  
   530  // basic phi simplifications
   531  (Phi (Const8  [c]) (Const8  [c])) -> (Const8  [c])
   532  (Phi (Const16 [c]) (Const16 [c])) -> (Const16 [c])
   533  (Phi (Const32 [c]) (Const32 [c])) -> (Const32 [c])
   534  (Phi (Const64 [c]) (Const64 [c])) -> (Const64 [c])
   535  
   536  // user nil checks
   537  (NeqPtr p (ConstNil)) -> (IsNonNil p)
   538  (NeqPtr (ConstNil) p) -> (IsNonNil p)
   539  (EqPtr p (ConstNil)) -> (Not (IsNonNil p))
   540  (EqPtr (ConstNil) p) -> (Not (IsNonNil p))
   541  
   542  // slice and interface comparisons
   543  // The frontend ensures that we can only compare against nil,
   544  // so we need only compare the first word (interface type or slice ptr).
   545  (EqInter x y)  -> (EqPtr  (ITab x) (ITab y))
   546  (NeqInter x y) -> (NeqPtr (ITab x) (ITab y))
   547  (EqSlice x y)  -> (EqPtr  (SlicePtr x) (SlicePtr y))
   548  (NeqSlice x y) -> (NeqPtr (SlicePtr x) (SlicePtr y))
   549  
   550  // Load of store of same address, with compatibly typed value and same size
   551  (Load <t1> p1 (Store [w] p2 x _)) && isSamePtr(p1,p2) && t1.Compare(x.Type)==CMPeq && w == t1.Size() -> x
   552  
   553  // Collapse OffPtr
   554  (OffPtr (OffPtr p [b]) [a]) -> (OffPtr p [a+b])
   555  (OffPtr p [0]) && v.Type.Compare(p.Type) == CMPeq -> p
   556  
   557  // indexing operations
   558  // Note: bounds check has already been done
   559  (ArrayIndex <t> [0] x:(Load ptr mem)) -> @x.Block (Load <t> ptr mem)
   560  (PtrIndex <t> ptr idx) && config.PtrSize == 4 -> (AddPtr ptr (Mul32 <config.fe.TypeInt()> idx (Const32 <config.fe.TypeInt()> [t.ElemType().Size()])))
   561  (PtrIndex <t> ptr idx) && config.PtrSize == 8 -> (AddPtr ptr (Mul64 <config.fe.TypeInt()> idx (Const64 <config.fe.TypeInt()> [t.ElemType().Size()])))
   562  
   563  // struct operations
   564  (StructSelect (StructMake1 x)) -> x
   565  (StructSelect [0] (StructMake2 x _)) -> x
   566  (StructSelect [1] (StructMake2 _ x)) -> x
   567  (StructSelect [0] (StructMake3 x _ _)) -> x
   568  (StructSelect [1] (StructMake3 _ x _)) -> x
   569  (StructSelect [2] (StructMake3 _ _ x)) -> x
   570  (StructSelect [0] (StructMake4 x _ _ _)) -> x
   571  (StructSelect [1] (StructMake4 _ x _ _)) -> x
   572  (StructSelect [2] (StructMake4 _ _ x _)) -> x
   573  (StructSelect [3] (StructMake4 _ _ _ x)) -> x
   574  
   575  (Load <t> _ _) && t.IsStruct() && t.NumFields() == 0 && config.fe.CanSSA(t) ->
   576    (StructMake0)
   577  (Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 1 && config.fe.CanSSA(t) ->
   578    (StructMake1
   579      (Load <t.FieldType(0)> ptr mem))
   580  (Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 2 && config.fe.CanSSA(t) ->
   581    (StructMake2
   582      (Load <t.FieldType(0)> ptr mem)
   583      (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem))
   584  (Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 3 && config.fe.CanSSA(t) ->
   585    (StructMake3
   586      (Load <t.FieldType(0)> ptr mem)
   587      (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem)
   588      (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem))
   589  (Load <t> ptr mem) && t.IsStruct() && t.NumFields() == 4 && config.fe.CanSSA(t) ->
   590    (StructMake4
   591      (Load <t.FieldType(0)> ptr mem)
   592      (Load <t.FieldType(1)> (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] ptr) mem)
   593      (Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem)
   594      (Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
   595  
   596  (StructSelect [i] x:(Load <t> ptr mem)) && !config.fe.CanSSA(t) ->
   597    @x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
   598  
   599  (Store _ (StructMake0) mem) -> mem
   600  (Store dst (StructMake1 <t> f0) mem) ->
   601    (Store [t.FieldType(0).Size()] dst f0 mem)
   602  (Store dst (StructMake2 <t> f0 f1) mem) ->
   603    (Store [t.FieldType(1).Size()]
   604      (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
   605      f1
   606      (Store [t.FieldType(0).Size()] dst f0 mem))
   607  (Store dst (StructMake3 <t> f0 f1 f2) mem) ->
   608    (Store [t.FieldType(2).Size()]
   609      (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
   610      f2
   611      (Store [t.FieldType(1).Size()]
   612        (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
   613        f1
   614        (Store [t.FieldType(0).Size()] dst f0 mem)))
   615  (Store dst (StructMake4 <t> f0 f1 f2 f3) mem) ->
   616    (Store [t.FieldType(3).Size()]
   617      (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] dst)
   618      f3
   619      (Store [t.FieldType(2).Size()]
   620        (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] dst)
   621        f2
   622        (Store [t.FieldType(1).Size()]
   623          (OffPtr <t.FieldType(1).PtrTo()> [t.FieldOff(1)] dst)
   624          f1
   625          (Store [t.FieldType(0).Size()] dst f0 mem))))
   626  
   627  // un-SSAable values use mem->mem copies
   628  (Store [size] dst (Load <t> src mem) mem) && !config.fe.CanSSA(t) -> (Move [size] dst src mem)
   629  (Store [size] dst (Load <t> src mem) (VarDef {x} mem)) && !config.fe.CanSSA(t) -> (Move [size] dst src (VarDef {x} mem))
   630  
   631  // string ops
   632  // Decomposing StringMake and lowering of StringPtr and StringLen
   633  // happens in a later pass, dec, so that these operations are available
   634  // to other passes for optimizations.
   635  (StringPtr (StringMake (Const64 <t> [c]) _)) -> (Const64 <t> [c])
   636  (StringLen (StringMake _ (Const64 <t> [c]))) -> (Const64 <t> [c])
   637  (ConstString {s}) && config.PtrSize == 4 && s.(string) == "" ->
   638    (StringMake (ConstNil) (Const32 <config.fe.TypeInt()> [0]))
   639  (ConstString {s}) && config.PtrSize == 8 && s.(string) == "" ->
   640    (StringMake (ConstNil) (Const64 <config.fe.TypeInt()> [0]))
   641  (ConstString {s}) && config.PtrSize == 4 && s.(string) != "" ->
   642    (StringMake
   643      (Addr <config.fe.TypeBytePtr()> {config.fe.StringData(s.(string))}
   644        (SB))
   645      (Const32 <config.fe.TypeInt()> [int64(len(s.(string)))]))
   646  (ConstString {s}) && config.PtrSize == 8 && s.(string) != "" ->
   647    (StringMake
   648      (Addr <config.fe.TypeBytePtr()> {config.fe.StringData(s.(string))}
   649        (SB))
   650      (Const64 <config.fe.TypeInt()> [int64(len(s.(string)))]))
   651  
   652  // slice ops
   653  // Only a few slice rules are provided here.  See dec.rules for
   654  // a more comprehensive set.
   655  (SliceLen (SliceMake _ (Const64 <t> [c]) _)) -> (Const64 <t> [c])
   656  (SliceCap (SliceMake _ _ (Const64 <t> [c]))) -> (Const64 <t> [c])
   657  (SlicePtr (SliceMake (SlicePtr x) _ _)) -> (SlicePtr x)
   658  (SliceLen (SliceMake _ (SliceLen x) _)) -> (SliceLen x)
   659  (SliceCap (SliceMake _ _ (SliceCap x))) -> (SliceCap x)
   660  (SliceCap (SliceMake _ _ (SliceLen x))) -> (SliceLen x)
   661  (ConstSlice) && config.PtrSize == 4 ->
   662    (SliceMake
   663      (ConstNil <v.Type.ElemType().PtrTo()>)
   664      (Const32 <config.fe.TypeInt()> [0])
   665      (Const32 <config.fe.TypeInt()> [0]))
   666  (ConstSlice) && config.PtrSize == 8 ->
   667    (SliceMake
   668      (ConstNil <v.Type.ElemType().PtrTo()>)
   669      (Const64 <config.fe.TypeInt()> [0])
   670      (Const64 <config.fe.TypeInt()> [0]))
   671  
   672  // interface ops
   673  (ConstInterface) ->
   674    (IMake
   675      (ConstNil <config.fe.TypeBytePtr()>)
   676      (ConstNil <config.fe.TypeBytePtr()>))
   677  
   678  (Check (NilCheck (GetG _) _) next) -> (Plain nil next)
   679  
   680  (If (Not cond) yes no) -> (If cond no yes)
   681  (If (ConstBool [c]) yes no) && c == 1 -> (First nil yes no)
   682  (If (ConstBool [c]) yes no) && c == 0 -> (First nil no yes)
   683  
   684  // Get rid of Convert ops for pointer arithmetic on unsafe.Pointer.
   685  (Convert (Add64 (Convert ptr mem) off) mem) -> (Add64 ptr off)
   686  (Convert (Add64 off (Convert ptr mem)) mem) -> (Add64 ptr off)
   687  (Convert (Convert ptr mem) mem) -> ptr
   688  
   689  // Decompose compound argument values
   690  (Arg {n} [off]) && v.Type.IsString() ->
   691    (StringMake
   692      (Arg <config.fe.TypeBytePtr()> {n} [off])
   693      (Arg <config.fe.TypeInt()> {n} [off+config.PtrSize]))
   694  
   695  (Arg {n} [off]) && v.Type.IsSlice() ->
   696    (SliceMake
   697      (Arg <v.Type.ElemType().PtrTo()> {n} [off])
   698      (Arg <config.fe.TypeInt()> {n} [off+config.PtrSize])
   699      (Arg <config.fe.TypeInt()> {n} [off+2*config.PtrSize]))
   700  
   701  (Arg {n} [off]) && v.Type.IsInterface() ->
   702    (IMake
   703      (Arg <config.fe.TypeBytePtr()> {n} [off])
   704      (Arg <config.fe.TypeBytePtr()> {n} [off+config.PtrSize]))
   705  
   706  (Arg {n} [off]) && v.Type.IsComplex() && v.Type.Size() == 16 ->
   707    (ComplexMake
   708      (Arg <config.fe.TypeFloat64()> {n} [off])
   709      (Arg <config.fe.TypeFloat64()> {n} [off+8]))
   710  
   711  (Arg {n} [off]) && v.Type.IsComplex() && v.Type.Size() == 8 ->
   712    (ComplexMake
   713      (Arg <config.fe.TypeFloat32()> {n} [off])
   714      (Arg <config.fe.TypeFloat32()> {n} [off+4]))
   715  
   716  (Arg <t>) && t.IsStruct() && t.NumFields() == 0 && config.fe.CanSSA(t) ->
   717    (StructMake0)
   718  (Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 1 && config.fe.CanSSA(t) ->
   719    (StructMake1
   720      (Arg <t.FieldType(0)> {n} [off+t.FieldOff(0)]))
   721  (Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 2 && config.fe.CanSSA(t) ->
   722    (StructMake2
   723      (Arg <t.FieldType(0)> {n} [off+t.FieldOff(0)])
   724      (Arg <t.FieldType(1)> {n} [off+t.FieldOff(1)]))
   725  (Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 3 && config.fe.CanSSA(t) ->
   726    (StructMake3
   727      (Arg <t.FieldType(0)> {n} [off+t.FieldOff(0)])
   728      (Arg <t.FieldType(1)> {n} [off+t.FieldOff(1)])
   729      (Arg <t.FieldType(2)> {n} [off+t.FieldOff(2)]))
   730  (Arg <t> {n} [off]) && t.IsStruct() && t.NumFields() == 4 && config.fe.CanSSA(t) ->
   731    (StructMake4
   732      (Arg <t.FieldType(0)> {n} [off+t.FieldOff(0)])
   733      (Arg <t.FieldType(1)> {n} [off+t.FieldOff(1)])
   734      (Arg <t.FieldType(2)> {n} [off+t.FieldOff(2)])
   735      (Arg <t.FieldType(3)> {n} [off+t.FieldOff(3)]))
   736  
   737  // strength reduction of divide by a constant.
   738  // Note: frontend does <=32 bits. We only need to do 64 bits here.
   739  // TODO: Do them all here?
   740  
   741  // Div/mod by 1.  Currently handled by frontend.
   742  //(Div64 n (Const64 [1])) -> n
   743  //(Div64u n (Const64 [1])) -> n
   744  //(Mod64 n (Const64 [1])) -> (Const64 [0])
   745  //(Mod64u n (Const64 [1])) -> (Const64 [0])
   746  
   747  // Unsigned divide by power of 2.
   748  (Div64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (Rsh64Ux64 n (Const64 <t> [log2(c)]))
   749  (Mod64u <t> n (Const64 [c])) && isPowerOfTwo(c) -> (And64 n (Const64 <t> [c-1]))
   750  
   751  // Signed divide by power of 2.  Currently handled by frontend.
   752  // n / c = n >> log(c)       if n >= 0
   753  //       = (n+c-1) >> log(c) if n < 0
   754  // We conditionally add c-1 by adding n>>63>>(64-log(c)) (first shift signed, second shift unsigned).
   755  //(Div64 <t> n (Const64 [c])) && isPowerOfTwo(c) ->
   756  //  (Rsh64x64
   757  //    (Add64 <t>
   758  //      n
   759  //      (Rsh64Ux64 <t>
   760  //        (Rsh64x64 <t> n (Const64 <t> [63]))
   761  //        (Const64 <t> [64-log2(c)])))
   762  //    (Const64 <t> [log2(c)]))
   763  
   764  // Unsigned divide, not a power of 2.  Strength reduce to a multiply.
   765  (Div64u <t> x (Const64 [c])) && umagic64ok(c) && !umagic64a(c) ->
   766    (Rsh64Ux64
   767      (Hmul64u <t>
   768        (Const64 <t> [umagic64m(c)])
   769        x)
   770      (Const64 <t> [umagic64s(c)]))
   771  (Div64u <t> x (Const64 [c])) && umagic64ok(c) && umagic64a(c) ->
   772    (Rsh64Ux64
   773      (Avg64u <t>
   774        (Hmul64u <t>
   775          x
   776          (Const64 <t> [umagic64m(c)]))
   777        x)
   778      (Const64 <t> [umagic64s(c)-1]))
   779  
   780  // Signed divide, not a power of 2.  Strength reduce to a multiply.
   781  (Div64 <t> x (Const64 [c])) && c > 0 && smagic64ok(c) && smagic64m(c) > 0 ->
   782    (Sub64 <t>
   783      (Rsh64x64 <t>
   784        (Hmul64 <t>
   785          (Const64 <t> [smagic64m(c)])
   786          x)
   787        (Const64 <t> [smagic64s(c)]))
   788      (Rsh64x64 <t>
   789        x
   790        (Const64 <t> [63])))
   791  (Div64 <t> x (Const64 [c])) && c > 0 && smagic64ok(c) && smagic64m(c) < 0 ->
   792    (Sub64 <t>
   793      (Rsh64x64 <t>
   794        (Add64 <t>
   795          (Hmul64 <t>
   796            (Const64 <t> [smagic64m(c)])
   797            x)
   798          x)
   799        (Const64 <t> [smagic64s(c)]))
   800      (Rsh64x64 <t>
   801        x
   802        (Const64 <t> [63])))
   803  (Div64 <t> x (Const64 [c])) && c < 0 && smagic64ok(c) && smagic64m(c) > 0 ->
   804    (Neg64 <t>
   805      (Sub64 <t>
   806        (Rsh64x64 <t>
   807          (Hmul64 <t>
   808            (Const64 <t> [smagic64m(c)])
   809            x)
   810          (Const64 <t> [smagic64s(c)]))
   811        (Rsh64x64 <t>
   812          x
   813          (Const64 <t> [63]))))
   814  (Div64 <t> x (Const64 [c])) && c < 0 && smagic64ok(c) && smagic64m(c) < 0 ->
   815    (Neg64 <t>
   816      (Sub64 <t>
   817        (Rsh64x64 <t>
   818          (Add64 <t>
   819            (Hmul64 <t>
   820              (Const64 <t> [smagic64m(c)])
   821              x)
   822            x)
   823          (Const64 <t> [smagic64s(c)]))
   824        (Rsh64x64 <t>
   825          x
   826          (Const64 <t> [63]))))
   827  
   828  // A%B = A-(A/B*B).
   829  // This implements % with two * and a bunch of ancillary ops.
   830  // One of the * is free if the user's code also computes A/B.
   831  (Mod64  <t> x (Const64 [c])) && x.Op != OpConst64 && smagic64ok(c)
   832    -> (Sub64 x (Mul64 <t> (Div64  <t> x (Const64 <t> [c])) (Const64 <t> [c])))
   833  (Mod64u <t> x (Const64 [c])) && x.Op != OpConst64 && umagic64ok(c)
   834    -> (Sub64 x (Mul64 <t> (Div64u <t> x (Const64 <t> [c])) (Const64 <t> [c])))