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