mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[ValueTracking] Handle non-zero add/mul recurrences more precisely
This is mainly for clarity: It doesn't make sense to do any negative/positive checks when dealing with a nuw add/mul. These only make sense to nsw add/mul.
This commit is contained in:
parent
eb6c470c5f
commit
0926f8f2a9
@ -2213,6 +2213,31 @@ static bool rangeMetadataExcludesValue(const MDNode* Ranges, const APInt& Value)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isNonZeroRecurrence(const PHINode *PN) {
|
||||||
|
// Try and detect a recurrence that monotonically increases from a
|
||||||
|
// starting value, as these are common as induction variables.
|
||||||
|
BinaryOperator *BO = nullptr;
|
||||||
|
Value *Start = nullptr, *Step = nullptr;
|
||||||
|
const APInt *StartC, *StepC;
|
||||||
|
if (!matchSimpleRecurrence(PN, BO, Start, Step) ||
|
||||||
|
!match(Start, m_APInt(StartC)) || !match(Step, m_APInt(StepC)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (BO->getOpcode()) {
|
||||||
|
case Instruction::Add:
|
||||||
|
return (BO->hasNoUnsignedWrap() && !StartC->isNullValue() &&
|
||||||
|
!StepC->isNullValue()) ||
|
||||||
|
(BO->hasNoSignedWrap() && StartC->isStrictlyPositive() &&
|
||||||
|
StepC->isNonNegative());
|
||||||
|
case Instruction::Mul:
|
||||||
|
return !StartC->isNullValue() &&
|
||||||
|
((BO->hasNoUnsignedWrap() && !StepC->isNullValue()) ||
|
||||||
|
(BO->hasNoSignedWrap() && StepC->isStrictlyPositive()));
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if the given value is known to be non-zero when defined. For
|
/// Return true if the given value is known to be non-zero when defined. For
|
||||||
/// vectors, return true if every demanded element is known to be non-zero when
|
/// vectors, return true if every demanded element is known to be non-zero when
|
||||||
/// defined. For pointers, if the context instruction and dominator tree are
|
/// defined. For pointers, if the context instruction and dominator tree are
|
||||||
@ -2454,22 +2479,9 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
|
|||||||
}
|
}
|
||||||
// PHI
|
// PHI
|
||||||
else if (const PHINode *PN = dyn_cast<PHINode>(V)) {
|
else if (const PHINode *PN = dyn_cast<PHINode>(V)) {
|
||||||
// Try and detect a recurrence that monotonically increases from a
|
if (Q.IIQ.UseInstrInfo && isNonZeroRecurrence(PN))
|
||||||
// starting value, as these are common as induction variables.
|
|
||||||
BinaryOperator *BO = nullptr;
|
|
||||||
Value *Start = nullptr, *Step = nullptr;
|
|
||||||
const APInt *StartC, *StepC;
|
|
||||||
if (Q.IIQ.UseInstrInfo && matchSimpleRecurrence(PN, BO, Start, Step) &&
|
|
||||||
match(Start, m_APInt(StartC)) && match(Step, m_APInt(StepC))) {
|
|
||||||
if (BO->getOpcode() == Instruction::Add &&
|
|
||||||
(BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap()) &&
|
|
||||||
StartC->isStrictlyPositive() && !StepC->isNegative())
|
|
||||||
return true;
|
return true;
|
||||||
if (BO->getOpcode() == Instruction::Mul &&
|
|
||||||
(BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap()) &&
|
|
||||||
!StartC->isNullValue() && StepC->isStrictlyPositive())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Check if all incoming values are non-zero using recursion.
|
// Check if all incoming values are non-zero using recursion.
|
||||||
Query RecQ = Q;
|
Query RecQ = Q;
|
||||||
unsigned NewDepth = std::max(Depth, MaxAnalysisRecursionDepth - 1);
|
unsigned NewDepth = std::max(Depth, MaxAnalysisRecursionDepth - 1);
|
||||||
|
@ -115,9 +115,7 @@ define i1 @test_add_nuw_negative_start(i8 %p, i8* %pq, i8 %n, i8 %r) {
|
|||||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
|
||||||
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
|
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
|
||||||
; CHECK: exit:
|
; CHECK: exit:
|
||||||
; CHECK-NEXT: [[ADD:%.*]] = or i8 [[A]], [[R:%.*]]
|
; CHECK-NEXT: ret i1 false
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[ADD]], 0
|
|
||||||
; CHECK-NEXT: ret i1 [[CMP]]
|
|
||||||
;
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %loop
|
br label %loop
|
||||||
@ -292,8 +290,7 @@ define i1 @test_mul_nuw_negative_step(i8 %p, i8* %pq, i8 %n, i8 %r) {
|
|||||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[A]], [[N:%.*]]
|
||||||
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
|
; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT:%.*]], label [[LOOP]]
|
||||||
; CHECK: exit:
|
; CHECK: exit:
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A]], 0
|
; CHECK-NEXT: ret i1 false
|
||||||
; CHECK-NEXT: ret i1 [[CMP]]
|
|
||||||
;
|
;
|
||||||
entry:
|
entry:
|
||||||
br label %loop
|
br label %loop
|
||||||
|
Loading…
Reference in New Issue
Block a user