138 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) (x & ((-1 << maskNbits) >> maskNbits)) << shiftNbits9; simplify to:10; (x << shiftNbits) & (-1 >> ((-(maskNbits+shiftNbits))+32))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:%.*]] = shl nsw i32 -1, [[NBITS:%.*]]19; CHECK-NEXT: [[T1:%.*]] = lshr i32 -1, [[NBITS]]20; CHECK-NEXT: [[T3:%.*]] = add i32 [[NBITS]], -121; CHECK-NEXT: call void @use32(i32 [[T0]])22; CHECK-NEXT: call void @use32(i32 [[T1]])23; CHECK-NEXT: call void @use32(i32 [[T3]])24; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[T3]]25; CHECK-NEXT: [[T4:%.*]] = and i32 [[TMP1]], 214748364726; CHECK-NEXT: ret i32 [[T4]]27;28 %t0 = shl i32 -1, %nbits29 %t1 = lshr i32 %t0, %nbits30 %t2 = and i32 %t1, %x31 %t3 = add i32 %nbits, -132 call void @use32(i32 %t0)33 call void @use32(i32 %t1)34 call void @use32(i32 %t3)35 %t4 = shl i32 %t2, %t3 ; shift is smaller than mask36 ret i32 %t437}38 39; Vectors40 41declare void @use8xi32(<8 x i32>)42 43define <8 x i32> @t2_vec_splat(<8 x i32> %x, <8 x i32> %nbits) {44; CHECK-LABEL: @t2_vec_splat(45; CHECK-NEXT: [[T0:%.*]] = shl nsw <8 x i32> splat (i32 -1), [[NBITS:%.*]]46; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS]]47; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], splat (i32 -1)48; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])49; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])50; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T3]])51; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T3]]52; CHECK-NEXT: [[T4:%.*]] = and <8 x i32> [[TMP1]], splat (i32 2147483647)53; CHECK-NEXT: ret <8 x i32> [[T4]]54;55 %t0 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits56 %t1 = lshr <8 x i32> %t0, %nbits57 %t2 = and <8 x i32> %t1, %x58 %t3 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>59 call void @use8xi32(<8 x i32> %t0)60 call void @use8xi32(<8 x i32> %t1)61 call void @use8xi32(<8 x i32> %t3)62 %t4 = shl <8 x i32> %t2, %t3 ; shift is smaller than mask63 ret <8 x i32> %t464}65 66define <8 x i32> @t2_vec_splat_poison(<8 x i32> %x, <8 x i32> %nbits) {67; CHECK-LABEL: @t2_vec_splat_poison(68; CHECK-NEXT: [[T0:%.*]] = shl nsw <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, [[NBITS:%.*]]69; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS]]70; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>71; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])72; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])73; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T3]])74; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T3]]75; CHECK-NEXT: [[T4:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>76; CHECK-NEXT: ret <8 x i32> [[T4]]77;78 %t0 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, %nbits79 %t1 = lshr <8 x i32> %t0, %nbits80 %t2 = and <8 x i32> %t1, %x81 %t3 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>82 call void @use8xi32(<8 x i32> %t0)83 call void @use8xi32(<8 x i32> %t1)84 call void @use8xi32(<8 x i32> %t3)85 %t4 = shl <8 x i32> %t2, %t3 ; shift is smaller than mask86 ret <8 x i32> %t487}88 89define <8 x i32> @t2_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {90; CHECK-LABEL: @t2_vec_nonsplat(91; CHECK-NEXT: [[T0:%.*]] = shl nsw <8 x i32> splat (i32 -1), [[NBITS:%.*]]92; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS]]93; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>94; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])95; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])96; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T3]])97; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T3]]98; CHECK-NEXT: [[T4:%.*]] = and <8 x i32> [[TMP1]], <i32 poison, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison>99; CHECK-NEXT: ret <8 x i32> [[T4]]100;101 %t0 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits102 %t1 = lshr <8 x i32> %t0, %nbits103 %t2 = and <8 x i32> %t1, %x104 %t3 = add <8 x i32> %nbits, <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>105 call void @use8xi32(<8 x i32> %t0)106 call void @use8xi32(<8 x i32> %t1)107 call void @use8xi32(<8 x i32> %t3)108 %t4 = shl <8 x i32> %t2, %t3 ; shift is smaller than mask109 ret <8 x i32> %t4110}111 112; Extra uses.113 114define i32 @n3_extrause(i32 %x, i32 %nbits) {115; CHECK-LABEL: @n3_extrause(116; CHECK-NEXT: [[T0:%.*]] = shl nsw i32 -1, [[NBITS:%.*]]117; CHECK-NEXT: [[T1:%.*]] = lshr i32 -1, [[NBITS]]118; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[X:%.*]]119; CHECK-NEXT: [[T3:%.*]] = add i32 [[NBITS]], -1120; CHECK-NEXT: call void @use32(i32 [[T0]])121; CHECK-NEXT: call void @use32(i32 [[T1]])122; CHECK-NEXT: call void @use32(i32 [[T2]])123; CHECK-NEXT: call void @use32(i32 [[T3]])124; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[T3]]125; CHECK-NEXT: ret i32 [[T4]]126;127 %t0 = shl i32 -1, %nbits128 %t1 = lshr i32 %t0, %nbits129 %t2 = and i32 %t1, %x130 %t3 = add i32 %nbits, -1131 call void @use32(i32 %t0)132 call void @use32(i32 %t1)133 call void @use32(i32 %t2) ; BAD134 call void @use32(i32 %t3)135 %t4 = shl i32 %t2, %t3 ; shift is smaller than mask136 ret i32 %t4137}138