[CVP] Simplify comparisons without constant operand

CVP currently only tries to simplify comparisons if there is a
constant operand. However, even if both are non-constant, we may
be able to determine the result of the comparison based on range
information.

IPSCCP is already capable of doing this, but because it runs very
early, it may miss some cases.

Differential Revision: https://reviews.llvm.org/D137253
This commit is contained in:
Nikita Popov 2022-11-02 11:25:42 +01:00
parent 150fc73dda
commit 68b24c3b44
5 changed files with 31 additions and 19 deletions

View File

@ -1859,9 +1859,27 @@ LazyValueInfo::Tristate LazyValueInfo::getPredicateAt(unsigned P, Value *LHS,
return getPredicateAt(CmpInst::getSwappedPredicate(Pred), RHS, C, CxtI,
UseBlockValue);
// Got two non-Constant values. While we could handle them somewhat,
// by getting their constant ranges, and applying ConstantRange::icmp(),
// so far it did not appear to be profitable.
// Got two non-Constant values. Try to determine the comparison results based
// on the block values of the two operands, e.g. because they have
// non-overlapping ranges.
if (UseBlockValue) {
Module *M = CxtI->getModule();
ValueLatticeElement L =
getImpl(PImpl, AC, M).getValueInBlock(LHS, CxtI->getParent(), CxtI);
if (L.isOverdefined())
return LazyValueInfo::Unknown;
ValueLatticeElement R =
getImpl(PImpl, AC, M).getValueInBlock(RHS, CxtI->getParent(), CxtI);
Type *Ty = CmpInst::makeCmpResultType(LHS->getType());
if (Constant *Res = L.getCompare((CmpInst::Predicate)P, Ty, R,
M->getDataLayout())) {
if (Res->isNullValue())
return LazyValueInfo::False;
if (Res->isOneValue())
return LazyValueInfo::True;
}
}
return LazyValueInfo::Unknown;
}

View File

@ -340,18 +340,16 @@ static bool processICmp(ICmpInst *Cmp, LazyValueInfo *LVI) {
/// exploiting range information.
static bool constantFoldCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
Value *Op0 = Cmp->getOperand(0);
auto *C = dyn_cast<Constant>(Cmp->getOperand(1));
if (!C)
return false;
Value *Op1 = Cmp->getOperand(1);
LazyValueInfo::Tristate Result =
LVI->getPredicateAt(Cmp->getPredicate(), Op0, C, Cmp,
LVI->getPredicateAt(Cmp->getPredicate(), Op0, Op1, Cmp,
/*UseBlockValue=*/true);
if (Result == LazyValueInfo::Unknown)
return false;
++NumCmps;
Constant *TorF = ConstantInt::get(Type::getInt1Ty(Cmp->getContext()), Result);
Constant *TorF =
ConstantInt::get(CmpInst::makeCmpResultType(Op0->getType()), Result);
Cmp->replaceAllUsesWith(TorF);
Cmp->eraseFromParent();
return true;

View File

@ -1180,10 +1180,8 @@ define void @non_const_range(i32 %a, i32 %b) {
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: [[A_100:%.*]] = add nuw nsw i32 [[A]], 100
; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[A_100]], [[B]]
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[A_100]], [[B]]
; CHECK-NEXT: call void @check1(i1 [[CMP4]])
; CHECK-NEXT: call void @check1(i1 true)
; CHECK-NEXT: call void @check1(i1 false)
; CHECK-NEXT: [[A_10:%.*]] = add nuw nsw i32 [[A]], 10
; CHECK-NEXT: [[CMP5:%.*]] = icmp ne i32 [[A_10]], [[B]]
; CHECK-NEXT: call void @check1(i1 [[CMP5]])
@ -1220,8 +1218,7 @@ define i1 @non_const_range_minmax(i8 %a, i8 %b) {
; CHECK-LABEL: @non_const_range_minmax(
; CHECK-NEXT: [[A2:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 10)
; CHECK-NEXT: [[B2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 11)
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A2]], [[B2]]
; CHECK-NEXT: ret i1 [[CMP1]]
; CHECK-NEXT: ret i1 true
;
%a2 = call i8 @llvm.umin.i8(i8 %a, i8 10)
%b2 = call i8 @llvm.umax.i8(i8 %b, i8 11)
@ -1229,6 +1226,7 @@ define i1 @non_const_range_minmax(i8 %a, i8 %b) {
ret i1 %cmp1
}
; FIXME: Also support vectors.
define <2 x i1> @non_const_range_minmax_vec(<2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: @non_const_range_minmax_vec(
; CHECK-NEXT: [[A2:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 10>)

View File

@ -209,8 +209,7 @@ define i1 @nsw_range1(i8 %b) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C:%.*]] = add nuw nsw i8 [[B:%.*]], -3
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[C]], 4
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C]], [[MUL]]
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
entry:
%c = add nuw nsw i8 %b, -3

View File

@ -412,8 +412,7 @@ define i1 @nsw_range1(i8 %b) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C:%.*]] = add nuw nsw i8 [[B:%.*]], -3
; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 [[C]], 2
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C]], [[SHL]]
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
entry:
%c = add nuw nsw i8 %b, -3