174 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; If we have a shift by sign-extended value, we can replace sign-extension5; with zero-extension.6 7define i32 @t0_shl(i32 %x, i8 %shamt) {8; CHECK-LABEL: @t0_shl(9; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext nneg i8 [[SHAMT:%.*]] to i3210; CHECK-NEXT: [[R:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE1]]11; CHECK-NEXT: ret i32 [[R]]12;13 %shamt_wide = sext i8 %shamt to i3214 %r = shl i32 %x, %shamt_wide15 ret i32 %r16}17define i32 @t1_lshr(i32 %x, i8 %shamt) {18; CHECK-LABEL: @t1_lshr(19; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext nneg i8 [[SHAMT:%.*]] to i3220; CHECK-NEXT: [[R:%.*]] = lshr i32 [[X:%.*]], [[SHAMT_WIDE1]]21; CHECK-NEXT: ret i32 [[R]]22;23 %shamt_wide = sext i8 %shamt to i3224 %r = lshr i32 %x, %shamt_wide25 ret i32 %r26}27define i32 @t2_ashr(i32 %x, i8 %shamt) {28; CHECK-LABEL: @t2_ashr(29; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext nneg i8 [[SHAMT:%.*]] to i3230; CHECK-NEXT: [[R:%.*]] = ashr i32 [[X:%.*]], [[SHAMT_WIDE1]]31; CHECK-NEXT: ret i32 [[R]]32;33 %shamt_wide = sext i8 %shamt to i3234 %r = ashr i32 %x, %shamt_wide35 ret i32 %r36}37 38define <2 x i32> @t3_vec_shl(<2 x i32> %x, <2 x i8> %shamt) {39; CHECK-LABEL: @t3_vec_shl(40; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext nneg <2 x i8> [[SHAMT:%.*]] to <2 x i32>41; CHECK-NEXT: [[R:%.*]] = shl <2 x i32> [[X:%.*]], [[SHAMT_WIDE1]]42; CHECK-NEXT: ret <2 x i32> [[R]]43;44 %shamt_wide = sext <2 x i8> %shamt to <2 x i32>45 %r = shl <2 x i32> %x, %shamt_wide46 ret <2 x i32> %r47}48define <2 x i32> @t4_vec_lshr(<2 x i32> %x, <2 x i8> %shamt) {49; CHECK-LABEL: @t4_vec_lshr(50; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext nneg <2 x i8> [[SHAMT:%.*]] to <2 x i32>51; CHECK-NEXT: [[R:%.*]] = lshr <2 x i32> [[X:%.*]], [[SHAMT_WIDE1]]52; CHECK-NEXT: ret <2 x i32> [[R]]53;54 %shamt_wide = sext <2 x i8> %shamt to <2 x i32>55 %r = lshr <2 x i32> %x, %shamt_wide56 ret <2 x i32> %r57}58define <2 x i32> @t5_vec_ashr(<2 x i32> %x, <2 x i8> %shamt) {59; CHECK-LABEL: @t5_vec_ashr(60; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext nneg <2 x i8> [[SHAMT:%.*]] to <2 x i32>61; CHECK-NEXT: [[R:%.*]] = ashr <2 x i32> [[X:%.*]], [[SHAMT_WIDE1]]62; CHECK-NEXT: ret <2 x i32> [[R]]63;64 %shamt_wide = sext <2 x i8> %shamt to <2 x i32>65 %r = ashr <2 x i32> %x, %shamt_wide66 ret <2 x i32> %r67}68 69define i32 @t6_twoshifts(i32 %x, i8 %shamt) {70; CHECK-LABEL: @t6_twoshifts(71; CHECK-NEXT: bb:72; CHECK-NEXT: br label [[WORK:%.*]]73; CHECK: work:74; CHECK-NEXT: br label [[END:%.*]]75; CHECK: end:76; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i3277; CHECK-NEXT: [[N0:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]78; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[N0]], [[SHAMT_WIDE]]79; CHECK-NEXT: ret i32 [[R]]80;81bb:82 %shamt_wide = sext i8 %shamt to i3283 br label %work84work:85 %n0 = shl i32 %x, %shamt_wide86 %r = ashr i32 %n0, %shamt_wide87 br label %end88end:89 ret i32 %r90}91 92; This is not valid for funnel shifts in general93declare i7 @llvm.fshl.i7(i7 %a, i7 %b, i7 %c)94declare i7 @llvm.fshr.i7(i7 %a, i7 %b, i7 %c)95define i7 @n7_fshl(i7 %x, i7 %y, i6 %shamt) {96; CHECK-LABEL: @n7_fshl(97; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i6 [[SHAMT:%.*]] to i798; CHECK-NEXT: [[R:%.*]] = call i7 @llvm.fshl.i7(i7 [[X:%.*]], i7 [[Y:%.*]], i7 [[SHAMT_WIDE]])99; CHECK-NEXT: ret i7 [[R]]100;101 %shamt_wide = sext i6 %shamt to i7102 %r = call i7 @llvm.fshl.i7(i7 %x, i7 %y, i7 %shamt_wide)103 ret i7 %r104}105define i7 @n8_fshr(i7 %x, i7 %y, i6 %shamt) {106; CHECK-LABEL: @n8_fshr(107; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i6 [[SHAMT:%.*]] to i7108; CHECK-NEXT: [[R:%.*]] = call i7 @llvm.fshr.i7(i7 [[X:%.*]], i7 [[Y:%.*]], i7 [[SHAMT_WIDE]])109; CHECK-NEXT: ret i7 [[R]]110;111 %shamt_wide = sext i6 %shamt to i7112 %r = call i7 @llvm.fshr.i7(i7 %x, i7 %y, i7 %shamt_wide)113 ret i7 %r114}115; And the cases that are safe are handled by SimplifyDemandedBits().116declare i8 @llvm.fshl.i8(i8 %a, i8 %b, i8 %c)117declare i8 @llvm.fshr.i8(i8 %a, i8 %b, i8 %c)118define i8 @t9_fshl(i8 %x, i8 %y, i6 %shamt) {119; CHECK-LABEL: @t9_fshl(120; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext i6 [[SHAMT:%.*]] to i8121; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SHAMT_WIDE1]])122; CHECK-NEXT: ret i8 [[R]]123;124 %shamt_wide = sext i6 %shamt to i8125 %r = call i8 @llvm.fshl.i8(i8 %x, i8 %y, i8 %shamt_wide)126 ret i8 %r127}128define i8 @t10_fshr(i8 %x, i8 %y, i6 %shamt) {129; CHECK-LABEL: @t10_fshr(130; CHECK-NEXT: [[SHAMT_WIDE1:%.*]] = zext i6 [[SHAMT:%.*]] to i8131; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[SHAMT_WIDE1]])132; CHECK-NEXT: ret i8 [[R]]133;134 %shamt_wide = sext i6 %shamt to i8135 %r = call i8 @llvm.fshr.i8(i8 %x, i8 %y, i8 %shamt_wide)136 ret i8 %r137}138 139declare void @use32(i32)140define i32 @n11_extrause(i32 %x, i8 %shamt) {141; CHECK-LABEL: @n11_extrause(142; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32143; CHECK-NEXT: call void @use32(i32 [[SHAMT_WIDE]])144; CHECK-NEXT: [[R:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]145; CHECK-NEXT: ret i32 [[R]]146;147 %shamt_wide = sext i8 %shamt to i32148 call void @use32(i32 %shamt_wide)149 %r = shl i32 %x, %shamt_wide150 ret i32 %r151}152define i32 @n12_twoshifts_and_extrause(i32 %x, i8 %shamt) {153; CHECK-LABEL: @n12_twoshifts_and_extrause(154; CHECK-NEXT: br label [[WORK:%.*]]155; CHECK: work:156; CHECK-NEXT: br label [[END:%.*]]157; CHECK: end:158; CHECK-NEXT: [[SHAMT_WIDE:%.*]] = sext i8 [[SHAMT:%.*]] to i32159; CHECK-NEXT: [[N0:%.*]] = shl i32 [[X:%.*]], [[SHAMT_WIDE]]160; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[N0]], [[SHAMT_WIDE]]161; CHECK-NEXT: call void @use32(i32 [[SHAMT_WIDE]])162; CHECK-NEXT: ret i32 [[R]]163;164 %shamt_wide = sext i8 %shamt to i32165 br label %work166work:167 %n0 = shl i32 %x, %shamt_wide168 %r = ashr i32 %n0, %shamt_wide169 br label %end170end:171 call void @use32(i32 %shamt_wide)172 ret i32 %r173}174