[llvm-commits] [llvm] r169573 - in /llvm/trunk: lib/Analysis/ValueTracking.cpp test/Transforms/InstSimplify/compare.ll

Daniel Dunbar daniel at zuster.org
Tue Dec 11 15:11:55 PST 2012


Actually, while you are at it, sqlite3 is also showing a jump for the same
commit range:

http://llvm.org/perf/db_default/v4/nts/graph?plot.0=7.402.2&highlight_run=6629
sqlite3 also seems to not have liked:
  http://llvm.org/viewvc/llvm-project?view=rev&revision=169697

 - Daniel


On Tue, Dec 11, 2012 at 2:59 PM, Chandler Carruth <chandlerc at gmail.com>wrote:

> Yea, for a single source to regress stably is weird... i'll look.
>
>
> On Tue, Dec 11, 2012 at 2:55 PM, Daniel Dunbar <daniel at zuster.org> wrote:
>
>> Hey Chandler,
>>
>> It looks like this might have caused a small regression on:
>>   SingleSource/Benchmarks/Shootout-C++/hash2
>> that seems to have stuck around:
>>
>> http://llvm.org/perf/db_default/v4/nts/graph?plot.0=7.41.2&highlight_run=6629
>>
>> It's pretty small, but might be interesting if you feel like
>> investigating.
>>
>>  - Daniel
>>
>>
>> On Thu, Dec 6, 2012 at 6:08 PM, Chandler Carruth <chandlerc at gmail.com>wrote:
>>
>>> Author: chandlerc
>>> Date: Thu Dec  6 20:08:58 2012
>>> New Revision: 169573
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=169573&view=rev
>>> Log:
>>> Add support to ValueTracking for determining that a pointer is non-null
>>> by virtue of inbounds GEPs that preclude a null pointer.
>>>
>>> This is a very common pattern in the code generated by std::vector and
>>> other standard library routines which use allocators that test for null
>>> pervasively. This is one step closer to teaching Clang+LLVM to be able
>>> to produce an empty function for:
>>>
>>>   void f() {
>>>     std::vector<int> v;
>>>     v.push_back(1);
>>>     v.push_back(2);
>>>     v.push_back(3);
>>>     v.push_back(4);
>>>   }
>>>
>>> Which is related to getting them to completely fold SmallVector
>>> push_back sequences into constants when inlining and other optimizations
>>> make that a possibility.
>>>
>>> Modified:
>>>     llvm/trunk/lib/Analysis/ValueTracking.cpp
>>>     llvm/trunk/test/Transforms/InstSimplify/compare.ll
>>>
>>> Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=169573&r1=169572&r2=169573&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Thu Dec  6 20:08:58 2012
>>> @@ -862,6 +862,72 @@
>>>    return false;
>>>  }
>>>
>>> +/// \brief Test whether a GEP's result is known to be non-null.
>>> +///
>>> +/// Uses properties inherent in a GEP to try to determine whether it is
>>> known
>>> +/// to be non-null.
>>> +///
>>> +/// Currently this routine does not support vector GEPs.
>>> +static bool isGEPKnownNonNull(GEPOperator *GEP, const DataLayout *DL,
>>> +                              unsigned Depth) {
>>> +  if (!GEP->isInBounds() || GEP->getPointerAddressSpace() != 0)
>>> +    return false;
>>> +
>>> +  // FIXME: Support vector-GEPs.
>>> +  assert(GEP->getType()->isPointerTy() && "We only support plain
>>> pointer GEP");
>>> +
>>> +  // If the base pointer is non-null, we cannot walk to a null address
>>> with an
>>> +  // inbounds GEP in address space zero.
>>> +  if (isKnownNonZero(GEP->getPointerOperand(), DL, Depth))
>>> +    return true;
>>> +
>>> +  // Past this, if we don't have DataLayout, we can't do much.
>>> +  if (!DL)
>>> +    return false;
>>> +
>>> +  // Walk the GEP operands and see if any operand introduces a non-zero
>>> offset.
>>> +  // If so, then the GEP cannot produce a null pointer, as doing so
>>> would
>>> +  // inherently violate the inbounds contract within address space zero.
>>> +  for (gep_type_iterator GTI = gep_type_begin(GEP), GTE =
>>> gep_type_end(GEP);
>>> +       GTI != GTE; ++GTI) {
>>> +    // Struct types are easy -- they must always be indexed by a
>>> constant.
>>> +    if (StructType *STy = dyn_cast<StructType>(*GTI)) {
>>> +      ConstantInt *OpC = cast<ConstantInt>(GTI.getOperand());
>>> +      unsigned ElementIdx = OpC->getZExtValue();
>>> +      const StructLayout *SL = DL->getStructLayout(STy);
>>> +      uint64_t ElementOffset = SL->getElementOffset(ElementIdx);
>>> +      if (ElementOffset > 0)
>>> +        return true;
>>> +      continue;
>>> +    }
>>> +
>>> +    // If we have a zero-sized type, the index doesn't matter. Keep
>>> looping.
>>> +    if (DL->getTypeAllocSize(GTI.getIndexedType()) == 0)
>>> +      continue;
>>> +
>>> +    // Fast path the constant operand case both for efficiency and so
>>> we don't
>>> +    // increment Depth when just zipping down an all-constant GEP.
>>> +    if (ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand())) {
>>> +      if (!OpC->isZero())
>>> +        return true;
>>> +      continue;
>>> +    }
>>> +
>>> +    // We post-increment Depth here because while isKnownNonZero
>>> increments it
>>> +    // as well, when we pop back up that increment won't persist. We
>>> don't want
>>> +    // to recurse 10k times just because we have 10k GEP operands. We
>>> don't
>>> +    // bail completely out because we want to handle constant GEPs
>>> regardless
>>> +    // of depth.
>>> +    if (Depth++ >= MaxDepth)
>>> +      continue;
>>> +
>>> +    if (isKnownNonZero(GTI.getOperand(), DL, Depth))
>>> +      return true;
>>> +  }
>>> +
>>> +  return false;
>>> +}
>>> +
>>>  /// isKnownNonZero - Return true if the given value is known to be
>>> non-zero
>>>  /// when defined.  For vectors return true if every element is known to
>>> be
>>>  /// non-zero when defined.  Supports values with integer or pointer
>>> type and
>>> @@ -881,6 +947,13 @@
>>>    if (Depth++ >= MaxDepth)
>>>      return false;
>>>
>>> +  // Check for pointer simplifications.
>>> +  if (V->getType()->isPointerTy()) {
>>> +    if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
>>> +      if (isGEPKnownNonNull(GEP, TD, Depth))
>>> +        return true;
>>> +  }
>>> +
>>>    unsigned BitWidth = getBitWidth(V->getType(), TD);
>>>
>>>    // X | Y != 0 if X != 0 or Y != 0.
>>>
>>> Modified: llvm/trunk/test/Transforms/InstSimplify/compare.ll
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/compare.ll?rev=169573&r1=169572&r2=169573&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/InstSimplify/compare.ll (original)
>>> +++ llvm/trunk/test/Transforms/InstSimplify/compare.ll Thu Dec  6
>>> 20:08:58 2012
>>> @@ -165,6 +165,46 @@
>>>    ret i1 %cmp
>>>  }
>>>
>>> +define i1 @gep13(i8* %ptr) {
>>> +; CHECK: @gep13
>>> +; We can prove this GEP is non-null because it is inbounds.
>>> +  %x = getelementptr inbounds i8* %ptr, i32 1
>>> +  %cmp = icmp eq i8* %x, null
>>> +  ret i1 %cmp
>>> +; CHECK-NEXT: ret i1 false
>>> +}
>>> +
>>> +define i1 @gep14({ {}, i8 }* %ptr) {
>>> +; CHECK: @gep14
>>> +; We can't simplify this because the offset of one in the GEP actually
>>> doesn't
>>> +; move the pointer.
>>> +  %x = getelementptr inbounds { {}, i8 }* %ptr, i32 0, i32 1
>>> +  %cmp = icmp eq i8* %x, null
>>> +  ret i1 %cmp
>>> +; CHECK-NOT: ret i1 false
>>> +}
>>> +
>>> +define i1 @gep15({ {}, [4 x {i8, i8}]}* %ptr, i32 %y) {
>>> +; CHECK: @gep15
>>> +; We can prove this GEP is non-null even though there is a user value,
>>> as we
>>> +; would necessarily violate inbounds on one side or the other.
>>> +  %x = getelementptr inbounds { {}, [4 x {i8, i8}]}* %ptr, i32 0, i32
>>> 1, i32 %y, i32 1
>>> +  %cmp = icmp eq i8* %x, null
>>> +  ret i1 %cmp
>>> +; CHECK-NEXT: ret i1 false
>>> +}
>>> +
>>> +define i1 @gep16(i8* %ptr, i32 %a) {
>>> +; CHECK: @gep16
>>> +; We can prove this GEP is non-null because it is inbounds and because
>>> we know
>>> +; %b is non-zero even though we don't know its value.
>>> +  %b = or i32 %a, 1
>>> +  %x = getelementptr inbounds i8* %ptr, i32 %b
>>> +  %cmp = icmp eq i8* %x, null
>>> +  ret i1 %cmp
>>> +; CHECK-NEXT: ret i1 false
>>> +}
>>> +
>>>  define i1 @zext(i32 %x) {
>>>  ; CHECK: @zext
>>>    %e1 = zext i32 %x to i64
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121211/3b9c8816/attachment.html>


More information about the llvm-commits mailing list