brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.2 KiB · c25b873 Raw
239 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;   b)  (trunc ((x & (~(-1 << maskNbits))))) << shiftNbits9; simplify to:10;   ((trunc(x)) << shiftNbits) & (~(-1 << (maskNbits+shiftNbits)))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:%.*]] = xor i64 [[T1]], -122; CHECK-NEXT:    [[T3:%.*]] = sub i32 32, [[NBITS]]23; CHECK-NEXT:    [[T4:%.*]] = and i64 [[X:%.*]], [[T2]]24; CHECK-NEXT:    call void @use32(i32 [[NBITS]])25; CHECK-NEXT:    call void @use64(i64 [[T0]])26; CHECK-NEXT:    call void @use64(i64 [[T1]])27; CHECK-NEXT:    call void @use64(i64 [[T2]])28; CHECK-NEXT:    call void @use32(i32 [[T3]])29; CHECK-NEXT:    call void @use64(i64 [[T4]])30; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[X]] to i3231; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[TMP1]], [[T3]]32; CHECK-NEXT:    ret i32 [[T6]]33;34  %t0 = zext i32 %nbits to i6435  %t1 = shl i64 -1, %t036  %t2 = xor i64 %t1, -137  %t3 = sub i32 32, %nbits38  %t4 = and i64 %t2, %x39 40  call void @use32(i32 %nbits)41  call void @use64(i64 %t0)42  call void @use64(i64 %t1)43  call void @use64(i64 %t2)44  call void @use32(i32 %t3)45  call void @use64(i64 %t4)46 47  %t5 = trunc i64 %t4 to i3248  %t6 = shl i32 %t5, %t349  ret i32 %t650}51 52; Vectors53 54declare void @use8xi32(<8 x i32>)55declare void @use8xi64(<8 x i64>)56 57define <8 x i32> @t1_vec_splat(<8 x i64> %x, <8 x i32> %nbits) {58; CHECK-LABEL: @t1_vec_splat(59; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>60; CHECK-NEXT:    [[T1:%.*]] = shl nsw <8 x i64> splat (i64 -1), [[T0]]61; CHECK-NEXT:    [[T2:%.*]] = xor <8 x i64> [[T1]], splat (i64 -1)62; CHECK-NEXT:    [[T3:%.*]] = sub <8 x i32> splat (i32 32), [[NBITS]]63; CHECK-NEXT:    [[T4:%.*]] = and <8 x i64> [[X:%.*]], [[T2]]64; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[NBITS]])65; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])66; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])67; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T2]])68; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T3]])69; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T4]])70; CHECK-NEXT:    [[TMP1:%.*]] = trunc <8 x i64> [[X]] to <8 x i32>71; CHECK-NEXT:    [[T6:%.*]] = shl <8 x i32> [[TMP1]], [[T3]]72; CHECK-NEXT:    ret <8 x i32> [[T6]]73;74  %t0 = zext <8 x i32> %nbits to <8 x i64>75  %t1 = shl <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>, %t076  %t2 = xor <8 x i64> %t1, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>77  %t3 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits78  %t4 = and <8 x i64> %t2, %x79 80  call void @use8xi32(<8 x i32> %nbits)81  call void @use8xi64(<8 x i64> %t0)82  call void @use8xi64(<8 x i64> %t1)83  call void @use8xi64(<8 x i64> %t2)84  call void @use8xi32(<8 x i32> %t3)85  call void @use8xi64(<8 x i64> %t4)86 87  %t5 = trunc <8 x i64> %t4 to <8 x i32>88  %t6 = shl <8 x i32> %t5, %t389  ret <8 x i32> %t690}91 92define <8 x i32> @t2_vec_splat_poison(<8 x i64> %x, <8 x i32> %nbits) {93; CHECK-LABEL: @t2_vec_splat_poison(94; CHECK-NEXT:    [[T0:%.*]] = zext <8 x i32> [[NBITS:%.*]] to <8 x i64>95; 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]]96; CHECK-NEXT:    [[T2:%.*]] = xor <8 x i64> [[T1]], <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>97; CHECK-NEXT:    [[T3:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 poison, i32 32>, [[NBITS]]98; CHECK-NEXT:    [[T4:%.*]] = and <8 x i64> [[X:%.*]], [[T2]]99; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[NBITS]])100; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T0]])101; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])102; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T2]])103; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T3]])104; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T4]])105; CHECK-NEXT:    [[TMP1:%.*]] = trunc <8 x i64> [[X]] to <8 x i32>106; CHECK-NEXT:    [[T6:%.*]] = shl <8 x i32> [[TMP1]], [[T3]]107; CHECK-NEXT:    ret <8 x i32> [[T6]]108;109  %t0 = zext <8 x i32> %nbits to <8 x i64>110  %t1 = shl <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>, %t0111  %t2 = xor <8 x i64> %t1, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 poison, i64 -1>112  %t3 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 poison, i32 32>, %nbits113  %t4 = and <8 x i64> %t2, %x114 115  call void @use8xi32(<8 x i32> %nbits)116  call void @use8xi64(<8 x i64> %t0)117  call void @use8xi64(<8 x i64> %t1)118  call void @use8xi64(<8 x i64> %t2)119  call void @use8xi32(<8 x i32> %t3)120  call void @use8xi64(<8 x i64> %t4)121 122  %t5 = trunc <8 x i64> %t4 to <8 x i32>123  %t6 = shl <8 x i32> %t5, %t3124  ret <8 x i32> %t6125}126 127define <8 x i32> @t3_vec_nonsplat(<8 x i64> %x, <8 x i32> %nbits) {128; CHECK-LABEL: @t3_vec_nonsplat(129; CHECK-NEXT:    [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -1, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0>130; CHECK-NEXT:    [[T1:%.*]] = zext <8 x i32> [[T0]] to <8 x i64>131; CHECK-NEXT:    [[T2:%.*]] = shl nsw <8 x i64> splat (i64 -1), [[T1]]132; CHECK-NEXT:    [[T3:%.*]] = xor <8 x i64> [[T2]], splat (i64 -1)133; CHECK-NEXT:    [[T4:%.*]] = sub <8 x i32> <i32 33, i32 32, i32 33, i32 32, i32 32, i32 32, i32 32, i32 32>, [[NBITS]]134; CHECK-NEXT:    [[T5:%.*]] = and <8 x i64> [[X:%.*]], [[T3]]135; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])136; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T1]])137; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T2]])138; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T3]])139; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T4]])140; CHECK-NEXT:    call void @use8xi64(<8 x i64> [[T5]])141; CHECK-NEXT:    [[TMP1:%.*]] = trunc <8 x i64> [[X]] to <8 x i32>142; CHECK-NEXT:    [[T7:%.*]] = shl <8 x i32> [[TMP1]], [[T4]]143; CHECK-NEXT:    ret <8 x i32> [[T7]]144;145  %t0 = add <8 x i32> %nbits, <i32 -1, i32 0, i32 0, i32 1, i32 0, i32 0, i32 0, i32 0>146  %t1 = zext <8 x i32> %t0 to <8 x i64>147  %t2 = shl <8 x i64> <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>, %t1 ; shifting by nbits-1148  %t3 = xor <8 x i64> %t2, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>149  %t4 = sub <8 x i32> <i32 33, i32 32, i32 33, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits150  %t5 = and <8 x i64> %t3, %x151 152  call void @use8xi32(<8 x i32> %t0)153  call void @use8xi64(<8 x i64> %t1)154  call void @use8xi64(<8 x i64> %t2)155  call void @use8xi64(<8 x i64> %t3)156  call void @use8xi32(<8 x i32> %t4)157  call void @use8xi64(<8 x i64> %t5)158 159  %t6 = trunc <8 x i64> %t5 to <8 x i32>160  %t7 = shl <8 x i32> %t6, %t4161  ret <8 x i32> %t7162}163 164; -1 can be truncated.165 166define i32 @t4_allones_trunc(i64 %x, i32 %nbits) {167; CHECK-LABEL: @t4_allones_trunc(168; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64169; CHECK-NEXT:    [[T1:%.*]] = shl nsw i64 -1, [[T0]]170; CHECK-NEXT:    [[T2:%.*]] = xor i64 [[T1]], 4294967295171; CHECK-NEXT:    [[T3:%.*]] = sub i32 32, [[NBITS]]172; CHECK-NEXT:    [[T4:%.*]] = and i64 [[T2]], [[X:%.*]]173; CHECK-NEXT:    call void @use32(i32 [[NBITS]])174; CHECK-NEXT:    call void @use64(i64 [[T0]])175; CHECK-NEXT:    call void @use64(i64 [[T1]])176; CHECK-NEXT:    call void @use64(i64 [[T2]])177; CHECK-NEXT:    call void @use32(i32 [[T3]])178; CHECK-NEXT:    call void @use64(i64 [[T4]])179; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[T4]] to i32180; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[T5]], [[T3]]181; CHECK-NEXT:    ret i32 [[T6]]182;183  %t0 = zext i32 %nbits to i64184  %t1 = shl i64 -1, %t0185  %t2 = xor i64 %t1, 4294967295186  %t3 = sub i32 32, %nbits187  %t4 = and i64 %t2, %x188 189  call void @use32(i32 %nbits)190  call void @use64(i64 %t0)191  call void @use64(i64 %t1)192  call void @use64(i64 %t2)193  call void @use32(i32 %t3)194  call void @use64(i64 %t4)195 196  %t5 = trunc i64 %t4 to i32197  %t6 = shl i32 %t5, %t3198  ret i32 %t6199}200 201; Extra uses202 203define i32 @n5_extrause(i64 %x, i32 %nbits) {204; CHECK-LABEL: @n5_extrause(205; CHECK-NEXT:    [[T0:%.*]] = zext i32 [[NBITS:%.*]] to i64206; CHECK-NEXT:    [[T1:%.*]] = shl nsw i64 -1, [[T0]]207; CHECK-NEXT:    [[T2:%.*]] = xor i64 [[T1]], -1208; CHECK-NEXT:    [[T3:%.*]] = sub i32 32, [[NBITS]]209; CHECK-NEXT:    [[T4:%.*]] = and i64 [[X:%.*]], [[T2]]210; CHECK-NEXT:    call void @use32(i32 [[NBITS]])211; CHECK-NEXT:    call void @use64(i64 [[T0]])212; CHECK-NEXT:    call void @use64(i64 [[T1]])213; CHECK-NEXT:    call void @use64(i64 [[T2]])214; CHECK-NEXT:    call void @use32(i32 [[T3]])215; CHECK-NEXT:    call void @use64(i64 [[T4]])216; CHECK-NEXT:    [[T5:%.*]] = trunc i64 [[T4]] to i32217; CHECK-NEXT:    call void @use32(i32 [[T5]])218; CHECK-NEXT:    [[T6:%.*]] = shl i32 [[T5]], [[T3]]219; CHECK-NEXT:    ret i32 [[T6]]220;221  %t0 = zext i32 %nbits to i64222  %t1 = shl i64 -1, %t0223  %t2 = xor i64 %t1, -1224  %t3 = sub i32 32, %nbits225  %t4 = and i64 %t2, %x226 227  call void @use32(i32 %nbits)228  call void @use64(i64 %t0)229  call void @use64(i64 %t1)230  call void @use64(i64 %t2)231  call void @use32(i32 %t3)232  call void @use64(i64 %t4)233 234  %t5 = trunc i64 %t4 to i32235  call void @use32(i32 %t5)236  %t6 = shl i32 %t5, %t3237  ret i32 %t6238}239