118 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; c) (x & (-1 >> 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:%.*]] = lshr i32 -1, [[NBITS:%.*]]19; CHECK-NEXT: [[T2:%.*]] = add i32 [[NBITS]], -120; CHECK-NEXT: call void @use32(i32 [[T0]])21; CHECK-NEXT: call void @use32(i32 [[T2]])22; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[T2]]23; CHECK-NEXT: [[T3:%.*]] = and i32 [[TMP1]], 214748364724; CHECK-NEXT: ret i32 [[T3]]25;26 %t0 = lshr i32 -1, %nbits27 %t1 = and i32 %t0, %x28 %t2 = add i32 %nbits, -129 call void @use32(i32 %t0)30 call void @use32(i32 %t2)31 %t3 = shl i32 %t1, %t2 ; shift is smaller than mask32 ret i32 %t333}34 35; Vectors36 37declare void @use8xi32(<8 x i32>)38 39define <8 x i32> @t1_vec_splat(<8 x i32> %x, <8 x i32> %nbits) {40; CHECK-LABEL: @t1_vec_splat(41; CHECK-NEXT: [[T0:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS:%.*]]42; CHECK-NEXT: [[T2:%.*]] = add <8 x i32> [[NBITS]], splat (i32 -1)43; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])44; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T2]])45; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T2]]46; CHECK-NEXT: [[T3:%.*]] = and <8 x i32> [[TMP1]], splat (i32 2147483647)47; CHECK-NEXT: ret <8 x i32> [[T3]]48;49 %t0 = lshr <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits50 %t1 = and <8 x i32> %t0, %x51 %t2 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>52 call void @use8xi32(<8 x i32> %t0)53 call void @use8xi32(<8 x i32> %t2)54 %t3 = shl <8 x i32> %t1, %t2 ; shift is smaller than mask55 ret <8 x i32> %t356}57 58define <8 x i32> @t1_vec_splat_poison(<8 x i32> %x, <8 x i32> %nbits) {59; CHECK-LABEL: @t1_vec_splat_poison(60; CHECK-NEXT: [[T0:%.*]] = lshr <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, [[NBITS:%.*]]61; CHECK-NEXT: [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>62; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])63; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T2]])64; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T2]]65; CHECK-NEXT: [[T3:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>66; CHECK-NEXT: ret <8 x i32> [[T3]]67;68 %t0 = lshr <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, %nbits69 %t1 = and <8 x i32> %t0, %x70 %t2 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>71 call void @use8xi32(<8 x i32> %t0)72 call void @use8xi32(<8 x i32> %t2)73 %t3 = shl <8 x i32> %t1, %t2 ; shift is smaller than mask74 ret <8 x i32> %t375}76 77define <8 x i32> @t1_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {78; CHECK-LABEL: @t1_vec_nonsplat(79; CHECK-NEXT: [[T0:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS:%.*]]80; CHECK-NEXT: [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>81; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])82; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T2]])83; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T2]]84; CHECK-NEXT: [[T3:%.*]] = and <8 x i32> [[TMP1]], <i32 poison, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison>85; CHECK-NEXT: ret <8 x i32> [[T3]]86;87 %t0 = lshr <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits88 %t1 = and <8 x i32> %t0, %x89 %t2 = add <8 x i32> %nbits, <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>90 call void @use8xi32(<8 x i32> %t0)91 call void @use8xi32(<8 x i32> %t2)92 %t3 = shl <8 x i32> %t1, %t2 ; shift is smaller than mask93 ret <8 x i32> %t394}95 96; Extra uses.97 98define i32 @n3_extrause(i32 %x, i32 %nbits) {99; CHECK-LABEL: @n3_extrause(100; CHECK-NEXT: [[T0:%.*]] = lshr i32 -1, [[NBITS:%.*]]101; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[X:%.*]]102; CHECK-NEXT: [[T2:%.*]] = add i32 [[NBITS]], -1103; CHECK-NEXT: call void @use32(i32 [[T0]])104; CHECK-NEXT: call void @use32(i32 [[T1]])105; CHECK-NEXT: call void @use32(i32 [[T2]])106; CHECK-NEXT: [[T3:%.*]] = shl i32 [[T1]], [[T2]]107; CHECK-NEXT: ret i32 [[T3]]108;109 %t0 = lshr i32 -1, %nbits110 %t1 = and i32 %t0, %x111 %t2 = add i32 %nbits, -1112 call void @use32(i32 %t0)113 call void @use32(i32 %t1) ; BAD114 call void @use32(i32 %t2)115 %t3 = shl i32 %t1, %t2 ; shift is smaller than mask116 ret i32 %t3117}118