Skip to content

Commit e38ccb7

Browse files
committed
Recommit "Generalize getInvertibleOperand recurrence handling slightly"
This was reverted because of a reported problem. It turned out this patch didn't introduce said problem, it just exposed it more widely. 15a4233 fixes the root issue, so this simple a) rebases over that, and b) adds a much more extensive comment explaining why that weakened assert is correct. Original commit message follows: Follow up to D99912, specifically the revert, fix, and reapply thereof. This generalizes the invertible recurrence logic in two ways: * By allowing mismatching operand numbers of the phi, we can recurse through a pair of phi recurrences whose operand orders have not been canonicalized. * By allowing recurrences through operand 1, we can invert these odd (but legal) recurrence. Differential Revision: https://reviews.llvm.org/D100884
1 parent 2df3426 commit e38ccb7

File tree

2 files changed

+38
-38
lines changed

2 files changed

+38
-38
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,26 +2521,31 @@ bool isKnownNonZero(const Value* V, unsigned Depth, const Query& Q) {
25212521
return isKnownNonZero(V, DemandedElts, Depth, Q);
25222522
}
25232523

2524-
/// If the pair of operators are the same invertible function of a single
2525-
/// operand return the index of that operand. Otherwise, return None. An
2526-
/// invertible function is one that is 1-to-1 and maps every input value
2527-
/// to exactly one output value. This is equivalent to saying that Op1
2528-
/// and Op2 are equal exactly when the specified pair of operands are equal,
2529-
/// (except that Op1 and Op2 may be poison more often.)
2530-
static Optional<unsigned> getInvertibleOperand(const Operator *Op1,
2531-
const Operator *Op2) {
2524+
/// If the pair of operators are the same invertible function, return the
2525+
/// the operands of the function corresponding to each input. Otherwise,
2526+
/// return None. An invertible function is one that is 1-to-1 and maps
2527+
/// every input value to exactly one output value. This is equivalent to
2528+
/// saying that Op1 and Op2 are equal exactly when the specified pair of
2529+
/// operands are equal, (except that Op1 and Op2 may be poison more often.)
2530+
static Optional<std::pair<Value*, Value*>>
2531+
getInvertibleOperands(const Operator *Op1,
2532+
const Operator *Op2) {
25322533
if (Op1->getOpcode() != Op2->getOpcode())
25332534
return None;
25342535

2536+
auto getOperands = [&](unsigned OpNum) -> auto {
2537+
return std::make_pair(Op1->getOperand(OpNum), Op2->getOperand(OpNum));
2538+
};
2539+
25352540
switch (Op1->getOpcode()) {
25362541
default:
25372542
break;
25382543
case Instruction::Add:
25392544
case Instruction::Sub:
25402545
if (Op1->getOperand(0) == Op2->getOperand(0))
2541-
return 1;
2546+
return getOperands(1);
25422547
if (Op1->getOperand(1) == Op2->getOperand(1))
2543-
return 0;
2548+
return getOperands(0);
25442549
break;
25452550
case Instruction::Mul: {
25462551
// invertible if A * B == (A * B) mod 2^N where A, and B are integers
@@ -2556,7 +2561,7 @@ static Optional<unsigned> getInvertibleOperand(const Operator *Op1,
25562561
if (Op1->getOperand(1) == Op2->getOperand(1) &&
25572562
isa<ConstantInt>(Op1->getOperand(1)) &&
25582563
!cast<ConstantInt>(Op1->getOperand(1))->isZero())
2559-
return 0;
2564+
return getOperands(0);
25602565
break;
25612566
}
25622567
case Instruction::Shl: {
@@ -2569,7 +2574,7 @@ static Optional<unsigned> getInvertibleOperand(const Operator *Op1,
25692574
break;
25702575

25712576
if (Op1->getOperand(1) == Op2->getOperand(1))
2572-
return 0;
2577+
return getOperands(0);
25732578
break;
25742579
}
25752580
case Instruction::AShr:
@@ -2580,13 +2585,13 @@ static Optional<unsigned> getInvertibleOperand(const Operator *Op1,
25802585
break;
25812586

25822587
if (Op1->getOperand(1) == Op2->getOperand(1))
2583-
return 0;
2588+
return getOperands(0);
25842589
break;
25852590
}
25862591
case Instruction::SExt:
25872592
case Instruction::ZExt:
25882593
if (Op1->getOperand(0)->getType() == Op2->getOperand(0)->getType())
2589-
return 0;
2594+
return getOperands(0);
25902595
break;
25912596
case Instruction::PHI: {
25922597
const PHINode *PN1 = cast<PHINode>(Op1);
@@ -2604,19 +2609,20 @@ static Optional<unsigned> getInvertibleOperand(const Operator *Op1,
26042609
!matchSimpleRecurrence(PN2, BO2, Start2, Step2))
26052610
break;
26062611

2607-
Optional<unsigned> Idx = getInvertibleOperand(cast<Operator>(BO1),
2608-
cast<Operator>(BO2));
2609-
if (!Idx || *Idx != 0)
2610-
break;
2611-
if (BO1->getOperand(*Idx) != PN1 || BO2->getOperand(*Idx) != PN2)
2612+
auto Values = getInvertibleOperands(cast<Operator>(BO1),
2613+
cast<Operator>(BO2));
2614+
if (!Values)
2615+
break;
2616+
2617+
// We have to be careful of mutually defined recurrences here. Ex:
2618+
// * X_i = X_(i-1) OP Y_(i-1), and Y_i = X_(i-1) OP V
2619+
// * X_i = Y_i = X_(i-1) OP Y_(i-1)
2620+
// The invertibility of these is complicated, and not worth reasoning
2621+
// about (yet?).
2622+
if (Values->first != PN1 || Values->second != PN2)
26122623
break;
26132624

2614-
// Phi operands might not be in the same order. TODO: generalize
2615-
// interface to return pair of operands.
2616-
if (PN1->getOperand(0) == BO1 && PN2->getOperand(0) == BO2)
2617-
return 1;
2618-
if (PN1->getOperand(1) == BO1 && PN2->getOperand(1) == BO2)
2619-
return 0;
2625+
return std::make_pair(Start1, Start2);
26202626
}
26212627
}
26222628
return None;
@@ -2713,11 +2719,9 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
27132719
auto *O1 = dyn_cast<Operator>(V1);
27142720
auto *O2 = dyn_cast<Operator>(V2);
27152721
if (O1 && O2 && O1->getOpcode() == O2->getOpcode()) {
2716-
if (Optional<unsigned> Opt = getInvertibleOperand(O1, O2)) {
2717-
unsigned Idx = *Opt;
2718-
return isKnownNonEqual(O1->getOperand(Idx), O2->getOperand(Idx),
2719-
Depth + 1, Q);
2720-
}
2722+
if (auto Values = getInvertibleOperands(O1, O2))
2723+
return isKnownNonEqual(Values->first, Values->second, Depth + 1, Q);
2724+
27212725
if (const PHINode *PN1 = dyn_cast<PHINode>(V1)) {
27222726
const PHINode *PN2 = cast<PHINode>(V2);
27232727
// FIXME: This is missing a generalization to handle the case where one is

llvm/test/Analysis/ValueTracking/known-non-equal.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,7 @@ define i1 @recurrence_add_op_order(i8 %A) {
736736
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10
737737
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
738738
; CHECK: exit:
739-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]]
740-
; CHECK-NEXT: ret i1 [[RES]]
739+
; CHECK-NEXT: ret i1 false
741740
;
742741
entry:
743742
%B = add i8 %A, 1
@@ -808,8 +807,7 @@ define i1 @recurrence_add_phi_different_order1(i8 %A) {
808807
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10
809808
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
810809
; CHECK: exit:
811-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]]
812-
; CHECK-NEXT: ret i1 [[RES]]
810+
; CHECK-NEXT: ret i1 false
813811
;
814812
entry:
815813
%B = add i8 %A, 1
@@ -843,8 +841,7 @@ define i1 @recurrence_add_phi_different_order2(i8 %A) {
843841
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10
844842
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
845843
; CHECK: exit:
846-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]]
847-
; CHECK-NEXT: ret i1 [[RES]]
844+
; CHECK-NEXT: ret i1 false
848845
;
849846
entry:
850847
%B = add i8 %A, 1
@@ -979,8 +976,7 @@ define i1 @recurrence_sub_op_order(i8 %A) {
979976
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10
980977
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
981978
; CHECK: exit:
982-
; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]]
983-
; CHECK-NEXT: ret i1 [[RES]]
979+
; CHECK-NEXT: ret i1 false
984980
;
985981
entry:
986982
%B = add i8 %A, 1

0 commit comments

Comments
 (0)