170 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; PR51305: prefer `-(x & 1)` over `(x << (bitwidth(x)-1)) a>> (bitwidth(x)-1)`5; as the pattern to splat the lowest bit.6 7declare void @use8(i8)8 9; Basic positive scalar tests10define i8 @t0(i8 %x) {11; CHECK-LABEL: @t0(12; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], 113; CHECK-NEXT: [[R:%.*]] = sub nsw i8 0, [[TMP1]]14; CHECK-NEXT: ret i8 [[R]]15;16 %i0 = shl i8 %x, 717 %r = ashr i8 %i0, 718 ret i8 %r19}20define i16 @t1_otherbitwidth(i16 %x) {21; CHECK-LABEL: @t1_otherbitwidth(22; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], 123; CHECK-NEXT: [[R:%.*]] = sub nsw i16 0, [[TMP1]]24; CHECK-NEXT: ret i16 [[R]]25;26 %i0 = shl i16 %x, 1527 %r = ashr i16 %i0, 1528 ret i16 %r29}30 31; Basic positive vector tests32define <2 x i8> @t2_vec(<2 x i8> %x) {33; CHECK-LABEL: @t2_vec(34; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], splat (i8 1)35; CHECK-NEXT: [[R:%.*]] = sub nsw <2 x i8> zeroinitializer, [[TMP1]]36; CHECK-NEXT: ret <2 x i8> [[R]]37;38 %i0 = shl <2 x i8> %x, <i8 7, i8 7>39 %r = ashr <2 x i8> %i0, <i8 7, i8 7>40 ret <2 x i8> %r41}42 43; TODO: The result constants should contain poison instead of undef.44 45define <3 x i8> @t3_vec_poison0(<3 x i8> %x) {46; CHECK-LABEL: @t3_vec_poison0(47; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i8> [[X:%.*]], <i8 1, i8 undef, i8 1>48; CHECK-NEXT: [[R:%.*]] = sub <3 x i8> zeroinitializer, [[TMP1]]49; CHECK-NEXT: ret <3 x i8> [[R]]50;51 %i0 = shl <3 x i8> %x, <i8 7, i8 poison, i8 7>52 %r = ashr <3 x i8> %i0, <i8 7, i8 7, i8 7>53 ret <3 x i8> %r54}55define <3 x i8> @t4_vec_poison1(<3 x i8> %x) {56; CHECK-LABEL: @t4_vec_poison1(57; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i8> [[X:%.*]], <i8 1, i8 undef, i8 1>58; CHECK-NEXT: [[R:%.*]] = sub <3 x i8> zeroinitializer, [[TMP1]]59; CHECK-NEXT: ret <3 x i8> [[R]]60;61 %i0 = shl <3 x i8> %x, <i8 7, i8 7, i8 7>62 %r = ashr <3 x i8> %i0, <i8 7, i8 poison, i8 7>63 ret <3 x i8> %r64}65define <3 x i8> @t5_vec_poison2(<3 x i8> %x) {66; CHECK-LABEL: @t5_vec_poison2(67; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i8> [[X:%.*]], <i8 1, i8 undef, i8 1>68; CHECK-NEXT: [[R:%.*]] = sub <3 x i8> zeroinitializer, [[TMP1]]69; CHECK-NEXT: ret <3 x i8> [[R]]70;71 %i0 = shl <3 x i8> %x, <i8 7, i8 poison, i8 7>72 %r = ashr <3 x i8> %i0, <i8 7, i8 poison, i8 7>73 ret <3 x i8> %r74}75 76; In general, the `shl` needs to go away.77define i8 @n6_extrause(i8 %x) {78; CHECK-LABEL: @n6_extrause(79; CHECK-NEXT: [[I0:%.*]] = shl i8 [[X:%.*]], 780; CHECK-NEXT: call void @use8(i8 [[I0]])81; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[I0]], 782; CHECK-NEXT: ret i8 [[R]]83;84 %i0 = shl i8 %x, 785 call void @use8(i8 %i0)86 %r = ashr i8 %i0, 787 ret i8 %r88}89 90; But, if the input to the shift is already masked, then we're fine.91define i8 @t7_already_masked(i8 %x) {92; CHECK-LABEL: @t7_already_masked(93; CHECK-NEXT: [[I0:%.*]] = and i8 [[X:%.*]], 194; CHECK-NEXT: call void @use8(i8 [[I0]])95; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], 196; CHECK-NEXT: [[R:%.*]] = sub nsw i8 0, [[TMP1]]97; CHECK-NEXT: ret i8 [[R]]98;99 %i0 = and i8 %x, 1100 call void @use8(i8 %i0)101 %i1 = shl i8 %i0, 7102 %r = ashr i8 %i1, 7103 ret i8 %r104}105; FIXME: we should fold this106define i8 @t8_already_masked_extrause(i8 %x) {107; CHECK-LABEL: @t8_already_masked_extrause(108; CHECK-NEXT: [[I0:%.*]] = and i8 [[X:%.*]], 1109; CHECK-NEXT: call void @use8(i8 [[I0]])110; CHECK-NEXT: [[I1:%.*]] = shl i8 [[X]], 7111; CHECK-NEXT: call void @use8(i8 [[I1]])112; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[I1]], 7113; CHECK-NEXT: ret i8 [[R]]114;115 %i0 = and i8 %x, 1116 call void @use8(i8 %i0)117 %i1 = shl i8 %i0, 7118 call void @use8(i8 %i1)119 %r = ashr i8 %i1, 7120 ret i8 %r121}122define i8 @n9_wrongly_masked_extrause(i8 %x) {123; CHECK-LABEL: @n9_wrongly_masked_extrause(124; CHECK-NEXT: [[I0:%.*]] = and i8 [[X:%.*]], 3125; CHECK-NEXT: call void @use8(i8 [[I0]])126; CHECK-NEXT: [[I1:%.*]] = shl i8 [[X]], 7127; CHECK-NEXT: call void @use8(i8 [[I1]])128; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[I1]], 7129; CHECK-NEXT: ret i8 [[R]]130;131 %i0 = and i8 %x, 3132 call void @use8(i8 %i0)133 %i1 = shl i8 %i0, 7134 call void @use8(i8 %i1)135 %r = ashr i8 %i1, 7136 ret i8 %r137}138 139; Wrong shift amounts140define i8 @n10(i8 %x) {141; CHECK-LABEL: @n10(142; CHECK-NEXT: [[I0:%.*]] = shl i8 [[X:%.*]], 6143; CHECK-NEXT: [[R:%.*]] = ashr i8 [[I0]], 7144; CHECK-NEXT: ret i8 [[R]]145;146 %i0 = shl i8 %x, 6 ; not 7147 %r = ashr i8 %i0, 7148 ret i8 %r149}150define i8 @n11(i8 %x) {151; CHECK-LABEL: @n11(152; CHECK-NEXT: [[I0:%.*]] = shl i8 [[X:%.*]], 7153; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[I0]], 6154; CHECK-NEXT: ret i8 [[R]]155;156 %i0 = shl i8 %x, 7157 %r = ashr i8 %i0, 6 ; not 7158 ret i8 %r159}160define i8 @n12(i8 %x) {161; CHECK-LABEL: @n12(162; CHECK-NEXT: [[I0:%.*]] = shl i8 [[X:%.*]], 6163; CHECK-NEXT: [[R:%.*]] = ashr exact i8 [[I0]], 6164; CHECK-NEXT: ret i8 [[R]]165;166 %i0 = shl i8 %x, 6 ; not 7167 %r = ashr i8 %i0, 6 ; not 7168 ret i8 %r169}170