; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc --verify-machineinstrs -mtriple=thumbv8.1m.main-none-eabi -mattr=+mve %s -o - | FileCheck %s -check-prefix=CHECK --check-prefix=CHECK-MVE ; RUN: llc --verify-machineinstrs -mtriple=thumbv8.1m.main-none-eabi %s -o - | FileCheck %s -check-prefix=CHECK --check-prefix=CHECK-NON-MVE define i64 @shift_left_reg(i64 %x, i64 %y) { ; CHECK-MVE-LABEL: shift_left_reg: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsll r0, r1, r2 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: shift_left_reg: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: rsb.w r3, r2, #32 ; CHECK-NON-MVE-NEXT: lsls r1, r2 ; CHECK-NON-MVE-NEXT: lsr.w r3, r0, r3 ; CHECK-NON-MVE-NEXT: orrs r1, r3 ; CHECK-NON-MVE-NEXT: subs.w r3, r2, #32 ; CHECK-NON-MVE-NEXT: it pl ; CHECK-NON-MVE-NEXT: lslpl.w r1, r0, r3 ; CHECK-NON-MVE-NEXT: lsl.w r0, r0, r2 ; CHECK-NON-MVE-NEXT: it pl ; CHECK-NON-MVE-NEXT: movpl r0, #0 ; CHECK-NON-MVE-NEXT: bx lr entry: %shl = shl i64 %x, %y ret i64 %shl } define i64 @shift_left_imm(i64 %x) { ; CHECK-MVE-LABEL: shift_left_imm: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsll r0, r1, #3 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: shift_left_imm: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsls r1, r1, #3 ; CHECK-NON-MVE-NEXT: orr.w r1, r1, r0, lsr #29 ; CHECK-NON-MVE-NEXT: lsls r0, r0, #3 ; CHECK-NON-MVE-NEXT: bx lr entry: %shl = shl i64 %x, 3 ret i64 %shl } define i64 @shift_left_imm_big(i64 %x) { ; CHECK-LABEL: shift_left_imm_big: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r1, r0, #16 ; CHECK-NEXT: movs r0, #0 ; CHECK-NEXT: bx lr entry: %shl = shl i64 %x, 48 ret i64 %shl } define i64 @shift_left_imm_big2(i64 %x) { ; CHECK-LABEL: shift_left_imm_big2: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: mov r1, r0 ; CHECK-NEXT: movs r0, #0 ; CHECK-NEXT: bx lr entry: %shl = shl i64 %x, 32 ret i64 %shl } define i64 @shift_left_imm_big3(i64 %x) { ; CHECK-LABEL: shift_left_imm_big3: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r1, r0, #1 ; CHECK-NEXT: movs r0, #0 ; CHECK-NEXT: bx lr entry: %shl = shl i64 %x, 33 ret i64 %shl } define i64 @shift_right_reg(i64 %x, i64 %y) { ; CHECK-MVE-LABEL: shift_right_reg: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: rsbs r2, r2, #0 ; CHECK-MVE-NEXT: lsll r0, r1, r2 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: shift_right_reg: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: rsb.w r3, r2, #32 ; CHECK-NON-MVE-NEXT: lsrs r0, r2 ; CHECK-NON-MVE-NEXT: lsl.w r3, r1, r3 ; CHECK-NON-MVE-NEXT: orrs r0, r3 ; CHECK-NON-MVE-NEXT: subs.w r3, r2, #32 ; CHECK-NON-MVE-NEXT: it pl ; CHECK-NON-MVE-NEXT: lsrpl.w r0, r1, r3 ; CHECK-NON-MVE-NEXT: lsr.w r1, r1, r2 ; CHECK-NON-MVE-NEXT: it pl ; CHECK-NON-MVE-NEXT: movpl r1, #0 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = lshr i64 %x, %y ret i64 %shr } define i64 @shift_right_imm(i64 %x) { ; CHECK-MVE-LABEL: shift_right_imm: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsrl r0, r1, #3 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: shift_right_imm: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsrs r0, r0, #3 ; CHECK-NON-MVE-NEXT: orr.w r0, r0, r1, lsl #29 ; CHECK-NON-MVE-NEXT: lsrs r1, r1, #3 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = lshr i64 %x, 3 ret i64 %shr } define i64 @shift_right_imm_big(i64 %x) { ; CHECK-LABEL: shift_right_imm_big: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsrs r0, r1, #16 ; CHECK-NEXT: movs r1, #0 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 48 ret i64 %shr } define i64 @shift_right_imm_big2(i64 %x) { ; CHECK-LABEL: shift_right_imm_big2: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: mov r0, r1 ; CHECK-NEXT: movs r1, #0 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 32 ret i64 %shr } define i64 @shift_right_imm_big3(i64 %x) { ; CHECK-LABEL: shift_right_imm_big3: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsrs r0, r1, #1 ; CHECK-NEXT: movs r1, #0 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 33 ret i64 %shr } define i64 @shift_arithmetic_right_reg(i64 %x, i64 %y) { ; CHECK-MVE-LABEL: shift_arithmetic_right_reg: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: asrl r0, r1, r2 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: shift_arithmetic_right_reg: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: rsb.w r3, r2, #32 ; CHECK-NON-MVE-NEXT: lsrs r0, r2 ; CHECK-NON-MVE-NEXT: lsl.w r3, r1, r3 ; CHECK-NON-MVE-NEXT: orrs r0, r3 ; CHECK-NON-MVE-NEXT: subs.w r3, r2, #32 ; CHECK-NON-MVE-NEXT: asr.w r2, r1, r2 ; CHECK-NON-MVE-NEXT: it pl ; CHECK-NON-MVE-NEXT: asrpl.w r0, r1, r3 ; CHECK-NON-MVE-NEXT: it pl ; CHECK-NON-MVE-NEXT: asrpl r2, r1, #31 ; CHECK-NON-MVE-NEXT: mov r1, r2 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = ashr i64 %x, %y ret i64 %shr } define i64 @shift_arithmetic_right_imm(i64 %x) { ; CHECK-MVE-LABEL: shift_arithmetic_right_imm: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: asrl r0, r1, #3 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: shift_arithmetic_right_imm: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsrs r0, r0, #3 ; CHECK-NON-MVE-NEXT: orr.w r0, r0, r1, lsl #29 ; CHECK-NON-MVE-NEXT: asrs r1, r1, #3 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = ashr i64 %x, 3 ret i64 %shr } %struct.bar = type { i16, i8, [5 x i8] } define arm_aapcs_vfpcc void @fn1(%struct.bar* nocapture %a) { ; CHECK-MVE-LABEL: fn1: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: ldr r2, [r0, #4] ; CHECK-MVE-NEXT: movs r1, #0 ; CHECK-MVE-NEXT: lsll r2, r1, #8 ; CHECK-MVE-NEXT: strb r1, [r0, #7] ; CHECK-MVE-NEXT: str.w r2, [r0, #3] ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: fn1: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: ldr r1, [r0, #4] ; CHECK-NON-MVE-NEXT: lsrs r2, r1, #24 ; CHECK-NON-MVE-NEXT: lsls r1, r1, #8 ; CHECK-NON-MVE-NEXT: strb r2, [r0, #7] ; CHECK-NON-MVE-NEXT: str.w r1, [r0, #3] ; CHECK-NON-MVE-NEXT: bx lr entry: %carey = getelementptr inbounds %struct.bar, %struct.bar* %a, i32 0, i32 2 %0 = bitcast [5 x i8]* %carey to i40* %bf.load = load i40, i40* %0, align 1 %bf.clear = and i40 %bf.load, -256 store i40 %bf.clear, i40* %0, align 1 ret void } %struct.a = type { i96 } define void @lsll_128bit_shift(%struct.a* nocapture %x) local_unnamed_addr #0 { ; CHECK-LABEL: lsll_128bit_shift: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: movs r1, #0 ; CHECK-NEXT: strd r1, r1, [r0] ; CHECK-NEXT: str r1, [r0, #8] ; CHECK-NEXT: bx lr entry: %0 = bitcast %struct.a* %x to i128* %bf.load = load i128, i128* %0, align 8 %bf.clear4 = and i128 %bf.load, -79228162514264337593543950336 store i128 %bf.clear4, i128* %0, align 8 ret void } %struct.b = type { i184 } define void @lsll_256bit_shift(%struct.b* nocapture %x) local_unnamed_addr #0 { ; CHECK-LABEL: lsll_256bit_shift: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: movs r1, #0 ; CHECK-NEXT: str r1, [r0, #16] ; CHECK-NEXT: strd r1, r1, [r0, #8] ; CHECK-NEXT: strd r1, r1, [r0] ; CHECK-NEXT: ldrb r1, [r0, #23] ; CHECK-NEXT: lsls r1, r1, #24 ; CHECK-NEXT: str r1, [r0, #20] ; CHECK-NEXT: bx lr entry: %0 = bitcast %struct.b* %x to i192* %bf.load = load i192, i192* %0, align 8 %bf.clear4 = and i192 %bf.load, -24519928653854221733733552434404946937899825954937634816 store i192 %bf.clear4, i192* %0, align 8 ret void } define i32 @ashr_demand_bottom3(i64 %x) { ; CHECK-MVE-LABEL: ashr_demand_bottom3: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsrl r0, r1, #3 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: ashr_demand_bottom3: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsrs r0, r0, #3 ; CHECK-NON-MVE-NEXT: orr.w r0, r0, r1, lsl #29 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = ashr i64 %x, 3 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lshr_demand_bottom3(i64 %x) { ; CHECK-MVE-LABEL: lshr_demand_bottom3: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsrl r0, r1, #3 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: lshr_demand_bottom3: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsrs r0, r0, #3 ; CHECK-NON-MVE-NEXT: orr.w r0, r0, r1, lsl #29 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = lshr i64 %x, 3 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lsl_demand_bottom3(i64 %x) { ; CHECK-LABEL: lsl_demand_bottom3: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r0, r0, #3 ; CHECK-NEXT: bx lr entry: %shr = shl i64 %x, 3 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @ashr_demand_bottom31(i64 %x) { ; CHECK-MVE-LABEL: ashr_demand_bottom31: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsrl r0, r1, #31 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: ashr_demand_bottom31: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsrs r0, r0, #31 ; CHECK-NON-MVE-NEXT: orr.w r0, r0, r1, lsl #1 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = ashr i64 %x, 31 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lshr_demand_bottom31(i64 %x) { ; CHECK-MVE-LABEL: lshr_demand_bottom31: ; CHECK-MVE: @ %bb.0: @ %entry ; CHECK-MVE-NEXT: lsrl r0, r1, #31 ; CHECK-MVE-NEXT: bx lr ; ; CHECK-NON-MVE-LABEL: lshr_demand_bottom31: ; CHECK-NON-MVE: @ %bb.0: @ %entry ; CHECK-NON-MVE-NEXT: lsrs r0, r0, #31 ; CHECK-NON-MVE-NEXT: orr.w r0, r0, r1, lsl #1 ; CHECK-NON-MVE-NEXT: bx lr entry: %shr = lshr i64 %x, 31 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lsl_demand_bottom31(i64 %x) { ; CHECK-LABEL: lsl_demand_bottom31: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r0, r0, #31 ; CHECK-NEXT: bx lr entry: %shr = shl i64 %x, 31 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @ashr_demand_bottom32(i64 %x) { ; CHECK-LABEL: ashr_demand_bottom32: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: mov r0, r1 ; CHECK-NEXT: bx lr entry: %shr = ashr i64 %x, 32 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lshr_demand_bottom32(i64 %x) { ; CHECK-LABEL: lshr_demand_bottom32: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: mov r0, r1 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 32 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lsl_demand_bottom32(i64 %x) { ; CHECK-LABEL: lsl_demand_bottom32: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: movs r0, #0 ; CHECK-NEXT: bx lr entry: %shr = shl i64 %x, 32 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @ashr_demand_bottom44(i64 %x) { ; CHECK-LABEL: ashr_demand_bottom44: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: asrs r0, r1, #12 ; CHECK-NEXT: bx lr entry: %shr = ashr i64 %x, 44 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lshr_demand_bottom44(i64 %x) { ; CHECK-LABEL: lshr_demand_bottom44: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsrs r0, r1, #12 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 44 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @lsl_demand_bottom44(i64 %x) { ; CHECK-LABEL: lsl_demand_bottom44: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: movs r0, #0 ; CHECK-NEXT: bx lr entry: %shr = shl i64 %x, 44 %t = trunc i64 %shr to i32 ret i32 %t } define i32 @ashr_demand_bottommask(i64 %x) { ; CHECK-LABEL: ashr_demand_bottommask: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r0, r1, #1 ; CHECK-NEXT: bx lr entry: %shr = ashr i64 %x, 31 %t = trunc i64 %shr to i32 %a = and i32 %t, -2 ret i32 %a } define i32 @lshr_demand_bottommask(i64 %x) { ; CHECK-LABEL: lshr_demand_bottommask: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r0, r1, #1 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 31 %t = trunc i64 %shr to i32 %a = and i32 %t, -2 ret i32 %a } define i32 @lsl_demand_bottommask(i64 %x) { ; CHECK-LABEL: lsl_demand_bottommask: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r0, r0, #31 ; CHECK-NEXT: bx lr entry: %shr = shl i64 %x, 31 %t = trunc i64 %shr to i32 %a = and i32 %t, -2 ret i32 %a } define i32 @ashr_demand_bottommask2(i64 %x) { ; CHECK-LABEL: ashr_demand_bottommask2: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: mvn r0, #2 ; CHECK-NEXT: and.w r0, r0, r1, lsl #1 ; CHECK-NEXT: bx lr entry: %shr = ashr i64 %x, 31 %t = trunc i64 %shr to i32 %a = and i32 %t, -4 ret i32 %a } define i32 @lshr_demand_bottommask2(i64 %x) { ; CHECK-LABEL: lshr_demand_bottommask2: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: mvn r0, #2 ; CHECK-NEXT: and.w r0, r0, r1, lsl #1 ; CHECK-NEXT: bx lr entry: %shr = lshr i64 %x, 31 %t = trunc i64 %shr to i32 %a = and i32 %t, -4 ret i32 %a } define i32 @lsl_demand_bottommask2(i64 %x) { ; CHECK-LABEL: lsl_demand_bottommask2: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: lsls r0, r0, #31 ; CHECK-NEXT: bx lr entry: %shr = shl i64 %x, 31 %t = trunc i64 %shr to i32 %a = and i32 %t, -4 ret i32 %a } define i32 @lsl_demand_topmask(i64 %x) { ; CHECK-LABEL: lsl_demand_topmask: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: ubfx r0, r0, #1, #28 ; CHECK-NEXT: bx lr entry: %sh = shl i64 %x, 31 %a = and i64 %sh, 1152921500311879680 ;0x0fffffff00000000 %l = ashr i64 %a, 32 %t = trunc i64 %l to i32 ret i32 %t }