brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.0 KiB · ebfa456 Raw
267 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 some pattern that leaves only some low bits set, and then performs5; left-shift of those bits, we can combine those two shifts into a shift+mask.6 7; There are many variants to this pattern:8;   d)  (trunc ((x & ((-1 << maskNbits) >> maskNbits)))) << shiftNbits9; simplify to:10;   ((trunc(x)) << shiftNbits) & (-1 >> ((-(maskNbits+shiftNbits))+32))11 12; Simple tests.13 14declare void @use32(i32)15declare void @use64(i64)16 17define i32 @t0_basic(i64 %x, i32 %nbits) {18; CHECK-LABEL: @t0_basic(19; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i6420; CHECK-NEXT:    [[T1:%.*]] = shl nsw i64 -1, [[T0]]21; CHECK-NEXT:    [[T2:%.*]] = lshr i64 -1, [[T0]]22; CHECK-NEXT:    [[T3:%.*]] = add i32 [[NBITS]], -3323; CHECK-NEXT:    call void @use64(i64 [[T0]])24; CHECK-NEXT:    call void @use64(i64 [[T1]])25; CHECK-NEXT:    call void @use64(i64 [[T2]])26; CHECK-NEXT:    call void @use32(i32 [[T3]])27; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i3228; CHECK-NEXT:    [[TMP2:%.*]] = shl i32 [[TMP1]], [[T3]]29; CHECK-NEXT:    [[T6:%.*]] = and i32 [[TMP2]], 214748364730; CHECK-NEXT:    ret i32 [[T6]]31;32  %t0 = zext i32 %nbits to i6433  %t1 = shl i64 -1, %t034  %t2 = lshr i64 %t1, %t035  %t3 = add i32 %nbits, -3336 37  call void @use64(i64 %t0)38  call void @use64(i64 %t1)39  call void @use64(i64 %t2)40  call void @use32(i32 %t3)41 42  %t4 = and i64 %t2, %x43  %t5 = trunc i64 %t4 to i3244  %t6 = shl i32 %t5, %t3 ; shift is smaller than mask45  ret i32 %t646}47 48; Vectors49 50declare void @use8xi32(<8 x i32>)51declare void @use8xi64(<8 x i64>)52 53define <8 x i32> @t1_vec_splat(<8 x i64> %x, <8 x i32> %nbits) {54; CHECK-LABEL: @t1_vec_splat(55; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>56; CHECK-NEXT:    [[T1:%.*]] = shl nsw <8 x i64> splat (i64 -1), [[T0]]57; CHECK-NEXT:    [[T2:%.*]] = lshr <8 x i64> splat (i64 -1), [[T0]]58; CHECK-NEXT:    [[T3:%.*]] = add <8 x i32> [[NBITS]], splat (i32 -33)59; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])60; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])61; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T2]])62; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T3]])63; CHECK-NEXT:    [[TMP1:%.*]] = trunc <8 x i64> [[X:%.*]] to <8 x i32>64; CHECK-NEXT:    [[TMP2:%.*]] = shl <8 x i32> [[TMP1]], [[T3]]65; CHECK-NEXT:    [[T6:%.*]] = and <8 x i32> [[TMP2]], splat (i32 2147483647)66; CHECK-NEXT:    ret <8 x i32> [[T6]]67;68  %t0 = zext <8 x i32> %nbits to <8 x i64>69  %t1 = shl <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>, %t070  %t2 = lshr <8 x i64> %t1, %t071  %t3 = add <8 x i32> %nbits, <i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 -33>72 73  call void @use8xi64(<8 x i64> %t0)74  call void @use8xi64(<8 x i64> %t1)75  call void @use8xi64(<8 x i64> %t2)76  call void @use8xi32(<8 x i32> %t3)77 78  %t4 = and <8 x i64> %t2, %x79  %t5 = trunc <8 x i64> %t4 to <8 x i32>80  %t6 = shl <8 x i32> %t5, %t3 ; shift is smaller than mask81  ret <8 x i32> %t682}83 84define <8 x i32> @t2_vec_splat_poison(<8 x i64> %x, <8 x i32> %nbits) {85; CHECK-LABEL: @t2_vec_splat_poison(86; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>87; CHECK-NEXT:    [[T1:%.*]] = shl nsw <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>, [[T0]]88; CHECK-NEXT:    [[T2:%.*]] = lshr <8 x i64> splat (i64 -1), [[T0]]89; CHECK-NEXT:    [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 poison, i32 -33>90; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])91; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])92; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T2]])93; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T3]])94; CHECK-NEXT:    [[TMP1:%.*]] = trunc <8 x i64> [[X:%.*]] to <8 x i32>95; CHECK-NEXT:    [[TMP2:%.*]] = shl <8 x i32> [[TMP1]], [[T3]]96; CHECK-NEXT:    [[T6:%.*]] = and <8 x i32> [[TMP2]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>97; CHECK-NEXT:    ret <8 x i32> [[T6]]98;99  %t0 = zext <8 x i32> %nbits to <8 x i64>100  %t1 = shl <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>, %t0101  %t2 = lshr <8 x i64> %t1, %t0102  %t3 = add <8 x i32> %nbits, <i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 -33, i32 poison, i32 -33>103 104  call void @use8xi64(<8 x i64> %t0)105  call void @use8xi64(<8 x i64> %t1)106  call void @use8xi64(<8 x i64> %t2)107  call void @use8xi32(<8 x i32> %t3)108 109  %t4 = and <8 x i64> %t2, %x110  %t5 = trunc <8 x i64> %t4 to <8 x i32>111  %t6 = shl <8 x i32> %t5, %t3 ; shift is smaller than mask112  ret <8 x i32> %t6113}114 115define <8 x i32> @t3_vec_nonsplat(<8 x i64> %x, <8 x i32> %nbits) {116; CHECK-LABEL: @t3_vec_nonsplat(117; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>118; CHECK-NEXT:    [[T1:%.*]] = shl nsw <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>, [[T0]]119; CHECK-NEXT:    [[T2:%.*]] = lshr <8 x i64> splat (i64 -1), [[T0]]120; CHECK-NEXT:    [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -64, i32 -63, i32 -33, i32 -32, i32 63, i32 64, i32 poison, i32 65>121; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])122; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])123; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T2]])124; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T3]])125; CHECK-NEXT:    [[TMP1:%.*]] = trunc <8 x i64> [[X:%.*]] to <8 x i32>126; CHECK-NEXT:    [[TMP2:%.*]] = shl <8 x i32> [[TMP1]], [[T3]]127; CHECK-NEXT:    [[T6:%.*]] = and <8 x i32> [[TMP2]], <i32 poison, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 poison, i32 poison>128; CHECK-NEXT:    ret <8 x i32> [[T6]]129;130  %t0 = zext <8 x i32> %nbits to <8 x i64>131  %t1 = shl <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>, %t0132  %t2 = lshr <8 x i64> %t1, %t0133  %t3 = add <8 x i32> %nbits, <i32 -64, i32 -63, i32 -33, i32 -32, i32 63, i32 64, i32 poison, i32 65>134 135  call void @use8xi64(<8 x i64> %t0)136  call void @use8xi64(<8 x i64> %t1)137  call void @use8xi64(<8 x i64> %t2)138  call void @use8xi32(<8 x i32> %t3)139 140  %t4 = and <8 x i64> %t2, %x141  %t5 = trunc <8 x i64> %t4 to <8 x i32>142  %t6 = shl <8 x i32> %t5, %t3 ; shift is smaller than mask143  ret <8 x i32> %t6144}145 146; Extra uses.147 148define i32 @n4_extrause0(i64 %x, i32 %nbits) {149; CHECK-LABEL: @n4_extrause0(150; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64151; CHECK-NEXT:    [[T1:%.*]] = shl nsw i64 -1, [[T0]]152; CHECK-NEXT:    [[T2:%.*]] = lshr i64 -1, [[T0]]153; CHECK-NEXT:    [[T3:%.*]] = add i32 [[NBITS]], -33154; CHECK-NEXT:    call void @use64(i64 [[T0]])155; CHECK-NEXT:    call void @use64(i64 [[T1]])156; CHECK-NEXT:    call void @use64(i64 [[T2]])157; CHECK-NEXT:    call void @use32(i32 [[T3]])158; CHECK-NEXT:    [[T4:%.*]] = and i64 [[T2]], [[X:%.*]]159; CHECK-NEXT:    call void @use64(i64 [[T4]])160; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[T4]] to i32161; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[T5]], [[T3]]162; CHECK-NEXT:    ret i32 [[T6]]163;164  %t0 = zext i32 %nbits to i64165  %t1 = shl i64 -1, %t0166  %t2 = lshr i64 %t1, %t0167  %t3 = add i32 %nbits, -33168 169  call void @use64(i64 %t0)170  call void @use64(i64 %t1)171  call void @use64(i64 %t2)172  call void @use32(i32 %t3)173 174  %t4 = and i64 %t2, %x175  call void @use64(i64 %t4)176  %t5 = trunc i64 %t4 to i32177  %t6 = shl i32 %t5, %t3 ; shift is smaller than mask178  ret i32 %t6179}180 181define i32 @n5_extrause1(i64 %x, i32 %nbits) {182; CHECK-LABEL: @n5_extrause1(183; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64184; CHECK-NEXT:    [[T1:%.*]] = shl nsw i64 -1, [[T0]]185; CHECK-NEXT:    [[T2:%.*]] = lshr i64 -1, [[T0]]186; CHECK-NEXT:    [[T3:%.*]] = add i32 [[NBITS]], -33187; CHECK-NEXT:    call void @use64(i64 [[T0]])188; CHECK-NEXT:    call void @use64(i64 [[T1]])189; CHECK-NEXT:    call void @use64(i64 [[T2]])190; CHECK-NEXT:    call void @use32(i32 [[T3]])191; CHECK-NEXT:    [[T4:%.*]] = and i64 [[T2]], [[X:%.*]]192; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[T4]] to i32193; CHECK-NEXT:    call void @use32(i32 [[T5]])194; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[T5]], [[T3]]195; CHECK-NEXT:    ret i32 [[T6]]196;197  %t0 = zext i32 %nbits to i64198  %t1 = shl i64 -1, %t0199  %t2 = lshr i64 %t1, %t0200  %t3 = add i32 %nbits, -33201 202  call void @use64(i64 %t0)203  call void @use64(i64 %t1)204  call void @use64(i64 %t2)205  call void @use32(i32 %t3)206 207  %t4 = and i64 %t2, %x208  %t5 = trunc i64 %t4 to i32209  call void @use32(i32 %t5)210  %t6 = shl i32 %t5, %t3 ; shift is smaller than mask211  ret i32 %t6212}213 214define i32 @n6_extrause2(i64 %x, i32 %nbits) {215; CHECK-LABEL: @n6_extrause2(216; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64217; CHECK-NEXT:    [[T1:%.*]] = shl nsw i64 -1, [[T0]]218; CHECK-NEXT:    [[T2:%.*]] = lshr i64 -1, [[T0]]219; CHECK-NEXT:    [[T3:%.*]] = add i32 [[NBITS]], -33220; CHECK-NEXT:    call void @use64(i64 [[T0]])221; CHECK-NEXT:    call void @use64(i64 [[T1]])222; CHECK-NEXT:    call void @use64(i64 [[T2]])223; CHECK-NEXT:    call void @use32(i32 [[T3]])224; CHECK-NEXT:    [[T4:%.*]] = and i64 [[T2]], [[X:%.*]]225; CHECK-NEXT:    call void @use64(i64 [[T4]])226; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[T4]] to i32227; CHECK-NEXT:    call void @use32(i32 [[T5]])228; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[T5]], [[T3]]229; CHECK-NEXT:    ret i32 [[T6]]230;231  %t0 = zext i32 %nbits to i64232  %t1 = shl i64 -1, %t0233  %t2 = lshr i64 %t1, %t0234  %t3 = add i32 %nbits, -33235 236  call void @use64(i64 %t0)237  call void @use64(i64 %t1)238  call void @use64(i64 %t2)239  call void @use32(i32 %t3)240 241  %t4 = and i64 %t2, %x242  call void @use64(i64 %t4)243  %t5 = trunc i64 %t4 to i32244  call void @use32(i32 %t5)245  %t6 = shl i32 %t5, %t3 ; shift is smaller than mask246  ret i32 %t6247}248 249; This is a miscompile if it ends by masking off the high bit of the result.250 251define i32 @PR51351(i64 %x, i32 %nbits) {252; CHECK-LABEL: @PR51351(253; CHECK-NEXT:    [[T3:%.*]] = add i32 [[NBITS:%.*]], -33254; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[X:%.*]] to i32255; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[T5]], [[T3]]256; CHECK-NEXT:    ret i32 [[T6]]257;258  %t0 = zext i32 %nbits to i64259  %t1 = shl i64 -1, %t0260  %t2 = ashr i64 %t1, %t0261  %t3 = add i32 %nbits, 4294967263262  %t4 = and i64 %t2, %x263  %t5 = trunc i64 %t4 to i32264  %t6 = shl i32 %t5, %t3265  ret i32 %t6266}267