270 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Iff trunc only chops off zero bits that were just shifted-in by the lshr,5; but no other bits, then we can instead do signed shift, and signext it.6; Note that we can replace trunc with trunc of new signed shift.7 8declare void @use32(i32)9declare void @use8(i8)10declare void @use4(i4)11declare void @usevec8(<2 x i8>)12declare void @usevec4(<2 x i4>)13 14define i16 @t0(i8 %x) {15; CHECK-LABEL: @t0(16; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 417; CHECK-NEXT: [[C:%.*]] = sext i8 [[TMP1]] to i1618; CHECK-NEXT: ret i16 [[C]]19;20 %a = lshr i8 %x, 421 %b = trunc i8 %a to i422 %c = sext i4 %b to i1623 ret i16 %c24}25 26define i16 @t1(i8 %x) {27; CHECK-LABEL: @t1(28; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X:%.*]], 529; CHECK-NEXT: [[C:%.*]] = sext i8 [[TMP1]] to i1630; CHECK-NEXT: ret i16 [[C]]31;32 %a = lshr i8 %x, 533 %b = trunc i8 %a to i334 %c = sext i3 %b to i1635 ret i16 %c36}37 38define i16 @t2(i7 %x) {39; CHECK-LABEL: @t2(40; CHECK-NEXT: [[TMP1:%.*]] = ashr i7 [[X:%.*]], 341; CHECK-NEXT: [[C:%.*]] = sext i7 [[TMP1]] to i1642; CHECK-NEXT: ret i16 [[C]]43;44 %a = lshr i7 %x, 345 %b = trunc i7 %a to i446 %c = sext i4 %b to i1647 ret i16 %c48}49 50; negative test - shift amount doesn't match trunc amount51 52define i16 @n3(i8 %x) {53; CHECK-LABEL: @n3(54; CHECK-NEXT: [[A:%.*]] = lshr i8 [[X:%.*]], 355; CHECK-NEXT: [[B:%.*]] = trunc i8 [[A]] to i456; CHECK-NEXT: [[C:%.*]] = sext i4 [[B]] to i1657; CHECK-NEXT: ret i16 [[C]]58;59 %a = lshr i8 %x, 360 %b = trunc i8 %a to i461 %c = sext i4 %b to i1662 ret i16 %c63}64 65define <2 x i16> @t4_vec_splat(<2 x i8> %x) {66; CHECK-LABEL: @t4_vec_splat(67; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i8> [[X:%.*]], splat (i8 4)68; CHECK-NEXT: [[C:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16>69; CHECK-NEXT: ret <2 x i16> [[C]]70;71 %a = lshr <2 x i8> %x, <i8 4, i8 4>72 %b = trunc <2 x i8> %a to <2 x i4>73 %c = sext <2 x i4> %b to <2 x i16>74 ret <2 x i16> %c75}76 77define <2 x i16> @t5_vec_poison(<2 x i8> %x) {78; CHECK-LABEL: @t5_vec_poison(79; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i8> [[X:%.*]], splat (i8 4)80; CHECK-NEXT: [[C:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16>81; CHECK-NEXT: ret <2 x i16> [[C]]82;83 %a = lshr <2 x i8> %x, <i8 4, i8 poison>84 %b = trunc <2 x i8> %a to <2 x i4>85 %c = sext <2 x i4> %b to <2 x i16>86 ret <2 x i16> %c87}88 89; TODO: We could convert %a to ashr and eliminate 2nd use of %b.90 91define i16 @t6_extrause0(i8 %x) {92; CHECK-LABEL: @t6_extrause0(93; CHECK-NEXT: [[A:%.*]] = lshr i8 [[X:%.*]], 494; CHECK-NEXT: [[B:%.*]] = trunc nuw i8 [[A]] to i495; CHECK-NEXT: call void @use4(i4 [[B]])96; CHECK-NEXT: [[C:%.*]] = sext i4 [[B]] to i1697; CHECK-NEXT: ret i16 [[C]]98;99 %a = lshr i8 %x, 4100 %b = trunc i8 %a to i4 ; has extra use, but we can deal with that101 call void @use4(i4 %b)102 %c = sext i4 %b to i16103 ret i16 %c104}105 106; TODO: We could convert %a to ashr and eliminate 2nd use of %b.107 108define <2 x i16> @t7_extrause0_vec_poison(<2 x i8> %x) {109; CHECK-LABEL: @t7_extrause0_vec_poison(110; CHECK-NEXT: [[A:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 poison>111; CHECK-NEXT: [[B:%.*]] = trunc nuw <2 x i8> [[A]] to <2 x i4>112; CHECK-NEXT: call void @usevec4(<2 x i4> [[B]])113; CHECK-NEXT: [[C:%.*]] = sext <2 x i4> [[B]] to <2 x i16>114; CHECK-NEXT: ret <2 x i16> [[C]]115;116 %a = lshr <2 x i8> %x, <i8 4, i8 poison>117 %b = trunc <2 x i8> %a to <2 x i4>118 call void @usevec4(<2 x i4> %b)119 %c = sext <2 x i4> %b to <2 x i16>120 ret <2 x i16> %c121}122 123; TODO: We could convert %a to ashr + mask (and) and eliminate %b.124 125define i16 @t8_extrause1(i8 %x) {126; CHECK-LABEL: @t8_extrause1(127; CHECK-NEXT: [[A:%.*]] = lshr i8 [[X:%.*]], 4128; CHECK-NEXT: call void @use8(i8 [[A]])129; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 [[X]], 4130; CHECK-NEXT: [[C:%.*]] = sext i8 [[TMP1]] to i16131; CHECK-NEXT: ret i16 [[C]]132;133 %a = lshr i8 %x, 4 ; has extra use, but we can deal with that134 call void @use8(i8 %a)135 %b = trunc i8 %a to i4136 %c = sext i4 %b to i16137 ret i16 %c138}139 140; TODO: We could convert %a to ashr + mask (and) and eliminate %b.141 142define <2 x i16> @t9_extrause1_vec_poison(<2 x i8> %x) {143; CHECK-LABEL: @t9_extrause1_vec_poison(144; CHECK-NEXT: [[A:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 poison>145; CHECK-NEXT: call void @usevec8(<2 x i8> [[A]])146; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i8> [[X]], splat (i8 4)147; CHECK-NEXT: [[C:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16>148; CHECK-NEXT: ret <2 x i16> [[C]]149;150 %a = lshr <2 x i8> %x, <i8 4, i8 poison>151 call void @usevec8(<2 x i8> %a)152 %b = trunc <2 x i8> %a to <2 x i4>153 %c = sext <2 x i4> %b to <2 x i16>154 ret <2 x i16> %c155}156define i16 @t10_extrause2(i8 %x) {157; CHECK-LABEL: @t10_extrause2(158; CHECK-NEXT: [[A:%.*]] = lshr i8 [[X:%.*]], 4159; CHECK-NEXT: call void @use8(i8 [[A]])160; CHECK-NEXT: [[B:%.*]] = trunc nuw i8 [[A]] to i4161; CHECK-NEXT: call void @use4(i4 [[B]])162; CHECK-NEXT: [[C:%.*]] = sext i4 [[B]] to i16163; CHECK-NEXT: ret i16 [[C]]164;165 %a = lshr i8 %x, 4 ; has extra use166 call void @use8(i8 %a)167 %b = trunc i8 %a to i4 ; has extra use168 call void @use4(i4 %b)169 %c = sext i4 %b to i16170 ret i16 %c171}172define <2 x i16> @t11_extrause2_vec_poison(<2 x i8> %x) {173; CHECK-LABEL: @t11_extrause2_vec_poison(174; CHECK-NEXT: [[A:%.*]] = lshr <2 x i8> [[X:%.*]], <i8 4, i8 poison>175; CHECK-NEXT: call void @usevec8(<2 x i8> [[A]])176; CHECK-NEXT: [[B:%.*]] = trunc nuw <2 x i8> [[A]] to <2 x i4>177; CHECK-NEXT: call void @usevec4(<2 x i4> [[B]])178; CHECK-NEXT: [[C:%.*]] = sext <2 x i4> [[B]] to <2 x i16>179; CHECK-NEXT: ret <2 x i16> [[C]]180;181 %a = lshr <2 x i8> %x, <i8 4, i8 poison>182 call void @usevec8(<2 x i8> %a)183 %b = trunc <2 x i8> %a to <2 x i4>184 call void @usevec4(<2 x i4> %b)185 %c = sext <2 x i4> %b to <2 x i16>186 ret <2 x i16> %c187}188 189define <2 x i10> @wide_source_shifted_signbit(<2 x i32> %x) {190; CHECK-LABEL: @wide_source_shifted_signbit(191; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> [[X:%.*]], splat (i32 24)192; CHECK-NEXT: [[C:%.*]] = trunc nsw <2 x i32> [[TMP1]] to <2 x i10>193; CHECK-NEXT: ret <2 x i10> [[C]]194;195 %a = lshr <2 x i32> %x, <i32 24, i32 24>196 %b = trunc <2 x i32> %a to <2 x i8>197 %c = sext <2 x i8> %b to <2 x i10>198 ret <2 x i10> %c199}200 201define i10 @wide_source_shifted_signbit_use1(i32 %x) {202; CHECK-LABEL: @wide_source_shifted_signbit_use1(203; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], 24204; CHECK-NEXT: call void @use32(i32 [[A]])205; CHECK-NEXT: [[TMP1:%.*]] = ashr i32 [[X]], 24206; CHECK-NEXT: [[C:%.*]] = trunc nsw i32 [[TMP1]] to i10207; CHECK-NEXT: ret i10 [[C]]208;209 %a = lshr i32 %x, 24210 call void @use32(i32 %a)211 %b = trunc i32 %a to i8212 %c = sext i8 %b to i10213 ret i10 %c214}215 216define i10 @wide_source_shifted_signbit_use2(i32 %x) {217; CHECK-LABEL: @wide_source_shifted_signbit_use2(218; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], 24219; CHECK-NEXT: [[B:%.*]] = trunc nuw i32 [[A]] to i8220; CHECK-NEXT: call void @use8(i8 [[B]])221; CHECK-NEXT: [[C:%.*]] = sext i8 [[B]] to i10222; CHECK-NEXT: ret i10 [[C]]223;224 %a = lshr i32 %x, 24225 %b = trunc i32 %a to i8226 call void @use8(i8 %b)227 %c = sext i8 %b to i10228 ret i10 %c229}230 231define i32 @same_source_shifted_signbit(i32 %x) {232; CHECK-LABEL: @same_source_shifted_signbit(233; CHECK-NEXT: [[C:%.*]] = ashr i32 [[X:%.*]], 24234; CHECK-NEXT: ret i32 [[C]]235;236 %a = lshr i32 %x, 24237 %b = trunc i32 %a to i8238 %c = sext i8 %b to i32239 ret i32 %c240}241 242define i32 @same_source_shifted_signbit_use1(i32 %x) {243; CHECK-LABEL: @same_source_shifted_signbit_use1(244; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], 24245; CHECK-NEXT: call void @use32(i32 [[A]])246; CHECK-NEXT: [[C:%.*]] = ashr i32 [[X]], 24247; CHECK-NEXT: ret i32 [[C]]248;249 %a = lshr i32 %x, 24250 call void @use32(i32 %a)251 %b = trunc i32 %a to i8252 %c = sext i8 %b to i32253 ret i32 %c254}255 256define i32 @same_source_shifted_signbit_use2(i32 %x) {257; CHECK-LABEL: @same_source_shifted_signbit_use2(258; CHECK-NEXT: [[A:%.*]] = lshr i32 [[X:%.*]], 24259; CHECK-NEXT: [[B:%.*]] = trunc nuw i32 [[A]] to i8260; CHECK-NEXT: call void @use8(i8 [[B]])261; CHECK-NEXT: [[C:%.*]] = sext i8 [[B]] to i32262; CHECK-NEXT: ret i32 [[C]]263;264 %a = lshr i32 %x, 24265 %b = trunc i32 %a to i8266 call void @use8(i8 %b)267 %c = sext i8 %b to i32268 ret i32 %c269}270