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