diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1477,18 +1477,56 @@ if (FalseSucc == P->getParent()) Pred = CmpInst::getInversePredicate(Pred); + APInt RHS = *RHSC; switch (Pred) { case CmpInst::Predicate::ICMP_EQ: - Known2 = KnownBits::makeConstant(*RHSC); + Known2 = KnownBits::makeConstant(RHS); break; + case CmpInst::Predicate::ICMP_ULT: + RHS -= 1; + [[fallthrough]]; case CmpInst::Predicate::ICMP_ULE: - Known2.Zero.setHighBits(RHSC->countl_zero()); + // X ule/ult Y implies highest set bit in X is leq highest set + // bit in Y. + Known2.Zero.setHighBits(RHS.countl_zero()); break; - case CmpInst::Predicate::ICMP_ULT: - Known2.Zero.setHighBits((*RHSC - 1).countl_zero()); + case CmpInst::Predicate::ICMP_UGT: + RHS += 1; + [[fallthrough]]; + case CmpInst::Predicate::ICMP_UGE: + // X uge/ugt Y implies any leading ones in Y must be set in X as + // well. + Known2.One.setHighBits(RHS.countl_one()); + break; + case CmpInst::Predicate::ICMP_SGT: + // X sgt -1 -> X doesn't have signbit set + RHS += 1; + [[fallthrough]]; + case CmpInst::Predicate::ICMP_SGE: + if (!RHS.isSignBitSet()) { + // X sge/sgt C_Positive -> same as uge/ugt but start from + // after the sign bit (and leave signbit unset). + RHS.setSignBit(); + Known2.One.setHighBits(RHS.countl_one()); + Known2.One.clearSignBit(); + Known2.Zero.setSignBit(); + } + break; + case CmpInst::Predicate::ICMP_SLT: + // X slt 0 -> X has signbit set + RHS -= 1; + [[fallthrough]]; + case CmpInst::Predicate::ICMP_SLE: + if (RHS.isSignBitSet()) { + // X sle/slt C_Negative -> same as ule/ult but start from + // after the sign bit (and leave signbit unset). + RHS.clearSignBit(); + Known2.Zero.setHighBits(RHS.countl_zero()); + Known2.Zero.clearSignBit(); + Known2.One.setSignBit(); + } break; default: - // TODO - add additional integer predicate handling. break; } } diff --git a/llvm/test/Analysis/ValueTracking/phi-known-bits.ll b/llvm/test/Analysis/ValueTracking/phi-known-bits.ll --- a/llvm/test/Analysis/ValueTracking/phi-known-bits.ll +++ b/llvm/test/Analysis/ValueTracking/phi-known-bits.ll @@ -7,9 +7,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], -65 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], 64 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 64 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -53,9 +51,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], -65 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], 64 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 64 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -99,9 +95,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 95 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], 96 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 96 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -145,9 +139,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -1 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ 0, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], -128 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 0 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -168,9 +160,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 63 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], 64 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 64 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -214,9 +204,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], -128 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 -128 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -237,9 +225,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -64 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ 0, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], 64 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 0 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -283,9 +269,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -64 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ 0, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = and i8 [[V]], 64 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 0 ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ;