1; RUN: llc -mtriple=armv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-ARM --check-prefix=CHECK-COMMON 2; RUN: llc -mtriple=armv7eb-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-BE 3; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-COMMON 4; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-COMMON 5; RUN: llc -mtriple=thumbv7m -mattr=+strict-align %s -o - | FileCheck %s --check-prefix=CHECK-ALIGN --check-prefix=CHECK-COMMON 6; RUN: llc -mtriple=thumbv6m %s -o - | FileCheck %s --check-prefix=CHECK-V6M 7 8@array = weak global [4 x i32] zeroinitializer 9 10define i32 @test_lshr_and1(i32 %x) { 11entry: 12;CHECK-LABEL: test_lshr_and1: 13;CHECK-COMMON: movw r1, :lower16:array 14;CHECK-COMMON-NEXT: and r0, r0, #12 15;CHECK-COMMON-NEXT: movt r1, :upper16:array 16;CHECK-COMMON-NEXT: ldr r0, [r1, r0] 17;CHECK-COMMON-NEXT: bx lr 18 %tmp2 = lshr i32 %x, 2 19 %tmp3 = and i32 %tmp2, 3 20 %tmp4 = getelementptr [4 x i32], [4 x i32]* @array, i32 0, i32 %tmp3 21 %tmp5 = load i32, i32* %tmp4, align 4 22 ret i32 %tmp5 23} 24define i32 @test_lshr_and2(i32 %x) { 25entry: 26;CHECK-LABEL: test_lshr_and2: 27;CHECK-COMMON: ubfx r0, r0, #1, #15 28;CHECK-ARM: add r0, r0, r0 29;CHECK-THUMB: add r0, r0 30;CHECK-COMMON: bx lr 31 %a = and i32 %x, 65534 32 %b = lshr i32 %a, 1 33 %c = and i32 %x, 65535 34 %d = lshr i32 %c, 1 35 %e = add i32 %b, %d 36 ret i32 %e 37} 38 39; CHECK-LABEL: test_lshr_load1 40; CHECK-BE: ldrb r0, [r0] 41; CHECK-COMMON: ldrb r0, [r0, #1] 42; CHECK-COMMON-NEXT: bx 43define arm_aapcscc i32 @test_lshr_load1(i16* %a) { 44entry: 45 %0 = load i16, i16* %a, align 2 46 %conv1 = zext i16 %0 to i32 47 %1 = lshr i32 %conv1, 8 48 ret i32 %1 49} 50 51; CHECK-LABEL: test_lshr_load1_sext 52; CHECK-ARM: ldrsh r0, [r0] 53; CHECK-ARM-NEXT: lsr r0, r0, #8 54; CHECK-THUMB: ldrsh.w r0, [r0] 55; CHECK-THUMB-NEXT: lsrs r0, r0, #8 56; CHECK-COMMON: bx 57define arm_aapcscc i32 @test_lshr_load1_sext(i16* %a) { 58entry: 59 %0 = load i16, i16* %a, align 2 60 %conv1 = sext i16 %0 to i32 61 %1 = lshr i32 %conv1, 8 62 ret i32 %1 63} 64 65; CHECK-LABEL: test_lshr_load1_fail 66; CHECK-COMMON: ldrh r0, [r0] 67; CHECK-ARM: lsr r0, r0, #9 68; CHECK-THUMB: lsrs r0, r0, #9 69; CHECK-COMMON: bx 70define arm_aapcscc i32 @test_lshr_load1_fail(i16* %a) { 71entry: 72 %0 = load i16, i16* %a, align 2 73 %conv1 = zext i16 %0 to i32 74 %1 = lshr i32 %conv1, 9 75 ret i32 %1 76} 77 78; CHECK-LABEL: test_lshr_load32 79; CHECK-COMMON: ldr r0, [r0] 80; CHECK-ARM: lsr r0, r0, #8 81; CHECK-THUMB: lsrs r0, r0, #8 82; CHECK-COMMON: bx 83define arm_aapcscc i32 @test_lshr_load32(i32* %a) { 84entry: 85 %0 = load i32, i32* %a, align 4 86 %1 = lshr i32 %0, 8 87 ret i32 %1 88} 89 90; CHECK-LABEL: test_lshr_load32_2 91; CHECK-BE: ldrh r0, [r0] 92; CHECK-COMMON: ldrh r0, [r0, #2] 93; CHECK-COMMON-NEXT: bx 94define arm_aapcscc i32 @test_lshr_load32_2(i32* %a) { 95entry: 96 %0 = load i32, i32* %a, align 4 97 %1 = lshr i32 %0, 16 98 ret i32 %1 99} 100 101; CHECK-LABEL: test_lshr_load32_1 102; CHECK-BE: ldrb r0, [r0] 103; CHECK-COMMON: ldrb r0, [r0, #3] 104; CHECK-COMMON-NEXT: bx 105define arm_aapcscc i32 @test_lshr_load32_1(i32* %a) { 106entry: 107 %0 = load i32, i32* %a, align 4 108 %1 = lshr i32 %0, 24 109 ret i32 %1 110} 111 112; CHECK-LABEL: test_lshr_load32_fail 113; CHECK-BE: ldr r0, [r0] 114; CHECK-BE-NEXT: lsr r0, r0, #15 115; CHECK-COMMON: ldr r0, [r0] 116; CHECK-ARM: lsr r0, r0, #15 117; CHECK-THUMB: lsrs r0, r0, #15 118; CHECK-COMMON: bx 119define arm_aapcscc i32 @test_lshr_load32_fail(i32* %a) { 120entry: 121 %0 = load i32, i32* %a, align 4 122 %1 = lshr i32 %0, 15 123 ret i32 %1 124} 125 126; CHECK-LABEL: test_lshr_load64_4_unaligned 127; CHECK-BE: ldr [[HIGH:r[0-9]+]], [r0] 128; CHECK-BE-NEXT: ldrh [[LOW:r[0-9]+]], [r0, #4] 129; CHECK-BE-NEXT: orr r0, [[LOW]], [[HIGH]], lsl #16 130; CHECK-V6M: ldrh [[LOW:r[0-9]+]], [r0, #2] 131; CHECK-V6M: ldr [[HIGH:r[0-9]+]], [r0, #4] 132; CHECK-V6M-NEXT: lsls [[HIGH]], [[HIGH]], #16 133; CHECK-V6M-NEXT: adds r0, r1, r0 134; CHECK-ALIGN: ldr [[HIGH:r[0-9]+]], [r0, #4] 135; CHECK-ALIGN-NEXT: ldrh [[LOW:r[0-9]+]], [r0, #2] 136; CHECK-ALIGN-NEXT: orr.w r0, [[LOW]], [[HIGH]], lsl #16 137; CHECK-ARM: ldr r0, [r0, #2] 138; CHECK-THUMB: ldr.w r0, [r0, #2] 139; CHECK-COMMON: bx 140define arm_aapcscc i32 @test_lshr_load64_4_unaligned(i64* %a) { 141entry: 142 %0 = load i64, i64* %a, align 8 143 %1 = lshr i64 %0, 16 144 %conv = trunc i64 %1 to i32 145 ret i32 %conv 146} 147 148; CHECK-LABEL: test_lshr_load64_1_lsb 149; CHECK-BE: ldr r1, [r0] 150; CHECK-BE-NEXT: ldrb r0, [r0, #4] 151; CHECK-BE-NEXT: orr r0, r0, r1, lsl #8 152; CHECK-ARM: ldr r0, [r0, #3] 153; CHECK-THUMB: ldr.w r0, [r0, #3] 154; CHECK-ALIGN: ldr [[HIGH:r[0-9]+]], [r0, #4] 155; CHECK-ALIGN-NEXT: ldrb [[LOW:r[0-9]+]], [r0, #3] 156; CHECK-ALIGN-NEXT: orr.w r0, [[LOW]], [[HIGH]], lsl #8 157; CHECK-COMMON: bx 158define arm_aapcscc i32 @test_lshr_load64_1_lsb(i64* %a) { 159entry: 160 %0 = load i64, i64* %a, align 8 161 %1 = lshr i64 %0, 24 162 %conv = trunc i64 %1 to i32 163 ret i32 %conv 164} 165 166; CHECK-LABEL: test_lshr_load64_1_msb 167; CHECK-BE: ldrb r0, [r0] 168; CHECK-BE-NEXT: bx 169; CHECK-COMMON: ldrb r0, [r0, #7] 170; CHECK-COMMON-NEXT: bx 171define arm_aapcscc i32 @test_lshr_load64_1_msb(i64* %a) { 172entry: 173 %0 = load i64, i64* %a, align 8 174 %1 = lshr i64 %0, 56 175 %conv = trunc i64 %1 to i32 176 ret i32 %conv 177} 178 179; CHECK-LABEL: test_lshr_load64_4 180; CHECK-BE: ldr r0, [r0] 181; CHECK-BE-NEXT: bx 182; CHECK-COMMON: ldr r0, [r0, #4] 183; CHECK-COMMON-NEXT: bx 184define arm_aapcscc i32 @test_lshr_load64_4(i64* %a) { 185entry: 186 %0 = load i64, i64* %a, align 8 187 %1 = lshr i64 %0, 32 188 %conv = trunc i64 %1 to i32 189 ret i32 %conv 190} 191 192; CHECK-LABEL: test_lshr_load64_2 193; CHECK-BE: ldrh r0, [r0] 194; CHECK-BE-NEXT: bx 195; CHECK-COMMON: ldrh r0, [r0, #6] 196; CHECK-COMMON-NEXT:bx 197define arm_aapcscc i32 @test_lshr_load64_2(i64* %a) { 198entry: 199 %0 = load i64, i64* %a, align 8 200 %1 = lshr i64 %0, 48 201 %conv = trunc i64 %1 to i32 202 ret i32 %conv 203} 204 205; CHECK-LABEL: test_lshr_load4_fail 206; CHECK-COMMON: ldrd r0, r1, [r0] 207; CHECK-ARM: lsr r0, r0, #8 208; CHECK-ARM-NEXT: orr r0, r0, r1, lsl #24 209; CHECK-THUMB: lsrs r0, r0, #8 210; CHECK-THUMB-NEXT: orr.w r0, r0, r1, lsl #24 211; CHECK-COMMON: bx 212define arm_aapcscc i32 @test_lshr_load4_fail(i64* %a) { 213entry: 214 %0 = load i64, i64* %a, align 8 215 %1 = lshr i64 %0, 8 216 %conv = trunc i64 %1 to i32 217 ret i32 %conv 218} 219 220; CHECK-LABEL: test_shift7_mask8 221; CHECK-BE: ldr r1, [r0] 222; CHECK-COMMON: ldr r1, [r0] 223; CHECK-COMMON: ubfx r1, r1, #7, #8 224; CHECK-COMMON: str r1, [r0] 225define arm_aapcscc void @test_shift7_mask8(i32* nocapture %p) { 226entry: 227 %0 = load i32, i32* %p, align 4 228 %shl = lshr i32 %0, 7 229 %and = and i32 %shl, 255 230 store i32 %and, i32* %p, align 4 231 ret void 232} 233 234; CHECK-LABEL: test_shift8_mask8 235; CHECK-BE: ldrb r1, [r0, #2] 236; CHECK-COMMON: ldrb r1, [r0, #1] 237; CHECK-COMMON: str r1, [r0] 238define arm_aapcscc void @test_shift8_mask8(i32* nocapture %p) { 239entry: 240 %0 = load i32, i32* %p, align 4 241 %shl = lshr i32 %0, 8 242 %and = and i32 %shl, 255 243 store i32 %and, i32* %p, align 4 244 ret void 245} 246 247; CHECK-LABEL: test_shift8_mask7 248; CHECK-BE: ldr r1, [r0] 249; CHECK-COMMON: ldr r1, [r0] 250; CHECK-COMMON: ubfx r1, r1, #8, #7 251; CHECK-COMMON: str r1, [r0] 252define arm_aapcscc void @test_shift8_mask7(i32* nocapture %p) { 253entry: 254 %0 = load i32, i32* %p, align 4 255 %shl = lshr i32 %0, 8 256 %and = and i32 %shl, 127 257 store i32 %and, i32* %p, align 4 258 ret void 259} 260 261; CHECK-LABEL: test_shift9_mask8 262; CHECK-BE: ldr r1, [r0] 263; CHECK-COMMON: ldr r1, [r0] 264; CHECK-COMMON: ubfx r1, r1, #9, #8 265; CHECK-COMMON: str r1, [r0] 266define arm_aapcscc void @test_shift9_mask8(i32* nocapture %p) { 267entry: 268 %0 = load i32, i32* %p, align 4 269 %shl = lshr i32 %0, 9 270 %and = and i32 %shl, 255 271 store i32 %and, i32* %p, align 4 272 ret void 273} 274 275; CHECK-LABEL: test_shift8_mask16 276; CHECK-ALIGN: ldr r1, [r0] 277; CHECK-ALIGN: ubfx r1, r1, #8, #16 278; CHECK-BE: ldrh r1, [r0, #1] 279; CHECK-ARM: ldrh r1, [r0, #1] 280; CHECK-THUMB: ldrh.w r1, [r0, #1] 281; CHECK-COMMON: str r1, [r0] 282define arm_aapcscc void @test_shift8_mask16(i32* nocapture %p) { 283entry: 284 %0 = load i32, i32* %p, align 4 285 %shl = lshr i32 %0, 8 286 %and = and i32 %shl, 65535 287 store i32 %and, i32* %p, align 4 288 ret void 289} 290 291; CHECK-LABEL: test_shift15_mask16 292; CHECK-COMMON: ldr r1, [r0] 293; CHECK-COMMON: ubfx r1, r1, #15, #16 294; CHECK-COMMON: str r1, [r0] 295define arm_aapcscc void @test_shift15_mask16(i32* nocapture %p) { 296entry: 297 %0 = load i32, i32* %p, align 4 298 %shl = lshr i32 %0, 15 299 %and = and i32 %shl, 65535 300 store i32 %and, i32* %p, align 4 301 ret void 302} 303 304; CHECK-LABEL: test_shift16_mask15 305; CHECK-BE: ldrh r1, [r0] 306; CHECK-COMMON: ldrh r1, [r0, #2] 307; CHECK-COMMON: bfc r1, #15, #17 308; CHECK-COMMON: str r1, [r0] 309define arm_aapcscc void @test_shift16_mask15(i32* nocapture %p) { 310entry: 311 %0 = load i32, i32* %p, align 4 312 %shl = lshr i32 %0, 16 313 %and = and i32 %shl, 32767 314 store i32 %and, i32* %p, align 4 315 ret void 316} 317 318; CHECK-LABEL: test_shift8_mask24 319; CHECK-BE: ldr r1, [r0] 320; CHECK-COMMON: ldr r1, [r0] 321; CHECK-ARM: lsr r1, r1, #8 322; CHECK-THUMB: lsrs r1, r1, #8 323; CHECK-COMMON: str r1, [r0] 324define arm_aapcscc void @test_shift8_mask24(i32* nocapture %p) { 325entry: 326 %0 = load i32, i32* %p, align 4 327 %shl = lshr i32 %0, 8 328 %and = and i32 %shl, 16777215 329 store i32 %and, i32* %p, align 4 330 ret void 331} 332 333; CHECK-LABEL: test_shift24_mask16 334; CHECK-BE: ldrb r1, [r0] 335; CHECK-COMMON: ldrb r1, [r0, #3] 336; CHECK-COMMON: str r1, [r0] 337define arm_aapcscc void @test_shift24_mask16(i32* nocapture %p) { 338entry: 339 %0 = load i32, i32* %p, align 4 340 %shl = lshr i32 %0, 24 341 %and = and i32 %shl, 65535 342 store i32 %and, i32* %p, align 4 343 ret void 344} 345 346; CHECK-LABEL: test_sext_shift8_mask8 347; CHECK-BE: ldrb r0, [r0] 348; CHECK-COMMON: ldrb r0, [r0, #1] 349; CHECK-COMMON: str r0, [r1] 350define arm_aapcscc void @test_sext_shift8_mask8(i16* %p, i32* %q) { 351entry: 352 %0 = load i16, i16* %p, align 4 353 %1 = sext i16 %0 to i32 354 %shl = lshr i32 %1, 8 355 %and = and i32 %shl, 255 356 store i32 %and, i32* %q, align 4 357 ret void 358} 359 360; CHECK-LABEL: test_sext_shift8_mask16 361; CHECK-ARM: ldrsh r0, [r0] 362; CHECK-BE: ldrsh r0, [r0] 363; CHECK-THUMB: ldrsh.w r0, [r0] 364; CHECK-COMMON: ubfx r0, r0, #8, #16 365; CHECK-COMMON: str r0, [r1] 366define arm_aapcscc void @test_sext_shift8_mask16(i16* %p, i32* %q) { 367entry: 368 %0 = load i16, i16* %p, align 4 369 %1 = sext i16 %0 to i32 370 %shl = lshr i32 %1, 8 371 %and = and i32 %shl, 65535 372 store i32 %and, i32* %q, align 4 373 ret void 374} 375 376; CHECK-LABEL: trunc_i64_mask_srl 377; CHECK-ARM: ldrh r2, [r1, #4] 378; CHECK-BE: ldrh r2, [r1, #2] 379define i1 @trunc_i64_mask_srl(i32 zeroext %AttrArgNo, i64* %ptr) { 380entry: 381 %bf.load.i = load i64, i64* %ptr, align 8 382 %bf.lshr.i = lshr i64 %bf.load.i, 32 383 %0 = trunc i64 %bf.lshr.i to i32 384 %bf.cast.i = and i32 %0, 65535 385 %cmp.i = icmp ugt i32 %bf.cast.i, %AttrArgNo 386 ret i1 %cmp.i 387} 388