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=38708 5 6; Pattern: 7; ~(-1 << bits) u< val 8; Should be transformed into: 9; (val l>> bits) != 0 10 11; ============================================================================ ; 12; Basic positive tests 13; ============================================================================ ; 14 15define i1 @p0(i8 %val, i8 %bits) { 16; CHECK-LABEL: @p0( 17; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]] 18; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0 19; CHECK-NEXT: ret i1 [[R]] 20; 21 %t0 = shl i8 -1, %bits 22 %t1 = xor i8 %t0, -1 23 %r = icmp ult i8 %t1, %val 24 ret i1 %r 25} 26 27; ============================================================================ ; 28; Vector tests 29; ============================================================================ ; 30 31define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) { 32; CHECK-LABEL: @p1_vec( 33; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS:%.*]] 34; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[VAL_HIGHBITS]], zeroinitializer 35; CHECK-NEXT: ret <2 x i1> [[R]] 36; 37 %t0 = shl <2 x i8> <i8 -1, i8 -1>, %bits 38 %t1 = xor <2 x i8> %t0, <i8 -1, i8 -1> 39 %r = icmp ult <2 x i8> %t1, %val 40 ret <2 x i1> %r 41} 42 43define <3 x i1> @p2_vec_undef0(<3 x i8> %val, <3 x i8> %bits) { 44; CHECK-LABEL: @p2_vec_undef0( 45; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]] 46; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer 47; CHECK-NEXT: ret <3 x i1> [[R]] 48; 49 %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %bits 50 %t1 = xor <3 x i8> %t0, <i8 -1, i8 -1, i8 -1> 51 %r = icmp ult <3 x i8> %t1, %val 52 ret <3 x i1> %r 53} 54 55define <3 x i1> @p2_vec_undef1(<3 x i8> %val, <3 x i8> %bits) { 56; CHECK-LABEL: @p2_vec_undef1( 57; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]] 58; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer 59; CHECK-NEXT: ret <3 x i1> [[R]] 60; 61 %t0 = shl <3 x i8> <i8 -1, i8 -1, i8 -1>, %bits 62 %t1 = xor <3 x i8> %t0, <i8 -1, i8 undef, i8 -1> 63 %r = icmp ult <3 x i8> %t1, %val 64 ret <3 x i1> %r 65} 66 67define <3 x i1> @p2_vec_undef2(<3 x i8> %val, <3 x i8> %bits) { 68; CHECK-LABEL: @p2_vec_undef2( 69; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]] 70; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer 71; CHECK-NEXT: ret <3 x i1> [[R]] 72; 73 %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %bits 74 %t1 = xor <3 x i8> %t0, <i8 -1, i8 undef, i8 -1> 75 %r = icmp ult <3 x i8> %t1, %val 76 ret <3 x i1> %r 77} 78 79; ============================================================================ ; 80; Commutativity tests. 81; ============================================================================ ; 82 83declare i8 @gen8() 84 85define i1 @c0(i8 %bits) { 86; CHECK-LABEL: @c0( 87; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8() 88; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]] 89; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0 90; CHECK-NEXT: ret i1 [[R]] 91; 92 %t0 = shl i8 -1, %bits 93 %t1 = xor i8 %t0, -1 94 %val = call i8 @gen8() 95 %r = icmp ugt i8 %val, %t1 ; swapped order and predicate 96 ret i1 %r 97} 98 99; What if we have the same pattern on both sides? 100define i1 @both(i8 %bits0, i8 %bits1) { 101; CHECK-LABEL: @both( 102; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS0:%.*]] 103; CHECK-NEXT: [[T2:%.*]] = shl i8 -1, [[BITS1:%.*]] 104; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T2]], [[T0]] 105; CHECK-NEXT: ret i1 [[R]] 106; 107 %t0 = shl i8 -1, %bits0 108 %t1 = xor i8 %t0, -1 109 %t2 = shl i8 -1, %bits1 110 %t3 = xor i8 %t2, -1 111 %r = icmp ult i8 %t1, %t3 112 ret i1 %r 113} 114 115; ============================================================================ ; 116; One-use tests. 117; ============================================================================ ; 118 119declare void @use8(i8) 120 121define i1 @oneuse0(i8 %val, i8 %bits) { 122; CHECK-LABEL: @oneuse0( 123; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]] 124; CHECK-NEXT: call void @use8(i8 [[T0]]) 125; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS]] 126; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0 127; CHECK-NEXT: ret i1 [[R]] 128; 129 %t0 = shl i8 -1, %bits 130 call void @use8(i8 %t0) 131 %t1 = xor i8 %t0, -1 132 %r = icmp ult i8 %t1, %val 133 ret i1 %r 134} 135 136define i1 @oneuse1(i8 %val, i8 %bits) { 137; CHECK-LABEL: @oneuse1( 138; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]] 139; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 140; CHECK-NEXT: call void @use8(i8 [[T1]]) 141; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]] 142; CHECK-NEXT: ret i1 [[R]] 143; 144 %t0 = shl i8 -1, %bits 145 %t1 = xor i8 %t0, -1 146 call void @use8(i8 %t1) 147 %r = icmp ult i8 %t1, %val 148 ret i1 %r 149} 150 151define i1 @oneuse2(i8 %val, i8 %bits) { 152; CHECK-LABEL: @oneuse2( 153; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]] 154; CHECK-NEXT: call void @use8(i8 [[T0]]) 155; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 156; CHECK-NEXT: call void @use8(i8 [[T1]]) 157; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]] 158; CHECK-NEXT: ret i1 [[R]] 159; 160 %t0 = shl i8 -1, %bits 161 call void @use8(i8 %t0) 162 %t1 = xor i8 %t0, -1 163 call void @use8(i8 %t1) 164 %r = icmp ult i8 %t1, %val 165 ret i1 %r 166} 167 168; ============================================================================ ; 169; Negative tests 170; ============================================================================ ; 171 172define i1 @n0(i8 %val, i8 %bits) { 173; CHECK-LABEL: @n0( 174; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]] 175; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 176; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]] 177; CHECK-NEXT: ret i1 [[R]] 178; 179 %t0 = shl i8 1, %bits ; constant is not -1 180 %t1 = xor i8 %t0, -1 181 %r = icmp ult i8 %t1, %val 182 ret i1 %r 183} 184 185define i1 @n1(i8 %val, i8 %bits) { 186; CHECK-LABEL: @n1( 187; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]] 188; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1 189; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]] 190; CHECK-NEXT: ret i1 [[R]] 191; 192 %t0 = shl i8 -1, %bits 193 %t1 = xor i8 %t0, 1 ; not 'not' 194 %r = icmp ult i8 %t1, %val 195 ret i1 %r 196} 197 198define <2 x i1> @n2_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) { 199; CHECK-LABEL: @n2_vec_nonsplat( 200; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 1>, [[BITS:%.*]] 201; CHECK-NEXT: [[T1:%.*]] = xor <2 x i8> [[T0]], <i8 -1, i8 -1> 202; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]] 203; CHECK-NEXT: ret <2 x i1> [[R]] 204; 205 %t0 = shl <2 x i8> <i8 -1, i8 1>, %bits ; again, wrong constant 206 %t1 = xor <2 x i8> %t0, <i8 -1, i8 -1> 207 %r = icmp ult <2 x i8> %t1, %val 208 ret <2 x i1> %r 209} 210 211define <2 x i1> @n3_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) { 212; CHECK-LABEL: @n3_vec_nonsplat( 213; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[BITS:%.*]] 214; CHECK-NEXT: [[T1:%.*]] = xor <2 x i8> [[T0]], <i8 -1, i8 1> 215; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]] 216; CHECK-NEXT: ret <2 x i1> [[R]] 217; 218 %t0 = shl <2 x i8> <i8 -1, i8 -1>, %bits 219 %t1 = xor <2 x i8> %t0, <i8 -1, i8 1> ; again, wrong constant 220 %r = icmp ult <2 x i8> %t1, %val 221 ret <2 x i1> %r 222} 223 224define i1 @n3(i8 %val, i8 %bits) { 225; CHECK-LABEL: @n3( 226; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]] 227; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 228; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T1]], [[VAL:%.*]] 229; CHECK-NEXT: ret i1 [[R]] 230; 231 %t0 = shl i8 -1, %bits 232 %t1 = xor i8 %t0, -1 233 %r = icmp ule i8 %t1, %val ; wrong predicate 234 ret i1 %r 235} 236 237define i1 @n4(i8 %bits) { 238; CHECK-LABEL: @n4( 239; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]] 240; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1 241; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8() 242; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[VAL]], [[T1]] 243; CHECK-NEXT: ret i1 [[R]] 244; 245 %t0 = shl i8 -1, %bits 246 %t1 = xor i8 %t0, -1 247 %val = call i8 @gen8() 248 %r = icmp uge i8 %val, %t1 ; swapped order and [wrong] predicate 249 ret i1 %r 250} 251