llvm.org GIT mirror llvm / 3547a7e
[ConstantRange] Add makeExactNoWrapRegion() I got confused on the terminology, and the change in D60598 was not correct. I was thinking of "exact" in terms of the result being non-approximate. However, the relevant distinction here is whether the result is * Largest range such that: Forall Y in Other: Forall X in Result: X BinOp Y does not wrap. (makeGuaranteedNoWrapRegion) * Smallest range such that: Forall Y in Other: Forall X not in Result: X BinOp Y wraps. (A hypothetical makeAllowedNoWrapRegion) * Both. (makeExactNoWrapRegion) I'm adding a separate makeExactNoWrapRegion method accepting a single APInt (same as makeExactICmpRegion) and using it in the places where the guarantee is relevant. Differential Revision: https://reviews.llvm.org/D60960 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359402 91177308-0d34-0410-b5e6-96231b3b80d8 Nikita Popov 1 year, 6 months ago
4 changed file(s) with 32 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
123123 static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred,
124124 const APInt &Other);
125125
126 /// Return the exact range containing all X such that "X BinOpC Y" is
127 /// guaranteed not to wrap (overflow) for all Y in Other.
126 /// Produce the largest range containing all X such that "X BinOp Y" is
127 /// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may
128 /// be *some* Y in Other for which additional X not contained in the result
129 /// also do not overflow.
128130 ///
129131 /// NoWrapKind must be one of OBO::NoUnsignedWrap or OBO::NoSignedWrap.
130132 ///
141143 const ConstantRange &Other,
142144 unsigned NoWrapKind);
143145
146 /// Produce the range that contains X if and only if "X BinOp Other" does
147 /// not wrap.
148 static ConstantRange makeExactNoWrapRegion(Instruction::BinaryOps BinOp,
149 const APInt &Other,
150 unsigned NoWrapKind);
151
144152 /// Set up \p Pred and \p RHS such that
145153 /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if
146154 /// successful.
11451145 return ValueLatticeElement::getOverdefined();
11461146
11471147 // Calculate the possible values of %x for which no overflow occurs.
1148 ConstantRange NWR = ConstantRange::makeGuaranteedNoWrapRegion(
1149 WO->getBinaryOp(), ConstantRange(*C), WO->getNoWrapKind());
1148 ConstantRange NWR = ConstantRange::makeExactNoWrapRegion(
1149 WO->getBinaryOp(), *C, WO->getNoWrapKind());
11501150
11511151 // If overflow is false, %x is constrained to NWR. If overflow is true, %x is
11521152 // constrained to it's inverse (all values that might cause overflow).
306306 makeSingleValueRegion(Other.getSignedMax()));
307307 }
308308 }
309 }
310
311 ConstantRange ConstantRange::makeExactNoWrapRegion(Instruction::BinaryOps BinOp,
312 const APInt &Other,
313 unsigned NoWrapKind) {
314 // makeGuaranteedNoWrapRegion() is exact for single-element ranges, as
315 // "for all" and "for any" coincide in this case.
316 return makeGuaranteedNoWrapRegion(BinOp, ConstantRange(Other), NoWrapKind);
309317 }
310318
311319 bool ConstantRange::isFullSet() const {
842850 ConstantRange ConstantRange::addWithNoSignedWrap(const APInt &Other) const {
843851 // Calculate the subset of this range such that "X + Other" is
844852 // guaranteed not to wrap (overflow) for all X in this subset.
845 // makeGuaranteedNoWrapRegion will produce an exact NSW range.
846 auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(BinaryOperator::Add,
847 ConstantRange(Other),
848 OverflowingBinaryOperator::NoSignedWrap);
853 auto NSWRange = ConstantRange::makeExactNoWrapRegion(
854 BinaryOperator::Add, Other, OverflowingBinaryOperator::NoSignedWrap);
849855 auto NSWConstrainedRange = intersectWith(NSWRange);
850856
851857 return NSWConstrainedRange.add(ConstantRange(Other));
11751175 ConstantRange::makeGuaranteedNoWrapRegion(BinOp, CR2, NoWrapKind);
11761176 ForeachNumInConstantRange(CR1, [&](const APInt &N1) {
11771177 bool NoOverflow = true;
1178 bool Overflow = true;
11781179 ForeachNumInConstantRange(CR2, [&](const APInt &N2) {
11791180 if (OverflowFn(N1, N2))
11801181 NoOverflow = false;
1182 else
1183 Overflow = false;
11811184 });
11821185 EXPECT_EQ(NoOverflow, NoWrap.contains(N1));
1186
1187 // The no-wrap range is exact for single-element ranges.
1188 if (CR2.isSingleElement()) {
1189 EXPECT_EQ(Overflow, !NoWrap.contains(N1));
1190 }
11831191 });
11841192 });
11851193 }
11861194
1187 // Show that makeGuaranteedNoWrapRegion is precise if only one of
1188 // NoUnsignedWrap or NoSignedWrap is used.
1195 // Show that makeGuaranteedNoWrapRegion() is maximal, and for single-element
1196 // ranges also exact.
11891197 TEST(ConstantRange, NoWrapRegionExhaustive) {
11901198 TestNoWrapRegionExhaustive(
11911199 Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap,