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,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue