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