Skip to content

Commit

Permalink
[InstCombine] Canonicalize icmp eq pow2 more thoroughly
Browse files Browse the repository at this point in the history
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 8df376d.

Differential Revision: https://reviews.llvm.org/D146149
  • Loading branch information
nikic committed Mar 16, 2023
1 parent ddbcd98 commit 61d2f3a
Show file tree
Hide file tree
Showing 6 changed files with 14 additions and 21 deletions.
16 changes: 6 additions & 10 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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: {
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/div.ll
Expand Up @@ -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]]
;
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/icmp-range.ll
Expand Up @@ -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}
Expand All @@ -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}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/icmp-shl-nsw.ll
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
Expand Up @@ -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
Expand Down
7 changes: 2 additions & 5 deletions llvm/test/Transforms/InstCombine/zext.ll
Expand Up @@ -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
Expand All @@ -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}
Expand Down

0 comments on commit 61d2f3a

Please sign in to comment.