<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Sat, Jul 11, 2015 at 1:10 PM Hal Finkel <<a href="mailto:hfinkel@anl.gov">hfinkel@anl.gov</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: hfinkel<br>
Date: Sat Jul 11 06:04:54 2015<br>
New Revision: 241981<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D241981-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=ZZ42yowg9jkrV9Hb7G0_zux-XIfZvGnXzMZyyDye2ts&s=YQvzaCOZ2H7u5fMgz_gXiptgnV0EDzWeuqJV0bH0n4I&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=241981&view=rev</a><br>
Log:<br>
Revert "Revert r236894 "[BasicAA] Fix zext & sext handling""<br>
<br>
r236894 caused PR23626 (Clang miscompiles webkit's base64 decoder), and was<br>
reverted in r237984. This reapplies the patch with an additional test case for<br>
PR23626 and the associated fix (both scales and offsets in the<br>
BasicAliasAnalysis::constantOffsetHeuristic should initially be zero).<br></blockquote><div><br></div><div>Unless I'm messing up somehow, both repros from PR23626 still seem to be broken ...</div><div><br></div><div>I'm going to revert.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Patch by Nick White, thanks!<br>
<br>
Added:<br>
    llvm/trunk/test/Analysis/BasicAA/bug.23540.ll<br>
    llvm/trunk/test/Analysis/BasicAA/q.bad.ll<br>
Modified:<br>
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp<br>
<br>
Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Analysis_BasicAliasAnalysis.cpp-3Frev-3D241981-26r1-3D241980-26r2-3D241981-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=ZZ42yowg9jkrV9Hb7G0_zux-XIfZvGnXzMZyyDye2ts&s=5xNeVIHfPtc_clR4YTRnCT0giLQhM2MTuV5mz5QDDhU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=241981&r1=241980&r2=241981&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Sat Jul 11 06:04:54 2015<br>
@@ -162,20 +162,26 @@ static bool isObjectSize(const Value *V,<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 namespace {<br>
-  enum ExtensionKind {<br>
-    EK_NotExtended,<br>
-    EK_SignExt,<br>
-    EK_ZeroExt<br>
-  };<br>
<br>
+// A linear transformation of a Value; this class represents ZExt(SExt(V,<br>
+// SExtBits), ZExtBits) * Scale + Offset.<br>
   struct VariableGEPIndex {<br>
+<br>
+    // An opaque Value - we can't decompose this further.<br>
     const Value *V;<br>
-    ExtensionKind Extension;<br>
+<br>
+    // We need to track what extensions we've done as we consider the same Value<br>
+    // with different extensions as different variables in a GEP's linear<br>
+    // expression;<br>
+    // e.g.: if V == -1, then sext(x) != zext(x).<br>
+    unsigned ZExtBits;<br>
+    unsigned SExtBits;<br>
+<br>
     int64_t Scale;<br>
<br>
     bool operator==(const VariableGEPIndex &Other) const {<br>
-      return V == Other.V && Extension == Other.Extension &&<br>
-        Scale == Other.Scale;<br>
+      return V == Other.V && ZExtBits == Other.ZExtBits &&<br>
+             SExtBits == Other.SExtBits && Scale == Other.Scale;<br>
     }<br>
<br>
     bool operator!=(const VariableGEPIndex &Other) const {<br>
@@ -193,10 +199,12 @@ namespace {<br>
 ///<br>
 /// Note that this looks through extends, so the high bits may not be<br>
 /// represented in the result.<br>
-static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset,<br>
-                                  ExtensionKind &Extension,<br>
-                                  const DataLayout &DL, unsigned Depth,<br>
-                                  AssumptionCache *AC, DominatorTree *DT) {<br>
+static const Value *GetLinearExpression(const Value *V, APInt &Scale,<br>
+                                        APInt &Offset, unsigned &ZExtBits,<br>
+                                        unsigned &SExtBits,<br>
+                                        const DataLayout &DL, unsigned Depth,<br>
+                                        AssumptionCache *AC, DominatorTree *DT,<br>
+                                        bool &NSW, bool &NUW) {<br>
   assert(V->getType()->isIntegerTy() && "Not an integer value");<br>
<br>
   // Limit our recursion depth.<br>
@@ -206,18 +214,32 @@ static Value *GetLinearExpression(Value<br>
     return V;<br>
   }<br>
<br>
-  if (ConstantInt *Const = dyn_cast<ConstantInt>(V)) {<br>
-    // if it's a constant, just convert it to an offset<br>
-    // and remove the variable.<br>
-    Offset += Const->getValue();<br>
+  if (const ConstantInt *Const = dyn_cast<ConstantInt>(V)) {<br>
+    // if it's a constant, just convert it to an offset and remove the variable.<br>
+    // If we've been called recursively the Offset bit width will be greater<br>
+    // than the constant's (the Offset's always as wide as the outermost call),<br>
+    // so we'll zext here and process any extension in the isa<SExtInst> &<br>
+    // isa<ZExtInst> cases below.<br>
+    Offset += Const->getValue().zextOrSelf(Offset.getBitWidth());<br>
     assert(Scale == 0 && "Constant values don't have a scale");<br>
     return V;<br>
   }<br>
<br>
-  if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(V)) {<br>
+  if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(V)) {<br>
     if (ConstantInt *RHSC = dyn_cast<ConstantInt>(BOp->getOperand(1))) {<br>
+<br>
+      // If we've been called recursively then Offset and Scale will be wider<br>
+      // that the BOp operands. We'll always zext it here as we'll process sign<br>
+      // extensions below (see the isa<SExtInst> / isa<ZExtInst> cases).<br>
+      APInt RHS = RHSC->getValue().zextOrSelf(Offset.getBitWidth());<br>
+<br>
       switch (BOp->getOpcode()) {<br>
-      default: break;<br>
+      default:<br>
+        // We don't understand this instruction, so we can't decompose it any<br>
+        // further.<br>
+        Scale = 1;<br>
+        Offset = 0;<br>
+        return V;<br>
       case Instruction::Or:<br>
         // X|C == X+C if all the bits in C are unset in X.  Otherwise we can't<br>
         // analyze it.<br>
@@ -226,45 +248,88 @@ static Value *GetLinearExpression(Value<br>
           break;<br>
         // FALL THROUGH.<br>
       case Instruction::Add:<br>
-        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension,<br>
-                                DL, Depth + 1, AC, DT);<br>
-        Offset += RHSC->getValue();<br>
-        return V;<br>
+        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,<br>
+                                SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);<br>
+        Offset += RHS;<br>
+        break;<br>
+      case Instruction::Sub:<br>
+        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,<br>
+                                SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);<br>
+        Offset -= RHS;<br>
+        break;<br>
       case Instruction::Mul:<br>
-        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension,<br>
-                                DL, Depth + 1, AC, DT);<br>
-        Offset *= RHSC->getValue();<br>
-        Scale *= RHSC->getValue();<br>
-        return V;<br>
+        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,<br>
+                                SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);<br>
+        Offset *= RHS;<br>
+        Scale *= RHS;<br>
+        break;<br>
       case Instruction::Shl:<br>
-        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension,<br>
-                                DL, Depth + 1, AC, DT);<br>
-        Offset <<= RHSC->getValue().getLimitedValue();<br>
-        Scale <<= RHSC->getValue().getLimitedValue();<br>
+        V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, ZExtBits,<br>
+                                SExtBits, DL, Depth + 1, AC, DT, NSW, NUW);<br>
+        Offset <<= RHS.getLimitedValue();<br>
+        Scale <<= RHS.getLimitedValue();<br>
+        // the semantics of nsw and nuw for left shifts don't match those of<br>
+        // multiplications, so we won't propagate them.<br>
+        NSW = NUW = false;<br>
         return V;<br>
       }<br>
+<br>
+      if (isa<OverflowingBinaryOperator>(BOp)) {<br>
+        NUW &= BOp->hasNoUnsignedWrap();<br>
+        NSW &= BOp->hasNoSignedWrap();<br>
+      }<br>
+      return V;<br>
     }<br>
   }<br>
<br>
   // Since GEP indices are sign extended anyway, we don't care about the high<br>
   // bits of a sign or zero extended value - just scales and offsets.  The<br>
   // extensions have to be consistent though.<br>
-  if ((isa<SExtInst>(V) && Extension != EK_ZeroExt) ||<br>
-      (isa<ZExtInst>(V) && Extension != EK_SignExt)) {<br>
+  if (isa<SExtInst>(V) || isa<ZExtInst>(V)) {<br>
     Value *CastOp = cast<CastInst>(V)->getOperand(0);<br>
-    unsigned OldWidth = Scale.getBitWidth();<br>
+    unsigned NewWidth = V->getType()->getPrimitiveSizeInBits();<br>
     unsigned SmallWidth = CastOp->getType()->getPrimitiveSizeInBits();<br>
-    Scale = Scale.trunc(SmallWidth);<br>
-    Offset = Offset.trunc(SmallWidth);<br>
-    Extension = isa<SExtInst>(V) ? EK_SignExt : EK_ZeroExt;<br>
-<br>
-    Value *Result = GetLinearExpression(CastOp, Scale, Offset, Extension, DL,<br>
-                                        Depth + 1, AC, DT);<br>
-    Scale = Scale.zext(OldWidth);<br>
-<br>
-    // We have to sign-extend even if Extension == EK_ZeroExt as we can't<br>
-    // decompose a sign extension (i.e. zext(x - 1) != zext(x) - zext(-1)).<br>
-    Offset = Offset.sext(OldWidth);<br>
+    unsigned OldZExtBits = ZExtBits, OldSExtBits = SExtBits;<br>
+    const Value *Result =<br>
+        GetLinearExpression(CastOp, Scale, Offset, ZExtBits, SExtBits, DL,<br>
+                            Depth + 1, AC, DT, NSW, NUW);<br>
+<br>
+    // zext(zext(%x)) == zext(%x), and similiarly for sext; we'll handle this<br>
+    // by just incrementing the number of bits we've extended by.<br>
+    unsigned ExtendedBy = NewWidth - SmallWidth;<br>
+<br>
+    if (isa<SExtInst>(V) && ZExtBits == 0) {<br>
+      // sext(sext(%x, a), b) == sext(%x, a + b)<br>
+<br>
+      if (NSW) {<br>
+        // We haven't sign-wrapped, so it's valid to decompose sext(%x + c)<br>
+        // into sext(%x) + sext(c). We'll sext the Offset ourselves:<br>
+        unsigned OldWidth = Offset.getBitWidth();<br>
+        Offset = Offset.trunc(SmallWidth).sext(NewWidth).zextOrSelf(OldWidth);<br>
+      } else {<br>
+        // We may have signed-wrapped, so don't decompose sext(%x + c) into<br>
+        // sext(%x) + sext(c)<br>
+        Scale = 1;<br>
+        Offset = 0;<br>
+        Result = CastOp;<br>
+        ZExtBits = OldZExtBits;<br>
+        SExtBits = OldSExtBits;<br>
+      }<br>
+      SExtBits += ExtendedBy;<br>
+    } else {<br>
+      // sext(zext(%x, a), b) = zext(zext(%x, a), b) = zext(%x, a + b)<br>
+<br>
+      if (!NUW) {<br>
+        // We may have unsigned-wrapped, so don't decompose zext(%x + c) into<br>
+        // zext(%x) + zext(c)<br>
+        Scale = 1;<br>
+        Offset = 0;<br>
+        Result = CastOp;<br>
+        ZExtBits = OldZExtBits;<br>
+        SExtBits = OldSExtBits;<br>
+      }<br>
+      ZExtBits += ExtendedBy;<br>
+    }<br>
<br>
     return Result;<br>
   }<br>
@@ -346,7 +411,7 @@ DecomposeGEPExpression(const Value *V, i<br>
     gep_type_iterator GTI = gep_type_begin(GEPOp);<br>
     for (User::const_op_iterator I = GEPOp->op_begin()+1,<br>
          E = GEPOp->op_end(); I != E; ++I) {<br>
-      Value *Index = *I;<br>
+      const Value *Index = *I;<br>
       // Compute the (potentially symbolic) offset in bytes for this index.<br>
       if (StructType *STy = dyn_cast<StructType>(*GTI++)) {<br>
         // For a struct, add the member offset.<br>
@@ -358,25 +423,27 @@ DecomposeGEPExpression(const Value *V, i<br>
       }<br>
<br>
       // For an array/pointer, add the element offset, explicitly scaled.<br>
-      if (ConstantInt *CIdx = dyn_cast<ConstantInt>(Index)) {<br>
+      if (const ConstantInt *CIdx = dyn_cast<ConstantInt>(Index)) {<br>
         if (CIdx->isZero()) continue;<br>
         BaseOffs += DL.getTypeAllocSize(*GTI) * CIdx->getSExtValue();<br>
         continue;<br>
       }<br>
<br>
       uint64_t Scale = DL.getTypeAllocSize(*GTI);<br>
-      ExtensionKind Extension = EK_NotExtended;<br>
+      unsigned ZExtBits = 0, SExtBits = 0;<br>
<br>
       // If the integer type is smaller than the pointer size, it is implicitly<br>
       // sign extended to pointer size.<br>
       unsigned Width = Index->getType()->getIntegerBitWidth();<br>
-      if (DL.getPointerSizeInBits(AS) > Width)<br>
-        Extension = EK_SignExt;<br>
+      unsigned PointerSize = DL.getPointerSizeInBits(AS);<br>
+      if (PointerSize > Width)<br>
+        SExtBits += PointerSize - Width;<br>
<br>
       // Use GetLinearExpression to decompose the index into a C1*V+C2 form.<br>
       APInt IndexScale(Width, 0), IndexOffset(Width, 0);<br>
-      Index = GetLinearExpression(Index, IndexScale, IndexOffset, Extension, DL,<br>
-                                  0, AC, DT);<br>
+      bool NSW = true, NUW = true;<br>
+      Index = GetLinearExpression(Index, IndexScale, IndexOffset, ZExtBits,<br>
+                                  SExtBits, DL, 0, AC, DT, NSW, NUW);<br>
<br>
       // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale.<br>
       // This gives us an aggregate computation of (C1*Scale)*V + C2*Scale.<br>
@@ -388,8 +455,8 @@ DecomposeGEPExpression(const Value *V, i<br>
       //   A[x][x] -> x*16 + x*4 -> x*20<br>
       // This also ensures that 'x' only appears in the index list once.<br>
       for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) {<br>
-        if (VarIndices[i].V == Index &&<br>
-            VarIndices[i].Extension == Extension) {<br>
+        if (VarIndices[i].V == Index && VarIndices[i].ZExtBits == ZExtBits &&<br>
+            VarIndices[i].SExtBits == SExtBits) {<br>
           Scale += VarIndices[i].Scale;<br>
           VarIndices.erase(VarIndices.begin()+i);<br>
           break;<br>
@@ -398,13 +465,13 @@ DecomposeGEPExpression(const Value *V, i<br>
<br>
       // Make sure that we have a scale that makes sense for this target's<br>
       // pointer size.<br>
-      if (unsigned ShiftBits = 64 - DL.getPointerSizeInBits(AS)) {<br>
+      if (unsigned ShiftBits = 64 - PointerSize) {<br>
         Scale <<= ShiftBits;<br>
         Scale = (int64_t)Scale >> ShiftBits;<br>
       }<br>
<br>
       if (Scale) {<br>
-        VariableGEPIndex Entry = {Index, Extension,<br>
+        VariableGEPIndex Entry = {Index, ZExtBits, SExtBits,<br>
                                   static_cast<int64_t>(Scale)};<br>
         VarIndices.push_back(Entry);<br>
       }<br>
@@ -540,6 +607,20 @@ namespace {<br>
     /// is we say noalias(V, phi(VA, VB)) if noalias(V, VA) and noalias(V, VB).<br>
     bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2);<br>
<br>
+    /// \brief A Heuristic for aliasGEP that searches for a constant offset<br>
+    /// between the variables.<br>
+    ///<br>
+    /// GetLinearExpression has some limitations, as generally zext(%x + 1)<br>
+    /// != zext(%x) + zext(1) if the arithmetic overflows. GetLinearExpression<br>
+    /// will therefore conservatively refuse to decompose these expressions.<br>
+    /// However, we know that, for all %x, zext(%x) != zext(%x + 1), even if<br>
+    /// the addition overflows.<br>
+    bool<br>
+    constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices,<br>
+                            uint64_t V1Size, uint64_t V2Size,<br>
+                            int64_t BaseOffset, const DataLayout *DL,<br>
+                            AssumptionCache *AC, DominatorTree *DT);<br>
+<br>
     /// \brief Dest and Src are the variable indices from two decomposed<br>
     /// GetElementPtr instructions GEP1 and GEP2 which have common base<br>
     /// pointers.  Subtract the GEP2 indices from GEP1 to find the symbolic<br>
@@ -936,6 +1017,60 @@ static AliasResult aliasSameBasePointerG<br>
   return MayAlias;<br>
 }<br>
<br>
+bool BasicAliasAnalysis::constantOffsetHeuristic(<br>
+    const SmallVectorImpl<VariableGEPIndex> &VarIndices, uint64_t V1Size,<br>
+    uint64_t V2Size, int64_t BaseOffset, const DataLayout *DL,<br>
+    AssumptionCache *AC, DominatorTree *DT) {<br>
+  if (VarIndices.size() != 2 || V1Size == MemoryLocation::UnknownSize ||<br>
+      V2Size == MemoryLocation::UnknownSize || !DL)<br>
+    return false;<br>
+<br>
+  const VariableGEPIndex &Var0 = VarIndices[0], &Var1 = VarIndices[1];<br>
+<br>
+  if (Var0.ZExtBits != Var1.ZExtBits || Var0.SExtBits != Var1.SExtBits ||<br>
+      Var0.Scale != -Var1.Scale)<br>
+    return false;<br>
+<br>
+  unsigned Width = Var1.V->getType()->getIntegerBitWidth();<br>
+<br>
+  // We'll strip off the Extensions of Var0 and Var1 and do another round<br>
+  // of GetLinearExpression decomposition. In the example above, if Var0<br>
+  // is zext(%x + 1) we should get V1 == %x and V1Offset == 1.<br>
+<br>
+  APInt V0Scale(Width, 0), V0Offset(Width, 0), V1Scale(Width, 0),<br>
+      V1Offset(Width, 0);<br>
+  bool NSW = true, NUW = true;<br>
+  unsigned V0ZExtBits = 0, V0SExtBits = 0, V1ZExtBits = 0, V1SExtBits = 0;<br>
+  const Value *V0 = GetLinearExpression(Var0.V, V0Scale, V0Offset, V0ZExtBits,<br>
+                                        V0SExtBits, *DL, 0, AC, DT, NSW, NUW);<br>
+  NSW = true, NUW = true;<br>
+  const Value *V1 = GetLinearExpression(Var1.V, V1Scale, V1Offset, V1ZExtBits,<br>
+                                        V1SExtBits, *DL, 0, AC, DT, NSW, NUW);<br>
+<br>
+  if (V0Scale != V1Scale || V0ZExtBits != V1ZExtBits ||<br>
+      V0SExtBits != V1SExtBits || !isValueEqualInPotentialCycles(V0, V1))<br>
+    return false;<br>
+<br>
+  // We have a hit - Var0 and Var1 only differ by a constant offset!<br>
+<br>
+  // If we've been sext'ed then zext'd the maximum difference between Var0 and<br>
+  // Var1 is possible to calculate, but we're just interested in the absolute<br>
+  // minumum difference between the two. The minimum distance may occur due to<br>
+  // wrapping; consider "add i3 %i, 5": if %i == 7 then 7 + 5 mod 8 == 4, and so<br>
+  // the minimum distance between %i and %i + 5 is 3.<br>
+  APInt MinDiff = V0Offset - V1Offset,<br>
+        Wrapped = APInt::getMaxValue(Width) - MinDiff + APInt(Width, 1);<br>
+  MinDiff = APIntOps::umin(MinDiff, Wrapped);<br>
+  uint64_t MinDiffBytes = MinDiff.getZExtValue() * std::abs(Var0.Scale);<br>
+<br>
+  // We can't definitely say whether GEP1 is before or after V2 due to wrapping<br>
+  // arithmetic (i.e. for some values of GEP1 and V2 GEP1 < V2, and for other<br>
+  // values GEP1 > V2). We'll therefore only declare NoAlias if both V1Size and<br>
+  // V2Size can fit in the MinDiffBytes gap.<br>
+  return V1Size + std::abs(BaseOffset) <= MinDiffBytes &&<br>
+         V2Size + std::abs(BaseOffset) <= MinDiffBytes;<br>
+}<br>
+<br>
 /// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction<br>
 /// against another pointer.  We know that V1 is a GEP, but we don't know<br>
 /// anything about V2.  UnderlyingV1 is GetUnderlyingObject(GEP1, DL),<br>
@@ -1158,7 +1293,7 @@ AliasResult BasicAliasAnalysis::aliasGEP<br>
<br>
         // Zero-extension widens the variable, and so forces the sign<br>
         // bit to zero.<br>
-        bool IsZExt = GEP1VariableIndices[i].Extension == EK_ZeroExt;<br>
+        bool IsZExt = GEP1VariableIndices[i].ZExtBits > 0 || isa<ZExtInst>(V);<br>
         SignKnownZero |= IsZExt;<br>
         SignKnownOne &= !IsZExt;<br>
<br>
@@ -1188,6 +1323,10 @@ AliasResult BasicAliasAnalysis::aliasGEP<br>
     // don't alias if V2Size can fit in the gap between V2 and GEP1BasePtr.<br>
     if (AllPositive && GEP1BaseOffset > 0 && V2Size <= (uint64_t) GEP1BaseOffset)<br>
       return NoAlias;<br>
+<br>
+    if (constantOffsetHeuristic(GEP1VariableIndices, V1Size, V2Size,<br>
+                                GEP1BaseOffset, DL, AC1, DT))<br>
+      return NoAlias;<br>
   }<br>
<br>
   // Statically, we can see that the base objects are the same, but the<br>
@@ -1527,14 +1666,14 @@ void BasicAliasAnalysis::GetIndexDiffere<br>
<br>
   for (unsigned i = 0, e = Src.size(); i != e; ++i) {<br>
     const Value *V = Src[i].V;<br>
-    ExtensionKind Extension = Src[i].Extension;<br>
+    unsigned ZExtBits = Src[i].ZExtBits, SExtBits = Src[i].SExtBits;<br>
     int64_t Scale = Src[i].Scale;<br>
<br>
     // Find V in Dest.  This is N^2, but pointer indices almost never have more<br>
     // than a few variable indexes.<br>
     for (unsigned j = 0, e = Dest.size(); j != e; ++j) {<br>
       if (!isValueEqualInPotentialCycles(Dest[j].V, V) ||<br>
-          Dest[j].Extension != Extension)<br>
+          Dest[j].ZExtBits != ZExtBits || Dest[j].SExtBits != SExtBits)<br>
         continue;<br>
<br>
       // If we found it, subtract off Scale V's from the entry in Dest.  If it<br>
@@ -1549,7 +1688,7 @@ void BasicAliasAnalysis::GetIndexDiffere<br>
<br>
     // If we didn't consume this entry, add it to the end of the Dest list.<br>
     if (Scale) {<br>
-      VariableGEPIndex Entry = { V, Extension, -Scale };<br>
+      VariableGEPIndex Entry = {V, ZExtBits, SExtBits, -Scale};<br>
       Dest.push_back(Entry);<br>
     }<br>
   }<br>
<br>
Added: llvm/trunk/test/Analysis/BasicAA/bug.23540.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_BasicAA_bug.23540.ll-3Frev-3D241981-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=ZZ42yowg9jkrV9Hb7G0_zux-XIfZvGnXzMZyyDye2ts&s=JUxwyZ5coMKTngg5_gQ8seQNHMSS-eIX2zwXzJTqWkU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/bug.23540.ll?rev=241981&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Analysis/BasicAA/bug.23540.ll (added)<br>
+++ llvm/trunk/test/Analysis/BasicAA/bug.23540.ll Sat Jul 11 06:04:54 2015<br>
@@ -0,0 +1,17 @@<br>
+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s<br>
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"<br>
+target triple = "x86_64-unknown-linux-gnu"<br>
+<br>
+@c = external global i32<br>
+<br>
+; CHECK-LABEL: f<br>
+; CHECK: PartialAlias: i32* %arrayidx, i32* %arrayidx6<br>
+define void @f() {<br>
+  %idxprom = zext i32 undef to i64<br>
+  %add4 = add i32 0, 1<br>
+  %idxprom5 = zext i32 %add4 to i64<br>
+  %arrayidx6 = getelementptr inbounds i32, i32* @c, i64 %idxprom5<br>
+  %arrayidx = getelementptr inbounds i32, i32* @c, i64 %idxprom<br>
+  ret void<br>
+}<br>
+<br>
<br>
Added: llvm/trunk/test/Analysis/BasicAA/q.bad.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_Analysis_BasicAA_q.bad.ll-3Frev-3D241981-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=ZZ42yowg9jkrV9Hb7G0_zux-XIfZvGnXzMZyyDye2ts&s=3d0UzYRN9Hc-LpdtEk34Rgx9B1s4gon0mmnzk9sH68A&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/q.bad.ll?rev=241981&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Analysis/BasicAA/q.bad.ll (added)<br>
+++ llvm/trunk/test/Analysis/BasicAA/q.bad.ll Sat Jul 11 06:04:54 2015<br>
@@ -0,0 +1,180 @@<br>
+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s<br>
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"<br>
+target triple = "thumbv7--linux-gnueabi"<br>
+<br>
+; CHECK-LABEL: test_zext_sext_amounts255<br>
+; CHECK: NoAlias: i8* %a, i8* %b<br>
+define void @test_zext_sext_amounts255(i8* %mem) {<br>
+  %sext.1 = sext i8 255 to i16<br>
+  %sext.zext.1 = zext i16 %sext.1 to i64<br>
+  %sext.2 = sext i8 255 to i32<br>
+  %sext.zext.2 = zext i32 %sext.2 to i64<br>
+  %a = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.1<br>
+  %b = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.2<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: test_zext_sext_amounts<br>
+; CHECK: PartialAlias: i8* %a, i8* %b<br>
+; %a and %b only PartialAlias as, although they're both zext(sext(%num)) they'll extend the sign by a different<br>
+; number of bits before zext-ing the remainder.<br>
+define void @test_zext_sext_amounts(i8* %mem, i8 %num) {<br>
+  %sext.1 = sext i8 %num to i16<br>
+  %sext.zext.1 = zext i16 %sext.1 to i64<br>
+  %sext.2 = sext i8 %num to i32<br>
+  %sext.zext.2 = zext i32 %sext.2 to i64<br>
+  %a = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.1<br>
+  %b = getelementptr inbounds i8, i8* %mem, i64 %sext.zext.2<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: based_on_pr18068<br>
+; CHECK: NoAlias: i8* %a, i8* %b<br>
+; CHECK: NoAlias: i8* %a, i8* %c<br>
+define void @based_on_pr18068(i32 %loaded, i8* %mem) {<br>
+  %loaded.64 = zext i32 %loaded to i64<br>
+  %add1 = add i32 %loaded, -1 ; unsigned wraps unless %loaded == 0<br>
+  %add1.64 = zext i32 %add1 to i64 ; is zext(%loaded) always != zext(%loaded - 1)? Yes -> NoAlias<br>
+  %sub1 = sub i32 %loaded, 1 ; unsigned wraps iff %loaded == 0<br>
+  %sub1.64 = zext i32 %sub1 to i64 ; is zext(%loaded) always != zext(%loaded - 1)? Yes -> NoAlias<br>
+  %a = getelementptr inbounds i8, i8* %mem, i64 %loaded.64<br>
+  %b = getelementptr inbounds i8, i8* %mem, i64 %add1.64<br>
+  %c = getelementptr inbounds i8, i8* %mem, i64 %sub1.64<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: test_path_dependence<br>
+; CHECK: PartialAlias: i8* %a, i8* %b<br>
+; CHECK: MustAlias: i8* %a, i8* %c<br>
+; CHECK: PartialAlias: i8* %a, i8* %d<br>
+define void @test_path_dependence(i32 %p, i8* %mem) {<br>
+  %p.minus1 = add i32 %p, -1 ; this will always unsigned-wrap, unless %p == 0<br>
+  %p.minus1.64 = zext i32 %p.minus1 to i64<br>
+  %p.64.again = add i64 %p.minus1.64, 1 ; either %p (if we wrapped) or 4294967296 (if we didn't)<br>
+<br>
+  %p.nsw.nuw.minus1 = sub nsw nuw i32 %p, 1 ; as nuw we know %p >= 1, and as nsw %p <=   2147483647<br>
+  %p.nsw.nuw.minus1.64 = zext i32 %p.nsw.nuw.minus1 to i64<br>
+  %p.nsw.nuw.64.again = add nsw nuw i64 %p.nsw.nuw.minus1.64, 1 ; ...so always exactly %p<br>
+<br>
+  %p.nsw.minus1 = sub nsw i32 %p, 1 ; only nsw, so can only guarantee %p != 0x10000000<br>
+  %p.nsw.minus1.64 = zext i32 %p.nsw.minus1 to i64 ; when %p > 0x10000000 (ie <= 0 as a signed number) then the zext will make this a huge positive number<br>
+  %p.nsw.64.again = add nsw i64 %p.nsw.minus1.64, 1 ; ...and so this is very much != %p<br>
+<br>
+  %p.64 = zext i32 %p to i64<br>
+  %a = getelementptr inbounds i8, i8* %mem, i64 %p.64<br>
+  %b = getelementptr inbounds i8, i8* %mem, i64 %p.64.again<br>
+  %c = getelementptr inbounds i8, i8* %mem, i64 %p.nsw.nuw.64.again<br>
+  %d = getelementptr inbounds i8, i8* %mem, i64 %p.nsw.64.again<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: test_zext_sext_255<br>
+; CHECK: NoAlias: i8* %a, i8* %b<br>
+define void @test_zext_sext_255(i8* %mem) {<br>
+  %zext.255 = zext i8 255 to i16 ; 0x00FF<br>
+  %sext.255 = sext i8 255 to i16 ; 0xFFFF<br>
+  %zext.sext.255 = zext i16 %sext.255 to i32 ; 0x0000FFFF<br>
+  %sext.zext.255 = sext i16 %zext.255 to i32 ; 0x000000FF<br>
+  %zext.zext.sext.255 = zext i32 %zext.sext.255 to i64<br>
+  %zext.sext.zext.255 = zext i32 %sext.zext.255 to i64<br>
+  %a = getelementptr inbounds i8, i8* %mem, i64 %zext.zext.sext.255<br>
+  %b = getelementptr inbounds i8, i8* %mem, i64 %zext.sext.zext.255<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: test_zext_sext_num<br>
+; CHECK: PartialAlias: i8* %a, i8* %b<br>
+; %a and %b NoAlias if %num == 255 (see @test_zext_sext_255), but %a and %b NoAlias for other values of %num (e.g. 0)<br>
+define void @test_zext_sext_num(i8* %mem, i8 %num) {<br>
+  %zext.num = zext i8 %num to i16<br>
+  %sext.num = sext i8 %num to i16<br>
+  %zext.sext.num = zext i16 %sext.num to i32<br>
+  %sext.zext.num = sext i16 %zext.num to i32<br>
+  %zext.zext.sext.num = zext i32 %zext.sext.num to i64<br>
+  %zext.sext.zext.num = zext i32 %sext.zext.num to i64<br>
+  %a = getelementptr inbounds i8, i8* %mem, i64 %zext.zext.sext.num<br>
+  %b = getelementptr inbounds i8, i8* %mem, i64 %zext.sext.zext.num<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: uncompressStream<br>
+; CHECK: MustAlias:  i8* %a, i8* %b<br>
+; CHECK: NoAlias:  i8* %a, i8* %c<br>
+define void @uncompressStream(i8* %mem) {<br>
+  %zext.255 = zext i8 255 to i32<br>
+  %sext.255 = sext i8 255 to i32<br>
+  %a = getelementptr inbounds i8, i8* %mem, i32 255<br>
+  %b = getelementptr inbounds i8, i8* %mem, i32 %zext.255<br>
+  %c = getelementptr inbounds i8, i8* %mem, i32 %sext.255<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: constantOffsetHeuristic_i3_i32<br>
+; CHECK: NoAlias:  i32* %a, i32* %b<br>
+; CHECK: NoAlias:  i32* %a, i32* %c<br>
+; CHECK: NoAlias:  i32* %b, i32* %c<br>
+define void @constantOffsetHeuristic_i3_i32(i32* %mem, i3 %val) {<br>
+  %zext.plus.7 = add nsw i3 %val, 7<br>
+  %zext.plus.4 = add nsw i3 %val, 4<br>
+  %zext.val = zext i3 %val to i32<br>
+  %zext.4 = zext i3 %zext.plus.4 to i32<br>
+  %zext.7 = zext i3 %zext.plus.7 to i32<br>
+  %a = getelementptr inbounds i32, i32* %mem, i32 %zext.4<br>
+  %b = getelementptr inbounds i32, i32* %mem, i32 %zext.7<br>
+  %c = getelementptr inbounds i32, i32* %mem, i32 %zext.val<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: constantOffsetHeuristic_i8_i32<br>
+; CHECK: NoAlias:  i32* %a, i32* %b<br>
+; CHECK: NoAlias:  i32* %a, i32* %c<br>
+; CHECK: NoAlias:  i32* %b, i32* %c<br>
+define void @constantOffsetHeuristic_i8_i32(i32* %mem, i8 %val) {<br>
+  %zext.plus.7 = add nsw i8 %val, 7<br>
+  %zext.plus.4 = add nsw i8 %val, 4<br>
+  %zext.val = zext i8 %val to i32<br>
+  %zext.4 = zext i8 %zext.plus.4 to i32<br>
+  %zext.7 = zext i8 %zext.plus.7 to i32<br>
+  %a = getelementptr inbounds i32, i32* %mem, i32 %zext.4<br>
+  %b = getelementptr inbounds i32, i32* %mem, i32 %zext.7<br>
+  %c = getelementptr inbounds i32, i32* %mem, i32 %zext.val<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: constantOffsetHeuristic_i3_i8<br>
+; CHECK: PartialAlias:  i32* %a, i32* %b<br>
+; CHECK: NoAlias:  i32* %a, i32* %c<br>
+; CHECK: PartialAlias:  i32* %b, i32* %c<br>
+define void @constantOffsetHeuristic_i3_i8(i8* %mem, i3 %val) {<br>
+  %zext.plus.7 = add nsw i3 %val, 7<br>
+  %zext.plus.4 = add nsw i3 %val, 4<br>
+  %zext.val = zext i3 %val to i32<br>
+  %zext.4 = zext i3 %zext.plus.4 to i32<br>
+  %zext.7 = zext i3 %zext.plus.7 to i32<br>
+  %a.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.4<br>
+  %b.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.7<br>
+  %c.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.val<br>
+  %a = bitcast i8* %a.8 to i32*<br>
+  %b = bitcast i8* %b.8 to i32*<br>
+  %c = bitcast i8* %c.8 to i32*<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: constantOffsetHeuristic_i8_i8<br>
+; CHECK: PartialAlias:  i32* %a, i32* %b<br>
+; CHECK: NoAlias:  i32* %a, i32* %c<br>
+; CHECK: NoAlias:  i32* %b, i32* %c<br>
+define void @constantOffsetHeuristic_i8_i8(i8* %mem, i8 %val) {<br>
+  %zext.plus.7 = add nsw i8 %val, 7<br>
+  %zext.plus.4 = add nsw i8 %val, 4<br>
+  %zext.val = zext i8 %val to i32<br>
+  %zext.4 = zext i8 %zext.plus.4 to i32<br>
+  %zext.7 = zext i8 %zext.plus.7 to i32<br>
+  %a.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.4<br>
+  %b.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.7<br>
+  %c.8 = getelementptr inbounds i8, i8* %mem, i32 %zext.val<br>
+  %a = bitcast i8* %a.8 to i32*<br>
+  %b = bitcast i8* %b.8 to i32*<br>
+  %c = bitcast i8* %c.8 to i32*<br>
+  ret void<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>