@@ -714,16 +714,58 @@ const SCEV *evaluateAtIteration(const SCEVAddRecExpr *ARE, const SCEV *It,
714714 return S;
715715}
716716
717- Optional<int64_t > compareSCEVs (const SCEV *LHS,
718- const SCEV *RHS,
717+ Optional<int64_t > compareSCEVs (const SCEV *LHS, const SCEV *RHS,
719718 ScalarEvolution *SE) {
720719 assert (SE && " ScalarEvolution must be specified!" );
721720 assert (LHS && RHS && " SCEV must be specified!" );
722721 TypeQueue TQLHS, TQRHS;
723722 auto InnerLHS = getTypeQueue (TQLHS, LHS);
724723 auto InnerRHS = getTypeQueue (TQRHS, RHS);
725- if (TQLHS != TQRHS)
724+ if (TQLHS != TQRHS) {
725+ // For cases like LHS = { zext(%v) - Const1 }, RHS = { zext(%v - Const2) }
726+ // TODO ([email protected] ): can we extend this check for sext? 727+ if (isa<SCEVZeroExtendExpr>(LHS) && isa<SCEVAddExpr>(RHS) ||
728+ isa<SCEVAddExpr>(LHS) && isa<SCEVZeroExtendExpr>(RHS)) {
729+ int SwapMult = 1 ;
730+ auto First{LHS}, Second{RHS};
731+ // Let the first SCEV be of kind { zext(%v) - Const1 } and the second
732+ // be of kind { zext(%v - Const2) }.
733+ if (isa<SCEVZeroExtendExpr>(LHS) && isa<SCEVAddExpr>(RHS)) {
734+ std::swap (First, Second);
735+ SwapMult = -1 ;
736+ }
737+ auto *FirstAdd = cast<SCEVAddExpr>(First);
738+ auto *FirstOp0 = FirstAdd->getOperand (0 );
739+ auto *FirstOp1 = FirstAdd->getOperand (1 );
740+ // Let the first operand always be a non-constant value.
741+ if (isa<SCEVConstant>(FirstOp0))
742+ std::swap (FirstOp0, FirstOp1);
743+ auto *FirstCast = dyn_cast<SCEVZeroExtendExpr>(FirstOp0);
744+ if (!FirstCast)
745+ return None;
746+ auto *FirstVar = FirstCast->getOperand ();
747+ if (!isa<SCEVUnknown>(FirstVar))
748+ return None;
749+ auto *SecondCast = dyn_cast<SCEVZeroExtendExpr>(Second);
750+ if (!SecondCast || !isa<SCEVAddExpr>(SecondCast->getOperand ()))
751+ return None;
752+ auto *SecondAdd = cast<SCEVAddExpr>(SecondCast->getOperand ());
753+ auto *SecondOp0 = SecondAdd->getOperand (0 );
754+ auto *SecondOp1 = SecondAdd->getOperand (1 );
755+ if (isa<SCEVConstant>(SecondOp0))
756+ std::swap (SecondOp0, SecondOp1);
757+ if (!isa<SCEVUnknown>(SecondOp0))
758+ return None;
759+ auto FirstVarVal = cast<SCEVUnknown>(FirstVar)->getValue ();
760+ auto FirstConst = cast<SCEVConstant>(FirstOp1)->getAPInt ().getSExtValue ();
761+ auto SecondVarVal = cast<SCEVUnknown>(SecondOp0)->getValue ();
762+ auto SecondConst =
763+ cast<SCEVConstant>(SecondOp1)->getAPInt ().getSExtValue ();
764+ if (FirstVarVal == SecondVarVal)
765+ return (FirstConst - SecondConst) * SwapMult;
766+ }
726767 return None;
768+ }
727769 if (auto Const = llvm::dyn_cast<llvm::SCEVConstant>(
728770 SE->getMinusSCEV (InnerLHS, InnerRHS)))
729771 return Const->getAPInt ().getSExtValue ();
0 commit comments