Index: llvm/include/llvm/Analysis/ValueTracking.h =================================================================== --- llvm/include/llvm/Analysis/ValueTracking.h +++ llvm/include/llvm/Analysis/ValueTracking.h @@ -462,8 +462,11 @@ /// Determine the possible constant range of an integer or vector of integer - /// value. This is intended as a cheap, non-recursive check. - ConstantRange computeConstantRange(const Value *V, bool UseInstrInfo = true); + /// value. The ForSigned flag determines whether ranges that do not wrap in + /// the signed or unsigned domains are preferred. This is intended as a + /// cheap, non-recursive check. + ConstantRange computeConstantRange(const Value *V, bool ForSigned, + bool UseInstrInfo = true); /// Return true if this function can prove that the instruction I will /// always transfer execution to one of its successors (including the next Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -2500,7 +2500,8 @@ if (RHS_CR.isFullSet()) return ConstantInt::getTrue(ITy); - ConstantRange LHS_CR = computeConstantRange(LHS, IIQ.UseInstrInfo); + ConstantRange LHS_CR = computeConstantRange( + LHS, CmpInst::isSigned(Pred), IIQ.UseInstrInfo); if (!LHS_CR.isFullSet()) { if (RHS_CR.contains(LHS_CR)) return ConstantInt::getTrue(ITy); Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4084,7 +4084,7 @@ OptimizationRemarkEmitter *ORE = nullptr, bool UseInstrInfo = true) { KnownBits Known = computeKnownBits( V, DL, Depth, AC, CxtI, DT, ORE, UseInstrInfo); - ConstantRange CR = computeConstantRange(V, UseInstrInfo); + ConstantRange CR = computeConstantRange(V, ForSigned, UseInstrInfo); return ConstantRange::fromKnownBits(Known, ForSigned).intersectWith(CR); } @@ -5444,7 +5444,8 @@ } static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower, - APInt &Upper, const InstrInfoQuery &IIQ) { + APInt &Upper, bool ForSigned, + const InstrInfoQuery &IIQ) { unsigned Width = Lower.getBitWidth(); const APInt *C; switch (BO.getOpcode()) { @@ -5469,15 +5470,30 @@ break; case Instruction::And: - if (match(BO.getOperand(1), m_APInt(C))) - // 'and x, C' produces [0, C]. - Upper = *C + 1; + if (match(BO.getOperand(1), m_APInt(C))) { + // 'and x, C' produces [0, C] in the unsigned domain + // or [C, C & SINT_MAX] in the signed domain if C has a sign bit. + if (ForSigned && C->isSignBitSet()) { + Lower = *C; + Upper = *C; + Upper.clearSignBit(); + ++Upper; + } else { + Upper = *C + 1; + } + } break; case Instruction::Or: - if (match(BO.getOperand(1), m_APInt(C))) - // 'or x, C' produces [C, UINT_MAX]. + if (match(BO.getOperand(1), m_APInt(C))) { + // 'or x, C' produces [C, UINT_MAX] in the unsigned domain + // or [C | SINT_MIN, SINT_MAX] in the signed domain if C has no sign bit. Lower = *C; + if (ForSigned && C->isSignBitClear()) { + Lower.setSignBit(); + Upper = APInt::getSignedMaxValue(Width) + 1; + } + } break; case Instruction::AShr: @@ -5690,7 +5706,8 @@ // TODO Handle min/max flavors. } -ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) { +ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned, + bool UseInstrInfo) { assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction"); const APInt *C; @@ -5702,7 +5719,7 @@ APInt Lower = APInt(BitWidth, 0); APInt Upper = APInt(BitWidth, 0); if (auto *BO = dyn_cast(V)) - setLimitsForBinOp(*BO, Lower, Upper, IIQ); + setLimitsForBinOp(*BO, Lower, Upper, ForSigned, IIQ); else if (auto *II = dyn_cast(V)) setLimitsForIntrinsic(*II, Lower, Upper); else if (auto *SI = dyn_cast(V)) Index: llvm/test/Transforms/InstSimplify/icmp-constant.ll =================================================================== --- llvm/test/Transforms/InstSimplify/icmp-constant.ll +++ llvm/test/Transforms/InstSimplify/icmp-constant.ll @@ -381,9 +381,7 @@ ; Single bit OR. define i1 @or2_true(i8 %x) { ; CHECK-LABEL: @or2_true( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], 64 -; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[Y]], -64 -; CHECK-NEXT: ret i1 [[Z]] +; CHECK-NEXT: ret i1 true ; %y = or i8 %x, 64 %z = icmp sge i8 %y, -64 @@ -405,9 +403,7 @@ ; 78 = 0b01001110; -50 = 0b11001110 define i1 @or3_true(i8 %x) { ; CHECK-LABEL: @or3_true( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[X:%.*]], 78 -; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[Y]], -50 -; CHECK-NEXT: ret i1 [[Z]] +; CHECK-NEXT: ret i1 true ; %y = or i8 %x, 78 %z = icmp sge i8 %y, -50 @@ -499,9 +495,7 @@ ; -75 = 0b10110101, 53 = 0b00110101 define i1 @and3_true1(i8 %x) { ; CHECK-LABEL: @and3_true1( -; CHECK-NEXT: [[Y:%.*]] = and i8 [[X:%.*]], -75 -; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[Y]], -75 -; CHECK-NEXT: ret i1 [[Z]] +; CHECK-NEXT: ret i1 true ; %y = and i8 %x, -75 %z = icmp sge i8 %y, -75 @@ -521,9 +515,7 @@ define i1 @and3_true2(i8 %x) { ; CHECK-LABEL: @and3_true2( -; CHECK-NEXT: [[Y:%.*]] = and i8 [[X:%.*]], -75 -; CHECK-NEXT: [[Z:%.*]] = icmp sle i8 [[Y]], 53 -; CHECK-NEXT: ret i1 [[Z]] +; CHECK-NEXT: ret i1 true ; %y = and i8 %x, -75 %z = icmp sle i8 %y, 53