[PATCH] D16343: [BasicAA] Fix for missing must alias information

Duncan P. N. Exon Smith via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 29 15:17:39 PST 2016


Aside from the suspected UB (which I think Philip was right about,
see my comments inline below), this seems pretty obviously correct.

A have a couple of other nitpicks below, but after that LGTM.
Philip, did you have anything else on your side?

> On 2016-Jan-27, at 19:55, Gerolf Hoflehner via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> Gerolf updated this revision to Diff 46214.
> Gerolf added a comment.
> 
> Philip, I removed the wrap for Scale as you suggested.

It would be a shame not to fix `Scale` while you're poking around.

I think the most incremental approach would be to outline the
`Scale` math into `adjustToPointerSize()` (creating reusable API
and fixing the UB in the same hopefully-NFC commit), and then add
the change to `BaseOffs` as a second step once Philip signs off.

> Please check if you agree with my comments. Thank you!
> 
> 
> http://reviews.llvm.org/D16343
> 
> Files:
>  lib/Analysis/BasicAliasAnalysis.cpp
>  test/Analysis/BasicAA/noalias-wraparound-bug.ll
> 
> Index: test/Analysis/BasicAA/noalias-wraparound-bug.ll
> ===================================================================
> --- /dev/null
> +++ test/Analysis/BasicAA/noalias-wraparound-bug.ll
> @@ -0,0 +1,24 @@
> +; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
> +
> +target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"
> +target triple = "i386-apple-macosx10.6.0"
> +
> +; We incorrectly returned noalias in the example below for "tmp5" and
> +; "tmp12" returning i32 32, since basicaa converted the offsets to 64b
> +; and missed the wrap-around
> +
> +define i32 @foo(i8* %buffer) {
> +entry:
> +  %tmp2 = getelementptr i8, i8* %buffer, i32 -2071408432
> +  %tmp3 = bitcast i8* %tmp2 to i32*
> +  %tmp4 = getelementptr i8, i8* %buffer, i32 128
> +  %tmp5 = bitcast i8* %tmp4 to i32*
> +  store i32 32, i32* %tmp5, align 4
> +  %tmp12 = getelementptr i32, i32* %tmp3, i32 -1629631508
> +  store i32 28, i32* %tmp12, align 4
> +  %tmp13 = getelementptr i8, i8* %buffer, i32 128
> +  %tmp14 = bitcast i8* %tmp13 to i32*
> +  %tmp2083 = load i32, i32* %tmp14, align 4
> +; CHECK: ret i32 28
> +  ret i32 %tmp2083
> +}
> Index: lib/Analysis/BasicAliasAnalysis.cpp
> ===================================================================
> --- lib/Analysis/BasicAliasAnalysis.cpp
> +++ lib/Analysis/BasicAliasAnalysis.cpp
> @@ -42,11 +42,10 @@
> /// Enable analysis of recursive PHI nodes.
> static cl::opt<bool> EnableRecPhiAnalysis("basicaa-recphi", cl::Hidden,
>                                           cl::init(false));
> -
> +#define DEBUG_TYPE "basicaa"
> /// SearchLimitReached / SearchTimes shows how often the limit of
> /// to decompose GEPs is reached. It will affect the precision
> /// of basic alias analysis.
> -#define DEBUG_TYPE "basicaa"

IMO, this cleanup should be separated into a prep NFC commit.
Might as well move the DEBUG_TYPE right under the #includes.

> STATISTIC(SearchLimitReached, "Number of times the limit to "
>                               "decompose GEPs is reached");
> STATISTIC(SearchTimes, "Number of times a GEP is decomposed");
> @@ -319,6 +318,17 @@
>   return V;
> }
> 
> +/// To ensure a pointer offset fits in an integer of size PointerSize
> +/// (in bits) when that size is smaller than 64. This is an issue in
> +/// particular for 32b programs with negative indices that rely on two's
> +/// complement wrap-arounds for correct alias information.
> +static int64_t adjustToPointerSize(int64_t Offset, unsigned PointerSize) {
> +  assert(PointerSize <= 64 && "Invalide PointerSize!");
> +  unsigned ShiftBits = 64 - PointerSize;
> +  Offset <<= ShiftBits;
> +  return Offset >> ShiftBits;

I think Philip might have been right about shifting of signed values
being iffy.  By my reading of C++11 5.8.2, the behaviour here is at
best implementation defined.

Switching to C11 6.5.7, point 4 says:
--
If E1 has a signed type and nonnegative value, and E1 × 2E2 is
representable in the result type, then that is the resulting value;
otherwise, the behavior is undefined.
--
By C11, this is definitely UB.

You could either create a local uint64_t:
--
return uint64_t(Offset) << ShiftBits >> ShiftBits;
--
or just use a mask:
--
assert(PointerSize > 0);
return Offset & UINT64_MAX << ShiftBits;
--

> +}
> +
> /// If V is a symbolic pointer expression, decompose it into a base pointer
> /// with a constant offset and a number of scaled symbolic offsets.
> ///
> @@ -387,6 +397,7 @@
>     unsigned AS = GEPOp->getPointerAddressSpace();
>     // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices.
>     gep_type_iterator GTI = gep_type_begin(GEPOp);
> +    unsigned PointerSize = DL.getPointerSizeInBits(AS);
>     for (User::const_op_iterator I = GEPOp->op_begin() + 1, E = GEPOp->op_end();
>          I != E; ++I) {
>       const Value *Index = *I;
> @@ -415,7 +426,6 @@
>       // If the integer type is smaller than the pointer size, it is implicitly
>       // sign extended to pointer size.
>       unsigned Width = Index->getType()->getIntegerBitWidth();
> -      unsigned PointerSize = DL.getPointerSizeInBits(AS);
>      if (PointerSize > Width)
>         SExtBits += PointerSize - Width;
> 
> @@ -457,6 +467,8 @@
>       }
>     }
> 
> +    // Take care of wrap-arounds
> +    BaseOffs = adjustToPointerSize(BaseOffs, PointerSize);
>     // Analyze the base pointer next.
>     V = GEPOp->getOperand(0);
>   } while (--MaxLookup);
> 
> 
> <D16343.46214.patch>_______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list