232 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; https://bugs.llvm.org/show_bug.cgi?id=381235 6; Pattern:7; x & C s>= x8; Should be transformed into:9; x s<= C10; Iff: isPowerOf2(C + 1)11; C must not be -1, but may be 0.12 13; ============================================================================ ;14; Basic positive tests15; ============================================================================ ;16 17define i1 @p0(i8 %x) {18; CHECK-LABEL: @p0(19; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X:%.*]], 420; CHECK-NEXT: ret i1 [[RET]]21;22 %tmp0 = and i8 %x, 323 %ret = icmp sge i8 %tmp0, %x24 ret i1 %ret25}26 27; ============================================================================ ;28; Vector tests29; ============================================================================ ;30 31define <2 x i1> @p1_vec_splat(<2 x i8> %x) {32; CHECK-LABEL: @p1_vec_splat(33; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X:%.*]], splat (i8 4)34; CHECK-NEXT: ret <2 x i1> [[RET]]35;36 %tmp0 = and <2 x i8> %x, <i8 3, i8 3>37 %ret = icmp sge <2 x i8> %tmp0, %x38 ret <2 x i1> %ret39}40 41define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) {42; CHECK-LABEL: @p2_vec_nonsplat(43; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 4, i8 16>44; CHECK-NEXT: ret <2 x i1> [[RET]]45;46 %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat.47 %ret = icmp sge <2 x i8> %tmp0, %x48 ret <2 x i1> %ret49}50 51define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) {52; CHECK-LABEL: @p2_vec_nonsplat_edgecase(53; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 4, i8 1>54; CHECK-NEXT: ret <2 x i1> [[RET]]55;56 %tmp0 = and <2 x i8> %x, <i8 3, i8 0>57 %ret = icmp sge <2 x i8> %tmp0, %x58 ret <2 x i1> %ret59}60 61define <3 x i1> @p3_vec_splat_poison(<3 x i8> %x) {62; CHECK-LABEL: @p3_vec_splat_poison(63; CHECK-NEXT: [[RET:%.*]] = icmp slt <3 x i8> [[X:%.*]], splat (i8 4)64; CHECK-NEXT: ret <3 x i1> [[RET]]65;66 %tmp0 = and <3 x i8> %x, <i8 3, i8 poison, i8 3>67 %ret = icmp sge <3 x i8> %tmp0, %x68 ret <3 x i1> %ret69}70 71; ============================================================================ ;72; One-use tests. We don't care about multi-uses here.73; ============================================================================ ;74 75declare void @use8(i8)76 77define i1 @oneuse0(i8 %x) {78; CHECK-LABEL: @oneuse0(79; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 380; CHECK-NEXT: call void @use8(i8 [[TMP0]])81; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], 482; CHECK-NEXT: ret i1 [[RET]]83;84 %tmp0 = and i8 %x, 385 call void @use8(i8 %tmp0)86 %ret = icmp sge i8 %tmp0, %x87 ret i1 %ret88}89 90; ============================================================================ ;91; Negative tests92; ============================================================================ ;93 94; Commutativity tests.95 96declare i8 @gen8()97 98define i1 @c0() {99; CHECK-LABEL: @c0(100; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()101; CHECK-NEXT: [[RET:%.*]] = icmp sgt i8 [[X]], -1102; CHECK-NEXT: ret i1 [[RET]]103;104 %x = call i8 @gen8()105 %tmp0 = and i8 %x, 3106 %ret = icmp sge i8 %x, %tmp0 ; swapped order107 ret i1 %ret108}109 110; ============================================================================ ;111; Rest of negative tests112; ============================================================================ ;113 114define i1 @n0(i8 %x) {115; CHECK-LABEL: @n0(116; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4117; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP0]], [[X]]118; CHECK-NEXT: ret i1 [[RET]]119;120 %tmp0 = and i8 %x, 4 ; power-of-two, but invalid.121 %ret = icmp sge i8 %tmp0, %x122 ret i1 %ret123}124 125define i1 @n1(i8 %x, i8 %y, i8 %notx) {126; CHECK-LABEL: @n1(127; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3128; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP0]], [[NOTX:%.*]]129; CHECK-NEXT: ret i1 [[RET]]130;131 %tmp0 = and i8 %x, 3132 %ret = icmp sge i8 %tmp0, %notx ; not %x133 ret i1 %ret134}135 136define <2 x i1> @n2(<2 x i8> %x) {137; CHECK-LABEL: @n2(138; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16>139; CHECK-NEXT: [[RET:%.*]] = icmp sge <2 x i8> [[TMP0]], [[X]]140; CHECK-NEXT: ret <2 x i1> [[RET]]141;142 %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.143 %ret = icmp sge <2 x i8> %tmp0, %x144 ret <2 x i1> %ret145}146 147; ============================================================================ ;148; Potential miscompiles.149; ============================================================================ ;150 151define i1 @nv(i8 %x, i8 %y) {152; CHECK-LABEL: @nv(153; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]154; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]]155; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP1]], [[X]]156; CHECK-NEXT: ret i1 [[RET]]157;158 %tmp0 = lshr i8 -1, %y159 %tmp1 = and i8 %tmp0, %x160 %ret = icmp sge i8 %tmp1, %x161 ret i1 %ret162}163 164define <2 x i1> @n3_vec(<2 x i8> %x) {165; CHECK-LABEL: @n3_vec(166; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 -1>167; CHECK-NEXT: [[RET:%.*]] = icmp sge <2 x i8> [[TMP0]], [[X]]168; CHECK-NEXT: ret <2 x i1> [[RET]]169;170 %tmp0 = and <2 x i8> %x, <i8 3, i8 -1>171 %ret = icmp sge <2 x i8> %tmp0, %x172 ret <2 x i1> %ret173}174 175define <3 x i1> @n4_vec(<3 x i8> %x) {176; CHECK-LABEL: @n4_vec(177; CHECK-NEXT: [[TMP0:%.*]] = and <3 x i8> [[X:%.*]], <i8 3, i8 poison, i8 -1>178; CHECK-NEXT: [[RET:%.*]] = icmp sge <3 x i8> [[TMP0]], [[X]]179; CHECK-NEXT: ret <3 x i1> [[RET]]180;181 %tmp0 = and <3 x i8> %x, <i8 3, i8 poison, i8 -1>182 %ret = icmp sge <3 x i8> %tmp0, %x183 ret <3 x i1> %ret184}185 186; Commutativity tests with variable187 188define i1 @cv0(i8 %y) {189; CHECK-LABEL: @cv0(190; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()191; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]192; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]]193; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP1]], [[X]]194; CHECK-NEXT: ret i1 [[RET]]195;196 %x = call i8 @gen8()197 %tmp0 = lshr i8 -1, %y198 %tmp1 = and i8 %x, %tmp0 ; swapped order199 %ret = icmp sge i8 %tmp1, %x200 ret i1 %ret201}202 203define i1 @cv1(i8 %y) {204; CHECK-LABEL: @cv1(205; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()206; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]207; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X]]208; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[X]], [[TMP1]]209; CHECK-NEXT: ret i1 [[RET]]210;211 %x = call i8 @gen8()212 %tmp0 = lshr i8 -1, %y213 %tmp1 = and i8 %tmp0, %x214 %ret = icmp sge i8 %x, %tmp1 ; swapped order215 ret i1 %ret216}217 218define i1 @cv2(i8 %y) {219; CHECK-LABEL: @cv2(220; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()221; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]222; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]]223; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[X]], [[TMP1]]224; CHECK-NEXT: ret i1 [[RET]]225;226 %x = call i8 @gen8()227 %tmp0 = lshr i8 -1, %y228 %tmp1 = and i8 %x, %tmp0 ; swapped order229 %ret = icmp sge i8 %x, %tmp1 ; swapped order230 ret i1 %ret231}232