[llvm-commits] [llvm] r169573 - in /llvm/trunk: lib/Analysis/ValueTracking.cpp test/Transforms/InstSimplify/compare.ll
Chandler Carruth
chandlerc at gmail.com
Tue Dec 11 14:59:20 PST 2012
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/582182aa/attachment.html>
More information about the llvm-commits
mailing list