Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -2513,14 +2513,15 @@ return isKnownNonZero(V, DemandedElts, Depth, Q); } -/// If the pair of operators are the same invertible function of a single -/// operand return the index of that operand. Otherwise, return None. An -/// invertible function is one that is 1-to-1 and maps every input value -/// to exactly one output value. This is equivalent to saying that Op1 -/// and Op2 are equal exactly when the specified pair of operands are equal, -/// (except that Op1 and Op2 may be poison more often.) -static Optional getInvertibleOperand(const Operator *Op1, - const Operator *Op2) { +/// If the pair of operators are the same invertible function of a single pair +/// of operands, return the respective operand numbers of said pair. +/// Otherwise, return None. An invertible function is one that is 1-to-1 and +/// maps every input value to exactly one output value. This is equivalent to +/// saying that Op1 and Op2 are equal exactly when the specified pair of +/// operands are equal, (except that Op1 and Op2 may be poison more often.) +static Optional> +getInvertibleOperand(const Operator *Op1, + const Operator *Op2) { if (Op1->getOpcode() != Op2->getOpcode()) return None; @@ -2530,9 +2531,9 @@ case Instruction::Add: case Instruction::Sub: if (Op1->getOperand(0) == Op2->getOperand(0)) - return 1; + return std::make_pair(1U, 1U); if (Op1->getOperand(1) == Op2->getOperand(1)) - return 0; + return std::make_pair(0U, 0U); break; case Instruction::Mul: { // invertible if A * B == (A * B) mod 2^N where A, and B are integers @@ -2548,7 +2549,7 @@ if (Op1->getOperand(1) == Op2->getOperand(1) && isa(Op1->getOperand(1)) && !cast(Op1->getOperand(1))->isZero()) - return 0; + return std::make_pair(0U, 0U); break; } case Instruction::Shl: { @@ -2561,7 +2562,7 @@ break; if (Op1->getOperand(1) == Op2->getOperand(1)) - return 0; + return std::make_pair(0U, 0U); break; } case Instruction::AShr: @@ -2572,13 +2573,13 @@ break; if (Op1->getOperand(1) == Op2->getOperand(1)) - return 0; + return std::make_pair(0U, 0U); break; } case Instruction::SExt: case Instruction::ZExt: if (Op1->getOperand(0)->getType() == Op2->getOperand(0)->getType()) - return 0; + return std::make_pair(0U, 0U); break; case Instruction::PHI: { const PHINode *PN1 = cast(Op1); @@ -2596,18 +2597,16 @@ !matchSimpleRecurrence(PN2, BO2, Start2, Step2)) break; - Optional Idx = getInvertibleOperand(cast(BO1), - cast(BO2)); - if (!Idx || *Idx != 0) + Optional> Idx = + getInvertibleOperand(cast(BO1), cast(BO2)); + if (!Idx || Idx->first != 0 || Idx->second != 0) break; - assert(BO1->getOperand(*Idx) == PN1 && BO2->getOperand(*Idx) == PN2); + assert(BO1->getOperand(Idx->first) == PN1 && + BO2->getOperand(Idx->second) == PN2); - // Phi operands might not be in the same order. TODO: generalize - // interface to return pair of operands. - if (PN1->getOperand(0) == BO1 && PN2->getOperand(0) == BO2) - return 1; - if (PN1->getOperand(1) == BO1 && PN2->getOperand(1) == BO2) - return 0; + // Phi operands might not be in the same order. + return std::make_pair(PN1->getOperand(0) == BO1 ? 1U : 0U, + PN2->getOperand(0) == BO2 ? 1U : 0U); } } return None; @@ -2704,10 +2703,9 @@ auto *O1 = dyn_cast(V1); auto *O2 = dyn_cast(V2); if (O1 && O2 && O1->getOpcode() == O2->getOpcode()) { - if (Optional Opt = getInvertibleOperand(O1, O2)) { - unsigned Idx = *Opt; - return isKnownNonEqual(O1->getOperand(Idx), O2->getOperand(Idx), - Depth + 1, Q); + if (auto Opt = getInvertibleOperand(O1, O2)) { + return isKnownNonEqual(O1->getOperand(Opt->first), + O2->getOperand(Opt->second), Depth + 1, Q); } if (const PHINode *PN1 = dyn_cast(V1)) { const PHINode *PN2 = cast(V2); Index: llvm/test/Analysis/ValueTracking/known-non-equal.ll =================================================================== --- llvm/test/Analysis/ValueTracking/known-non-equal.ll +++ llvm/test/Analysis/ValueTracking/known-non-equal.ll @@ -810,8 +810,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 @@ -845,8 +844,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