[PATCH] D12905: [SCEV][LV] Introduce SCEV Predicates and use them to re-implement stride versioning

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 15:14:22 PDT 2015


sanjoy requested changes to this revision.
sanjoy added a reviewer: sanjoy.
sanjoy added a comment.
This revision now requires changes to proceed.

Reviewed the SCEV bits.  I don't know enough about the other bits to comment on those.


================
Comment at: include/llvm/Analysis/ScalarEvolution.h:184
@@ +183,3 @@
+    unsigned short getType() const { return SCEVPredicateType; }
+    /// \brief Returns the estimated complexity of this predicate.
+    /// This is roughly measured in the number of run-time checks required.
----------------
Minor: I'd put newlines between method declarations.

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:191
@@ +190,3 @@
+    /// \brief Returns true if this predicate implies \p N.
+    virtual bool contains(const SCEVPredicate *N) const = 0;
+    /// \brief Prints a textual representation of this predicate.
----------------
Also minor, but why not just call it `implies`?

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:197
@@ +196,3 @@
+    /// In case no checks are needed nullptr is returned.
+    virtual Value *generateCheck(Instruction *Loc, ScalarEvolution *SE,
+                                 const DataLayout *DL, SCEVExpander &Exp) = 0;
----------------
Please document `Loc`, and pass in things that cannot be `nullptr`, like `SE` or `DL` as references.

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:208
@@ +207,3 @@
+    // We assume that E0 == E1
+    const SCEV *E0;
+    const SCEV *E1;
----------------
The restriction that `LHS` is a `SCEVUnknown` seems somewhat arbitrary; but if you want to keep it, please change the type of `E0` to be `SCEVUnknown`.

Also, rename `E0` and `E1` to `LHS` and `RHS` to sync with the documentation, or change the documentation to refer to these as `E0` or `E1`.

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:220
@@ +219,3 @@
+
+    const SCEV *getLHS() { return E0; }
+    const SCEV *getRHS() { return E1; }
----------------
Same comment here -- if your invariant is that `E0` is a `SCEVUnknown`, then make that obvious in the type.

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:234
@@ +233,3 @@
+  /// SCEVUnionPredicate - This class represents a composition of other
+  /// SCEV predicates, and is the class that most clients will interact with.
+  ///
----------------
I haven't read the whole patch yet, but I think the doc should state if a `SCEVUnionPredicate` represents a logical and or a logical or (or sometimes one and sometimes the other) of the predicates it contains.

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:239
@@ +238,3 @@
+    /// Storage for different predicates that make up this union of predicates.
+    SmallVector<SCEVEqualPredicate, 16> IdPreds;
+
----------------
I agree with @mzolotukhin -- this won't work once you have different types of predicates.  You'll need a "host" to contain the allocations, perhaps using a `BumpPtrAllocator` or something similar.

================
Comment at: include/llvm/Analysis/ScalarEvolution.h:258
@@ +257,3 @@
+    /// generated we will return a pair of nullptr.
+    std::pair<Instruction *, Instruction *>
+    generateGuardCond(Instruction *Loc, ScalarEvolution *SE);
----------------
Why do you need to return a pair of instructions?  Why not just return a `Value *` computing the result of the predicate?  This will also obviate the need to create a "fake or" in the implementation, and you'll just be able to return what IRBuilder gave you.

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9106
@@ +9105,3 @@
+bool SCEVEqualPredicate::contains(const SCEVPredicate *N) const {
+  const SCEVEqualPredicate *Op = dyn_cast<const SCEVEqualPredicate>(N);
+
----------------
Use `const auto *`.

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9111
@@ +9110,3 @@
+
+  if ((Op->E0 == E0 && Op->E1 == E1) || (Op->E0 == E1 && Op->E1 == E0))
+    return true;
----------------
Why not just `return (Op->E0 == E0 && Op->E1 == E1) || (Op->E0 == E1 && Op->E1 == E0)`?

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9127
@@ +9126,3 @@
+
+  Value *C = Builder.CreateICmpNE(Expr0, Expr1, "ident.check");
+  return C;
----------------
Why not just `return Builder.CreateICmpNE(...)`?

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9150
@@ +9149,3 @@
+std::pair<Instruction *, Instruction *>
+SCEVUnionPredicate::generateGuardCond(Instruction *Loc, ScalarEvolution *SE) {
+  IRBuilder<> GuardBuilder(Loc);
----------------
As I've mentioned in the declaration of `generateGuardCond`, I don't see why you need to return a range of instructions.  I'd rather have this return a `Value *`, and do away with `getFirstInst` and the fake `or` instruction.

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9199
@@ +9198,3 @@
+                       [this](SCEVPredicate *I) { return this->contains(I); });
+  return std::any_of(Preds.begin(), Preds.end(),
+                     [N](SCEVPredicate *I) { return I->contains(N); });
----------------
I think this should be `std::all_of` to be consistent with the interpretation of `SCEVUnionPredicate` in `generateCheck` -- to prove `(X|Y)->Z` you need to prove `(X->Z)&&(Y->Z)`.

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9209
@@ +9208,3 @@
+void SCEVUnionPredicate::add(const SCEVPredicate *N) {
+  if (const SCEVEqualPredicate *EP = dyn_cast<const SCEVEqualPredicate>(N)) {
+    for (auto Pred : IdPreds)
----------------
Nit: here and elsewhere, prefer using `const auto *` or `auto *` when the type is obvious from the RHS.

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9210
@@ +9209,3 @@
+  if (const SCEVEqualPredicate *EP = dyn_cast<const SCEVEqualPredicate>(N)) {
+    for (auto Pred : IdPreds)
+      if (Pred.contains(EP))
----------------
[Optional] Why not `std::any_of`?

================
Comment at: lib/Analysis/ScalarEvolution.cpp:9213
@@ +9212,3 @@
+        return;
+    IdPreds.push_back(*EP);
+    Preds.push_back(&IdPreds.back());
----------------
As mentioned earlier, this allocation scheme is not quite right.


http://reviews.llvm.org/D12905





More information about the llvm-commits mailing list