242 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 sgt i8 [[X:%.*]], 320; CHECK-NEXT: ret i1 [[RET]]21;22 %tmp0 = and i8 %x, 323 %ret = icmp slt 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 sgt <2 x i8> [[X:%.*]], splat (i8 3)34; CHECK-NEXT: ret <2 x i1> [[RET]]35;36 %tmp0 = and <2 x i8> %x, <i8 3, i8 3>37 %ret = icmp slt <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 sgt <2 x i8> [[X:%.*]], <i8 3, i8 15>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 slt <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 sgt <2 x i8> [[X:%.*]], <i8 3, i8 0>54; CHECK-NEXT: ret <2 x i1> [[RET]]55;56 %tmp0 = and <2 x i8> %x, <i8 3, i8 0>57 %ret = icmp slt <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 sgt <3 x i8> [[X:%.*]], <i8 3, i8 poison, i8 3>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 slt <3 x i8> %tmp0, %x68 ret <3 x i1> %ret69}70 71define <3 x i1> @p3_vec_nonsplat_poison(<3 x i8> %x) {72; CHECK-LABEL: @p3_vec_nonsplat_poison(73; CHECK-NEXT: [[RET:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 poison, i8 15, i8 3>74; CHECK-NEXT: ret <3 x i1> [[RET]]75;76 %tmp0 = and <3 x i8> %x, <i8 poison, i8 15, i8 3>77 %ret = icmp slt <3 x i8> %tmp0, %x78 ret <3 x i1> %ret79}80 81; ============================================================================ ;82; One-use tests. We don't care about multi-uses here.83; ============================================================================ ;84 85declare void @use8(i8)86 87define i1 @oneuse0(i8 %x) {88; CHECK-LABEL: @oneuse0(89; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 390; CHECK-NEXT: call void @use8(i8 [[TMP0]])91; CHECK-NEXT: [[RET:%.*]] = icmp sgt i8 [[X]], 392; CHECK-NEXT: ret i1 [[RET]]93;94 %tmp0 = and i8 %x, 395 call void @use8(i8 %tmp0)96 %ret = icmp slt i8 %tmp0, %x97 ret i1 %ret98}99 100; ============================================================================ ;101; Negative tests102; ============================================================================ ;103 104; Commutativity tests.105 106declare i8 @gen8()107 108define i1 @c0() {109; CHECK-LABEL: @c0(110; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()111; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], 0112; CHECK-NEXT: ret i1 [[RET]]113;114 %x = call i8 @gen8()115 %tmp0 = and i8 %x, 3116 %ret = icmp slt i8 %x, %tmp0 ; swapped order117 ret i1 %ret118}119 120; ============================================================================ ;121; Rest of negative tests122; ============================================================================ ;123 124define i1 @n0(i8 %x) {125; CHECK-LABEL: @n0(126; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4127; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP0]], [[X]]128; CHECK-NEXT: ret i1 [[RET]]129;130 %tmp0 = and i8 %x, 4 ; power-of-two, but invalid.131 %ret = icmp slt i8 %tmp0, %x132 ret i1 %ret133}134 135define i1 @n1(i8 %x, i8 %y, i8 %notx) {136; CHECK-LABEL: @n1(137; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3138; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP0]], [[NOTX:%.*]]139; CHECK-NEXT: ret i1 [[RET]]140;141 %tmp0 = and i8 %x, 3142 %ret = icmp slt i8 %tmp0, %notx ; not %x143 ret i1 %ret144}145 146define <2 x i1> @n2(<2 x i8> %x) {147; CHECK-LABEL: @n2(148; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16>149; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]]150; CHECK-NEXT: ret <2 x i1> [[RET]]151;152 %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.153 %ret = icmp slt <2 x i8> %tmp0, %x154 ret <2 x i1> %ret155}156 157; ============================================================================ ;158; Potential miscompiles.159; ============================================================================ ;160 161define i1 @nv(i8 %x, i8 %y) {162; CHECK-LABEL: @nv(163; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]164; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]]165; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP1]], [[X]]166; CHECK-NEXT: ret i1 [[RET]]167;168 %tmp0 = lshr i8 -1, %y169 %tmp1 = and i8 %tmp0, %x170 %ret = icmp slt i8 %tmp1, %x171 ret i1 %ret172}173 174define <2 x i1> @n3(<2 x i8> %x) {175; CHECK-LABEL: @n3(176; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 -1>177; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]]178; CHECK-NEXT: ret <2 x i1> [[RET]]179;180 %tmp0 = and <2 x i8> %x, <i8 3, i8 -1>181 %ret = icmp slt <2 x i8> %tmp0, %x182 ret <2 x i1> %ret183}184 185define <3 x i1> @n4(<3 x i8> %x) {186; CHECK-LABEL: @n4(187; CHECK-NEXT: [[TMP0:%.*]] = and <3 x i8> [[X:%.*]], <i8 3, i8 poison, i8 -1>188; CHECK-NEXT: [[RET:%.*]] = icmp slt <3 x i8> [[TMP0]], [[X]]189; CHECK-NEXT: ret <3 x i1> [[RET]]190;191 %tmp0 = and <3 x i8> %x, <i8 3, i8 poison, i8 -1>192 %ret = icmp slt <3 x i8> %tmp0, %x193 ret <3 x i1> %ret194}195 196; Commutativity tests with variable197 198define i1 @cv0(i8 %y) {199; CHECK-LABEL: @cv0(200; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()201; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]202; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]]203; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP1]], [[X]]204; CHECK-NEXT: ret i1 [[RET]]205;206 %x = call i8 @gen8()207 %tmp0 = lshr i8 -1, %y208 %tmp1 = and i8 %x, %tmp0 ; swapped order209 %ret = icmp slt i8 %tmp1, %x210 ret i1 %ret211}212 213define i1 @cv1(i8 %y) {214; CHECK-LABEL: @cv1(215; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()216; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]217; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X]]218; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP1]]219; CHECK-NEXT: ret i1 [[RET]]220;221 %x = call i8 @gen8()222 %tmp0 = lshr i8 -1, %y223 %tmp1 = and i8 %tmp0, %x224 %ret = icmp slt i8 %x, %tmp1 ; swapped order225 ret i1 %ret226}227 228define i1 @cv2(i8 %y) {229; CHECK-LABEL: @cv2(230; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()231; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]232; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]]233; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP1]]234; CHECK-NEXT: ret i1 [[RET]]235;236 %x = call i8 @gen8()237 %tmp0 = lshr i8 -1, %y238 %tmp1 = and i8 %x, %tmp0 ; swapped order239 %ret = icmp slt i8 %x, %tmp1 ; swapped order240 ret i1 %ret241}242