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; If we have a shift by sign-extended value, we can replace sign-extension 5; with zero-extension. 6 7define i32 @t0_shl(i32 %x, i8 %shamt) nounwind { 8; CHECK-LABEL: t0_shl: 9; CHECK: // %bb.0: 10; CHECK-NEXT: sxtb w8, w1 11; CHECK-NEXT: lsl w0, w0, w8 12; CHECK-NEXT: ret 13 %shamt_wide = sext i8 %shamt to i32 14 %r = shl i32 %x, %shamt_wide 15 ret i32 %r 16} 17define i32 @t1_lshr(i32 %x, i8 %shamt) nounwind { 18; CHECK-LABEL: t1_lshr: 19; CHECK: // %bb.0: 20; CHECK-NEXT: sxtb w8, w1 21; CHECK-NEXT: lsr w0, w0, w8 22; CHECK-NEXT: ret 23 %shamt_wide = sext i8 %shamt to i32 24 %r = lshr i32 %x, %shamt_wide 25 ret i32 %r 26} 27define i32 @t2_ashr(i32 %x, i8 %shamt) nounwind { 28; CHECK-LABEL: t2_ashr: 29; CHECK: // %bb.0: 30; CHECK-NEXT: sxtb w8, w1 31; CHECK-NEXT: asr w0, w0, w8 32; CHECK-NEXT: ret 33 %shamt_wide = sext i8 %shamt to i32 34 %r = ashr i32 %x, %shamt_wide 35 ret i32 %r 36} 37 38define <4 x i32> @t3_vec_shl(<4 x i32> %x, <4 x i8> %shamt) nounwind { 39; CHECK-LABEL: t3_vec_shl: 40; CHECK: // %bb.0: 41; CHECK-NEXT: ushll v1.4s, v1.4h, #0 42; CHECK-NEXT: shl v1.4s, v1.4s, #24 43; CHECK-NEXT: sshr v1.4s, v1.4s, #24 44; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s 45; CHECK-NEXT: ret 46 %shamt_wide = sext <4 x i8> %shamt to <4 x i32> 47 %r = shl <4 x i32> %x, %shamt_wide 48 ret <4 x i32> %r 49} 50define <4 x i32> @t4_vec_lshr(<4 x i32> %x, <4 x i8> %shamt) nounwind { 51; CHECK-LABEL: t4_vec_lshr: 52; CHECK: // %bb.0: 53; CHECK-NEXT: ushll v1.4s, v1.4h, #0 54; CHECK-NEXT: shl v1.4s, v1.4s, #24 55; CHECK-NEXT: sshr v1.4s, v1.4s, #24 56; CHECK-NEXT: neg v1.4s, v1.4s 57; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s 58; CHECK-NEXT: ret 59 %shamt_wide = sext <4 x i8> %shamt to <4 x i32> 60 %r = lshr <4 x i32> %x, %shamt_wide 61 ret <4 x i32> %r 62} 63define <4 x i32> @t5_vec_ashr(<4 x i32> %x, <4 x i8> %shamt) nounwind { 64; CHECK-LABEL: t5_vec_ashr: 65; CHECK: // %bb.0: 66; CHECK-NEXT: ushll v1.4s, v1.4h, #0 67; CHECK-NEXT: shl v1.4s, v1.4s, #24 68; CHECK-NEXT: sshr v1.4s, v1.4s, #24 69; CHECK-NEXT: neg v1.4s, v1.4s 70; CHECK-NEXT: sshl v0.4s, v0.4s, v1.4s 71; CHECK-NEXT: ret 72 %shamt_wide = sext <4 x i8> %shamt to <4 x i32> 73 %r = ashr <4 x i32> %x, %shamt_wide 74 ret <4 x i32> %r 75} 76 77; This is not valid for funnel shifts 78declare i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c) 79declare i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c) 80define i32 @n6_fshl(i32 %x, i32 %y, i8 %shamt) nounwind { 81; CHECK-LABEL: n6_fshl: 82; CHECK: // %bb.0: 83; CHECK-NEXT: lsr w8, w1, #1 84; CHECK-NEXT: // kill: def $w2 killed $w2 def $x2 85; CHECK-NEXT: mvn w9, w2 86; CHECK-NEXT: lsl w10, w0, w2 87; CHECK-NEXT: lsr w8, w8, w9 88; CHECK-NEXT: orr w0, w10, w8 89; CHECK-NEXT: ret 90 %shamt_wide = sext i8 %shamt to i32 91 %r = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %shamt_wide) 92 ret i32 %r 93} 94define i32 @n7_fshr(i32 %x, i32 %y, i8 %shamt) nounwind { 95; CHECK-LABEL: n7_fshr: 96; CHECK: // %bb.0: 97; CHECK-NEXT: lsl w8, w0, #1 98; CHECK-NEXT: // kill: def $w2 killed $w2 def $x2 99; CHECK-NEXT: mvn w9, w2 100; CHECK-NEXT: lsr w10, w1, w2 101; CHECK-NEXT: lsl w8, w8, w9 102; CHECK-NEXT: orr w0, w8, w10 103; CHECK-NEXT: ret 104 %shamt_wide = sext i8 %shamt to i32 105 %r = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %shamt_wide) 106 ret i32 %r 107} 108 109define i32 @n8_extrause(i32 %x, i8 %shamt, ptr %shamt_wide_store) nounwind { 110; CHECK-LABEL: n8_extrause: 111; CHECK: // %bb.0: 112; CHECK-NEXT: sxtb w8, w1 113; CHECK-NEXT: lsl w0, w0, w8 114; CHECK-NEXT: str w8, [x2] 115; CHECK-NEXT: ret 116 %shamt_wide = sext i8 %shamt to i32 117 store i32 %shamt_wide, ptr %shamt_wide_store, align 4 118 %r = shl i32 %x, %shamt_wide 119 ret i32 %r 120} 121