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 9define 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 22define 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 35define 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 48define 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 65define 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 78define 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 91define 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 104define 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 121define 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 134define 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 147define 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 164define 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 179define 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 200declare void @use32(i32) nounwind 201 202define 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 x30, [sp, #-32]! // 8-byte Folded Spill 206; CHECK-NEXT: eor w8, w0, w1 207; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill 208; CHECK-NEXT: and w20, w8, #0xffff00 209; CHECK-NEXT: mov w0, w20 210; CHECK-NEXT: mov w19, w1 211; CHECK-NEXT: bl use32 212; CHECK-NEXT: eor w0, w20, w19 213; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload 214; CHECK-NEXT: ldr x30, [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 223define 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 x30, [sp, #-32]! // 8-byte Folded Spill 227; CHECK-NEXT: eor w0, w0, w1 228; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-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 x20, x19, [sp, #16] // 16-byte Folded Reload 234; CHECK-NEXT: ldr x30, [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 245define 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 260define 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