1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; If we have some pattern that leaves only some low bits set, and then performs 5; 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)) << shiftNbits 9; 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]], -1 20; 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]], 2147483647 24; CHECK-NEXT: ret i32 [[T3]] 25; 26 %t0 = lshr i32 -1, %nbits 27 %t1 = and i32 %t0, %x 28 %t2 = add i32 %nbits, -1 29 call void @use32(i32 %t0) 30 call void @use32(i32 %t2) 31 %t3 = shl i32 %t1, %t2 ; shift is smaller than mask 32 ret i32 %t3 33} 34 35; Vectors 36 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> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, [[NBITS:%.*]] 42; CHECK-NEXT: [[T2:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, 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]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, 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>, %nbits 50 %t1 = and <8 x i32> %t0, %x 51 %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 mask 55 ret <8 x i32> %t3 56} 57 58define <8 x i32> @t1_vec_splat_undef(<8 x i32> %x, <8 x i32> %nbits) { 59; CHECK-LABEL: @t1_vec_splat_undef( 60; CHECK-NEXT: [[T0:%.*]] = lshr <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, 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 undef, 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 undef, i32 -1>, %nbits 69 %t1 = and <8 x i32> %t0, %x 70 %t2 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, 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 mask 74 ret <8 x i32> %t3 75} 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> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, 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>, %nbits 88 %t1 = and <8 x i32> %t0, %x 89 %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 mask 93 ret <8 x i32> %t3 94} 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]], -1 103; 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, %nbits 110 %t1 = and i32 %t0, %x 111 %t2 = add i32 %nbits, -1 112 call void @use32(i32 %t0) 113 call void @use32(i32 %t1) ; BAD 114 call void @use32(i32 %t2) 115 %t3 = shl i32 %t1, %t2 ; shift is smaller than mask 116 ret i32 %t3 117} 118