1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; https://bugs.llvm.org/show_bug.cgi?id=38149 5 6; Pattern: 7; ((%x << MaskedBits) a>> MaskedBits) == %x 8; Should be transformed into: 9; (add %x, (1 << (KeptBits-1))) u< (1 << KeptBits) 10; Where KeptBits = bitwidth(%x) - MaskedBits 11 12; ============================================================================ ; 13; Basic positive tests 14; ============================================================================ ; 15 16define i1 @p0(i8 %x) { 17; CHECK-LABEL: @p0( 18; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 4 19; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 8 20; CHECK-NEXT: ret i1 [[TMP2]] 21; 22 %tmp0 = shl i8 %x, 5 23 %tmp1 = ashr exact i8 %tmp0, 5 24 %tmp2 = icmp eq i8 %tmp1, %x 25 ret i1 %tmp2 26} 27 28; Big unusual bit width, https://bugs.llvm.org/show_bug.cgi?id=38204 29define i1 @pb(i65 %x) { 30; CHECK-LABEL: @pb( 31; CHECK-NEXT: [[TMP1:%.*]] = add i65 [[X:%.*]], 9223372036854775808 32; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i65 [[TMP1]], -1 33; CHECK-NEXT: ret i1 [[TMP2]] 34; 35 %tmp0 = shl i65 %x, 1 36 %tmp1 = ashr exact i65 %tmp0, 1 37 %tmp2 = icmp eq i65 %x, %tmp1 38 ret i1 %tmp2 39} 40 41; ============================================================================ ; 42; Vector tests 43; ============================================================================ ; 44 45define <2 x i1> @p1_vec_splat(<2 x i8> %x) { 46; CHECK-LABEL: @p1_vec_splat( 47; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 4, i8 4> 48; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i8> [[TMP1]], <i8 8, i8 8> 49; CHECK-NEXT: ret <2 x i1> [[TMP2]] 50; 51 %tmp0 = shl <2 x i8> %x, <i8 5, i8 5> 52 %tmp1 = ashr exact <2 x i8> %tmp0, <i8 5, i8 5> 53 %tmp2 = icmp eq <2 x i8> %tmp1, %x 54 ret <2 x i1> %tmp2 55} 56 57define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { 58; CHECK-LABEL: @p2_vec_nonsplat( 59; CHECK-NEXT: [[TMP0:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 6> 60; CHECK-NEXT: [[TMP1:%.*]] = ashr exact <2 x i8> [[TMP0]], <i8 5, i8 6> 61; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], [[X]] 62; CHECK-NEXT: ret <2 x i1> [[TMP2]] 63; 64 %tmp0 = shl <2 x i8> %x, <i8 5, i8 6> 65 %tmp1 = ashr exact <2 x i8> %tmp0, <i8 5, i8 6> 66 %tmp2 = icmp eq <2 x i8> %tmp1, %x 67 ret <2 x i1> %tmp2 68} 69 70define <3 x i1> @p3_vec_undef0(<3 x i8> %x) { 71; CHECK-LABEL: @p3_vec_undef0( 72; CHECK-NEXT: [[TMP0:%.*]] = shl <3 x i8> [[X:%.*]], <i8 5, i8 undef, i8 5> 73; CHECK-NEXT: [[TMP1:%.*]] = ashr exact <3 x i8> [[TMP0]], <i8 5, i8 5, i8 5> 74; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <3 x i8> [[TMP1]], [[X]] 75; CHECK-NEXT: ret <3 x i1> [[TMP2]] 76; 77 %tmp0 = shl <3 x i8> %x, <i8 5, i8 undef, i8 5> 78 %tmp1 = ashr exact <3 x i8> %tmp0, <i8 5, i8 5, i8 5> 79 %tmp2 = icmp eq <3 x i8> %tmp1, %x 80 ret <3 x i1> %tmp2 81} 82 83define <3 x i1> @p4_vec_undef1(<3 x i8> %x) { 84; CHECK-LABEL: @p4_vec_undef1( 85; CHECK-NEXT: [[TMP0:%.*]] = shl <3 x i8> [[X:%.*]], <i8 5, i8 5, i8 5> 86; CHECK-NEXT: [[TMP1:%.*]] = ashr exact <3 x i8> [[TMP0]], <i8 5, i8 undef, i8 5> 87; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <3 x i8> [[TMP1]], [[X]] 88; CHECK-NEXT: ret <3 x i1> [[TMP2]] 89; 90 %tmp0 = shl <3 x i8> %x, <i8 5, i8 5, i8 5> 91 %tmp1 = ashr exact <3 x i8> %tmp0, <i8 5, i8 undef, i8 5> 92 %tmp2 = icmp eq <3 x i8> %tmp1, %x 93 ret <3 x i1> %tmp2 94} 95 96define <3 x i1> @p5_vec_undef2(<3 x i8> %x) { 97; CHECK-LABEL: @p5_vec_undef2( 98; CHECK-NEXT: [[TMP0:%.*]] = shl <3 x i8> [[X:%.*]], <i8 5, i8 undef, i8 5> 99; CHECK-NEXT: [[TMP1:%.*]] = ashr exact <3 x i8> [[TMP0]], <i8 5, i8 undef, i8 5> 100; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <3 x i8> [[TMP1]], [[X]] 101; CHECK-NEXT: ret <3 x i1> [[TMP2]] 102; 103 %tmp0 = shl <3 x i8> %x, <i8 5, i8 undef, i8 5> 104 %tmp1 = ashr exact <3 x i8> %tmp0, <i8 5, i8 undef, i8 5> 105 %tmp2 = icmp eq <3 x i8> %tmp1, %x 106 ret <3 x i1> %tmp2 107} 108 109; ============================================================================ ; 110; Commutativity tests. 111; ============================================================================ ; 112 113declare i8 @gen8() 114 115define i1 @c0() { 116; CHECK-LABEL: @c0( 117; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 118; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], 4 119; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 8 120; CHECK-NEXT: ret i1 [[TMP2]] 121; 122 %x = call i8 @gen8() 123 %tmp0 = shl i8 %x, 5 124 %tmp1 = ashr exact i8 %tmp0, 5 125 %tmp2 = icmp eq i8 %x, %tmp1 ; swapped order 126 ret i1 %tmp2 127} 128 129; ============================================================================ ; 130; One-use tests. 131; ============================================================================ ; 132 133declare void @use8(i8) 134 135define i1 @n_oneuse0(i8 %x) { 136; CHECK-LABEL: @n_oneuse0( 137; CHECK-NEXT: [[TMP0:%.*]] = shl i8 [[X:%.*]], 5 138; CHECK-NEXT: call void @use8(i8 [[TMP0]]) 139; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X]], 4 140; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 8 141; CHECK-NEXT: ret i1 [[TMP2]] 142; 143 %tmp0 = shl i8 %x, 5 144 call void @use8(i8 %tmp0) 145 %tmp1 = ashr exact i8 %tmp0, 5 146 %tmp2 = icmp eq i8 %tmp1, %x 147 ret i1 %tmp2 148} 149 150define i1 @n_oneuse1(i8 %x) { 151; CHECK-LABEL: @n_oneuse1( 152; CHECK-NEXT: [[TMP0:%.*]] = shl i8 [[X:%.*]], 5 153; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 5 154; CHECK-NEXT: call void @use8(i8 [[TMP1]]) 155; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[X]] 156; CHECK-NEXT: ret i1 [[TMP2]] 157; 158 %tmp0 = shl i8 %x, 5 159 %tmp1 = ashr exact i8 %tmp0, 5 160 call void @use8(i8 %tmp1) 161 %tmp2 = icmp eq i8 %tmp1, %x 162 ret i1 %tmp2 163} 164 165define i1 @n_oneuse2(i8 %x) { 166; CHECK-LABEL: @n_oneuse2( 167; CHECK-NEXT: [[TMP0:%.*]] = shl i8 [[X:%.*]], 5 168; CHECK-NEXT: call void @use8(i8 [[TMP0]]) 169; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 5 170; CHECK-NEXT: call void @use8(i8 [[TMP1]]) 171; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[X]] 172; CHECK-NEXT: ret i1 [[TMP2]] 173; 174 %tmp0 = shl i8 %x, 5 175 call void @use8(i8 %tmp0) 176 %tmp1 = ashr exact i8 %tmp0, 5 177 call void @use8(i8 %tmp1) 178 %tmp2 = icmp eq i8 %tmp1, %x 179 ret i1 %tmp2 180} 181 182; ============================================================================ ; 183; Negative tests 184; ============================================================================ ; 185 186define i1 @n0(i8 %x) { 187; CHECK-LABEL: @n0( 188; CHECK-NEXT: [[TMP0:%.*]] = shl i8 [[X:%.*]], 5 189; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 3 190; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[X]] 191; CHECK-NEXT: ret i1 [[TMP2]] 192; 193 %tmp0 = shl i8 %x, 5 194 %tmp1 = ashr exact i8 %tmp0, 3 ; not 5 195 %tmp2 = icmp eq i8 %tmp1, %x 196 ret i1 %tmp2 197} 198 199define i1 @n1(i8 %x) { 200; CHECK-LABEL: @n1( 201; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 8 202; CHECK-NEXT: ret i1 [[TMP1]] 203; 204 %tmp0 = shl i8 %x, 5 205 %tmp1 = lshr exact i8 %tmp0, 5 ; not ashr 206 %tmp2 = icmp eq i8 %tmp1, %x 207 ret i1 %tmp2 208} 209 210define i1 @n2(i8 %x, i8 %y) { 211; CHECK-LABEL: @n2( 212; CHECK-NEXT: [[TMP0:%.*]] = shl i8 [[X:%.*]], 5 213; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 5 214; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[Y:%.*]] 215; CHECK-NEXT: ret i1 [[TMP2]] 216; 217 %tmp0 = shl i8 %x, 5 218 %tmp1 = ashr exact i8 %tmp0, 5 219 %tmp2 = icmp eq i8 %tmp1, %y ; not %x 220 ret i1 %tmp2 221} 222 223define <2 x i1> @n3_vec_nonsplat(<2 x i8> %x) { 224; CHECK-LABEL: @n3_vec_nonsplat( 225; CHECK-NEXT: [[TMP0:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 5> 226; CHECK-NEXT: [[TMP1:%.*]] = ashr exact <2 x i8> [[TMP0]], <i8 5, i8 3> 227; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], [[X]] 228; CHECK-NEXT: ret <2 x i1> [[TMP2]] 229; 230 %tmp0 = shl <2 x i8> %x, <i8 5, i8 5> 231 %tmp1 = ashr exact <2 x i8> %tmp0, <i8 5, i8 3> ; 3 instead of 5 232 %tmp2 = icmp eq <2 x i8> %tmp1, %x 233 ret <2 x i1> %tmp2 234} 235