From: Nikita Popov Date: Wed, 15 Mar 2023 15:40:59 +0000 (+0100) Subject: [InstCombine] Canonicalize icmp eq pow2 more thoroughly X-Git-Tag: upstream/17.0.6~14619 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=61d2f3a71e61929bf9b07c90e21d268090417bdb;p=platform%2Fupstream%2Fllvm.git [InstCombine] Canonicalize icmp eq pow2 more thoroughly We currently already canonicalize icmp eq (%x & Pow2), Pow2 to icmp ne (%x & Pow2), 0. This patch generalizes the fold based on known bits. In particular, this allows us to handle comparisons against !range !{i64 0, i64 2} loads, which addresses an optimization regression in Rust caused by 8df376db7282b955e7990cb8887ee9dcd3565040. Differential Revision: https://reviews.llvm.org/D146149 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index b790bb7..b1d59d3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3239,16 +3239,6 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant( } break; } - case Instruction::And: { - const APInt *BOC; - if (match(BOp1, m_APInt(BOC))) { - // If we have ((X & C) == C), turn it into ((X & C) != 0). - if (C == *BOC && C.isPowerOf2()) - return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, - BO, Constant::getNullValue(RHS->getType())); - } - break; - } case Instruction::UDiv: if (C.isZero()) { // (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A) @@ -5771,6 +5761,12 @@ Instruction *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) { } } } + + // Op0 eq C_Pow2 -> Op0 ne 0 if Op0 is known to be C_Pow2 or zero. + if (Op1Known.isConstant() && Op1Known.getConstant().isPowerOf2() && + (Op0Known & Op1Known) == Op0Known) + return new ICmpInst(CmpInst::getInversePredicate(Pred), Op0, + ConstantInt::getNullValue(Op1->getType())); break; } case ICmpInst::ICMP_ULT: { diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll index 59871f5..1f0081b 100644 --- a/llvm/test/Transforms/InstCombine/div.ll +++ b/llvm/test/Transforms/InstCombine/div.ll @@ -400,7 +400,7 @@ define i32 @test28(i32 %a) { define i32 @test29(i32 %a) { ; CHECK-LABEL: @test29( -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[A:%.*]], 0 ; CHECK-NEXT: [[DIV:%.*]] = zext i1 [[TMP1]] to i32 ; CHECK-NEXT: ret i32 [[DIV]] ; diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll index 29b601f..4281e09 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -1004,7 +1004,7 @@ define i1 @icmp_eq_bool_0(ptr %ptr) { define i1 @icmp_eq_bool_1(ptr %ptr) { ; CHECK-LABEL: @icmp_eq_bool_1( ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG6]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[VAL]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[VAL]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2} @@ -1026,7 +1026,7 @@ define i1 @icmp_ne_bool_0(ptr %ptr) { define i1 @icmp_ne_bool_1(ptr %ptr) { ; CHECK-LABEL: @icmp_ne_bool_1( ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG6]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[VAL]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[VAL]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2} diff --git a/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll b/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll index 3294042..6b9ea1f 100644 --- a/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll @@ -162,7 +162,7 @@ define i1 @icmp_sgt8(i8 %x) { define i1 @icmp_sgt9(i8 %x) { ; CHECK-LABEL: @icmp_sgt9( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %shl = shl nsw i8 %x, 7 @@ -303,7 +303,7 @@ define i1 @icmp_sle8(i8 %x) { define i1 @icmp_sle9(i8 %x) { ; CHECK-LABEL: @icmp_sle9( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %shl = shl nsw i8 %x, 7 diff --git a/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll b/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll index 6ef1c6c..33c9b59 100644 --- a/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll @@ -2767,7 +2767,7 @@ define i1 @lshrult_03_00_exact(i4 %x) { define i1 @lshrult_03_01_exact(i4 %x) { ; CHECK-LABEL: @lshrult_03_01_exact( -; CHECK-NEXT: [[C:%.*]] = icmp ne i4 [[X:%.*]], -8 +; CHECK-NEXT: [[C:%.*]] = icmp eq i4 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[C]] ; %s = lshr exact i4 %x, 3 diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll index dd781c7..8aa2a10 100644 --- a/llvm/test/Transforms/InstCombine/zext.ll +++ b/llvm/test/Transforms/InstCombine/zext.ll @@ -718,9 +718,7 @@ define i64 @zext_icmp_eq_bool_0(ptr %ptr) { define i64 @zext_icmp_eq_bool_1(ptr %ptr) { ; CHECK-LABEL: @zext_icmp_eq_bool_1( ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG0]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[VAL]], 1 -; CHECK-NEXT: [[LEN:%.*]] = zext i1 [[CMP]] to i64 -; CHECK-NEXT: ret i64 [[LEN]] +; CHECK-NEXT: ret i64 [[VAL]] ; %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2} %cmp = icmp eq i64 %val, 1 @@ -742,8 +740,7 @@ define i64 @zext_icmp_ne_bool_0(ptr %ptr) { define i64 @zext_icmp_ne_bool_1(ptr %ptr) { ; CHECK-LABEL: @zext_icmp_ne_bool_1( ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR:%.*]], align 8, !range [[RNG0]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[VAL]], 1 -; CHECK-NEXT: [[LEN:%.*]] = zext i1 [[CMP]] to i64 +; CHECK-NEXT: [[LEN:%.*]] = xor i64 [[VAL]], 1 ; CHECK-NEXT: ret i64 [[LEN]] ; %val = load i64, ptr %ptr, align 8, !range !{i64 0, i64 2}