[PATCH] D71690: [SCEV] get a more accurate range for AddRecExpr with nuw flag

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 8 10:21:26 PST 2020


nikic added inline comments.


================
Comment at: llvm/lib/Analysis/ScalarEvolution.cpp:5661
+        MinValue = getUnsignedRangeMin(AddRec->getStart());
+      else {
+        ConstantRange StartRange =
----------------
shchenz wrote:
> nikic wrote:
> > shchenz wrote:
> > > nikic wrote:
> > > > shchenz wrote:
> > > > > sanjoy.google wrote:
> > > > > > Can you comment on why you need the else block?
> > > > > If we use `getUnsignedRangeMin(AddRec->getStart())` as minimum value for SignedRange of the start of AddRec, we may get wrong result. For example, assuming we get range `[137, 227)` as result of `getUnsignedRangeMin(AddRec->getStart());` for type `i8`,  if we want to return it as SignedRange, it will be `[-119, -29)`, this is invalid range for AddRec with `nuw` even for SignedRange?
> > > > Why is `[-119, -29)` an invalid range?
> > > For SCEV1 `{x,+,stride}<nuw>`, when we try to get a signed range for SCEV1, the result range should be contained in [0, SINT_MAX +1)? 
> > > If we use `getUnsignedRangeMin(AddRec->getStart())` to get start value range, it should be any value in [0, UINT_MAX + 1), so the start min can be a value between [ SINT_MAX +1, UINT_MAX + 1), like 137 for type `i8`. If the signed range for SCEV1 is [137, 227), it is not inside the expected range [0, 128). For this case, we should return empty for SCEV1 SignedRange?
> > I still don't really get it. Why would the range need to be inside [0, SINT_MAX]? For example, let's say the start range is `[-100, -90]`, then that could still result in a valid nuw addrec, e.g. because we have `iv == -10` as a loop exit condition. "nuw" doesn't imply that the numbers can't be "negative", as long as the addrec does not cross zero.
> Ah, thanks, got your idea.
> 
> we get
> `-->  {-10,+,1}<nuw><%loop> U: [-10,0) S: [-10,0)`
> 
> So signed range for a SCEV with `nuw` flag may still be a range in the negative part.
Thanks, this looks better. What isn't clear to me though is why we can't just always use `getUnsignedRangeMin()` here. Shouldn't that always be correct and potentially give a better result?

Or is there some rule that you are not allowed to use the unsigned range while computing a signed range?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71690/new/

https://reviews.llvm.org/D71690





More information about the llvm-commits mailing list