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: 5; (data & (-1 << nbits)) outer>> nbits 6; Or 7; ((data inner>> nbits) << nbits) outer>> nbits 8; The mask is redundant, and can be dropped: 9; data outer>> nbits 10; This is valid for both lshr and ashr in both positions and any combination. 11; We must *not* preserve 'exact' on that final right-shift. 12 13define i32 @t0_lshr(i32 %data, i32 %nbits) { 14; CHECK-LABEL: @t0_lshr( 15; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] 16; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 17; CHECK-NEXT: [[T2:%.*]] = lshr exact i32 [[T1]], [[NBITS]] 18; CHECK-NEXT: ret i32 [[T2]] 19; 20 %t0 = shl i32 -1, %nbits 21 %t1 = and i32 %t0, %data 22 %t2 = lshr exact i32 %t1, %nbits ; while there, test that we *don't* propagate 'exact' 23 ret i32 %t2 24} 25define i32 @t1_sshr(i32 %data, i32 %nbits) { 26; CHECK-LABEL: @t1_sshr( 27; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] 28; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 29; CHECK-NEXT: [[T2:%.*]] = ashr exact i32 [[T1]], [[NBITS]] 30; CHECK-NEXT: ret i32 [[T2]] 31; 32 %t0 = shl i32 -1, %nbits 33 %t1 = and i32 %t0, %data 34 %t2 = ashr exact i32 %t1, %nbits ; while there, test that we *don't* propagate 'exact' 35 ret i32 %t2 36} 37 38; Vectors 39 40define <4 x i32> @t2_vec(<4 x i32> %data, <4 x i32> %nbits) { 41; CHECK-LABEL: @t2_vec( 42; CHECK-NEXT: [[T0:%.*]] = shl <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, [[NBITS:%.*]] 43; CHECK-NEXT: [[T1:%.*]] = and <4 x i32> [[T0]], [[DATA:%.*]] 44; CHECK-NEXT: [[T2:%.*]] = lshr <4 x i32> [[T1]], [[NBITS]] 45; CHECK-NEXT: ret <4 x i32> [[T2]] 46; 47 %t0 = shl <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, %nbits 48 %t1 = and <4 x i32> %t0, %data 49 %t2 = lshr <4 x i32> %t1, %nbits 50 ret <4 x i32> %t2 51} 52 53define <4 x i32> @t3_vec_undef(<4 x i32> %data, <4 x i32> %nbits) { 54; CHECK-LABEL: @t3_vec_undef( 55; CHECK-NEXT: [[T0:%.*]] = shl <4 x i32> <i32 -1, i32 -1, i32 undef, i32 -1>, [[NBITS:%.*]] 56; CHECK-NEXT: [[T1:%.*]] = and <4 x i32> [[T0]], [[DATA:%.*]] 57; CHECK-NEXT: [[T2:%.*]] = lshr <4 x i32> [[T1]], [[NBITS]] 58; CHECK-NEXT: ret <4 x i32> [[T2]] 59; 60 %t0 = shl <4 x i32> <i32 -1, i32 -1, i32 undef, i32 -1>, %nbits 61 %t1 = and <4 x i32> %t0, %data 62 %t2 = lshr <4 x i32> %t1, %nbits 63 ret <4 x i32> %t2 64} 65 66; Extra uses 67 68declare void @use32(i32) 69 70define i32 @t4_extrause0(i32 %data, i32 %nbits) { 71; CHECK-LABEL: @t4_extrause0( 72; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] 73; CHECK-NEXT: call void @use32(i32 [[T0]]) 74; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 75; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 76; CHECK-NEXT: ret i32 [[T2]] 77; 78 %t0 = shl i32 -1, %nbits 79 call void @use32(i32 %t0) 80 %t1 = and i32 %t0, %data 81 %t2 = lshr i32 %t1, %nbits 82 ret i32 %t2 83} 84 85define i32 @t5_extrause1(i32 %data, i32 %nbits) { 86; CHECK-LABEL: @t5_extrause1( 87; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] 88; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 89; CHECK-NEXT: call void @use32(i32 [[T1]]) 90; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 91; CHECK-NEXT: ret i32 [[T2]] 92; 93 %t0 = shl i32 -1, %nbits 94 %t1 = and i32 %t0, %data 95 call void @use32(i32 %t1) 96 %t2 = lshr i32 %t1, %nbits 97 ret i32 %t2 98} 99 100define i32 @t6_extrause2(i32 %data, i32 %nbits) { 101; CHECK-LABEL: @t6_extrause2( 102; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] 103; CHECK-NEXT: call void @use32(i32 [[T0]]) 104; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 105; CHECK-NEXT: call void @use32(i32 [[T1]]) 106; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 107; CHECK-NEXT: ret i32 [[T2]] 108; 109 %t0 = shl i32 -1, %nbits 110 call void @use32(i32 %t0) 111 %t1 = and i32 %t0, %data 112 call void @use32(i32 %t1) 113 %t2 = lshr i32 %t1, %nbits 114 ret i32 %t2 115} 116 117; Non-canonical mask pattern. Let's just test a single case with all-extra uses. 118 119define i32 @t7_noncanonical_lshr_lshr_extrauses(i32 %data, i32 %nbits) { 120; CHECK-LABEL: @t7_noncanonical_lshr_lshr_extrauses( 121; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[DATA:%.*]], [[NBITS:%.*]] 122; CHECK-NEXT: call void @use32(i32 [[T0]]) 123; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]] 124; CHECK-NEXT: call void @use32(i32 [[T1]]) 125; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 126; CHECK-NEXT: ret i32 [[T2]] 127; 128 %t0 = lshr i32 %data, %nbits 129 call void @use32(i32 %t0) 130 %t1 = shl i32 %t0, %nbits 131 call void @use32(i32 %t1) 132 %t2 = lshr i32 %t1, %nbits 133 ret i32 %t2 134} 135 136define i32 @t8_noncanonical_lshr_ashr_extrauses(i32 %data, i32 %nbits) { 137; CHECK-LABEL: @t8_noncanonical_lshr_ashr_extrauses( 138; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[DATA:%.*]], [[NBITS:%.*]] 139; CHECK-NEXT: call void @use32(i32 [[T0]]) 140; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]] 141; CHECK-NEXT: call void @use32(i32 [[T1]]) 142; CHECK-NEXT: [[T2:%.*]] = ashr i32 [[T1]], [[NBITS]] 143; CHECK-NEXT: ret i32 [[T2]] 144; 145 %t0 = lshr i32 %data, %nbits 146 call void @use32(i32 %t0) 147 %t1 = shl i32 %t0, %nbits 148 call void @use32(i32 %t1) 149 %t2 = ashr i32 %t1, %nbits 150 ret i32 %t2 151} 152 153define i32 @t9_noncanonical_ashr_lshr_extrauses(i32 %data, i32 %nbits) { 154; CHECK-LABEL: @t9_noncanonical_ashr_lshr_extrauses( 155; CHECK-NEXT: [[T0:%.*]] = ashr i32 [[DATA:%.*]], [[NBITS:%.*]] 156; CHECK-NEXT: call void @use32(i32 [[T0]]) 157; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]] 158; CHECK-NEXT: call void @use32(i32 [[T1]]) 159; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 160; CHECK-NEXT: ret i32 [[T2]] 161; 162 %t0 = ashr i32 %data, %nbits 163 call void @use32(i32 %t0) 164 %t1 = shl i32 %t0, %nbits 165 call void @use32(i32 %t1) 166 %t2 = lshr i32 %t1, %nbits 167 ret i32 %t2 168} 169 170define i32 @t10_noncanonical_ashr_ashr_extrauses(i32 %data, i32 %nbits) { 171; CHECK-LABEL: @t10_noncanonical_ashr_ashr_extrauses( 172; CHECK-NEXT: [[T0:%.*]] = ashr i32 [[DATA:%.*]], [[NBITS:%.*]] 173; CHECK-NEXT: call void @use32(i32 [[T0]]) 174; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS]] 175; CHECK-NEXT: call void @use32(i32 [[T1]]) 176; CHECK-NEXT: [[T2:%.*]] = ashr i32 [[T1]], [[NBITS]] 177; CHECK-NEXT: ret i32 [[T2]] 178; 179 %t0 = ashr i32 %data, %nbits 180 call void @use32(i32 %t0) 181 %t1 = shl i32 %t0, %nbits 182 call void @use32(i32 %t1) 183 %t2 = ashr i32 %t1, %nbits 184 ret i32 %t2 185} 186 187; Commutativity 188 189declare i32 @gen32() 190 191define i32 @t11_commutative(i32 %nbits) { 192; CHECK-LABEL: @t11_commutative( 193; CHECK-NEXT: [[DATA:%.*]] = call i32 @gen32() 194; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] 195; CHECK-NEXT: [[T1:%.*]] = and i32 [[DATA]], [[T0]] 196; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 197; CHECK-NEXT: ret i32 [[T2]] 198; 199 %data = call i32 @gen32() 200 %t0 = shl i32 -1, %nbits 201 %t1 = and i32 %data, %t0 ; swapped 202 %t2 = lshr i32 %t1, %nbits 203 ret i32 %t2 204} 205 206; Negative tests 207 208define i32 @n12(i32 %data, i32 %nbits) { 209; CHECK-LABEL: @n12( 210; CHECK-NEXT: [[T0:%.*]] = shl i32 2147483647, [[NBITS:%.*]] 211; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 212; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS]] 213; CHECK-NEXT: ret i32 [[T2]] 214; 215 %t0 = shl i32 2147483647, %nbits ; must be shifting -1 216 %t1 = and i32 %t0, %data 217 %t2 = lshr i32 %t1, %nbits 218 ret i32 %t2 219} 220 221define i32 @n13(i32 %data, i32 %nbits0, i32 %nbits1) { 222; CHECK-LABEL: @n13( 223; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS0:%.*]] 224; CHECK-NEXT: [[T1:%.*]] = and i32 [[T0]], [[DATA:%.*]] 225; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS1:%.*]] 226; CHECK-NEXT: ret i32 [[T2]] 227; 228 %t0 = shl i32 -1, %nbits0 229 %t1 = and i32 %t0, %data 230 %t2 = lshr i32 %t1, %nbits1 ; different shift amounts 231 ret i32 %t2 232} 233 234define i32 @n14(i32 %data, i32 %nbits0, i32 %nbits1, i32 %nbits2) { 235; CHECK-LABEL: @n14( 236; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[DATA:%.*]], [[NBITS0:%.*]] 237; CHECK-NEXT: call void @use32(i32 [[T0]]) 238; CHECK-NEXT: [[T1:%.*]] = shl i32 [[T0]], [[NBITS1:%.*]] 239; CHECK-NEXT: call void @use32(i32 [[T1]]) 240; CHECK-NEXT: [[T2:%.*]] = lshr i32 [[T1]], [[NBITS2:%.*]] 241; CHECK-NEXT: ret i32 [[T2]] 242; 243 %t0 = lshr i32 %data, %nbits0 244 call void @use32(i32 %t0) 245 %t1 = shl i32 %t0, %nbits1 ; different shift amounts 246 call void @use32(i32 %t1) 247 %t2 = lshr i32 %t1, %nbits2 ; different shift amounts 248 ret i32 %t2 249} 250