1# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 2# 3# Check that we can fold (x & mask) -> x when (x & mask) is known to equal x. 4# 5# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s 6 7--- 8name: remove_and_with_one_bit 9legalized: true 10tracksRegLiveness: true 11body: | 12 bb.0: 13 liveins: $w0, $w1 14 ; G_ICMP produces a single bit. The mask is 1. 15 ; 16 ; cmp = 000...0? 17 ; mask = 000...01 18 ; cmp & mask = 000...0? 19 ; 20 ; Remove the G_AND. 21 ; 22 ; CHECK-LABEL: name: remove_and_with_one_bit 23 ; CHECK: liveins: $w0, $w1 24 ; CHECK: %x:_(s32) = COPY $w0 25 ; CHECK: %y:_(s32) = COPY $w1 26 ; CHECK: %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y 27 ; CHECK: $w0 = COPY %cmp(s32) 28 ; CHECK: RET_ReallyLR implicit $w0 29 %x:_(s32) = COPY $w0 30 %y:_(s32) = COPY $w1 31 %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y 32 %mask:_(s32) = G_CONSTANT i32 1 33 %and:_(s32) = G_AND %cmp(s32), %mask 34 $w0 = COPY %and(s32) 35 RET_ReallyLR implicit $w0 36 37... 38--- 39name: remove_and_all_ones_mask 40legalized: true 41tracksRegLiveness: true 42body: | 43 bb.0: 44 liveins: $w0, $w1, $w2 45 ; -1 is all ones. Therefore z & -1 = z. Remove the G_AND. 46 ; 47 ; CHECK-LABEL: name: remove_and_all_ones_mask 48 ; CHECK: liveins: $w0, $w1, $w2 49 ; CHECK: %z:_(s32) = COPY $w2 50 ; CHECK: $w0 = COPY %z(s32) 51 ; CHECK: RET_ReallyLR implicit $w0 52 %x:_(s32) = COPY $w0 53 %y:_(s32) = COPY $w1 54 %z:_(s32) = COPY $w2 55 %mask:_(s32) = G_CONSTANT i32 -1 56 %and:_(s32) = G_AND %z(s32), %mask 57 $w0 = COPY %and(s32) 58 RET_ReallyLR implicit $w0 59 60... 61--- 62name: remove_and_all_ones_zext 63legalized: true 64tracksRegLiveness: true 65body: | 66 bb.0: 67 liveins: $w0, $w1, $w2 68 ; %z is a s32, so it can be at most the all-ones value on 32 bits. 69 ; In decimal this is 4294967295. Any zero-extension of %z is at most this 70 ; value. 71 ; 72 ; Therefore, zext(z) & 4294967295 == z. Remove the G_AND. 73 ; 74 ; CHECK-LABEL: name: remove_and_all_ones_zext 75 ; CHECK: liveins: $w0, $w1, $w2 76 ; CHECK: %z:_(s32) = COPY $w2 77 ; CHECK: %ext:_(s64) = G_ZEXT %z(s32) 78 ; CHECK: $x0 = COPY %ext(s64) 79 ; CHECK: RET_ReallyLR implicit $x0 80 %x:_(s32) = COPY $w0 81 %y:_(s32) = COPY $w1 82 %z:_(s32) = COPY $w2 83 %ext:_(s64) = G_ZEXT %z 84 %mask:_(s64) = G_CONSTANT i64 4294967295 85 %and:_(s64) = G_AND %ext(s64), %mask 86 $x0 = COPY %and(s64) 87 RET_ReallyLR implicit $x0 88 89... 90--- 91name: remove_and_all_ones_anyext 92legalized: true 93tracksRegLiveness: true 94body: | 95 bb.0: 96 liveins: $w0, $w1, $w2 97 ; This is the same as the zext case. 98 ; 99 ; CHECK-LABEL: name: remove_and_all_ones_anyext 100 ; CHECK: liveins: $w0, $w1, $w2 101 ; CHECK: %z:_(s32) = COPY $w2 102 ; CHECK: %ext:_(s64) = G_ZEXT %z(s32) 103 ; CHECK: $x0 = COPY %ext(s64) 104 ; CHECK: RET_ReallyLR implicit $x0 105 %x:_(s32) = COPY $w0 106 %y:_(s32) = COPY $w1 107 %z:_(s32) = COPY $w2 108 %ext:_(s64) = G_ZEXT %z 109 %mask:_(s64) = G_CONSTANT i64 4294967295 110 %and:_(s64) = G_AND %ext(s64), %mask 111 $x0 = COPY %and(s64) 112 RET_ReallyLR implicit $x0 113 114... 115--- 116name: dont_remove_all_ones_sext 117legalized: true 118tracksRegLiveness: true 119body: | 120 bb.0: 121 liveins: $w0, $w1, $w2 122 ; We don't know if the sign bit is set on %z. So, the value in %ext may have 123 ; higher bits set than 4294967295. 124 ; 125 ; CHECK-LABEL: name: dont_remove_all_ones_sext 126 ; CHECK: liveins: $w0, $w1, $w2 127 ; CHECK: %z:_(s32) = COPY $w2 128 ; CHECK: %ext:_(s64) = G_SEXT %z(s32) 129 ; CHECK: %mask:_(s64) = G_CONSTANT i64 4294967295 130 ; CHECK: %and:_(s64) = G_AND %ext, %mask 131 ; CHECK: $x0 = COPY %and(s64) 132 ; CHECK: RET_ReallyLR implicit $x0 133 %x:_(s32) = COPY $w0 134 %y:_(s32) = COPY $w1 135 %z:_(s32) = COPY $w2 136 %ext:_(s64) = G_SEXT %z 137 %mask:_(s64) = G_CONSTANT i64 4294967295 138 %and:_(s64) = G_AND %ext(s64), %mask 139 $x0 = COPY %and(s64) 140 RET_ReallyLR implicit $x0 141 142... 143--- 144name: remove_and_positive_constant_sext 145legalized: true 146tracksRegLiveness: true 147body: | 148 bb.0: 149 liveins: $w0, $w1, $w2 150 ; We know the sign bit is not set on %z. Therefore, 151 ; 152 ; z = ext = 42 = 000...0101010 153 ; mask = 0000...0111111 154 ; 155 ; So z & mask == z 156 ; CHECK-LABEL: name: remove_and_positive_constant_sext 157 ; CHECK: liveins: $w0, $w1, $w2 158 ; CHECK: %z:_(s32) = G_CONSTANT i32 42 159 ; CHECK: %ext:_(s64) = G_SEXT %z(s32) 160 ; CHECK: $x0 = COPY %ext(s64) 161 ; CHECK: RET_ReallyLR implicit $x0 162 %x:_(s32) = COPY $w0 163 %y:_(s32) = COPY $w1 164 %z:_(s32) = G_CONSTANT i32 42 165 %ext:_(s64) = G_SEXT %z 166 %mask:_(s64) = G_CONSTANT i64 63 167 %and:_(s64) = G_AND %ext(s64), %mask 168 $x0 = COPY %and(s64) 169 RET_ReallyLR implicit $x0 170 171... 172--- 173name: not_a_mask 174legalized: true 175tracksRegLiveness: true 176body: | 177 bb.0: 178 liveins: $w0, $w1 179 ; 6 is not a mask, so we should still have the G_AND. 180 ; 181 ; CHECK-LABEL: name: not_a_mask 182 ; CHECK: liveins: $w0, $w1 183 ; CHECK: %x:_(s32) = COPY $w0 184 ; CHECK: %y:_(s32) = COPY $w1 185 ; CHECK: %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y 186 ; CHECK: %mask:_(s32) = G_CONSTANT i32 6 187 ; CHECK: %and:_(s32) = G_AND %cmp, %mask 188 ; CHECK: $w0 = COPY %and(s32) 189 ; CHECK: RET_ReallyLR implicit $w0 190 %x:_(s32) = COPY $w0 191 %y:_(s32) = COPY $w1 192 %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y 193 %mask:_(s32) = G_CONSTANT i32 6 194 %and:_(s32) = G_AND %cmp(s32), %mask 195 $w0 = COPY %and(s32) 196 RET_ReallyLR implicit $w0 197 198... 199--- 200name: unknown_val 201legalized: true 202tracksRegLiveness: true 203body: | 204 bb.0: 205 liveins: $w0, $w1, $w2 206 ; We don't know what's in $w2, so we can't remove the G_AND without a mask 207 ; that fills every bit in the type. 208 ; 209 ; CHECK-LABEL: name: unknown_val 210 ; CHECK: liveins: $w0, $w1, $w2 211 ; CHECK: %z:_(s32) = COPY $w2 212 ; CHECK: %one:_(s32) = G_CONSTANT i32 32 213 ; CHECK: %and:_(s32) = G_AND %z, %one 214 ; CHECK: $w0 = COPY %and(s32) 215 ; CHECK: RET_ReallyLR implicit $w0 216 %x:_(s32) = COPY $w0 217 %y:_(s32) = COPY $w1 218 %z:_(s32) = COPY $w2 219 %one:_(s32) = G_CONSTANT i32 32 220 %and:_(s32) = G_AND %z(s32), %one 221 $w0 = COPY %and(s32) 222 RET_ReallyLR implicit $w0 223... 224