diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2580,6 +2580,35 @@ if (Op1->getOperand(0)->getType() == Op2->getOperand(0)->getType()) return 0; break; + case Instruction::PHI: { + const PHINode *PN1 = cast(Op1); + const PHINode *PN2 = cast(Op2); + + // If PN1 and PN2 are both recurrences, can we prove the entire recurrences + // are a single invertible function of the start values? Note that repeated + // application of an invertible function is also invertible + BinaryOperator *BO1 = nullptr; + Value *Start1 = nullptr, *Step1 = nullptr; + BinaryOperator *BO2 = nullptr; + Value *Start2 = nullptr, *Step2 = nullptr; + if (PN1->getParent() != PN2->getParent() || + !matchSimpleRecurrence(PN1, BO1, Start1, Step1) || + !matchSimpleRecurrence(PN2, BO2, Start2, Step2)) + break; + + Optional Idx = getInvertibleOperand(cast(BO1), + cast(BO2)); + if (!Idx || *Idx != 0) + break; + assert(BO1->getOperand(*Idx) == PN1 && BO2->getOperand(*Idx) == PN2); + + if (PN1->getOperand(0) == BO1) { + assert(PN2->getOperand(0) == BO2); + return 1; + } + assert(PN1->getOperand(1) == BO1 && PN2->getOperand(1) == BO2); + return 0; + } } return None; } diff --git a/llvm/test/Analysis/ValueTracking/known-non-equal.ll b/llvm/test/Analysis/ValueTracking/known-non-equal.ll --- a/llvm/test/Analysis/ValueTracking/known-non-equal.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-equal.ll @@ -598,8 +598,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1 @@ -775,8 +774,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1 @@ -810,8 +808,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1 @@ -912,8 +909,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1 @@ -1049,8 +1045,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1 @@ -1186,8 +1181,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1 @@ -1323,8 +1317,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[IV_NEXT]], 10 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[A_IV]], [[B_IV]] -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; entry: %B = add i8 %A, 1