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 & C s< x 8; Should be transformed into: 9; x s> C 10; Iff: isPowerOf2(C + 1) 11; C must not be -1, but may be 0. 12 13; ============================================================================ ; 14; Basic positive tests 15; ============================================================================ ; 16 17define i1 @p0(i8 %x) { 18; CHECK-LABEL: @p0( 19; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 3 20; CHECK-NEXT: ret i1 [[TMP1]] 21; 22 %tmp0 = and i8 %x, 3 23 %ret = icmp slt i8 %tmp0, %x 24 ret i1 %ret 25} 26 27; ============================================================================ ; 28; Vector tests 29; ============================================================================ ; 30 31define <2 x i1> @p1_vec_splat(<2 x i8> %x) { 32; CHECK-LABEL: @p1_vec_splat( 33; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 3, i8 3> 34; CHECK-NEXT: ret <2 x i1> [[TMP1]] 35; 36 %tmp0 = and <2 x i8> %x, <i8 3, i8 3> 37 %ret = icmp slt <2 x i8> %tmp0, %x 38 ret <2 x i1> %ret 39} 40 41define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { 42; CHECK-LABEL: @p2_vec_nonsplat( 43; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 3, i8 15> 44; CHECK-NEXT: ret <2 x i1> [[TMP1]] 45; 46 %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat. 47 %ret = icmp slt <2 x i8> %tmp0, %x 48 ret <2 x i1> %ret 49} 50 51define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) { 52; CHECK-LABEL: @p2_vec_nonsplat_edgecase( 53; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 0> 54; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]] 55; CHECK-NEXT: ret <2 x i1> [[RET]] 56; 57 %tmp0 = and <2 x i8> %x, <i8 3, i8 0> 58 %ret = icmp slt <2 x i8> %tmp0, %x 59 ret <2 x i1> %ret 60} 61 62define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) { 63; CHECK-LABEL: @p3_vec_splat_undef( 64; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 3, i8 3, i8 3> 65; CHECK-NEXT: ret <3 x i1> [[TMP1]] 66; 67 %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 3> 68 %ret = icmp slt <3 x i8> %tmp0, %x 69 ret <3 x i1> %ret 70} 71 72define <3 x i1> @p3_vec_nonsplat_undef(<3 x i8> %x) { 73; CHECK-LABEL: @p3_vec_nonsplat_undef( 74; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 15, i8 15, i8 3> 75; CHECK-NEXT: ret <3 x i1> [[TMP1]] 76; 77 %tmp0 = and <3 x i8> %x, <i8 undef, i8 15, i8 3> 78 %ret = icmp slt <3 x i8> %tmp0, %x 79 ret <3 x i1> %ret 80} 81 82; ============================================================================ ; 83; One-use tests. We don't care about multi-uses here. 84; ============================================================================ ; 85 86declare void @use8(i8) 87 88define i1 @oneuse0(i8 %x) { 89; CHECK-LABEL: @oneuse0( 90; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3 91; CHECK-NEXT: call void @use8(i8 [[TMP0]]) 92; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X]], 3 93; CHECK-NEXT: ret i1 [[TMP1]] 94; 95 %tmp0 = and i8 %x, 3 96 call void @use8(i8 %tmp0) 97 %ret = icmp slt i8 %tmp0, %x 98 ret i1 %ret 99} 100 101; ============================================================================ ; 102; Negative tests 103; ============================================================================ ; 104 105; Commutativity tests. 106 107declare i8 @gen8() 108 109define i1 @c0() { 110; CHECK-LABEL: @c0( 111; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 112; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 3 113; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP0]] 114; CHECK-NEXT: ret i1 [[RET]] 115; 116 %x = call i8 @gen8() 117 %tmp0 = and i8 %x, 3 118 %ret = icmp slt i8 %x, %tmp0 ; swapped order 119 ret i1 %ret 120} 121 122; ============================================================================ ; 123; Rest of negative tests 124; ============================================================================ ; 125 126define i1 @n0(i8 %x) { 127; CHECK-LABEL: @n0( 128; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4 129; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP0]], [[X]] 130; CHECK-NEXT: ret i1 [[RET]] 131; 132 %tmp0 = and i8 %x, 4 ; power-of-two, but invalid. 133 %ret = icmp slt i8 %tmp0, %x 134 ret i1 %ret 135} 136 137define i1 @n1(i8 %x, i8 %y, i8 %notx) { 138; CHECK-LABEL: @n1( 139; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3 140; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP0]], [[NOTX:%.*]] 141; CHECK-NEXT: ret i1 [[RET]] 142; 143 %tmp0 = and i8 %x, 3 144 %ret = icmp slt i8 %tmp0, %notx ; not %x 145 ret i1 %ret 146} 147 148define <2 x i1> @n2(<2 x i8> %x) { 149; CHECK-LABEL: @n2( 150; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16> 151; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]] 152; CHECK-NEXT: ret <2 x i1> [[RET]] 153; 154 %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid. 155 %ret = icmp slt <2 x i8> %tmp0, %x 156 ret <2 x i1> %ret 157} 158 159; ============================================================================ ; 160; Potential miscompiles. 161; ============================================================================ ; 162 163define i1 @nv(i8 %x, i8 %y) { 164; CHECK-LABEL: @nv( 165; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 166; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]] 167; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP1]], [[X]] 168; CHECK-NEXT: ret i1 [[RET]] 169; 170 %tmp0 = lshr i8 -1, %y 171 %tmp1 = and i8 %tmp0, %x 172 %ret = icmp slt i8 %tmp1, %x 173 ret i1 %ret 174} 175 176define <2 x i1> @n3(<2 x i8> %x) { 177; CHECK-LABEL: @n3( 178; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 -1> 179; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]] 180; CHECK-NEXT: ret <2 x i1> [[RET]] 181; 182 %tmp0 = and <2 x i8> %x, <i8 3, i8 -1> 183 %ret = icmp slt <2 x i8> %tmp0, %x 184 ret <2 x i1> %ret 185} 186 187define <3 x i1> @n4(<3 x i8> %x) { 188; CHECK-LABEL: @n4( 189; CHECK-NEXT: [[TMP0:%.*]] = and <3 x i8> [[X:%.*]], <i8 3, i8 undef, i8 -1> 190; CHECK-NEXT: [[RET:%.*]] = icmp slt <3 x i8> [[TMP0]], [[X]] 191; CHECK-NEXT: ret <3 x i1> [[RET]] 192; 193 %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 -1> 194 %ret = icmp slt <3 x i8> %tmp0, %x 195 ret <3 x i1> %ret 196} 197 198; Commutativity tests with variable 199 200define i1 @cv0(i8 %y) { 201; CHECK-LABEL: @cv0( 202; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 203; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 204; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]] 205; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP1]], [[X]] 206; CHECK-NEXT: ret i1 [[RET]] 207; 208 %x = call i8 @gen8() 209 %tmp0 = lshr i8 -1, %y 210 %tmp1 = and i8 %x, %tmp0 ; swapped order 211 %ret = icmp slt i8 %tmp1, %x 212 ret i1 %ret 213} 214 215define i1 @cv1(i8 %y) { 216; CHECK-LABEL: @cv1( 217; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 218; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 219; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X]] 220; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP1]] 221; CHECK-NEXT: ret i1 [[RET]] 222; 223 %x = call i8 @gen8() 224 %tmp0 = lshr i8 -1, %y 225 %tmp1 = and i8 %tmp0, %x 226 %ret = icmp slt i8 %x, %tmp1 ; swapped order 227 ret i1 %ret 228} 229 230define i1 @cv2(i8 %y) { 231; CHECK-LABEL: @cv2( 232; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 233; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 234; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]] 235; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP1]] 236; CHECK-NEXT: ret i1 [[RET]] 237; 238 %x = call i8 @gen8() 239 %tmp0 = lshr i8 -1, %y 240 %tmp1 = and i8 %x, %tmp0 ; swapped order 241 %ret = icmp slt i8 %x, %tmp1 ; swapped order 242 ret i1 %ret 243} 244