158 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) (x & (~(-1 << maskNbits))) << shiftNbits9; simplify to:10; (x << shiftNbits) & (~(-1 << (maskNbits+shiftNbits)))11 12; Simple tests.13 14declare void @use32(i32)15 16define i32 @t0_basic(i32 %x, i32 %nbits) {17; CHECK-LABEL: @t0_basic(18; CHECK-NEXT: [[T0:%.*]] = add i32 [[NBITS:%.*]], -119; CHECK-NEXT: [[T1:%.*]] = shl nsw i32 -1, [[T0]]20; CHECK-NEXT: [[T2:%.*]] = xor i32 [[T1]], -121; CHECK-NEXT: [[T4:%.*]] = sub i32 32, [[NBITS]]22; CHECK-NEXT: call void @use32(i32 [[T0]])23; CHECK-NEXT: call void @use32(i32 [[T1]])24; CHECK-NEXT: call void @use32(i32 [[T2]])25; CHECK-NEXT: call void @use32(i32 [[T4]])26; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[T4]]27; CHECK-NEXT: [[T5:%.*]] = and i32 [[TMP1]], 214748364728; CHECK-NEXT: ret i32 [[T5]]29;30 %t0 = add i32 %nbits, -131 %t1 = shl i32 -1, %t0 ; shifting by nbits-132 %t2 = xor i32 %t1, -133 %t3 = and i32 %t2, %x34 %t4 = sub i32 32, %nbits35 call void @use32(i32 %t0)36 call void @use32(i32 %t1)37 call void @use32(i32 %t2)38 call void @use32(i32 %t4)39 %t5 = shl i32 %t3, %t440 ret i32 %t541}42 43; Vectors44 45declare void @use8xi32(<8 x i32>)46 47define <8 x i32> @t1_vec_splat(<8 x i32> %x, <8 x i32> %nbits) {48; CHECK-LABEL: @t1_vec_splat(49; CHECK-NEXT: [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], splat (i32 -1)50; CHECK-NEXT: [[T1:%.*]] = shl nsw <8 x i32> splat (i32 -1), [[T0]]51; CHECK-NEXT: [[T2:%.*]] = xor <8 x i32> [[T1]], splat (i32 -1)52; CHECK-NEXT: [[T4:%.*]] = sub <8 x i32> splat (i32 32), [[NBITS]]53; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])54; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])55; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T2]])56; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T4]])57; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T4]]58; CHECK-NEXT: [[T5:%.*]] = and <8 x i32> [[TMP1]], splat (i32 2147483647)59; CHECK-NEXT: ret <8 x i32> [[T5]]60;61 %t0 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>62 %t1 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %t063 %t2 = xor <8 x i32> %t1, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>64 %t3 = and <8 x i32> %t2, %x65 %t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits66 call void @use8xi32(<8 x i32> %t0)67 call void @use8xi32(<8 x i32> %t1)68 call void @use8xi32(<8 x i32> %t2)69 call void @use8xi32(<8 x i32> %t4)70 %t5 = shl <8 x i32> %t3, %t471 ret <8 x i32> %t572}73 74define <8 x i32> @t1_vec_splat_poison(<8 x i32> %x, <8 x i32> %nbits) {75; CHECK-LABEL: @t1_vec_splat_poison(76; CHECK-NEXT: [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>77; CHECK-NEXT: [[T1:%.*]] = shl nsw <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, [[T0]]78; CHECK-NEXT: [[T2:%.*]] = xor <8 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>79; CHECK-NEXT: [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 poison, i32 32>, [[NBITS]]80; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])81; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])82; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T2]])83; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T4]])84; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T4]]85; CHECK-NEXT: [[T5:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>86; CHECK-NEXT: ret <8 x i32> [[T5]]87;88 %t0 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>89 %t1 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, %t090 %t2 = xor <8 x i32> %t1, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>91 %t3 = and <8 x i32> %t2, %x92 %t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 poison, i32 32>, %nbits93 call void @use8xi32(<8 x i32> %t0)94 call void @use8xi32(<8 x i32> %t1)95 call void @use8xi32(<8 x i32> %t2)96 call void @use8xi32(<8 x i32> %t4)97 %t5 = shl <8 x i32> %t3, %t498 ret <8 x i32> %t599}100 101define <8 x i32> @t2_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {102; CHECK-LABEL: @t2_vec_nonsplat(103; CHECK-NEXT: [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -33, i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32>104; CHECK-NEXT: [[T1:%.*]] = shl nsw <8 x i32> splat (i32 -1), [[T0]]105; CHECK-NEXT: [[T2:%.*]] = xor <8 x i32> [[T1]], splat (i32 -1)106; CHECK-NEXT: [[T4:%.*]] = sub <8 x i32> splat (i32 32), [[NBITS]]107; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])108; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])109; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T2]])110; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T4]])111; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T4]]112; CHECK-NEXT: [[T5:%.*]] = and <8 x i32> [[TMP1]], <i32 poison, i32 0, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 poison>113; CHECK-NEXT: ret <8 x i32> [[T5]]114;115 %t0 = add <8 x i32> %nbits, <i32 -33, i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32>116 %t1 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %t0117 %t2 = xor <8 x i32> %t1, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>118 %t3 = and <8 x i32> %t2, %x119 %t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits120 call void @use8xi32(<8 x i32> %t0)121 call void @use8xi32(<8 x i32> %t1)122 call void @use8xi32(<8 x i32> %t2)123 call void @use8xi32(<8 x i32> %t4)124 %t5 = shl <8 x i32> %t3, %t4125 ret <8 x i32> %t5126}127 128; Extra uses.129 130define i32 @n3_extrause(i32 %x, i32 %nbits) {131; CHECK-LABEL: @n3_extrause(132; CHECK-NEXT: [[T0:%.*]] = add i32 [[NBITS:%.*]], -1133; CHECK-NEXT: [[T1:%.*]] = shl nsw i32 -1, [[T0]]134; CHECK-NEXT: [[T2:%.*]] = xor i32 [[T1]], -1135; CHECK-NEXT: [[T3:%.*]] = and i32 [[X:%.*]], [[T2]]136; CHECK-NEXT: [[T4:%.*]] = sub i32 32, [[NBITS]]137; CHECK-NEXT: call void @use32(i32 [[T0]])138; CHECK-NEXT: call void @use32(i32 [[T1]])139; CHECK-NEXT: call void @use32(i32 [[T2]])140; CHECK-NEXT: call void @use32(i32 [[T3]])141; CHECK-NEXT: call void @use32(i32 [[T4]])142; CHECK-NEXT: [[T5:%.*]] = shl i32 [[T3]], [[T4]]143; CHECK-NEXT: ret i32 [[T5]]144;145 %t0 = add i32 %nbits, -1146 %t1 = shl i32 -1, %t0 ; shifting by nbits-1147 %t2 = xor i32 %t1, -1148 %t3 = and i32 %t2, %x ; this mask must be one-use.149 %t4 = sub i32 32, %nbits150 call void @use32(i32 %t0)151 call void @use32(i32 %t1)152 call void @use32(i32 %t2)153 call void @use32(i32 %t3) ; BAD154 call void @use32(i32 %t4)155 %t5 = shl i32 %t3, %t4156 ret i32 %t5157}158