Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -1584,12 +1584,101 @@ // to be set. The comparison is equal to a signed comparison under this // assumption. bool NonNeg = ICond->isUnsigned(); - LHS = getPwAff(S, BB, InvalidDomainMap, - SE.getSCEVAtScope(ICond->getOperand(0), L), NonNeg); - RHS = getPwAff(S, BB, InvalidDomainMap, - SE.getSCEVAtScope(ICond->getOperand(1), L), NonNeg); - ConsequenceCondSet = - buildConditionSet(ICond->getPredicate(), LHS, RHS, Domain); + + // Checking wrap-around for ICMP_ULT. + // ICMP_SLT is handled by design. + if (ICond->getPredicate() == ICmpInst::ICMP_ULT) { + // Case handling for 0 <= LHS < RHS + // But assuming LHS might have MSB set. + LHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(0), L), false); + RHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(1), L), true); + + isl_set *ge, *gt; + ge = isl_pw_aff_ge_set( + isl_pw_aff_copy(LHS), + isl_pw_aff_read_from_str(S.getIslCtx(), + "{ [i0] -> [(0)] }")); // 0 <= LHS + gt = isl_pw_aff_gt_set(RHS, + LHS); // LHS < RHS + + ConsequenceCondSet = isl_set_intersect(ge, gt); + ConsequenceCondSet = setDimensionIds(Domain, ConsequenceCondSet); + + } + // Checking wrap-around for ICMP_UGT. + // ICMP_SGT is handled by design. + else if (ICond->getPredicate() == ICmpInst::ICMP_UGT) { + // Case handling for LHS > RHS >= 0. + // But assuming RHS might have MSB set. + LHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(0), L), true); + RHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(1), L), false); + + isl_set *ge, *gt; + gt = isl_pw_aff_gt_set(LHS, + isl_pw_aff_copy(RHS)); // LHS > RHS + ge = isl_pw_aff_ge_set( + RHS, isl_pw_aff_copy(isl_pw_aff_read_from_str( + S.getIslCtx(), "{ [i0] -> [(0)] }"))); // RHS >= 0 + + ConsequenceCondSet = isl_set_intersect(ge, gt); + ConsequenceCondSet = setDimensionIds(Domain, ConsequenceCondSet); + + } + // Checking wrap-around for ICMP_UGE. + // ICMP_SGE is handled by design. + else if (ICond->getPredicate() == ICmpInst::ICMP_UGE) { + // Case handling for LHS >= RHS >= 0. + // But assuming RHS might have MSB set. + LHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(0), L), true); + RHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(1), L), false); + + isl_set *ge_1, *ge_2; + ge_1 = isl_pw_aff_ge_set(LHS, + isl_pw_aff_copy(RHS)); // LHS >= RHS + ge_2 = isl_pw_aff_ge_set( + RHS, isl_pw_aff_copy(isl_pw_aff_read_from_str( + S.getIslCtx(), "{ [i0] -> [(0)] }"))); // RHS >= 0 + + ConsequenceCondSet = isl_set_intersect(ge_1, ge_2); + ConsequenceCondSet = setDimensionIds(Domain, ConsequenceCondSet); + + } + // Checking wrap-around for ICMP_ULE. + // ICMP_SLE is handled by design. + else if (ICond->getPredicate() == ICmpInst::ICMP_ULE) { + // Case handling for 0 <= LHS <= RHS + // But assuming LHS might have MSB set. + LHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(0), L), false); + RHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(1), L), true); + + isl_set *ge_1, *ge_2; + ge_1 = isl_pw_aff_ge_set( + isl_pw_aff_copy(LHS), + isl_pw_aff_read_from_str(S.getIslCtx(), + "{ [i0] -> [(0)] }")); // 0 <= LHS + ge_2 = isl_pw_aff_gt_set(RHS, + LHS); // LHS <= RHS + + ConsequenceCondSet = isl_set_intersect(ge_1, ge_2); + ConsequenceCondSet = setDimensionIds(Domain, ConsequenceCondSet); + + } else { + LHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(0), L), NonNeg); + RHS = getPwAff(S, BB, InvalidDomainMap, + SE.getSCEVAtScope(ICond->getOperand(1), L), NonNeg); + + ConsequenceCondSet = + buildConditionSet(ICond->getPredicate(), LHS, RHS, Domain); + } } // If no terminator was given we are only looking for parameter constraints Index: test/ScopInfo/unsigned_wrap_ugt.ll =================================================================== --- test/ScopInfo/unsigned_wrap_ugt.ll +++ test/ScopInfo/unsigned_wrap_ugt.ll @@ -0,0 +1,37 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s + +define void @func(double* noalias nonnull %A) { +entry: + br label %for + + for: + %j = phi i32 [-1, %entry], [%j.inc, %inc] + %j.cmp = icmp slt i32 %j, 65 + br i1 %j.cmp, label %body, label %exit + + body: + %inbounds = icmp ugt i32 64, %j + br i1 %inbounds, label %ifinbounds, label %ifoutbounds + + ifinbounds: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + store double 42.0, double* %A_idx + br label %inc + + ifoutbounds: + br label %inc + + inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + + exit: + br label %return + + return: + ret void +} + + +; CHECK: Region: %for---%return + Index: test/ScopInfo/unsigned_wrap_ult.ll =================================================================== --- test/ScopInfo/unsigned_wrap_ult.ll +++ test/ScopInfo/unsigned_wrap_ult.ll @@ -0,0 +1,37 @@ +; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s + +define void @func(double* noalias nonnull %A) { +entry: + br label %for + + for: + %j = phi i32 [-1, %entry], [%j.inc, %inc] + %j.cmp = icmp slt i32 %j, 65 + br i1 %j.cmp, label %body, label %exit + + body: + %inbounds = icmp ult i32 %j, 64 + br i1 %inbounds, label %ifinbounds, label %ifoutbounds + + ifinbounds: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + store double 42.0, double* %A_idx + br label %inc + + ifoutbounds: + br label %inc + + inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + + exit: + br label %return + + return: + ret void +} + + +; CHECK: Region: %for---%return +