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 9define 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 21define 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 33define 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 45define 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 61define 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 74define 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 87define 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 100define 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 116define 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 129define 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 142define 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 159define 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 174define 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 195declare void @use32(i32) nounwind 196 197define 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 218define 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 240define 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 253define 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