forked from OSchip/llvm-project
[LVI] Simplify and generalize handling of clamp patterns
Instead of handling a number of special cases for selects, handle this generally when inferring ranges from conditions. We already infer ranges from `x + C pred C2` to `x`, so doing the same for `x pred C2` to `x + C` is straightforward.
This commit is contained in:
parent
906deaa0d9
commit
a917fb89dc
llvm
|
@ -875,48 +875,6 @@ Optional<ValueLatticeElement> LazyValueInfoImpl::solveBlockValueSelect(
|
|||
FalseVal = intersect(FalseVal,
|
||||
getValueFromCondition(SI->getFalseValue(), Cond, false));
|
||||
|
||||
// Handle clamp idioms such as:
|
||||
// %24 = constantrange<0, 17>
|
||||
// %39 = icmp eq i32 %24, 0
|
||||
// %40 = add i32 %24, -1
|
||||
// %siv.next = select i1 %39, i32 16, i32 %40
|
||||
// %siv.next = constantrange<0, 17> not <-1, 17>
|
||||
// In general, this can handle any clamp idiom which tests the edge
|
||||
// condition via an equality or inequality.
|
||||
if (auto *ICI = dyn_cast<ICmpInst>(Cond)) {
|
||||
ICmpInst::Predicate Pred = ICI->getPredicate();
|
||||
Value *A = ICI->getOperand(0);
|
||||
if (ConstantInt *CIBase = dyn_cast<ConstantInt>(ICI->getOperand(1))) {
|
||||
auto addConstants = [](ConstantInt *A, ConstantInt *B) {
|
||||
assert(A->getType() == B->getType());
|
||||
return ConstantInt::get(A->getType(), A->getValue() + B->getValue());
|
||||
};
|
||||
// See if either input is A + C2, subject to the constraint from the
|
||||
// condition that A != C when that input is used. We can assume that
|
||||
// that input doesn't include C + C2.
|
||||
ConstantInt *CIAdded;
|
||||
switch (Pred) {
|
||||
default: break;
|
||||
case ICmpInst::ICMP_EQ:
|
||||
if (match(SI->getFalseValue(), m_Add(m_Specific(A),
|
||||
m_ConstantInt(CIAdded)))) {
|
||||
auto ResNot = addConstants(CIBase, CIAdded);
|
||||
FalseVal = intersect(FalseVal,
|
||||
ValueLatticeElement::getNot(ResNot));
|
||||
}
|
||||
break;
|
||||
case ICmpInst::ICMP_NE:
|
||||
if (match(SI->getTrueValue(), m_Add(m_Specific(A),
|
||||
m_ConstantInt(CIAdded)))) {
|
||||
auto ResNot = addConstants(CIBase, CIAdded);
|
||||
TrueVal = intersect(TrueVal,
|
||||
ValueLatticeElement::getNot(ResNot));
|
||||
}
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ValueLatticeElement Result = TrueVal;
|
||||
Result.mergeIn(FalseVal);
|
||||
return Result;
|
||||
|
@ -1089,6 +1047,13 @@ static bool matchICmpOperand(APInt &Offset, Value *LHS, Value *Val,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Handle the symmetric case. This appears in saturation patterns like
|
||||
// (x == 16) ? 16 : (x + 1).
|
||||
if (match(Val, m_Add(m_Specific(LHS), m_APInt(C)))) {
|
||||
Offset = -*C;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If (x | y) < C, then (x < C) && (y < C).
|
||||
if (match(LHS, m_c_Or(m_Specific(Val), m_Value())) &&
|
||||
(Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE))
|
||||
|
|
|
@ -587,8 +587,7 @@ define i1 @clamp_low3(i32 %a) {
|
|||
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sgt i32 [[A]], 5
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
; CHECK: out:
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
|
@ -615,8 +614,7 @@ define i1 @clamp_low4(i32 %a) {
|
|||
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sle i32 [[A]], 5
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], -1
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 4
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
; CHECK: out:
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
|
@ -697,8 +695,7 @@ define i1 @clamp_high3(i32 %a) {
|
|||
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp slt i32 [[A]], 5
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
; CHECK: out:
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
|
@ -725,8 +722,7 @@ define i1 @clamp_high4(i32 %a) {
|
|||
; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp sge i32 [[A]], 5
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 1
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[SEL]], 6
|
||||
; CHECK-NEXT: ret i1 [[RES]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
; CHECK: out:
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue