forked from OSchip/llvm-project
[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:
parent
150fc73dda
commit
68b24c3b44
|
@ -1859,9 +1859,27 @@ LazyValueInfo::Tristate LazyValueInfo::getPredicateAt(unsigned P, Value *LHS,
|
||||||
return getPredicateAt(CmpInst::getSwappedPredicate(Pred), RHS, C, CxtI,
|
return getPredicateAt(CmpInst::getSwappedPredicate(Pred), RHS, C, CxtI,
|
||||||
UseBlockValue);
|
UseBlockValue);
|
||||||
|
|
||||||
// Got two non-Constant values. While we could handle them somewhat,
|
// Got two non-Constant values. Try to determine the comparison results based
|
||||||
// by getting their constant ranges, and applying ConstantRange::icmp(),
|
// on the block values of the two operands, e.g. because they have
|
||||||
// so far it did not appear to be profitable.
|
// 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;
|
return LazyValueInfo::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -340,18 +340,16 @@ static bool processICmp(ICmpInst *Cmp, LazyValueInfo *LVI) {
|
||||||
/// exploiting range information.
|
/// exploiting range information.
|
||||||
static bool constantFoldCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
|
static bool constantFoldCmp(CmpInst *Cmp, LazyValueInfo *LVI) {
|
||||||
Value *Op0 = Cmp->getOperand(0);
|
Value *Op0 = Cmp->getOperand(0);
|
||||||
auto *C = dyn_cast<Constant>(Cmp->getOperand(1));
|
Value *Op1 = Cmp->getOperand(1);
|
||||||
if (!C)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
LazyValueInfo::Tristate Result =
|
LazyValueInfo::Tristate Result =
|
||||||
LVI->getPredicateAt(Cmp->getPredicate(), Op0, C, Cmp,
|
LVI->getPredicateAt(Cmp->getPredicate(), Op0, Op1, Cmp,
|
||||||
/*UseBlockValue=*/true);
|
/*UseBlockValue=*/true);
|
||||||
if (Result == LazyValueInfo::Unknown)
|
if (Result == LazyValueInfo::Unknown)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
++NumCmps;
|
++NumCmps;
|
||||||
Constant *TorF = ConstantInt::get(Type::getInt1Ty(Cmp->getContext()), Result);
|
Constant *TorF =
|
||||||
|
ConstantInt::get(CmpInst::makeCmpResultType(Op0->getType()), Result);
|
||||||
Cmp->replaceAllUsesWith(TorF);
|
Cmp->replaceAllUsesWith(TorF);
|
||||||
Cmp->eraseFromParent();
|
Cmp->eraseFromParent();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1180,10 +1180,8 @@ define void @non_const_range(i32 %a, i32 %b) {
|
||||||
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
|
; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
|
||||||
; CHECK: if:
|
; CHECK: if:
|
||||||
; CHECK-NEXT: [[A_100:%.*]] = add nuw nsw i32 [[A]], 100
|
; 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 true)
|
||||||
; CHECK-NEXT: call void @check1(i1 [[CMP3]])
|
; CHECK-NEXT: call void @check1(i1 false)
|
||||||
; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i32 [[A_100]], [[B]]
|
|
||||||
; CHECK-NEXT: call void @check1(i1 [[CMP4]])
|
|
||||||
; CHECK-NEXT: [[A_10:%.*]] = add nuw nsw i32 [[A]], 10
|
; CHECK-NEXT: [[A_10:%.*]] = add nuw nsw i32 [[A]], 10
|
||||||
; CHECK-NEXT: [[CMP5:%.*]] = icmp ne i32 [[A_10]], [[B]]
|
; CHECK-NEXT: [[CMP5:%.*]] = icmp ne i32 [[A_10]], [[B]]
|
||||||
; CHECK-NEXT: call void @check1(i1 [[CMP5]])
|
; 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-LABEL: @non_const_range_minmax(
|
||||||
; CHECK-NEXT: [[A2:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 10)
|
; 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: [[B2:%.*]] = call i8 @llvm.umax.i8(i8 [[B:%.*]], i8 11)
|
||||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A2]], [[B2]]
|
; CHECK-NEXT: ret i1 true
|
||||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
||||||
;
|
;
|
||||||
%a2 = call i8 @llvm.umin.i8(i8 %a, i8 10)
|
%a2 = call i8 @llvm.umin.i8(i8 %a, i8 10)
|
||||||
%b2 = call i8 @llvm.umax.i8(i8 %b, i8 11)
|
%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
|
ret i1 %cmp1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; FIXME: Also support vectors.
|
||||||
define <2 x i1> @non_const_range_minmax_vec(<2 x i8> %a, <2 x i8> %b) {
|
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-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>)
|
; CHECK-NEXT: [[A2:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 10>)
|
||||||
|
|
|
@ -209,8 +209,7 @@ define i1 @nsw_range1(i8 %b) {
|
||||||
; CHECK-NEXT: entry:
|
; CHECK-NEXT: entry:
|
||||||
; CHECK-NEXT: [[C:%.*]] = add nuw nsw i8 [[B:%.*]], -3
|
; CHECK-NEXT: [[C:%.*]] = add nuw nsw i8 [[B:%.*]], -3
|
||||||
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[C]], 4
|
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i8 [[C]], 4
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C]], [[MUL]]
|
; CHECK-NEXT: ret i1 false
|
||||||
; CHECK-NEXT: ret i1 [[CMP]]
|
|
||||||
;
|
;
|
||||||
entry:
|
entry:
|
||||||
%c = add nuw nsw i8 %b, -3
|
%c = add nuw nsw i8 %b, -3
|
||||||
|
|
|
@ -412,8 +412,7 @@ define i1 @nsw_range1(i8 %b) {
|
||||||
; CHECK-NEXT: entry:
|
; CHECK-NEXT: entry:
|
||||||
; CHECK-NEXT: [[C:%.*]] = add nuw nsw i8 [[B:%.*]], -3
|
; CHECK-NEXT: [[C:%.*]] = add nuw nsw i8 [[B:%.*]], -3
|
||||||
; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 [[C]], 2
|
; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 [[C]], 2
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[C]], [[SHL]]
|
; CHECK-NEXT: ret i1 false
|
||||||
; CHECK-NEXT: ret i1 [[CMP]]
|
|
||||||
;
|
;
|
||||||
entry:
|
entry:
|
||||||
%c = add nuw nsw i8 %b, -3
|
%c = add nuw nsw i8 %b, -3
|
||||||
|
|
Loading…
Reference in New Issue