[llvm-commits] PATCH: Add support for tracking pairs of pointers with a constant offset to inline cost estimation

Nick Lewycky nicholas at mxc.ca
Thu Mar 8 22:41:25 PST 2012


Chandler Carruth wrote:
> Hello folks!
>
> This is an early patch, it still has some rough edges. In particular, I
> want to clean up the body of the loop which looks for operations to
> simplify in the function body, but I wanted to start showing people
> where I'm going here and get any feedback sooner rather than later.

+  // Check which direction the expect result points so that we know how 
to flip
+  // the value across bitwise operations.
    bool Result = ICI->isTrueWhenEqual();

We don't flip the value, all instructions we recursively visit must all 
return Result. If they don't, we don't visit them.

+void InlineCostAnalyzer::FunctionInfo::countCodeReductionForPointerPair(
+    const CodeMetrics &Metrics, DenseMap<Value *, unsigned> &PointerArgs,
+    Value *V, unsigned ArgIdx) {
+  SmallVector<Value *, 4> Worklist;
+  Worklist.push_back(V);
+  do {
+    Value *V = Worklist.pop_back_val();
+    for (Value::use_iterator UI = V->use_begin(), E = V->use_end();
+         UI != E; ++UI){

Missing space before {

+      if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
+        // If the GEP has variable indices, we won't be able to do much 
with it.
+        if (!GEP->hasAllConstantIndices())
+          continue;

inbounds should be sufficient as well.

Also, this function should handle SelectInst. Something like:

   // Track through a select between two related pointers.
   if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
     Value *ThisArg = SI->getTrueValue();
     Value *OtherArg = SI->getFalseValue();
     if (ThisArg != V)
       std::swap(ThisArg, OtherArg);
     if (ThisArg != V)
       continue;

     DenseMap<Value *, unsigned>::const_iterator ArgIt =
         PointerArgs.find(OtherArg);
     if (ArgIt != PointerArgs.end() &&
         *ArgIt == ArgIdx) {
       PointerArgs[SI] = ArgIdx;
       Worklist.push_back(SI);
       continue;
     }
   }

.

+static bool isPointerPairConstantRelated(Value *X, Value *Y) {
+  // Unroll both sides until we hit a fixed point where the pointer 
value "came
+  // from". If the two values are constant-related, they will halt at 
the same
+  // fixed point.
+  while (stripConstantGEP(X) || stripBitCast(X))
+    ;
+  while (stripConstantGEP(Y) || stripBitCast(Y))
+    ;
+
+  return X == Y;
+}

This is nearly X->stripPointerCasts() == Y->stripPointerCasts(), but 
includes non-zero GEPs. I suggest taking 
lib/Analysis/InstructionSimplify.cpp's stripPointerAdjustments() and 
either make it a method on Value* like stripPointerCasts, or else 
somewhere publicly visible in libAnalysis.

Nick

> The motivation for these heroics (and I recognize that these are
> heroics) is to handle cases like:
>
> template <typename IteratorT>
> foo my_algorithm(IteratorT first, IteratorT last) {
>    if (std::distance(first, last) < 42) {
>      // Algorithm A
>    } else {
>      // Algorithm B
>    }
> }
>
> Without this patch, the inline cost will be assumed to be the total size
> of the function, even when we call it like so:
>
> void test(int *ptr) {
>    foo bar = my_algorithm(ptr, ptr + 13);
> }
>
> Here, the arguments are a known constant offset, and yet we won't see
> that, or see that only one half of the branch in my_algorithm is going
> to survive. This causes missed optimizations every time we use an STL
> algorithm on a fixed buffer (usually a stack object).
>
> The patch tries to track these correlated pointer values, and detect
> when they're used in a way that will simplify. Initial testing shows
> that it works, but I haven't yet reduced my big test cases into nice
> small feature tests for the test suite. Clearly, that has to happen
> before check-in.
>
>
> Let me know your thoughts! I'll post a new patch as I clean it up, and
> I'll also post numbers as I have them on the impact this gives.
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list