1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s 3 4 ; https://bugs.llvm.org/show_bug.cgi?id=37104 5 6 ; X: [byte3] [byte0] 7 ; Y: [byte2][byte1] 8 9 define i8 @out8_constmask(i8 %x, i8 %y) { 10 ; CHECK-LABEL: out8_constmask: 11 ; CHECK: // %bb.0: 12 ; CHECK-NEXT: lsr w8, w0, #2 13 ; CHECK-NEXT: bfi w1, w8, #2, #4 14 ; CHECK-NEXT: mov w0, w1 15 ; CHECK-NEXT: ret 16 %mx = and i8 %x, 60 17 %my = and i8 %y, -61 18 %r = or i8 %mx, %my 19 ret i8 %r 20 } 21 22 define i16 @out16_constmask(i16 %x, i16 %y) { 23 ; CHECK-LABEL: out16_constmask: 24 ; CHECK: // %bb.0: 25 ; CHECK-NEXT: lsr w8, w0, #4 26 ; CHECK-NEXT: bfi w1, w8, #4, #8 27 ; CHECK-NEXT: mov w0, w1 28 ; CHECK-NEXT: ret 29 %mx = and i16 %x, 4080 30 %my = and i16 %y, -4081 31 %r = or i16 %mx, %my 32 ret i16 %r 33 } 34 35 define i32 @out32_constmask(i32 %x, i32 %y) { 36 ; CHECK-LABEL: out32_constmask: 37 ; CHECK: // %bb.0: 38 ; CHECK-NEXT: lsr w8, w0, #8 39 ; CHECK-NEXT: bfi w1, w8, #8, #16 40 ; CHECK-NEXT: mov w0, w1 41 ; CHECK-NEXT: ret 42 %mx = and i32 %x, 16776960 43 %my = and i32 %y, -16776961 44 %r = or i32 %mx, %my 45 ret i32 %r 46 } 47 48 define i64 @out64_constmask(i64 %x, i64 %y) { 49 ; CHECK-LABEL: out64_constmask: 50 ; CHECK: // %bb.0: 51 ; CHECK-NEXT: lsr x8, x0, #16 52 ; CHECK-NEXT: bfi x1, x8, #16, #32 53 ; CHECK-NEXT: mov x0, x1 54 ; CHECK-NEXT: ret 55 %mx = and i64 %x, 281474976645120 56 %my = and i64 %y, -281474976645121 57 %r = or i64 %mx, %my 58 ret i64 %r 59 } 60 61 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 62 ; Should be the same as the previous one. 63 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 64 65 define i8 @in8_constmask(i8 %x, i8 %y) { 66 ; CHECK-LABEL: in8_constmask: 67 ; CHECK: // %bb.0: 68 ; CHECK-NEXT: eor w8, w0, w1 69 ; CHECK-NEXT: and w8, w8, #0x3c 70 ; CHECK-NEXT: eor w0, w8, w1 71 ; CHECK-NEXT: ret 72 %n0 = xor i8 %x, %y 73 %n1 = and i8 %n0, 60 74 %r = xor i8 %n1, %y 75 ret i8 %r 76 } 77 78 define i16 @in16_constmask(i16 %x, i16 %y) { 79 ; CHECK-LABEL: in16_constmask: 80 ; CHECK: // %bb.0: 81 ; CHECK-NEXT: eor w8, w0, w1 82 ; CHECK-NEXT: and w8, w8, #0xff0 83 ; CHECK-NEXT: eor w0, w8, w1 84 ; CHECK-NEXT: ret 85 %n0 = xor i16 %x, %y 86 %n1 = and i16 %n0, 4080 87 %r = xor i16 %n1, %y 88 ret i16 %r 89 } 90 91 define i32 @in32_constmask(i32 %x, i32 %y) { 92 ; CHECK-LABEL: in32_constmask: 93 ; CHECK: // %bb.0: 94 ; CHECK-NEXT: eor w8, w0, w1 95 ; CHECK-NEXT: and w8, w8, #0xffff00 96 ; CHECK-NEXT: eor w0, w8, w1 97 ; CHECK-NEXT: ret 98 %n0 = xor i32 %x, %y 99 %n1 = and i32 %n0, 16776960 100 %r = xor i32 %n1, %y 101 ret i32 %r 102 } 103 104 define i64 @in64_constmask(i64 %x, i64 %y) { 105 ; CHECK-LABEL: in64_constmask: 106 ; CHECK: // %bb.0: 107 ; CHECK-NEXT: eor x8, x0, x1 108 ; CHECK-NEXT: and x8, x8, #0xffffffff0000 109 ; CHECK-NEXT: eor x0, x8, x1 110 ; CHECK-NEXT: ret 111 %n0 = xor i64 %x, %y 112 %n1 = and i64 %n0, 281474976645120 113 %r = xor i64 %n1, %y 114 ret i64 %r 115 } 116 117 ; ============================================================================ ; 118 ; Constant Commutativity tests. 119 ; ============================================================================ ; 120 121 define i32 @in_constmask_commutativity_0_1(i32 %x, i32 %y) { 122 ; CHECK-LABEL: in_constmask_commutativity_0_1: 123 ; CHECK: // %bb.0: 124 ; CHECK-NEXT: eor w8, w0, w1 125 ; CHECK-NEXT: and w8, w8, #0xffff00 126 ; CHECK-NEXT: eor w0, w1, w8 127 ; CHECK-NEXT: ret 128 %n0 = xor i32 %x, %y 129 %n1 = and i32 %n0, 16776960 130 %r = xor i32 %y, %n1 ; swapped 131 ret i32 %r 132 } 133 134 define i32 @in_constmask_commutativity_1_0(i32 %x, i32 %y) { 135 ; CHECK-LABEL: in_constmask_commutativity_1_0: 136 ; CHECK: // %bb.0: 137 ; CHECK-NEXT: eor w8, w0, w1 138 ; CHECK-NEXT: and w8, w8, #0xffff00 139 ; CHECK-NEXT: eor w0, w8, w0 140 ; CHECK-NEXT: ret 141 %n0 = xor i32 %x, %y 142 %n1 = and i32 %n0, 16776960 143 %r = xor i32 %n1, %x ; %x instead of %y 144 ret i32 %r 145 } 146 147 define i32 @in_constmask_commutativity_1_1(i32 %x, i32 %y) { 148 ; CHECK-LABEL: in_constmask_commutativity_1_1: 149 ; CHECK: // %bb.0: 150 ; CHECK-NEXT: eor w8, w0, w1 151 ; CHECK-NEXT: and w8, w8, #0xffff00 152 ; CHECK-NEXT: eor w0, w0, w8 153 ; CHECK-NEXT: ret 154 %n0 = xor i32 %x, %y 155 %n1 = and i32 %n0, 16776960 156 %r = xor i32 %x, %n1 ; swapped, %x instead of %y 157 ret i32 %r 158 } 159 160 ; ============================================================================ ; 161 ; Y is an 'and' too. 162 ; ============================================================================ ; 163 164 define i32 @in_complex_y0_constmask(i32 %x, i32 %y_hi, i32 %y_low) { 165 ; CHECK-LABEL: in_complex_y0_constmask: 166 ; CHECK: // %bb.0: 167 ; CHECK-NEXT: and w8, w1, w2 168 ; CHECK-NEXT: eor w9, w0, w8 169 ; CHECK-NEXT: and w9, w9, #0xffff00 170 ; CHECK-NEXT: eor w0, w9, w8 171 ; CHECK-NEXT: ret 172 %y = and i32 %y_hi, %y_low 173 %n0 = xor i32 %x, %y 174 %n1 = and i32 %n0, 16776960 175 %r = xor i32 %n1, %y 176 ret i32 %r 177 } 178 179 define i32 @in_complex_y1_constmask(i32 %x, i32 %y_hi, i32 %y_low) { 180 ; CHECK-LABEL: in_complex_y1_constmask: 181 ; CHECK: // %bb.0: 182 ; CHECK-NEXT: and w8, w1, w2 183 ; CHECK-NEXT: eor w9, w0, w8 184 ; CHECK-NEXT: and w9, w9, #0xffff00 185 ; CHECK-NEXT: eor w0, w8, w9 186 ; CHECK-NEXT: ret 187 %y = and i32 %y_hi, %y_low 188 %n0 = xor i32 %x, %y 189 %n1 = and i32 %n0, 16776960 190 %r = xor i32 %y, %n1 191 ret i32 %r 192 } 193 194 ; ============================================================================ ; 195 ; Negative tests. Should not be folded. 196 ; ============================================================================ ; 197 198 ; Multi-use tests. 199 200 declare void @use32(i32) nounwind 201 202 define i32 @in_multiuse_A_constmask(i32 %x, i32 %y, i32 %z) nounwind { 203 ; CHECK-LABEL: in_multiuse_A_constmask: 204 ; CHECK: // %bb.0: 205 ; CHECK-NEXT: str x20, [sp, #-32]! // 8-byte Folded Spill 206 ; CHECK-NEXT: eor w8, w0, w1 207 ; CHECK-NEXT: and w20, w8, #0xffff00 208 ; CHECK-NEXT: mov w0, w20 209 ; CHECK-NEXT: stp x19, x30, [sp, #16] // 8-byte Folded Spill 210 ; CHECK-NEXT: mov w19, w1 211 ; CHECK-NEXT: bl use32 212 ; CHECK-NEXT: eor w0, w20, w19 213 ; CHECK-NEXT: ldp x19, x30, [sp, #16] // 8-byte Folded Reload 214 ; CHECK-NEXT: ldr x20, [sp], #32 // 8-byte Folded Reload 215 ; CHECK-NEXT: ret 216 %n0 = xor i32 %x, %y 217 %n1 = and i32 %n0, 16776960 218 call void @use32(i32 %n1) 219 %r = xor i32 %n1, %y 220 ret i32 %r 221 } 222 223 define i32 @in_multiuse_B_constmask(i32 %x, i32 %y, i32 %z) nounwind { 224 ; CHECK-LABEL: in_multiuse_B_constmask: 225 ; CHECK: // %bb.0: 226 ; CHECK-NEXT: str x20, [sp, #-32]! // 8-byte Folded Spill 227 ; CHECK-NEXT: eor w0, w0, w1 228 ; CHECK-NEXT: stp x19, x30, [sp, #16] // 8-byte Folded Spill 229 ; CHECK-NEXT: mov w19, w1 230 ; CHECK-NEXT: and w20, w0, #0xffff00 231 ; CHECK-NEXT: bl use32 232 ; CHECK-NEXT: eor w0, w20, w19 233 ; CHECK-NEXT: ldp x19, x30, [sp, #16] // 8-byte Folded Reload 234 ; CHECK-NEXT: ldr x20, [sp], #32 // 8-byte Folded Reload 235 ; CHECK-NEXT: ret 236 %n0 = xor i32 %x, %y 237 %n1 = and i32 %n0, 16776960 238 call void @use32(i32 %n0) 239 %r = xor i32 %n1, %y 240 ret i32 %r 241 } 242 243 ; Various bad variants 244 245 define i32 @n0_badconstmask(i32 %x, i32 %y) { 246 ; CHECK-LABEL: n0_badconstmask: 247 ; CHECK: // %bb.0: 248 ; CHECK-NEXT: mov w9, #256 249 ; CHECK-NEXT: movk w9, #65280, lsl #16 250 ; CHECK-NEXT: and w8, w0, #0xffff00 251 ; CHECK-NEXT: and w9, w1, w9 252 ; CHECK-NEXT: orr w0, w8, w9 253 ; CHECK-NEXT: ret 254 %mx = and i32 %x, 16776960 255 %my = and i32 %y, -16776960 ; instead of -16776961 256 %r = or i32 %mx, %my 257 ret i32 %r 258 } 259 260 define i32 @n1_thirdvar_constmask(i32 %x, i32 %y, i32 %z) { 261 ; CHECK-LABEL: n1_thirdvar_constmask: 262 ; CHECK: // %bb.0: 263 ; CHECK-NEXT: eor w8, w0, w1 264 ; CHECK-NEXT: and w8, w8, #0xffff00 265 ; CHECK-NEXT: eor w0, w8, w2 266 ; CHECK-NEXT: ret 267 %n0 = xor i32 %x, %y 268 %n1 = and i32 %n0, 16776960 269 %r = xor i32 %n1, %z ; instead of %y 270 ret i32 %r 271 } 272