[PATCH] D11860: [SCEV] Apply NSW and NUW flags via poison value analysis for sub, mul and shl
Sanjoy Das via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 13 00:54:52 PDT 2015
sanjoy added inline comments.
================
Comment at: lib/Analysis/ScalarEvolution.cpp:3381
@@ +3380,3 @@
+ // Let M be the minimum representable signed value. Then -RHS
+ // signed-wraps if and only if RHS is M. That can happen even for
+ // a NSW subtraction because e.g. -M signed-wraps even though -1 - M
----------------
My subjective opinion is that since there is no direct representation of `-X` in LLVM IR, we ultimately have to choose a specific representation to reason about. The specific representation is not obvious either since both `sub 0 X` and `mul -1 X` are equally valid, so it is nice to be explicit about these things. Moreover, here things are doubly confusing since `sub 0 X` and `mul -1 X` have identical behavior w.r.t. `nsw` so there is no easy way for the reader to "check" if (s)he understood the intent correctly.
However, objectively, I don't think there is any problem with directly proving things about a mathematical negation operation, so I'd suggest just putting in a sentence either here or above on what exactly you mean by `-RHS`.
================
Comment at: lib/Analysis/ScalarEvolution.cpp:3408
@@ +3407,3 @@
+ // not know that in this case.
+ if (RHSIsNotMinSigned || isa<SCEVAddRecExpr>(RHS))
+ NegFlags = SCEV::FlagNSW;
----------------
But what if you have a loop nested within other, and LHS is an addrec on the inner loop while RHS is an addrec on the outer loop? Then `LHS - RHS` would be an addrec on the inner loop (so the `nsw` is guaranteed to apply only on the inner loop), but `RHS` has a larger scope than the inner loop while still being an add rec.
IOW, something like this:
```
define void @f(i32 %outer_l, i32 %inner_l) {
entry:
br label %outer
outer:
%o_idx = phi i32 [ 0, %entry ], [ %o_idx.inc, %outer.be ]
%o_idx.inc = add i32 %o_idx, 1
%cond = icmp eq i32 %o_idx, 42
br i1 %cond, label %inner, label %outer.be
inner:
%i_idx = phi i32 [ 0, %outer ], [ %i_idx.inc, %inner ]
%i_idx.inc = add i32 %i_idx, 1
%v = sub nsw i32 %i_idx, %o_idx
%cond2 = icmp eq i32 %i_idx, %inner_l
br i1 %cond2, label %outer.be, label %inner
outer.be:
%cond3 = icmp eq i32 %o_idx, %outer_l
br i1 %cond3, label %exit, label %outer
exit:
ret void
}
```
where `%v` is an add rec for the `%inner` loop while `%o_idx` is an add rec on the outer loop.
================
Comment at: lib/Analysis/ScalarEvolution.cpp:4135
@@ -4098,2 +4134,3 @@
+ if (!BinOp) return SCEV::FlagAnyWrap;
// Return early if there are no flags to propagate to the SCEV.
----------------
Then I'd suggest `if (isa<ConstantExpr>(V)) return FlagAnyWrap;`, that makes the code more obvious.
================
Comment at: lib/Analysis/ScalarEvolution.cpp:4428
@@ -4372,3 +4427,3 @@
APInt::getOneBitSet(BitWidth, SA->getZExtValue()));
- return getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X));
+ return getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X), Flags);
}
----------------
SGTM.
http://reviews.llvm.org/D11860
More information about the llvm-commits
mailing list