[PATCH] Remove SCEVCache and FindConstantPointers from complete loop unrolling heuristic.

Chandler Carruth chandlerc at gmail.com
Thu Jun 4 17:14:00 PDT 2015


As Andy said, really nice use of SCEV. This is exactly the direction I was hoping for here.

Detailed comments below. Mostly this is about sorting out minor details, naming, and how to cache these things.


================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:281-288
@@ +280,10 @@
+  /// \brief A cache of pointer bases corresponding to GEP (or derived from GEP)
+  /// instructions.
+  ///
+  /// In order to find the base pointer one needs to perform non-trivial
+  /// traversal of the corresponding SCEV expression, so it's good to have the
+  /// results saved.
+  /// The instruction doesn't have to be GetElementPtrInst - for instance, it
+  /// could be PHINode. That's why we use a generic Instruction type here.
+  SmallDenseMap<Instruction *, Value *> GEPPointerBases;
+
----------------
Based on this (very nice) comment, the name should just be "PointerBases"... Or even better, BasePointers. But see below...

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:315
@@ +314,3 @@
+  /// it instead.
+  bool SCEVSimplify(Instruction *I) {
+    if (!SE.isSCEVable(I->getType()))
----------------
I think a better name for this would be 'simplifyInstWithSCEV'

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:326
@@ +325,3 @@
+    if (auto *AR = dyn_cast<SCEVAddRecExpr>(S)) {
+      const SCEV *IterationNumber = SE.getConstant(APInt(64, Iteration));
+      const SCEV *ValueAtIteration =
----------------
I'd compute this as part of the constructor (and thus once).

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:338-339
@@ +337,4 @@
+        return false;
+      if (auto *Offset =
+              dyn_cast<SCEVConstant>(SE.getMinusSCEV(ValueAtIteration, Base))) {
+        GEPPointerBases[I] = Base->getValue();
----------------
For pointer types, is this the byte difference or are the units in something other than bytes?

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:340-341
@@ +339,4 @@
+              dyn_cast<SCEVConstant>(SE.getMinusSCEV(ValueAtIteration, Base))) {
+        GEPPointerBases[I] = Base->getValue();
+        SimplifiedValues[I] = Offset->getValue();
+        return true;
----------------
I don't think this quite works.

The offset value, while constant, is not the simplification of this instruction. For example, if the offset is 2, and we see 'icmp eq' of I and the constant '2', it shouldn't be able to constant fold.

I think you want to store a mapping from instruction to a pair of Value* and Constant*, "BasePointersAndOffsets" or some such. Not sure of a good name here.

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:361-362
@@ -487,2 +360,4 @@
   bool visitBinaryOperator(BinaryOperator &I) {
+    if (SCEVSimplify(&I))
+      return true;
     Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
----------------
Is this better than constant folding? It's not clear to me that it is, it seems like it might be much more expensive.

I think I would change the *end* of this function to 'if (SimpleV) return true;' and then add a final return that was essentially 'return Base::visitBinaryOperator(I);' so its clear you're just delegating.

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:387-389
@@ -511,8 +386,5 @@
     Value *AddrOp = I.getPointerOperand();
-    if (!isa<Constant>(AddrOp))
-      if (Constant *SimplifiedAddrOp = SimplifiedValues.lookup(AddrOp))
-        AddrOp = SimplifiedAddrOp;
-
     auto *GEP = dyn_cast<GetElementPtrInst>(AddrOp);
     if (!GEP)
       return false;
+
----------------
This shouldn't be needed now, right?

================
Comment at: lib/Transforms/Scalar/LoopUnrollPass.cpp:407-411
@@ -533,9 +406,7 @@
 
     // This calculation should never overflow because we bound Iteration quite
     // low and both the start and step are 32-bit integers. We use signed
     // integers so that UBSan will catch if a bug sneaks into the code.
     int ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U;
-    int64_t Index = ((int64_t)OptionalGEPDesc->Start +
-                     (int64_t)OptionalGEPDesc->Step * (int64_t)Iteration) /
-                    ElemSize;
+    int64_t Index = SimplifiedAddrOp->getLimitedValue() / ElemSize;
     if (Index >= CDS->getNumElements()) {
----------------
The comment above doesn't make much sense any more. =]

I'd also consider bailing or asserting if the offset requires lots of bits here rather than limiting it.

http://reviews.llvm.org/D10205

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the llvm-commits mailing list