[polly] 81fc53a - [SCEV] Introduce SCEVPtrToIntExpr (PR46786)

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 30 01:14:04 PDT 2020


Author: Roman Lebedev
Date: 2020-10-30T11:13:35+03:00
New Revision: 81fc53a36a4e3ca5cc9d5bc9b3ea32f304e35b93

URL: https://github.com/llvm/llvm-project/commit/81fc53a36a4e3ca5cc9d5bc9b3ea32f304e35b93
DIFF: https://github.com/llvm/llvm-project/commit/81fc53a36a4e3ca5cc9d5bc9b3ea32f304e35b93.diff

LOG: [SCEV] Introduce SCEVPtrToIntExpr (PR46786)

And use it to model LLVM IR's `ptrtoint` cast.

This is essentially an alternative to D88806, but with no chance for
all the problems it caused due to having the cast as implicit there.
(see rG7ee6c402474a2f5fd21c403e7529f97f6362fdb3)

As we've established by now, there are at least two reasons why we want this:
* It will allow SCEV to actually model the `ptrtoint` casts
  and their operands, instead of treating them as `SCEVUnknown`
* It should help with initial problem of PR46786 - this should eventually allow us
  to not loose pointer-ness of an expression in more cases

As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=46786 | PR46786 ]], in principle,
we could just extend `SCEVUnknown` with a `is ptrtoint` cast, because `ScalarEvolution::getPtrToIntExpr()`
should sink the cast as far down into the expression as possible,
so in the end we should always end up with `SCEVPtrToIntExpr` of `SCEVUnknown`.

But i think that it isn't the best solution, because it doesn't really matter
from memory consumption side - there probably won't be *that* many `SCEVPtrToIntExpr`s
for it to matter, and it allows for much better discoverability.

Reviewed By: mkazantsev

Differential Revision: https://reviews.llvm.org/D89456

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ScalarEvolution.h
    llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
    llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
    llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
    llvm/test/Analysis/ScalarEvolution/add-expr-pointer-operand-sorting.ll
    llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
    llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
    llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
    llvm/test/Other/constant-fold-gep.ll
    llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
    polly/include/polly/Support/SCEVAffinator.h
    polly/lib/Support/SCEVAffinator.cpp
    polly/lib/Support/SCEVValidator.cpp
    polly/lib/Support/ScopHelper.cpp
    polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
    polly/test/ScopInfo/int2ptr_ptr2int.ll
    polly/test/ScopInfo/int2ptr_ptr2int_2.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 37f4ad43639f..e7b81a45ba90 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -512,6 +512,7 @@ class ScalarEvolution {
   const SCEV *getConstant(ConstantInt *V);
   const SCEV *getConstant(const APInt &Val);
   const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
+  const SCEV *getPtrToIntExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
   const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
   const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);
   const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth = 0);

diff  --git a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
index 480f92c117a0..24f0c51487bd 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionDivision.h
@@ -33,6 +33,7 @@ struct SCEVDivision : public SCEVVisitor<SCEVDivision, void> {
 
   // Except in the trivial case described above, we do not know how to divide
   // Expr by Denominator for the following functions with empty implementation.
+  void visitPtrToIntExpr(const SCEVPtrToIntExpr *Numerator) {}
   void visitTruncateExpr(const SCEVTruncateExpr *Numerator) {}
   void visitZeroExtendExpr(const SCEVZeroExtendExpr *Numerator) {}
   void visitSignExtendExpr(const SCEVSignExtendExpr *Numerator) {}

diff  --git a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
index b995de7d88d5..37e675f08afc 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -40,7 +40,7 @@ class Type;
     // folders simpler.
     scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr,
     scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUMinExpr, scSMinExpr,
-    scUnknown, scCouldNotCompute
+    scPtrToInt, scUnknown, scCouldNotCompute
   };
 
   /// This class represents a constant integer value.
@@ -72,13 +72,13 @@ class Type;
   }
 
   /// This is the base class for unary cast operator classes.
-  class SCEVIntegralCastExpr : public SCEV {
+  class SCEVCastExpr : public SCEV {
   protected:
     std::array<const SCEV *, 1> Operands;
     Type *Ty;
 
-    SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
-                         const SCEV *op, Type *ty);
+    SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy, const SCEV *op,
+                 Type *ty);
 
   public:
     const SCEV *getOperand() const { return Operands[0]; }
@@ -95,6 +95,35 @@ class Type;
     size_t getNumOperands() const { return 1; }
     Type *getType() const { return Ty; }
 
+    /// Methods for support type inquiry through isa, cast, and dyn_cast:
+    static bool classof(const SCEV *S) {
+      return S->getSCEVType() == scPtrToInt || S->getSCEVType() == scTruncate ||
+             S->getSCEVType() == scZeroExtend ||
+             S->getSCEVType() == scSignExtend;
+    }
+  };
+
+  /// This class represents a cast from a pointer to a pointer-sized integer
+  /// value.
+  class SCEVPtrToIntExpr : public SCEVCastExpr {
+    friend class ScalarEvolution;
+
+    SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy);
+
+  public:
+    /// Methods for support type inquiry through isa, cast, and dyn_cast:
+    static bool classof(const SCEV *S) {
+      return S->getSCEVType() == scPtrToInt;
+    }
+  };
+
+  /// This is the base class for unary integral cast operator classes.
+  class SCEVIntegralCastExpr : public SCEVCastExpr {
+  protected:
+    SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
+                         const SCEV *op, Type *ty);
+
+  public:
     /// Methods for support type inquiry through isa, cast, and dyn_cast:
     static bool classof(const SCEV *S) {
       return S->getSCEVType() == scTruncate ||
@@ -541,6 +570,8 @@ class Type;
       switch (S->getSCEVType()) {
       case scConstant:
         return ((SC*)this)->visitConstant((const SCEVConstant*)S);
+      case scPtrToInt:
+        return ((SC *)this)->visitPtrToIntExpr((const SCEVPtrToIntExpr *)S);
       case scTruncate:
         return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S);
       case scZeroExtend:
@@ -606,10 +637,11 @@ class Type;
         case scConstant:
         case scUnknown:
           continue;
+        case scPtrToInt:
         case scTruncate:
         case scZeroExtend:
         case scSignExtend:
-          push(cast<SCEVIntegralCastExpr>(S)->getOperand());
+          push(cast<SCEVCastExpr>(S)->getOperand());
           continue;
         case scAddExpr:
         case scMulExpr:
@@ -698,6 +730,13 @@ class Type;
       return Constant;
     }
 
+    const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
+      const SCEV *Operand = ((SC *)this)->visit(Expr->getOperand());
+      return Operand == Expr->getOperand()
+                 ? Expr
+                 : SE.getPtrToIntExpr(Operand, Expr->getType());
+    }
+
     const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
       const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
       return Operand == Expr->getOperand()

diff  --git a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
index 77360cb2671d..c672691838cf 100644
--- a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
+++ b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h
@@ -446,6 +446,8 @@ class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
 
   Value *visitConstant(const SCEVConstant *S) { return S->getValue(); }
 
+  Value *visitPtrToIntExpr(const SCEVPtrToIntExpr *S);
+
   Value *visitTruncateExpr(const SCEVTruncateExpr *S);
 
   Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S);

diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 7a8d66438854..11b99553bf6b 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -252,6 +252,13 @@ void SCEV::print(raw_ostream &OS) const {
   case scConstant:
     cast<SCEVConstant>(this)->getValue()->printAsOperand(OS, false);
     return;
+  case scPtrToInt: {
+    const SCEVPtrToIntExpr *PtrToInt = cast<SCEVPtrToIntExpr>(this);
+    const SCEV *Op = PtrToInt->getOperand();
+    OS << "(ptrtoint " << *Op->getType() << " " << *Op << " to "
+       << *PtrToInt->getType() << ")";
+    return;
+  }
   case scTruncate: {
     const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(this);
     const SCEV *Op = Trunc->getOperand();
@@ -375,10 +382,11 @@ Type *SCEV::getType() const {
   switch (getSCEVType()) {
   case scConstant:
     return cast<SCEVConstant>(this)->getType();
+  case scPtrToInt:
   case scTruncate:
   case scZeroExtend:
   case scSignExtend:
-    return cast<SCEVIntegralCastExpr>(this)->getType();
+    return cast<SCEVCastExpr>(this)->getType();
   case scAddRecExpr:
   case scMulExpr:
   case scUMaxExpr:
@@ -456,13 +464,24 @@ ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) {
   return getConstant(ConstantInt::get(ITy, V, isSigned));
 }
 
-SCEVIntegralCastExpr::SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID,
-                                           SCEVTypes SCEVTy, const SCEV *op,
-                                           Type *ty)
+SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
+                           const SCEV *op, Type *ty)
     : SCEV(ID, SCEVTy, computeExpressionSize(op)), Ty(ty) {
   Operands[0] = op;
 }
 
+SCEVPtrToIntExpr::SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op,
+                                   Type *ITy)
+    : SCEVCastExpr(ID, scPtrToInt, Op, ITy) {
+  assert(getOperand()->getType()->isPointerTy() && Ty->isIntegerTy() &&
+         "Must be a non-bit-width-changing pointer-to-integer cast!");
+}
+
+SCEVIntegralCastExpr::SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID,
+                                           SCEVTypes SCEVTy, const SCEV *op,
+                                           Type *ty)
+    : SCEVCastExpr(ID, SCEVTy, op, ty) {}
+
 SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, const SCEV *op,
                                    Type *ty)
     : SCEVIntegralCastExpr(ID, scTruncate, op, ty) {
@@ -790,11 +809,12 @@ static int CompareSCEVComplexity(
     return X;
   }
 
+  case scPtrToInt:
   case scTruncate:
   case scZeroExtend:
   case scSignExtend: {
-    const SCEVIntegralCastExpr *LC = cast<SCEVIntegralCastExpr>(LHS);
-    const SCEVIntegralCastExpr *RC = cast<SCEVIntegralCastExpr>(RHS);
+    const SCEVCastExpr *LC = cast<SCEVCastExpr>(LHS);
+    const SCEVCastExpr *RC = cast<SCEVCastExpr>(RHS);
 
     // Compare cast expressions by operand.
     int X = CompareSCEVComplexity(EqCacheSCEV, EqCacheValue, LI,
@@ -1013,6 +1033,42 @@ const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It,
 //                    SCEV Expression folder implementations
 //===----------------------------------------------------------------------===//
 
+const SCEV *ScalarEvolution::getPtrToIntExpr(const SCEV *Op, Type *Ty,
+                                             unsigned Depth) {
+  assert(Ty->isIntegerTy() && "Target type must be an integer type!");
+
+  // We could be called with an integer-typed operands during SCEV rewrites.
+  // Since the operand is an integer already, just perform zext/trunc/self cast.
+  if (!Op->getType()->isPointerTy())
+    return getTruncateOrZeroExtend(Op, Ty);
+
+  FoldingSetNodeID ID;
+  ID.AddInteger(scPtrToInt);
+  ID.AddPointer(Op);
+  void *IP = nullptr;
+  if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP))
+    return getTruncateOrZeroExtend(S, Ty);
+
+  assert(!isa<SCEVConstant>(Op) &&
+         "SCEVConstant is an integer, no constant folding to do.");
+
+  // FIXME: simplifications.
+
+  // The cast wasn't folded; create an explicit cast node. We can reuse
+  // the existing insert position since if we get here, we won't have
+  // made any changes which would invalidate it.
+  Type *IntPtrTy = getDataLayout().getIntPtrType(Op->getType());
+  assert(getDataLayout().getTypeSizeInBits(getEffectiveSCEVType(
+             Op->getType())) == getDataLayout().getTypeSizeInBits(IntPtrTy) &&
+         "We can only model ptrtoint if SCEV's effective (integer) type is "
+         "sufficiently wide to represent all possible pointer values.");
+  SCEV *S = new (SCEVAllocator)
+      SCEVPtrToIntExpr(ID.Intern(SCEVAllocator), Op, IntPtrTy);
+  UniqueSCEVs.InsertNode(S, IP);
+  addToLoopUseLists(S);
+  return getTruncateOrZeroExtend(S, Ty);
+}
+
 const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
                                              unsigned Depth) {
   assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) &&
@@ -3528,15 +3584,18 @@ const SCEV *ScalarEvolution::getUMinExpr(SmallVectorImpl<const SCEV *> &Ops) {
 }
 
 const SCEV *ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) {
-  // We can bypass creating a target-independent
-  // constant expression and then folding it back into a ConstantInt.
-  // This is just a compile-time optimization.
   if (isa<ScalableVectorType>(AllocTy)) {
     Constant *NullPtr = Constant::getNullValue(AllocTy->getPointerTo());
     Constant *One = ConstantInt::get(IntTy, 1);
     Constant *GEP = ConstantExpr::getGetElementPtr(AllocTy, NullPtr, One);
-    return getSCEV(ConstantExpr::getPtrToInt(GEP, IntTy));
+    // Note that the expression we created is the final expression, we don't
+    // want to simplify it any further Also, if we call a normal getSCEV(),
+    // we'll end up in an endless recursion. So just create an SCEVUnknown.
+    return getUnknown(ConstantExpr::getPtrToInt(GEP, IntTy));
   }
+  // We can bypass creating a target-independent
+  // constant expression and then folding it back into a ConstantInt.
+  // This is just a compile-time optimization.
   return getConstant(IntTy, getDataLayout().getTypeAllocSize(AllocTy));
 }
 
@@ -5007,8 +5066,15 @@ static bool IsAvailableOnEntry(const Loop *L, DominatorTree &DT, const SCEV *S,
 
     bool follow(const SCEV *S) {
       switch (S->getSCEVType()) {
-      case scConstant: case scTruncate: case scZeroExtend: case scSignExtend:
-      case scAddExpr: case scMulExpr: case scUMaxExpr: case scSMaxExpr:
+      case scConstant:
+      case scPtrToInt:
+      case scTruncate:
+      case scZeroExtend:
+      case scSignExtend:
+      case scAddExpr:
+      case scMulExpr:
+      case scUMaxExpr:
+      case scSMaxExpr:
       case scUMinExpr:
       case scSMinExpr:
         // These expressions are available if their operand(s) is/are.
@@ -5266,6 +5332,9 @@ uint32_t ScalarEvolution::GetMinTrailingZerosImpl(const SCEV *S) {
   if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
     return C->getAPInt().countTrailingZeros();
 
+  if (const SCEVPtrToIntExpr *I = dyn_cast<SCEVPtrToIntExpr>(S))
+    return GetMinTrailingZeros(I->getOperand());
+
   if (const SCEVTruncateExpr *T = dyn_cast<SCEVTruncateExpr>(S))
     return std::min(GetMinTrailingZeros(T->getOperand()),
                     (uint32_t)getTypeSizeInBits(T->getType()));
@@ -5471,6 +5540,11 @@ ScalarEvolution::getRangeRef(const SCEV *S,
                                                      RangeType));
   }
 
+  if (const SCEVPtrToIntExpr *PtrToInt = dyn_cast<SCEVPtrToIntExpr>(S)) {
+    ConstantRange X = getRangeRef(PtrToInt->getOperand(), SignHint);
+    return setRange(PtrToInt, SignHint, X);
+  }
+
   if (const SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
     ConstantRange X = getRangeRef(Trunc->getOperand(), SignHint);
     return setRange(Trunc, SignHint,
@@ -6077,6 +6151,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
   } else if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
     return getConstant(CI);
   else if (isa<ConstantPointerNull>(V))
+    // FIXME: we shouldn't special-case null pointer constant.
     return getZero(V->getType());
   else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
     return GA->isInterposable() ? getUnknown(V) : getSCEV(GA->getAliasee());
@@ -6412,6 +6487,29 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       return getSCEV(U->getOperand(0));
     break;
 
+  case Instruction::PtrToInt: {
+    // Pointer to integer cast is straight-forward, so do model it.
+    Value *Ptr = U->getOperand(0);
+    const SCEV *Op = getSCEV(Ptr);
+    Type *DstIntTy = U->getType();
+    // SCEV doesn't have constant pointer expression type, but it supports
+    // nullptr constant (and only that one), which is modelled in SCEV as a
+    // zero integer constant. So just skip the ptrtoint cast for constants.
+    if (isa<SCEVConstant>(Op))
+      return getTruncateOrZeroExtend(Op, DstIntTy);
+    Type *PtrTy = Ptr->getType();
+    Type *IntPtrTy = getDataLayout().getIntPtrType(PtrTy);
+    // But only if effective SCEV (integer) type is wide enough to represent
+    // all possible pointer values.
+    if (getDataLayout().getTypeSizeInBits(getEffectiveSCEVType(PtrTy)) !=
+        getDataLayout().getTypeSizeInBits(IntPtrTy))
+      return getUnknown(V);
+    return getPtrToIntExpr(Op, DstIntTy);
+  }
+  case Instruction::IntToPtr:
+    // Just don't deal with inttoptr casts.
+    return getUnknown(V);
+
   case Instruction::SDiv:
     // If both operands are non-negative, this is just an udiv.
     if (isKnownNonNegative(getSCEV(U->getOperand(0))) &&
@@ -6426,11 +6524,6 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
       return getURemExpr(getSCEV(U->getOperand(0)), getSCEV(U->getOperand(1)));
     break;
 
-  // It's tempting to handle inttoptr and ptrtoint as no-ops, however this can
-  // lead to pointer expressions which cannot safely be expanded to GEPs,
-  // because ScalarEvolution doesn't respect the GEP aliasing rules when
-  // simplifying integer expressions.
-
   case Instruction::GetElementPtr:
     return createNodeForGEP(cast<GEPOperator>(U));
 
@@ -8090,6 +8183,13 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
       return ConstantExpr::getZExt(CastOp, SZ->getType());
     return nullptr;
   }
+  case scPtrToInt: {
+    const SCEVPtrToIntExpr *P2I = cast<SCEVPtrToIntExpr>(V);
+    if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
+      return ConstantExpr::getPtrToInt(CastOp, P2I->getType());
+
+    return nullptr;
+  }
   case scTruncate: {
     const SCEVTruncateExpr *ST = cast<SCEVTruncateExpr>(V);
     if (Constant *CastOp = BuildConstantFromSCEV(ST->getOperand()))
@@ -8397,6 +8497,13 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
     return getTruncateExpr(Op, Cast->getType());
   }
 
+  if (const SCEVPtrToIntExpr *Cast = dyn_cast<SCEVPtrToIntExpr>(V)) {
+    const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L);
+    if (Op == Cast->getOperand())
+      return Cast; // must be loop invariant
+    return getPtrToIntExpr(Op, Cast->getType());
+  }
+
   llvm_unreachable("Unknown SCEV type!");
 }
 
@@ -11973,10 +12080,11 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
   switch (S->getSCEVType()) {
   case scConstant:
     return LoopInvariant;
+  case scPtrToInt:
   case scTruncate:
   case scZeroExtend:
   case scSignExtend:
-    return getLoopDisposition(cast<SCEVIntegralCastExpr>(S)->getOperand(), L);
+    return getLoopDisposition(cast<SCEVCastExpr>(S)->getOperand(), L);
   case scAddRecExpr: {
     const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(S);
 
@@ -12080,10 +12188,11 @@ ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) {
   switch (S->getSCEVType()) {
   case scConstant:
     return ProperlyDominatesBlock;
+  case scPtrToInt:
   case scTruncate:
   case scZeroExtend:
   case scSignExtend:
-    return getBlockDisposition(cast<SCEVIntegralCastExpr>(S)->getOperand(), BB);
+    return getBlockDisposition(cast<SCEVCastExpr>(S)->getOperand(), BB);
   case scAddRecExpr: {
     // This uses a "dominates" query instead of "properly dominates" query
     // to test for proper dominance too, because the instruction which

diff  --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 83d2b6f29952..c4d90a477a56 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -663,7 +663,7 @@ const Loop *SCEVExpander::getRelevantLoop(const SCEV *S) {
       L = PickMostRelevantLoop(L, getRelevantLoop(Op), SE.DT);
     return RelevantLoops[N] = L;
   }
-  if (const SCEVIntegralCastExpr *C = dyn_cast<SCEVIntegralCastExpr>(S)) {
+  if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(S)) {
     const Loop *Result = getRelevantLoop(C->getOperand());
     return RelevantLoops[C] = Result;
   }
@@ -1661,6 +1661,12 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
   return expand(T);
 }
 
+Value *SCEVExpander::visitPtrToIntExpr(const SCEVPtrToIntExpr *S) {
+  Value *V =
+      expandCodeForImpl(S->getOperand(), S->getOperand()->getType(), false);
+  return Builder.CreatePtrToInt(V, S->getType());
+}
+
 Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) {
   Type *Ty = SE.getEffectiveSCEVType(S->getType());
   Value *V = expandCodeForImpl(
@@ -2241,6 +2247,9 @@ template<typename T> static int costAndCollectOperands(
   case scUnknown:
   case scConstant:
     return 0;
+  case scPtrToInt:
+    Cost = CastCost(Instruction::PtrToInt);
+    break;
   case scTruncate:
     Cost = CastCost(Instruction::Trunc);
     break;
@@ -2368,10 +2377,11 @@ bool SCEVExpander::isHighCostExpansionHelper(
     return BudgetRemaining < 0;
   }
   case scTruncate:
+  case scPtrToInt:
   case scZeroExtend:
   case scSignExtend: {
-    int Cost = costAndCollectOperands<SCEVIntegralCastExpr>(WorkItem, TTI,
-                                                            CostKind, Worklist);
+    int Cost =
+        costAndCollectOperands<SCEVCastExpr>(WorkItem, TTI, CostKind, Worklist);
     BudgetRemaining -= Cost;
     return false; // Will answer upon next entry into this function.
   }

diff  --git a/llvm/test/Analysis/ScalarEvolution/add-expr-pointer-operand-sorting.ll b/llvm/test/Analysis/ScalarEvolution/add-expr-pointer-operand-sorting.ll
index 93a3bf4d4c37..c60eafd413d5 100644
--- a/llvm/test/Analysis/ScalarEvolution/add-expr-pointer-operand-sorting.ll
+++ b/llvm/test/Analysis/ScalarEvolution/add-expr-pointer-operand-sorting.ll
@@ -33,9 +33,9 @@ define i32 @d(i32 %base) {
 ; CHECK-NEXT:    %1 = load i32*, i32** @c, align 8
 ; CHECK-NEXT:    --> %1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %sub.ptr.lhs.cast = ptrtoint i32* %1 to i64
-; CHECK-NEXT:    --> %sub.ptr.lhs.cast U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
+; CHECK-NEXT:    --> (ptrtoint i32* %1 to i64) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, ptrtoint ([1 x i32]* @b to i64)
-; CHECK-NEXT:    --> ((-1 * ptrtoint ([1 x i32]* @b to i64)) + %sub.ptr.lhs.cast) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
+; CHECK-NEXT:    --> ((-1 * (ptrtoint [1 x i32]* @b to i64)) + (ptrtoint i32* %1 to i64)) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %sub.ptr.div = sdiv exact i64 %sub.ptr.sub, 4
 ; CHECK-NEXT:    --> %sub.ptr.div U: full-set S: [-2305843009213693952,2305843009213693952) Exits: <<Unknown>> LoopDispositions: { %for.cond: Variant }
 ; CHECK-NEXT:    %arrayidx1 = getelementptr inbounds [1 x i8], [1 x i8]* %arrayidx, i64 0, i64 %sub.ptr.div

diff  --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
index 7707ebbc176c..e2fc84c8d71c 100644
--- a/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
@@ -186,19 +186,19 @@ define void @f3(i8* %x_addr, i8* %y_addr, i32* %tmp_addr) {
 ; CHECK-NEXT:    %ptr = bitcast [16 x i8]* @z_addr to i8*
 ; CHECK-NEXT:    --> @z_addr U: [0,-3) S: [-9223372036854775808,9223372036854775805)
 ; CHECK-NEXT:    %int0 = ptrtoint i8* %ptr to i32
-; CHECK-NEXT:    --> %int0 U: [0,-3) S: [-2147483648,2147483645)
+; CHECK-NEXT:    --> (trunc i64 (ptrtoint [16 x i8]* @z_addr to i64) to i32) U: [0,-3) S: [-2147483648,2147483645)
 ; CHECK-NEXT:    %int5 = add i32 %int0, 5
-; CHECK-NEXT:    --> (5 + %int0) U: [5,2) S: [-2147483643,-2147483646)
+; CHECK-NEXT:    --> (5 + (trunc i64 (ptrtoint [16 x i8]* @z_addr to i64) to i32)) U: [5,2) S: [-2147483643,-2147483646)
 ; CHECK-NEXT:    %int.zext = zext i32 %int5 to i64
-; CHECK-NEXT:    --> (1 + (zext i32 (4 + %int0) to i64))<nuw><nsw> U: [1,4294967294) S: [1,4294967297)
+; CHECK-NEXT:    --> (1 + (zext i32 (4 + (trunc i64 (ptrtoint [16 x i8]* @z_addr to i64) to i32)) to i64))<nuw><nsw> U: [1,4294967294) S: [1,4294967297)
 ; CHECK-NEXT:    %ptr_noalign = bitcast [16 x i8]* @z_addr_noalign to i8*
 ; CHECK-NEXT:    --> @z_addr_noalign U: full-set S: full-set
 ; CHECK-NEXT:    %int0_na = ptrtoint i8* %ptr_noalign to i32
-; CHECK-NEXT:    --> %int0_na U: full-set S: full-set
+; CHECK-NEXT:    --> (trunc i64 (ptrtoint [16 x i8]* @z_addr_noalign to i64) to i32) U: full-set S: full-set
 ; CHECK-NEXT:    %int5_na = add i32 %int0_na, 5
-; CHECK-NEXT:    --> (5 + %int0_na) U: full-set S: full-set
+; CHECK-NEXT:    --> (5 + (trunc i64 (ptrtoint [16 x i8]* @z_addr_noalign to i64) to i32)) U: full-set S: full-set
 ; CHECK-NEXT:    %int.zext_na = zext i32 %int5_na to i64
-; CHECK-NEXT:    --> (zext i32 (5 + %int0_na) to i64) U: [0,4294967296) S: [0,4294967296)
+; CHECK-NEXT:    --> (zext i32 (5 + (trunc i64 (ptrtoint [16 x i8]* @z_addr_noalign to i64) to i32)) to i64) U: [0,4294967296) S: [0,4294967296)
 ; CHECK-NEXT:    %tmp = load i32, i32* %tmp_addr, align 4
 ; CHECK-NEXT:    --> %tmp U: full-set S: full-set
 ; CHECK-NEXT:    %mul = and i32 %tmp, -4

diff  --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
index f6364939bb39..34d4f701c6d1 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
@@ -18,9 +18,9 @@ define hidden i32* @trunc_ptr_to_i64(i8* %arg, i32* %arg10) {
 ; PTR64_IDX64-NEXT:    %tmp = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
 ; PTR64_IDX64-NEXT:    --> {0,+,2}<%bb11> U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %bb11: Computable }
 ; PTR64_IDX64-NEXT:    %tmp12 = getelementptr i8, i8* %arg, i64 ptrtoint ([0 x i8]* @global to i64)
-; PTR64_IDX64-NEXT:    --> (ptrtoint ([0 x i8]* @global to i64) + %arg) U: full-set S: full-set Exits: (ptrtoint ([0 x i8]* @global to i64) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR64_IDX64-NEXT:    --> ((ptrtoint [0 x i8]* @global to i64) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i64) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR64_IDX64-NEXT:    %tmp13 = bitcast i8* %tmp12 to i32*
-; PTR64_IDX64-NEXT:    --> (ptrtoint ([0 x i8]* @global to i64) + %arg) U: full-set S: full-set Exits: (ptrtoint ([0 x i8]* @global to i64) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR64_IDX64-NEXT:    --> ((ptrtoint [0 x i8]* @global to i64) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i64) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR64_IDX64-NEXT:    %tmp14 = load i32, i32* %tmp13, align 4
 ; PTR64_IDX64-NEXT:    --> %tmp14 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb11: Variant }
 ; PTR64_IDX64-NEXT:    %tmp18 = add i32 %tmp, 2
@@ -52,9 +52,9 @@ define hidden i32* @trunc_ptr_to_i64(i8* %arg, i32* %arg10) {
 ; PTR16_IDX16-NEXT:    %tmp = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
 ; PTR16_IDX16-NEXT:    --> {0,+,2}<%bb11> U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %bb11: Computable }
 ; PTR16_IDX16-NEXT:    %tmp12 = getelementptr i8, i8* %arg, i64 ptrtoint ([0 x i8]* @global to i64)
-; PTR16_IDX16-NEXT:    --> ((trunc i64 ptrtoint ([0 x i8]* @global to i64) to i16) + %arg) U: full-set S: full-set Exits: ((trunc i64 ptrtoint ([0 x i8]* @global to i64) to i16) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR16_IDX16-NEXT:    --> ((ptrtoint [0 x i8]* @global to i16) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i16) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR16_IDX16-NEXT:    %tmp13 = bitcast i8* %tmp12 to i32*
-; PTR16_IDX16-NEXT:    --> ((trunc i64 ptrtoint ([0 x i8]* @global to i64) to i16) + %arg) U: full-set S: full-set Exits: ((trunc i64 ptrtoint ([0 x i8]* @global to i64) to i16) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR16_IDX16-NEXT:    --> ((ptrtoint [0 x i8]* @global to i16) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i16) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR16_IDX16-NEXT:    %tmp14 = load i32, i32* %tmp13, align 4
 ; PTR16_IDX16-NEXT:    --> %tmp14 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb11: Variant }
 ; PTR16_IDX16-NEXT:    %tmp18 = add i32 %tmp, 2
@@ -105,9 +105,9 @@ define hidden i32* @trunc_ptr_to_i32(i8* %arg, i32* %arg10) {
 ; PTR64_IDX64-NEXT:    %tmp = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
 ; PTR64_IDX64-NEXT:    --> {0,+,2}<%bb11> U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %bb11: Computable }
 ; PTR64_IDX64-NEXT:    %tmp12 = getelementptr i8, i8* %arg, i32 ptrtoint ([0 x i8]* @global to i32)
-; PTR64_IDX64-NEXT:    --> ((sext i32 ptrtoint ([0 x i8]* @global to i32) to i64) + %arg) U: full-set S: full-set Exits: ((sext i32 ptrtoint ([0 x i8]* @global to i32) to i64) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR64_IDX64-NEXT:    --> ((sext i32 (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i32) to i64) + %arg) U: full-set S: full-set Exits: ((sext i32 (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i32) to i64) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR64_IDX64-NEXT:    %tmp13 = bitcast i8* %tmp12 to i32*
-; PTR64_IDX64-NEXT:    --> ((sext i32 ptrtoint ([0 x i8]* @global to i32) to i64) + %arg) U: full-set S: full-set Exits: ((sext i32 ptrtoint ([0 x i8]* @global to i32) to i64) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR64_IDX64-NEXT:    --> ((sext i32 (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i32) to i64) + %arg) U: full-set S: full-set Exits: ((sext i32 (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i32) to i64) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR64_IDX64-NEXT:    %tmp14 = load i32, i32* %tmp13, align 4
 ; PTR64_IDX64-NEXT:    --> %tmp14 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb11: Variant }
 ; PTR64_IDX64-NEXT:    %tmp18 = add i32 %tmp, 2
@@ -139,9 +139,9 @@ define hidden i32* @trunc_ptr_to_i32(i8* %arg, i32* %arg10) {
 ; PTR16_IDX16-NEXT:    %tmp = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
 ; PTR16_IDX16-NEXT:    --> {0,+,2}<%bb11> U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %bb11: Computable }
 ; PTR16_IDX16-NEXT:    %tmp12 = getelementptr i8, i8* %arg, i32 ptrtoint ([0 x i8]* @global to i32)
-; PTR16_IDX16-NEXT:    --> ((trunc i32 ptrtoint ([0 x i8]* @global to i32) to i16) + %arg) U: full-set S: full-set Exits: ((trunc i32 ptrtoint ([0 x i8]* @global to i32) to i16) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR16_IDX16-NEXT:    --> ((ptrtoint [0 x i8]* @global to i16) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i16) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR16_IDX16-NEXT:    %tmp13 = bitcast i8* %tmp12 to i32*
-; PTR16_IDX16-NEXT:    --> ((trunc i32 ptrtoint ([0 x i8]* @global to i32) to i16) + %arg) U: full-set S: full-set Exits: ((trunc i32 ptrtoint ([0 x i8]* @global to i32) to i16) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR16_IDX16-NEXT:    --> ((ptrtoint [0 x i8]* @global to i16) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i16) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR16_IDX16-NEXT:    %tmp14 = load i32, i32* %tmp13, align 4
 ; PTR16_IDX16-NEXT:    --> %tmp14 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb11: Variant }
 ; PTR16_IDX16-NEXT:    %tmp18 = add i32 %tmp, 2
@@ -192,9 +192,9 @@ define hidden i32* @trunc_ptr_to_i128(i8* %arg, i32* %arg10) {
 ; PTR64_IDX64-NEXT:    %tmp = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
 ; PTR64_IDX64-NEXT:    --> {0,+,2}<%bb11> U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %bb11: Computable }
 ; PTR64_IDX64-NEXT:    %tmp12 = getelementptr i8, i8* %arg, i128 ptrtoint ([0 x i8]* @global to i128)
-; PTR64_IDX64-NEXT:    --> ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i64) + %arg) U: full-set S: full-set Exits: ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i64) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR64_IDX64-NEXT:    --> ((ptrtoint [0 x i8]* @global to i64) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i64) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR64_IDX64-NEXT:    %tmp13 = bitcast i8* %tmp12 to i32*
-; PTR64_IDX64-NEXT:    --> ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i64) + %arg) U: full-set S: full-set Exits: ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i64) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR64_IDX64-NEXT:    --> ((ptrtoint [0 x i8]* @global to i64) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i64) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR64_IDX64-NEXT:    %tmp14 = load i32, i32* %tmp13, align 4
 ; PTR64_IDX64-NEXT:    --> %tmp14 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb11: Variant }
 ; PTR64_IDX64-NEXT:    %tmp18 = add i32 %tmp, 2
@@ -226,9 +226,9 @@ define hidden i32* @trunc_ptr_to_i128(i8* %arg, i32* %arg10) {
 ; PTR16_IDX16-NEXT:    %tmp = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
 ; PTR16_IDX16-NEXT:    --> {0,+,2}<%bb11> U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %bb11: Computable }
 ; PTR16_IDX16-NEXT:    %tmp12 = getelementptr i8, i8* %arg, i128 ptrtoint ([0 x i8]* @global to i128)
-; PTR16_IDX16-NEXT:    --> ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i16) + %arg) U: full-set S: full-set Exits: ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i16) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR16_IDX16-NEXT:    --> ((ptrtoint [0 x i8]* @global to i16) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i16) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR16_IDX16-NEXT:    %tmp13 = bitcast i8* %tmp12 to i32*
-; PTR16_IDX16-NEXT:    --> ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i16) + %arg) U: full-set S: full-set Exits: ((trunc i128 ptrtoint ([0 x i8]* @global to i128) to i16) + %arg) LoopDispositions: { %bb11: Invariant }
+; PTR16_IDX16-NEXT:    --> ((ptrtoint [0 x i8]* @global to i16) + %arg) U: full-set S: full-set Exits: ((ptrtoint [0 x i8]* @global to i16) + %arg) LoopDispositions: { %bb11: Invariant }
 ; PTR16_IDX16-NEXT:    %tmp14 = load i32, i32* %tmp13, align 4
 ; PTR16_IDX16-NEXT:    --> %tmp14 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb11: Variant }
 ; PTR16_IDX16-NEXT:    %tmp18 = add i32 %tmp, 2
@@ -275,27 +275,49 @@ bb17:                                             ; preds = %bb11
 }
 
 define void @zext_ptr_to_i32(i32 %arg, i32 %arg6) {
-; X64-LABEL: 'zext_ptr_to_i32'
-; X64-NEXT:  Classifying expressions for: @zext_ptr_to_i32
-; X64-NEXT:    %tmp = sub i32 %arg, ptrtoint ([0 x i8]* @global to i32)
-; X64-NEXT:    --> ((-1 * ptrtoint ([0 x i8]* @global to i32)) + %arg) U: full-set S: full-set Exits: ((-1 * ptrtoint ([0 x i8]* @global to i32)) + %arg) LoopDispositions: { %bb7: Invariant }
-; X64-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
-; X64-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
-; X64-NEXT:  Determining loop execution counts for: @zext_ptr_to_i32
-; X64-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
-; X64-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
-; X64-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+; PTR64_IDX64-LABEL: 'zext_ptr_to_i32'
+; PTR64_IDX64-NEXT:  Classifying expressions for: @zext_ptr_to_i32
+; PTR64_IDX64-NEXT:    %tmp = sub i32 %arg, ptrtoint ([0 x i8]* @global to i32)
+; PTR64_IDX64-NEXT:    --> ((-1 * (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i32)) + %arg) U: full-set S: full-set Exits: ((-1 * (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i32)) + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR64_IDX64-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR64_IDX64-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR64_IDX64-NEXT:  Determining loop execution counts for: @zext_ptr_to_i32
+; PTR64_IDX64-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR64_IDX64-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR64_IDX64-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
 ;
-; X32-LABEL: 'zext_ptr_to_i32'
-; X32-NEXT:  Classifying expressions for: @zext_ptr_to_i32
-; X32-NEXT:    %tmp = sub i32 %arg, ptrtoint ([0 x i8]* @global to i32)
-; X32-NEXT:    --> ((-1 * ptrtoint ([0 x i8]* @global to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * ptrtoint ([0 x i8]* @global to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
-; X32-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
-; X32-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
-; X32-NEXT:  Determining loop execution counts for: @zext_ptr_to_i32
-; X32-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
-; X32-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
-; X32-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+; PTR64_IDX32-LABEL: 'zext_ptr_to_i32'
+; PTR64_IDX32-NEXT:  Classifying expressions for: @zext_ptr_to_i32
+; PTR64_IDX32-NEXT:    %tmp = sub i32 %arg, ptrtoint ([0 x i8]* @global to i32)
+; PTR64_IDX32-NEXT:    --> ((-1 * ptrtoint ([0 x i8]* @global to i32)) + %arg) U: full-set S: full-set Exits: ((-1 * ptrtoint ([0 x i8]* @global to i32)) + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR64_IDX32-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR64_IDX32-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR64_IDX32-NEXT:  Determining loop execution counts for: @zext_ptr_to_i32
+; PTR64_IDX32-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR64_IDX32-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR64_IDX32-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+;
+; PTR16_IDX16-LABEL: 'zext_ptr_to_i32'
+; PTR16_IDX16-NEXT:  Classifying expressions for: @zext_ptr_to_i32
+; PTR16_IDX16-NEXT:    %tmp = sub i32 %arg, ptrtoint ([0 x i8]* @global to i32)
+; PTR16_IDX16-NEXT:    --> ((-1 * (zext i16 (ptrtoint [0 x i8]* @global to i16) to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * (zext i16 (ptrtoint [0 x i8]* @global to i16) to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR16_IDX16-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR16_IDX16-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR16_IDX16-NEXT:  Determining loop execution counts for: @zext_ptr_to_i32
+; PTR16_IDX16-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR16_IDX16-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR16_IDX16-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+;
+; PTR16_IDX32-LABEL: 'zext_ptr_to_i32'
+; PTR16_IDX32-NEXT:  Classifying expressions for: @zext_ptr_to_i32
+; PTR16_IDX32-NEXT:    %tmp = sub i32 %arg, ptrtoint ([0 x i8]* @global to i32)
+; PTR16_IDX32-NEXT:    --> ((-1 * ptrtoint ([0 x i8]* @global to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * ptrtoint ([0 x i8]* @global to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR16_IDX32-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR16_IDX32-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR16_IDX32-NEXT:  Determining loop execution counts for: @zext_ptr_to_i32
+; PTR16_IDX32-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR16_IDX32-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR16_IDX32-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
 ;
 bb:
   br label %bb7
@@ -312,16 +334,49 @@ bb10:                                             ; preds = %bb7
 }
 
 define void @sext_to_i32(i32 %arg, i32 %arg6) {
-; ALL-LABEL: 'sext_to_i32'
-; ALL-NEXT:  Classifying expressions for: @sext_to_i32
-; ALL-NEXT:    %tmp = sub i32 %arg, sext (i16 ptrtoint ([0 x i8]* @global to i16) to i32)
-; ALL-NEXT:    --> ((-1 * (sext i16 ptrtoint ([0 x i8]* @global to i16) to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * (sext i16 ptrtoint ([0 x i8]* @global to i16) to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
-; ALL-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
-; ALL-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
-; ALL-NEXT:  Determining loop execution counts for: @sext_to_i32
-; ALL-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
-; ALL-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
-; ALL-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+; PTR64_IDX64-LABEL: 'sext_to_i32'
+; PTR64_IDX64-NEXT:  Classifying expressions for: @sext_to_i32
+; PTR64_IDX64-NEXT:    %tmp = sub i32 %arg, sext (i16 ptrtoint ([0 x i8]* @global to i16) to i32)
+; PTR64_IDX64-NEXT:    --> ((-1 * (sext i16 (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i16) to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * (sext i16 (trunc i64 (ptrtoint [0 x i8]* @global to i64) to i16) to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR64_IDX64-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR64_IDX64-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR64_IDX64-NEXT:  Determining loop execution counts for: @sext_to_i32
+; PTR64_IDX64-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR64_IDX64-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR64_IDX64-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+;
+; PTR64_IDX32-LABEL: 'sext_to_i32'
+; PTR64_IDX32-NEXT:  Classifying expressions for: @sext_to_i32
+; PTR64_IDX32-NEXT:    %tmp = sub i32 %arg, sext (i16 ptrtoint ([0 x i8]* @global to i16) to i32)
+; PTR64_IDX32-NEXT:    --> ((-1 * (sext i16 ptrtoint ([0 x i8]* @global to i16) to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * (sext i16 ptrtoint ([0 x i8]* @global to i16) to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR64_IDX32-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR64_IDX32-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR64_IDX32-NEXT:  Determining loop execution counts for: @sext_to_i32
+; PTR64_IDX32-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR64_IDX32-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR64_IDX32-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+;
+; PTR16_IDX16-LABEL: 'sext_to_i32'
+; PTR16_IDX16-NEXT:  Classifying expressions for: @sext_to_i32
+; PTR16_IDX16-NEXT:    %tmp = sub i32 %arg, sext (i16 ptrtoint ([0 x i8]* @global to i16) to i32)
+; PTR16_IDX16-NEXT:    --> ((-1 * (sext i16 (ptrtoint [0 x i8]* @global to i16) to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * (sext i16 (ptrtoint [0 x i8]* @global to i16) to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR16_IDX16-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR16_IDX16-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR16_IDX16-NEXT:  Determining loop execution counts for: @sext_to_i32
+; PTR16_IDX16-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR16_IDX16-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR16_IDX16-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
+;
+; PTR16_IDX32-LABEL: 'sext_to_i32'
+; PTR16_IDX32-NEXT:  Classifying expressions for: @sext_to_i32
+; PTR16_IDX32-NEXT:    %tmp = sub i32 %arg, sext (i16 ptrtoint ([0 x i8]* @global to i16) to i32)
+; PTR16_IDX32-NEXT:    --> ((-1 * (sext i16 ptrtoint ([0 x i8]* @global to i16) to i32))<nsw> + %arg) U: full-set S: full-set Exits: ((-1 * (sext i16 ptrtoint ([0 x i8]* @global to i16) to i32))<nsw> + %arg) LoopDispositions: { %bb7: Invariant }
+; PTR16_IDX32-NEXT:    %tmp9 = select i1 %tmp8, i16 0, i16 1
+; PTR16_IDX32-NEXT:    --> %tmp9 U: [0,2) S: [-2,2) Exits: <<Unknown>> LoopDispositions: { %bb7: Variant }
+; PTR16_IDX32-NEXT:  Determining loop execution counts for: @sext_to_i32
+; PTR16_IDX32-NEXT:  Loop %bb7: Unpredictable backedge-taken count.
+; PTR16_IDX32-NEXT:  Loop %bb7: Unpredictable max backedge-taken count.
+; PTR16_IDX32-NEXT:  Loop %bb7: Unpredictable predicated backedge-taken count.
 ;
 bb:
   br label %bb7
@@ -338,39 +393,73 @@ bb10:                                             ; preds = %bb7
 }
 
 define i64 @sext_like_noop(i32 %n) {
-; X64-LABEL: 'sext_like_noop'
-; X64-NEXT:  Classifying expressions for: @sext_like_noop
-; X64-NEXT:    %ii = sext i32 %i to i64
-; X64-NEXT:    --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32)) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
-; X64-NEXT:    %div = sdiv i64 55555, %ii
-; X64-NEXT:    --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 sext (i32 add (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32), i32 -1) to i64)) U: full-set S: full-set
-; X64-NEXT:    %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
-; X64-NEXT:    --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32)) LoopDispositions: { %for.body: Computable }
-; X64-NEXT:    %inc = add nuw i32 %i, 1
-; X64-NEXT:    --> {2,+,1}<nuw><%for.body> U: [2,0) S: [2,0) Exits: ptrtoint (i64 (i32)* @sext_like_noop to i32) LoopDispositions: { %for.body: Computable }
-; X64-NEXT:  Determining loop execution counts for: @sext_like_noop
-; X64-NEXT:  Loop %for.body: backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))
-; X64-NEXT:  Loop %for.body: max backedge-taken count is -1
-; X64-NEXT:  Loop %for.body: Predicated backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))
-; X64-NEXT:   Predicates:
-; X64:       Loop %for.body: Trip multiple is 1
+; PTR64_IDX64-LABEL: 'sext_like_noop'
+; PTR64_IDX64-NEXT:  Classifying expressions for: @sext_like_noop
+; PTR64_IDX64-NEXT:    %ii = sext i32 %i to i64
+; PTR64_IDX64-NEXT:    --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (-1 + (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32)) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
+; PTR64_IDX64-NEXT:    %div = sdiv i64 55555, %ii
+; PTR64_IDX64-NEXT:    --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 sext (i32 add (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32), i32 -1) to i64)) U: full-set S: full-set
+; PTR64_IDX64-NEXT:    %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
+; PTR64_IDX64-NEXT:    --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32)) LoopDispositions: { %for.body: Computable }
+; PTR64_IDX64-NEXT:    %inc = add nuw i32 %i, 1
+; PTR64_IDX64-NEXT:    --> {2,+,1}<nuw><%for.body> U: [2,0) S: [2,0) Exits: (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32) LoopDispositions: { %for.body: Computable }
+; PTR64_IDX64-NEXT:  Determining loop execution counts for: @sext_like_noop
+; PTR64_IDX64-NEXT:  Loop %for.body: backedge-taken count is (-2 + (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32))
+; PTR64_IDX64-NEXT:  Loop %for.body: max backedge-taken count is -1
+; PTR64_IDX64-NEXT:  Loop %for.body: Predicated backedge-taken count is (-2 + (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32))
+; PTR64_IDX64-NEXT:   Predicates:
+; PTR64_IDX64:       Loop %for.body: Trip multiple is 1
+;
+; PTR64_IDX32-LABEL: 'sext_like_noop'
+; PTR64_IDX32-NEXT:  Classifying expressions for: @sext_like_noop
+; PTR64_IDX32-NEXT:    %ii = sext i32 %i to i64
+; PTR64_IDX32-NEXT:    --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32)) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
+; PTR64_IDX32-NEXT:    %div = sdiv i64 55555, %ii
+; PTR64_IDX32-NEXT:    --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 sext (i32 add (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32), i32 -1) to i64)) U: full-set S: full-set
+; PTR64_IDX32-NEXT:    %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
+; PTR64_IDX32-NEXT:    --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32)) LoopDispositions: { %for.body: Computable }
+; PTR64_IDX32-NEXT:    %inc = add nuw i32 %i, 1
+; PTR64_IDX32-NEXT:    --> {2,+,1}<nuw><%for.body> U: [2,0) S: [2,0) Exits: ptrtoint (i64 (i32)* @sext_like_noop to i32) LoopDispositions: { %for.body: Computable }
+; PTR64_IDX32-NEXT:  Determining loop execution counts for: @sext_like_noop
+; PTR64_IDX32-NEXT:  Loop %for.body: backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))
+; PTR64_IDX32-NEXT:  Loop %for.body: max backedge-taken count is -1
+; PTR64_IDX32-NEXT:  Loop %for.body: Predicated backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))
+; PTR64_IDX32-NEXT:   Predicates:
+; PTR64_IDX32:       Loop %for.body: Trip multiple is 1
+;
+; PTR16_IDX16-LABEL: 'sext_like_noop'
+; PTR16_IDX16-NEXT:  Classifying expressions for: @sext_like_noop
+; PTR16_IDX16-NEXT:    %ii = sext i32 %i to i64
+; PTR16_IDX16-NEXT:    --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (-1 + (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i64))<nsw> U: [-1,65535) S: [-1,65535)
+; PTR16_IDX16-NEXT:    %div = sdiv i64 55555, %ii
+; PTR16_IDX16-NEXT:    --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 add (i64 zext (i16 ptrtoint (i64 (i32)* @sext_like_noop to i16) to i64), i64 -1)) U: full-set S: full-set
+; PTR16_IDX16-NEXT:    %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
+; PTR16_IDX16-NEXT:    --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i32))<nsw> LoopDispositions: { %for.body: Computable }
+; PTR16_IDX16-NEXT:    %inc = add nuw i32 %i, 1
+; PTR16_IDX16-NEXT:    --> {2,+,1}<nuw><%for.body> U: [2,0) S: [2,0) Exits: (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i32) LoopDispositions: { %for.body: Computable }
+; PTR16_IDX16-NEXT:  Determining loop execution counts for: @sext_like_noop
+; PTR16_IDX16-NEXT:  Loop %for.body: backedge-taken count is (-2 + (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i32))<nsw>
+; PTR16_IDX16-NEXT:  Loop %for.body: max backedge-taken count is -1
+; PTR16_IDX16-NEXT:  Loop %for.body: Predicated backedge-taken count is (-2 + (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i32))<nsw>
+; PTR16_IDX16-NEXT:   Predicates:
+; PTR16_IDX16:       Loop %for.body: Trip multiple is 1
 ;
-; X32-LABEL: 'sext_like_noop'
-; X32-NEXT:  Classifying expressions for: @sext_like_noop
-; X32-NEXT:    %ii = sext i32 %i to i64
-; X32-NEXT:    --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (-1 + (sext i32 ptrtoint (i64 (i32)* @sext_like_noop to i32) to i64))<nsw> U: [-1,65535) S: [-65537,65535)
-; X32-NEXT:    %div = sdiv i64 55555, %ii
-; X32-NEXT:    --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 add (i64 sext (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32) to i64), i64 -1)) U: full-set S: full-set
-; X32-NEXT:    %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
-; X32-NEXT:    --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw> LoopDispositions: { %for.body: Computable }
-; X32-NEXT:    %inc = add nuw i32 %i, 1
-; X32-NEXT:    --> {2,+,1}<nuw><%for.body> U: [2,0) S: [2,0) Exits: ptrtoint (i64 (i32)* @sext_like_noop to i32) LoopDispositions: { %for.body: Computable }
-; X32-NEXT:  Determining loop execution counts for: @sext_like_noop
-; X32-NEXT:  Loop %for.body: backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw>
-; X32-NEXT:  Loop %for.body: max backedge-taken count is -1
-; X32-NEXT:  Loop %for.body: Predicated backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw>
-; X32-NEXT:   Predicates:
-; X32:       Loop %for.body: Trip multiple is 1
+; PTR16_IDX32-LABEL: 'sext_like_noop'
+; PTR16_IDX32-NEXT:  Classifying expressions for: @sext_like_noop
+; PTR16_IDX32-NEXT:    %ii = sext i32 %i to i64
+; PTR16_IDX32-NEXT:    --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (-1 + (sext i32 ptrtoint (i64 (i32)* @sext_like_noop to i32) to i64))<nsw> U: [-1,65535) S: [-65537,65535)
+; PTR16_IDX32-NEXT:    %div = sdiv i64 55555, %ii
+; PTR16_IDX32-NEXT:    --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 add (i64 sext (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32) to i64), i64 -1)) U: full-set S: full-set
+; PTR16_IDX32-NEXT:    %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
+; PTR16_IDX32-NEXT:    --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw> LoopDispositions: { %for.body: Computable }
+; PTR16_IDX32-NEXT:    %inc = add nuw i32 %i, 1
+; PTR16_IDX32-NEXT:    --> {2,+,1}<nuw><%for.body> U: [2,0) S: [2,0) Exits: ptrtoint (i64 (i32)* @sext_like_noop to i32) LoopDispositions: { %for.body: Computable }
+; PTR16_IDX32-NEXT:  Determining loop execution counts for: @sext_like_noop
+; PTR16_IDX32-NEXT:  Loop %for.body: backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw>
+; PTR16_IDX32-NEXT:  Loop %for.body: max backedge-taken count is -1
+; PTR16_IDX32-NEXT:  Loop %for.body: Predicated backedge-taken count is (-2 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw>
+; PTR16_IDX32-NEXT:   Predicates:
+; PTR16_IDX32:       Loop %for.body: Trip multiple is 1
 ;
 entry:
   %cmp6 = icmp sgt i32 %n, 1

diff  --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
index 313acf5aa301..9a6c77e8968e 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
@@ -16,25 +16,25 @@ define void @ptrtoint(i8* %in, i64* %out0, i32* %out1, i16* %out2, i128* %out3)
 ; X64-LABEL: 'ptrtoint'
 ; X64-NEXT:  Classifying expressions for: @ptrtoint
 ; X64-NEXT:    %p0 = ptrtoint i8* %in to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* %in to i64) U: full-set S: full-set
 ; X64-NEXT:    %p1 = ptrtoint i8* %in to i32
-; X64-NEXT:    --> %p1 U: full-set S: full-set
+; X64-NEXT:    --> (trunc i64 (ptrtoint i8* %in to i64) to i32) U: full-set S: full-set
 ; X64-NEXT:    %p2 = ptrtoint i8* %in to i16
-; X64-NEXT:    --> %p2 U: full-set S: full-set
+; X64-NEXT:    --> (trunc i64 (ptrtoint i8* %in to i64) to i16) U: full-set S: full-set
 ; X64-NEXT:    %p3 = ptrtoint i8* %in to i128
-; X64-NEXT:    --> %p3 U: [0,18446744073709551616) S: [-18446744073709551616,18446744073709551616)
+; X64-NEXT:    --> (zext i64 (ptrtoint i8* %in to i64) to i128) U: [0,18446744073709551616) S: [0,18446744073709551616)
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint
 ;
 ; X32-LABEL: 'ptrtoint'
 ; X32-NEXT:  Classifying expressions for: @ptrtoint
 ; X32-NEXT:    %p0 = ptrtoint i8* %in to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* %in to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:    %p1 = ptrtoint i8* %in to i32
-; X32-NEXT:    --> %p1 U: full-set S: full-set
+; X32-NEXT:    --> (ptrtoint i8* %in to i32) U: full-set S: full-set
 ; X32-NEXT:    %p2 = ptrtoint i8* %in to i16
-; X32-NEXT:    --> %p2 U: full-set S: full-set
+; X32-NEXT:    --> (trunc i32 (ptrtoint i8* %in to i32) to i16) U: full-set S: full-set
 ; X32-NEXT:    %p3 = ptrtoint i8* %in to i128
-; X32-NEXT:    --> %p3 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* %in to i32) to i128) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint
 ;
   %p0 = ptrtoint i8* %in to i64
@@ -53,25 +53,25 @@ define void @ptrtoint_as1(i8 addrspace(1)* %in, i64* %out0, i32* %out1, i16* %ou
 ; X64-LABEL: 'ptrtoint_as1'
 ; X64-NEXT:  Classifying expressions for: @ptrtoint_as1
 ; X64-NEXT:    %p0 = ptrtoint i8 addrspace(1)* %in to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8 addrspace(1)* %in to i64) U: full-set S: full-set
 ; X64-NEXT:    %p1 = ptrtoint i8 addrspace(1)* %in to i32
-; X64-NEXT:    --> %p1 U: full-set S: full-set
+; X64-NEXT:    --> (trunc i64 (ptrtoint i8 addrspace(1)* %in to i64) to i32) U: full-set S: full-set
 ; X64-NEXT:    %p2 = ptrtoint i8 addrspace(1)* %in to i16
-; X64-NEXT:    --> %p2 U: full-set S: full-set
+; X64-NEXT:    --> (trunc i64 (ptrtoint i8 addrspace(1)* %in to i64) to i16) U: full-set S: full-set
 ; X64-NEXT:    %p3 = ptrtoint i8 addrspace(1)* %in to i128
-; X64-NEXT:    --> %p3 U: [0,18446744073709551616) S: [-18446744073709551616,18446744073709551616)
+; X64-NEXT:    --> (zext i64 (ptrtoint i8 addrspace(1)* %in to i64) to i128) U: [0,18446744073709551616) S: [0,18446744073709551616)
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_as1
 ;
 ; X32-LABEL: 'ptrtoint_as1'
 ; X32-NEXT:  Classifying expressions for: @ptrtoint_as1
 ; X32-NEXT:    %p0 = ptrtoint i8 addrspace(1)* %in to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8 addrspace(1)* %in to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:    %p1 = ptrtoint i8 addrspace(1)* %in to i32
-; X32-NEXT:    --> %p1 U: full-set S: full-set
+; X32-NEXT:    --> (ptrtoint i8 addrspace(1)* %in to i32) U: full-set S: full-set
 ; X32-NEXT:    %p2 = ptrtoint i8 addrspace(1)* %in to i16
-; X32-NEXT:    --> %p2 U: full-set S: full-set
+; X32-NEXT:    --> (trunc i32 (ptrtoint i8 addrspace(1)* %in to i32) to i16) U: full-set S: full-set
 ; X32-NEXT:    %p3 = ptrtoint i8 addrspace(1)* %in to i128
-; X32-NEXT:    --> %p3 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8 addrspace(1)* %in to i32) to i128) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_as1
 ;
   %p0 = ptrtoint i8 addrspace(1)* %in to i64
@@ -92,7 +92,7 @@ define void @ptrtoint_of_bitcast(i8* %in, i64* %out0) {
 ; X64-NEXT:    %in_casted = bitcast i8* %in to float*
 ; X64-NEXT:    --> %in U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint float* %in_casted to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* %in to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_bitcast
 ;
 ; X32-LABEL: 'ptrtoint_of_bitcast'
@@ -100,7 +100,7 @@ define void @ptrtoint_of_bitcast(i8* %in, i64* %out0) {
 ; X32-NEXT:    %in_casted = bitcast i8* %in to float*
 ; X32-NEXT:    --> %in U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint float* %in_casted to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* %in to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_bitcast
 ;
   %in_casted = bitcast i8* %in to float*
@@ -116,7 +116,7 @@ define void @ptrtoint_of_addrspacecast(i8* %in, i64* %out0) {
 ; X64-NEXT:    %in_casted = addrspacecast i8* %in to i8 addrspace(1)*
 ; X64-NEXT:    --> %in_casted U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint i8 addrspace(1)* %in_casted to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8 addrspace(1)* %in_casted to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_addrspacecast
 ;
 ; X32-LABEL: 'ptrtoint_of_addrspacecast'
@@ -124,7 +124,7 @@ define void @ptrtoint_of_addrspacecast(i8* %in, i64* %out0) {
 ; X32-NEXT:    %in_casted = addrspacecast i8* %in to i8 addrspace(1)*
 ; X32-NEXT:    --> %in_casted U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint i8 addrspace(1)* %in_casted to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8 addrspace(1)* %in_casted to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_addrspacecast
 ;
   %in_casted = addrspacecast i8* %in to i8 addrspace(1)*
@@ -140,7 +140,7 @@ define void @ptrtoint_of_inttoptr(i64 %in, i64* %out0) {
 ; X64-NEXT:    %in_casted = inttoptr i64 %in to i8*
 ; X64-NEXT:    --> %in_casted U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint i8* %in_casted to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* %in_casted to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_inttoptr
 ;
 ; X32-LABEL: 'ptrtoint_of_inttoptr'
@@ -148,7 +148,7 @@ define void @ptrtoint_of_inttoptr(i64 %in, i64* %out0) {
 ; X32-NEXT:    %in_casted = inttoptr i64 %in to i8*
 ; X32-NEXT:    --> %in_casted U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint i8* %in_casted to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* %in_casted to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_inttoptr
 ;
   %in_casted = inttoptr i64 %in to i8*
@@ -162,7 +162,7 @@ define void @ptrtoint_of_nullptr(i64* %out0) {
 ; ALL-LABEL: 'ptrtoint_of_nullptr'
 ; ALL-NEXT:  Classifying expressions for: @ptrtoint_of_nullptr
 ; ALL-NEXT:    %p0 = ptrtoint i8* null to i64
-; ALL-NEXT:    --> %p0 U: [0,1) S: [-1,1)
+; ALL-NEXT:    --> 0 U: [0,1) S: [0,1)
 ; ALL-NEXT:  Determining loop execution counts for: @ptrtoint_of_nullptr
 ;
   %p0 = ptrtoint i8* null to i64
@@ -172,11 +172,17 @@ define void @ptrtoint_of_nullptr(i64* %out0) {
 
 ; A constant inttoptr argument of an ptrtoint is still bad.
 define void @ptrtoint_of_constantexpr_inttoptr(i64* %out0) {
-; ALL-LABEL: 'ptrtoint_of_constantexpr_inttoptr'
-; ALL-NEXT:  Classifying expressions for: @ptrtoint_of_constantexpr_inttoptr
-; ALL-NEXT:    %p0 = ptrtoint i8* inttoptr (i64 42 to i8*) to i64
-; ALL-NEXT:    --> %p0 U: [42,43) S: [-64,64)
-; ALL-NEXT:  Determining loop execution counts for: @ptrtoint_of_constantexpr_inttoptr
+; X64-LABEL: 'ptrtoint_of_constantexpr_inttoptr'
+; X64-NEXT:  Classifying expressions for: @ptrtoint_of_constantexpr_inttoptr
+; X64-NEXT:    %p0 = ptrtoint i8* inttoptr (i64 42 to i8*) to i64
+; X64-NEXT:    --> (ptrtoint i8* inttoptr (i64 42 to i8*) to i64) U: [42,43) S: [-64,64)
+; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_constantexpr_inttoptr
+;
+; X32-LABEL: 'ptrtoint_of_constantexpr_inttoptr'
+; X32-NEXT:  Classifying expressions for: @ptrtoint_of_constantexpr_inttoptr
+; X32-NEXT:    %p0 = ptrtoint i8* inttoptr (i64 42 to i8*) to i64
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* inttoptr (i64 42 to i8*) to i32) to i64) U: [42,43) S: [0,4294967296)
+; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_constantexpr_inttoptr
 ;
   %p0 = ptrtoint i8* inttoptr (i64 42 to i8*) to i64
   store i64 %p0, i64* %out0
@@ -190,7 +196,7 @@ define void @ptrtoint_of_gep(i8* %in, i64* %out0) {
 ; X64-NEXT:    %in_adj = getelementptr inbounds i8, i8* %in, i64 42
 ; X64-NEXT:    --> (42 + %in)<nsw> U: [-9223372036854775766,-9223372036854775808) S: [-9223372036854775766,-9223372036854775808)
 ; X64-NEXT:    %p0 = ptrtoint i8* %in_adj to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* (42 + %in)<nsw> to i64) U: [-9223372036854775766,-9223372036854775808) S: [-9223372036854775766,-9223372036854775808)
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_gep
 ;
 ; X32-LABEL: 'ptrtoint_of_gep'
@@ -198,7 +204,7 @@ define void @ptrtoint_of_gep(i8* %in, i64* %out0) {
 ; X32-NEXT:    %in_adj = getelementptr inbounds i8, i8* %in, i64 42
 ; X32-NEXT:    --> (42 + %in)<nsw> U: [-2147483606,-2147483648) S: [-2147483606,-2147483648)
 ; X32-NEXT:    %p0 = ptrtoint i8* %in_adj to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* (42 + %in)<nsw> to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_gep
 ;
   %in_adj = getelementptr inbounds i8, i8* %in, i64 42
@@ -220,7 +226,7 @@ define void @ptrtoint_of_addrec(i32* %in, i32 %count) {
 ; X64-NEXT:    %i7 = getelementptr inbounds i32, i32* %in, i64 %i6
 ; X64-NEXT:    --> {%in,+,4}<nsw><%loop> U: full-set S: full-set Exits: (-4 + (4 * (zext i32 %count to i64))<nuw><nsw> + %in) LoopDispositions: { %loop: Computable }
 ; X64-NEXT:    %i8 = ptrtoint i32* %i7 to i64
-; X64-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; X64-NEXT:    --> (ptrtoint i32* {%in,+,4}<nsw><%loop> to i64) U: full-set S: full-set Exits: (ptrtoint i32* (-4 + (4 * (zext i32 %count to i64))<nuw><nsw> + %in) to i64) LoopDispositions: { %loop: Computable }
 ; X64-NEXT:    %i9 = add nuw nsw i64 %i6, 1
 ; X64-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: (zext i32 %count to i64) LoopDispositions: { %loop: Computable }
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_addrec
@@ -239,7 +245,7 @@ define void @ptrtoint_of_addrec(i32* %in, i32 %count) {
 ; X32-NEXT:    %i7 = getelementptr inbounds i32, i32* %in, i64 %i6
 ; X32-NEXT:    --> {%in,+,4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %in) LoopDispositions: { %loop: Computable }
 ; X32-NEXT:    %i8 = ptrtoint i32* %i7 to i64
-; X32-NEXT:    --> %i8 U: [0,4294967296) S: [-4294967296,4294967296) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; X32-NEXT:    --> (zext i32 (ptrtoint i32* {%in,+,4}<%loop> to i32) to i64) U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 (ptrtoint i32* (-4 + (4 * %count) + %in) to i32) to i64) LoopDispositions: { %loop: Computable }
 ; X32-NEXT:    %i9 = add nuw nsw i64 %i6, 1
 ; X32-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: (zext i32 %count to i64) LoopDispositions: { %loop: Computable }
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_addrec
@@ -274,7 +280,7 @@ define void @ptrtoint_of_umax(i8* %in0, i8* %in1, i64* %out0) {
 ; X64-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X64-NEXT:    --> (%in0 umax %in1) U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* (%in0 umax %in1) to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_umax
 ;
 ; X32-LABEL: 'ptrtoint_of_umax'
@@ -282,7 +288,7 @@ define void @ptrtoint_of_umax(i8* %in0, i8* %in1, i64* %out0) {
 ; X32-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X32-NEXT:    --> (%in0 umax %in1) U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* (%in0 umax %in1) to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_umax
 ;
   %c = icmp uge i8* %in0, %in1
@@ -298,7 +304,7 @@ define void @ptrtoint_of_smax(i8* %in0, i8* %in1, i64* %out0) {
 ; X64-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X64-NEXT:    --> (%in0 smax %in1) U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* (%in0 smax %in1) to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_smax
 ;
 ; X32-LABEL: 'ptrtoint_of_smax'
@@ -306,7 +312,7 @@ define void @ptrtoint_of_smax(i8* %in0, i8* %in1, i64* %out0) {
 ; X32-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X32-NEXT:    --> (%in0 smax %in1) U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* (%in0 smax %in1) to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_smax
 ;
   %c = icmp sge i8* %in0, %in1
@@ -322,7 +328,7 @@ define void @ptrtoint_of_umin(i8* %in0, i8* %in1, i64* %out0) {
 ; X64-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X64-NEXT:    --> (%in0 umin %in1) U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* (%in0 umin %in1) to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_umin
 ;
 ; X32-LABEL: 'ptrtoint_of_umin'
@@ -330,7 +336,7 @@ define void @ptrtoint_of_umin(i8* %in0, i8* %in1, i64* %out0) {
 ; X32-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X32-NEXT:    --> (%in0 umin %in1) U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* (%in0 umin %in1) to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_umin
 ;
   %c = icmp ule i8* %in0, %in1
@@ -346,7 +352,7 @@ define void @ptrtoint_of_smin(i8* %in0, i8* %in1, i64* %out0) {
 ; X64-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X64-NEXT:    --> (%in0 smin %in1) U: full-set S: full-set
 ; X64-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X64-NEXT:    --> %p0 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* (%in0 smin %in1) to i64) U: full-set S: full-set
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_smin
 ;
 ; X32-LABEL: 'ptrtoint_of_smin'
@@ -354,7 +360,7 @@ define void @ptrtoint_of_smin(i8* %in0, i8* %in1, i64* %out0) {
 ; X32-NEXT:    %s = select i1 %c, i8* %in0, i8* %in1
 ; X32-NEXT:    --> (%in0 smin %in1) U: full-set S: full-set
 ; X32-NEXT:    %p0 = ptrtoint i8* %s to i64
-; X32-NEXT:    --> %p0 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* (%in0 smin %in1) to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_smin
 ;
   %c = icmp sle i8* %in0, %in1
@@ -372,17 +378,17 @@ define void @pr46786_c26_char(i8* %arg, i8* %arg1, i8* %arg2) {
 ; X64-LABEL: 'pr46786_c26_char'
 ; X64-NEXT:  Classifying expressions for: @pr46786_c26_char
 ; X64-NEXT:    %i4 = ptrtoint i8* %arg to i64
-; X64-NEXT:    --> %i4 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* %arg to i64) U: full-set S: full-set
 ; X64-NEXT:    %i7 = phi i8* [ %arg, %bb3 ], [ %i14, %bb6 ]
 ; X64-NEXT:    --> {%arg,+,1}<nuw><%bb6> U: full-set S: full-set Exits: (-1 + %arg1) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i8 = load i8, i8* %i7, align 1
 ; X64-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X64-NEXT:    %i9 = ptrtoint i8* %i7 to i64
-; X64-NEXT:    --> %i9 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> (ptrtoint i8* {%arg,+,1}<nuw><%bb6> to i64) U: full-set S: full-set Exits: (ptrtoint i8* (-1 + %arg1) to i64) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i10 = sub i64 %i9, %i4
-; X64-NEXT:    --> ((-1 * %i4) + %i9) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> ((-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* {%arg,+,1}<nuw><%bb6> to i64)) U: full-set S: full-set Exits: ((-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* (-1 + %arg1) to i64)) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i11 = getelementptr inbounds i8, i8* %arg2, i64 %i10
-; X64-NEXT:    --> ((-1 * %i4) + %i9 + %arg2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> ((-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* {%arg,+,1}<nuw><%bb6> to i64) + %arg2) U: full-set S: full-set Exits: ((-1 * (ptrtoint i8* %arg to i64)) + (ptrtoint i8* (-1 + %arg1) to i64) + %arg2) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i12 = load i8, i8* %i11, align 1
 ; X64-NEXT:    --> %i12 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X64-NEXT:    %i13 = add i8 %i12, %i8
@@ -399,17 +405,17 @@ define void @pr46786_c26_char(i8* %arg, i8* %arg1, i8* %arg2) {
 ; X32-LABEL: 'pr46786_c26_char'
 ; X32-NEXT:  Classifying expressions for: @pr46786_c26_char
 ; X32-NEXT:    %i4 = ptrtoint i8* %arg to i64
-; X32-NEXT:    --> %i4 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* %arg to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:    %i7 = phi i8* [ %arg, %bb3 ], [ %i14, %bb6 ]
 ; X32-NEXT:    --> {%arg,+,1}<nuw><%bb6> U: full-set S: full-set Exits: (-1 + %arg1) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i8 = load i8, i8* %i7, align 1
 ; X32-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X32-NEXT:    %i9 = ptrtoint i8* %i7 to i64
-; X32-NEXT:    --> %i9 U: [0,4294967296) S: [-4294967296,4294967296) Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* {%arg,+,1}<nuw><%bb6> to i32) to i64) U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 (ptrtoint i8* (-1 + %arg1) to i32) to i64) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i10 = sub i64 %i9, %i4
-; X32-NEXT:    --> ((-1 * %i4)<nsw> + %i9) U: [-4294967295,4294967296) S: [-8589934591,8589934592) Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> ((zext i32 (ptrtoint i8* {%arg,+,1}<nuw><%bb6> to i32) to i64) + (-1 * (zext i32 (ptrtoint i8* %arg to i32) to i64))<nsw>) U: [-4294967295,4294967296) S: [-4294967295,4294967296) Exits: ((zext i32 (ptrtoint i8* (-1 + %arg1) to i32) to i64) + (-1 * (zext i32 (ptrtoint i8* %arg to i32) to i64))<nsw>) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i11 = getelementptr inbounds i8, i8* %arg2, i64 %i10
-; X32-NEXT:    --> ((trunc i64 %i9 to i32) + (-1 * (trunc i64 %i4 to i32)) + %arg2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> ((-1 * (ptrtoint i8* %arg to i32)) + (ptrtoint i8* {%arg,+,1}<nuw><%bb6> to i32) + %arg2) U: full-set S: full-set Exits: ((-1 * (ptrtoint i8* %arg to i32)) + (ptrtoint i8* (-1 + %arg1) to i32) + %arg2) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i12 = load i8, i8* %i11, align 1
 ; X32-NEXT:    --> %i12 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X32-NEXT:    %i13 = add i8 %i12, %i8
@@ -457,19 +463,19 @@ define void @pr46786_c26_int(i32* %arg, i32* %arg1, i32* %arg2) {
 ; X64-LABEL: 'pr46786_c26_int'
 ; X64-NEXT:  Classifying expressions for: @pr46786_c26_int
 ; X64-NEXT:    %i4 = ptrtoint i32* %arg to i64
-; X64-NEXT:    --> %i4 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i32* %arg to i64) U: full-set S: full-set
 ; X64-NEXT:    %i7 = phi i32* [ %arg, %bb3 ], [ %i15, %bb6 ]
 ; X64-NEXT:    --> {%arg,+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i8 = load i32, i32* %i7, align 4
 ; X64-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X64-NEXT:    %i9 = ptrtoint i32* %i7 to i64
-; X64-NEXT:    --> %i9 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64) U: full-set S: full-set Exits: (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i10 = sub i64 %i9, %i4
-; X64-NEXT:    --> ((-1 * %i4) + %i9) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64)) U: full-set S: full-set Exits: ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64)) LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i11 = ashr exact i64 %i10, 2
-; X64-NEXT:    --> (((((-1 * %i4) + %i9) smax ((-1 * %i9) + %i4)) /u 4) * (1 smin (-1 smax ((-1 * %i4) + %i9))))<nsw> U: [-4611686018427387903,4611686018427387904) S: [-4611686018427387903,4611686018427387904) Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> (((((-1 * (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64)) + (ptrtoint i32* %arg to i64)) smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64))) /u 4) * (1 smin (-1 smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64)))))<nsw> U: [-4611686018427387903,4611686018427387904) S: [-4611686018427387903,4611686018427387904) Exits: (((((-1 * (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64)) + (ptrtoint i32* %arg to i64)) smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64))) /u 4) * (1 smin (-1 smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64)))))<nsw> LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i12 = getelementptr inbounds i32, i32* %arg2, i64 %i11
-; X64-NEXT:    --> ((4 * ((((-1 * %i4) + %i9) smax ((-1 * %i9) + %i4)) /u 4) * (1 smin (-1 smax ((-1 * %i4) + %i9)))) + %arg2)<nsw> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X64-NEXT:    --> ((4 * ((((-1 * (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64)) + (ptrtoint i32* %arg to i64)) smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64))) /u 4) * (1 smin (-1 smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i64))))) + %arg2)<nsw> U: full-set S: full-set Exits: ((4 * ((((-1 * (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64)) + (ptrtoint i32* %arg to i64)) smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64))) /u 4) * (1 smin (-1 smax ((-1 * (ptrtoint i32* %arg to i64)) + (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i64))))) + %arg2)<nsw> LoopDispositions: { %bb6: Computable }
 ; X64-NEXT:    %i13 = load i32, i32* %i12, align 4
 ; X64-NEXT:    --> %i13 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X64-NEXT:    %i14 = add nsw i32 %i13, %i8
@@ -486,19 +492,19 @@ define void @pr46786_c26_int(i32* %arg, i32* %arg1, i32* %arg2) {
 ; X32-LABEL: 'pr46786_c26_int'
 ; X32-NEXT:  Classifying expressions for: @pr46786_c26_int
 ; X32-NEXT:    %i4 = ptrtoint i32* %arg to i64
-; X32-NEXT:    --> %i4 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i32* %arg to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:    %i7 = phi i32* [ %arg, %bb3 ], [ %i15, %bb6 ]
 ; X32-NEXT:    --> {%arg,+,4}<nuw><%bb6> U: full-set S: full-set Exits: ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i8 = load i32, i32* %i7, align 4
 ; X32-NEXT:    --> %i8 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X32-NEXT:    %i9 = ptrtoint i32* %i7 to i64
-; X32-NEXT:    --> %i9 U: [0,4294967296) S: [-4294967296,4294967296) Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> (zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64) U: [0,4294967296) S: [0,4294967296) Exits: (zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i10 = sub i64 %i9, %i4
-; X32-NEXT:    --> ((-1 * %i4)<nsw> + %i9) U: [-4294967295,4294967296) S: [-8589934591,8589934592) Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> ((zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>) U: [-4294967295,4294967296) S: [-4294967295,4294967296) Exits: ((zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>) LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i11 = ashr exact i64 %i10, 2
-; X32-NEXT:    --> (((((-1 * %i4)<nsw> + %i9) smax ((-1 * %i9)<nsw> + %i4)) /u 4) * (1 smin (-1 smax ((-1 * %i4)<nsw> + %i9))))<nsw> U: [-4611686018427387903,4611686018427387904) S: [-4611686018427387903,4611686018427387904) Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> (((((zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>) smax ((zext i32 (ptrtoint i32* %arg to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64))<nsw>)) /u 4) * (1 smin (-1 smax ((zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>))))<nsw> U: [-4611686018427387903,4611686018427387904) S: [-4611686018427387903,4611686018427387904) Exits: (((((zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>) smax ((zext i32 (ptrtoint i32* %arg to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64))<nsw>)) /u 4) * (1 smin (-1 smax ((zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>))))<nsw> LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i12 = getelementptr inbounds i32, i32* %arg2, i64 %i11
-; X32-NEXT:    --> ((4 * (trunc i64 (((((-1 * %i4)<nsw> + %i9) smax ((-1 * %i9)<nsw> + %i4)) /u 4) * (1 smin (-1 smax ((-1 * %i4)<nsw> + %i9))))<nsw> to i32))<nsw> + %arg2)<nsw> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
+; X32-NEXT:    --> ((4 * (trunc i64 (((((zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>) smax ((zext i32 (ptrtoint i32* %arg to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64))<nsw>)) /u 4) * (1 smin (-1 smax ((zext i32 (ptrtoint i32* {%arg,+,4}<nuw><%bb6> to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>))))<nsw> to i32))<nsw> + %arg2)<nsw> U: full-set S: full-set Exits: ((4 * (trunc i64 (((((zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>) smax ((zext i32 (ptrtoint i32* %arg to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64))<nsw>)) /u 4) * (1 smin (-1 smax ((zext i32 (ptrtoint i32* ((4 * ((-4 + (-1 * %arg) + %arg1) /u 4))<nuw> + %arg) to i32) to i64) + (-1 * (zext i32 (ptrtoint i32* %arg to i32) to i64))<nsw>))))<nsw> to i32))<nsw> + %arg2)<nsw> LoopDispositions: { %bb6: Computable }
 ; X32-NEXT:    %i13 = load i32, i32* %i12, align 4
 ; X32-NEXT:    --> %i13 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb6: Variant }
 ; X32-NEXT:    %i14 = add nsw i32 %i13, %i8
@@ -543,9 +549,9 @@ define void @ptrtoint_of_integer(i8* %arg, i64 %arg1, i1 %arg2) local_unnamed_ad
 ; X64-LABEL: 'ptrtoint_of_integer'
 ; X64-NEXT:  Classifying expressions for: @ptrtoint_of_integer
 ; X64-NEXT:    %i4 = ptrtoint i8* %arg to i64
-; X64-NEXT:    --> %i4 U: full-set S: full-set
+; X64-NEXT:    --> (ptrtoint i8* %arg to i64) U: full-set S: full-set
 ; X64-NEXT:    %i6 = sub i64 %i4, %arg1
-; X64-NEXT:    --> ((-1 * %arg1) + %i4) U: full-set S: full-set
+; X64-NEXT:    --> ((-1 * %arg1) + (ptrtoint i8* %arg to i64)) U: full-set S: full-set
 ; X64-NEXT:    %i9 = phi i64 [ 1, %bb7 ], [ %i11, %bb10 ]
 ; X64-NEXT:    --> {1,+,1}<nuw><%bb8> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %bb8: Computable }
 ; X64-NEXT:    %i11 = add nuw i64 %i9, 1
@@ -553,16 +559,16 @@ define void @ptrtoint_of_integer(i8* %arg, i64 %arg1, i1 %arg2) local_unnamed_ad
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_integer
 ; X64-NEXT:  Loop %bb8: <multiple exits> Unpredictable backedge-taken count.
 ; X64-NEXT:    exit count for bb8: ***COULDNOTCOMPUTE***
-; X64-NEXT:    exit count for bb10: (-2 + (-1 * %arg1) + %i4)
+; X64-NEXT:    exit count for bb10: (-2 + (-1 * %arg1) + (ptrtoint i8* %arg to i64))
 ; X64-NEXT:  Loop %bb8: max backedge-taken count is -1
 ; X64-NEXT:  Loop %bb8: Unpredictable predicated backedge-taken count.
 ;
 ; X32-LABEL: 'ptrtoint_of_integer'
 ; X32-NEXT:  Classifying expressions for: @ptrtoint_of_integer
 ; X32-NEXT:    %i4 = ptrtoint i8* %arg to i64
-; X32-NEXT:    --> %i4 U: [0,4294967296) S: [-4294967296,4294967296)
+; X32-NEXT:    --> (zext i32 (ptrtoint i8* %arg to i32) to i64) U: [0,4294967296) S: [0,4294967296)
 ; X32-NEXT:    %i6 = sub i64 %i4, %arg1
-; X32-NEXT:    --> ((-1 * %arg1) + %i4) U: full-set S: full-set
+; X32-NEXT:    --> ((zext i32 (ptrtoint i8* %arg to i32) to i64) + (-1 * %arg1)) U: full-set S: full-set
 ; X32-NEXT:    %i9 = phi i64 [ 1, %bb7 ], [ %i11, %bb10 ]
 ; X32-NEXT:    --> {1,+,1}<nuw><%bb8> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %bb8: Computable }
 ; X32-NEXT:    %i11 = add nuw i64 %i9, 1
@@ -570,7 +576,7 @@ define void @ptrtoint_of_integer(i8* %arg, i64 %arg1, i1 %arg2) local_unnamed_ad
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_integer
 ; X32-NEXT:  Loop %bb8: <multiple exits> Unpredictable backedge-taken count.
 ; X32-NEXT:    exit count for bb8: ***COULDNOTCOMPUTE***
-; X32-NEXT:    exit count for bb10: (-2 + (-1 * %arg1) + %i4)
+; X32-NEXT:    exit count for bb10: (-2 + (zext i32 (ptrtoint i8* %arg to i32) to i64) + (-1 * %arg1))
 ; X32-NEXT:  Loop %bb8: max backedge-taken count is -1
 ; X32-NEXT:  Loop %bb8: Unpredictable predicated backedge-taken count.
 ;

diff  --git a/llvm/test/Other/constant-fold-gep.ll b/llvm/test/Other/constant-fold-gep.ll
index 8be214713d5c..ec39c3229b2d 100644
--- a/llvm/test/Other/constant-fold-gep.ll
+++ b/llvm/test/Other/constant-fold-gep.ll
@@ -313,31 +313,31 @@ define i1* @hoo1() nounwind {
 ; TO: }
 ; SCEV: Classifying expressions for: @fa
 ; SCEV:   %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2310) to i64
-; SCEV:   -->  (2310 * sizeof(double))
+; SCEV:   -->  18480
 ; SCEV: Classifying expressions for: @fb
 ; SCEV:   %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) to i64
-; SCEV:   -->  alignof(double)
+; SCEV:   -->  8
 ; SCEV: Classifying expressions for: @fc
 ; SCEV:   %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 2) to i64
-; SCEV:   -->  (2 * sizeof(double))
+; SCEV:   -->  16
 ; SCEV: Classifying expressions for: @fd
 ; SCEV:   %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double, double* null, i32 1) to i64), i64 11) to i64
-; SCEV:   -->  (11 * sizeof(double))
+; SCEV:   -->  88
 ; SCEV: Classifying expressions for: @fe
 ; SCEV:   %t = bitcast i64 ptrtoint (double* getelementptr ({ double, float, double, double }, { double, float, double, double }* null, i64 0, i32 2) to i64) to i64
-; SCEV:   -->  offsetof({ double, float, double, double }, 2)
+; SCEV:   -->  16
 ; SCEV: Classifying expressions for: @ff
 ; SCEV:   %t = bitcast i64 1 to i64
 ; SCEV:   -->  1
 ; SCEV: Classifying expressions for: @fg
 ; SCEV:   %t = bitcast i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) to i64
-; SCEV:   -->  alignof(double)
+; SCEV:   -->  8
 ; SCEV: Classifying expressions for: @fh
 ; SCEV:   %t = bitcast i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64) to i64
-; SCEV:   -->  sizeof(i1*)
+; SCEV:   --> 8
 ; SCEV: Classifying expressions for: @fi
 ; SCEV:   %t = bitcast i64 ptrtoint (i1** getelementptr ({ i1, i1* }, { i1, i1* }* null, i64 0, i32 1) to i64) to i64
-; SCEV:   -->  alignof(i1*)
+; SCEV:   --> 8
 
 define i64 @fa() nounwind {
   %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}, {[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64
@@ -408,13 +408,13 @@ define i64 @fi() nounwind {
 ; TO: }
 ; SCEV: Classifying expressions for: @fM
 ; SCEV:   %t = bitcast i64* getelementptr (i64, i64* null, i32 1) to i64*
-; SCEV:   -->  8
+; SCEV:    --> 8
 ; SCEV: Classifying expressions for: @fN
 ; SCEV:   %t = bitcast i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1) to i64*
-; SCEV:   -->  8
+; SCEV:   --> 8
 ; SCEV: Classifying expressions for: @fO
 ; SCEV:   %t = bitcast i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1) to i64*
-; SCEV:   -->  8
+; SCEV:   --> 8
 
 define i64* @fM() nounwind {
   %t = bitcast i64* getelementptr (i64, i64* null, i32 1) to i64*

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll b/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
index 245b38325565..8a07a49303d2 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
@@ -59,20 +59,20 @@ define void @_Z15IntegerToStringjjR7Vector2(i32 %i, i32 %radix, %struct.Vector2*
 ; CHECK-NEXT:    [[TMP14:%.*]] = load i16*, i16** [[MBEGIN]], align 8
 ; CHECK-NEXT:    [[TMP48:%.*]] = zext i32 [[TMP16]] to i64
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i16, i16* [[TMP14]], i64 [[TMP48]]
-; CHECK-NEXT:    [[TMP3:%.*]] = shl nuw i64 [[IDX_EXT21]], 1
+; CHECK-NEXT:    [[SCEVGEP1:%.*]] = bitcast i16* [[SCEVGEP]] to i8*
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[LSR_IV8:%.*]] = phi [33 x i16]* [ [[TMP4:%.*]], [[FOR_BODY]] ], [ [[TMP2]], [[FOR_BODY_LR_PH]] ]
-; CHECK-NEXT:    [[LSR_IV2:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[TMP3]], [[FOR_BODY_LR_PH]] ]
-; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i16* [ [[SCEVGEP1:%.*]], [[FOR_BODY]] ], [ [[SCEVGEP]], [[FOR_BODY_LR_PH]] ]
+; CHECK-NEXT:    [[LSR_IV8:%.*]] = phi [33 x i16]* [ [[TMP3:%.*]], [[FOR_BODY]] ], [ [[TMP2]], [[FOR_BODY_LR_PH]] ]
+; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_LR_PH]] ]
 ; CHECK-NEXT:    [[LSR_IV810:%.*]] = bitcast [33 x i16]* [[LSR_IV8]] to i16*
+; CHECK-NEXT:    [[UGLYGEP:%.*]] = getelementptr i8, i8* [[SCEVGEP1]], i64 [[LSR_IV]]
+; CHECK-NEXT:    [[UGLYGEP2:%.*]] = bitcast i8* [[UGLYGEP]] to i16*
 ; CHECK-NEXT:    [[TMP29:%.*]] = load i16, i16* [[LSR_IV810]], align 2
-; CHECK-NEXT:    store i16 [[TMP29]], i16* [[LSR_IV]], align 2
-; CHECK-NEXT:    [[SCEVGEP1]] = getelementptr i16, i16* [[LSR_IV]], i64 1
-; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV2]], -2
+; CHECK-NEXT:    store i16 [[TMP29]], i16* [[UGLYGEP2]], align 2
+; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], 2
 ; CHECK-NEXT:    [[LSR_IV_NEXT3:%.*]] = inttoptr i64 [[LSR_IV_NEXT]] to i16*
 ; CHECK-NEXT:    [[SCEVGEP9:%.*]] = getelementptr [33 x i16], [33 x i16]* [[LSR_IV8]], i64 0, i64 1
-; CHECK-NEXT:    [[TMP4]] = bitcast i16* [[SCEVGEP9]] to [33 x i16]*
+; CHECK-NEXT:    [[TMP3]] = bitcast i16* [[SCEVGEP9]] to [33 x i16]*
 ; CHECK-NEXT:    [[CMP27:%.*]] = icmp eq i16* [[LSR_IV_NEXT3]], null
 ; CHECK-NEXT:    br i1 [[CMP27]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]
 ; CHECK:       for.end.loopexit:

diff  --git a/polly/include/polly/Support/SCEVAffinator.h b/polly/include/polly/Support/SCEVAffinator.h
index 018630a0378f..f5d771188571 100644
--- a/polly/include/polly/Support/SCEVAffinator.h
+++ b/polly/include/polly/Support/SCEVAffinator.h
@@ -99,6 +99,7 @@ struct SCEVAffinator : public llvm::SCEVVisitor<SCEVAffinator, PWACtx> {
 
   PWACtx visit(const llvm::SCEV *E);
   PWACtx visitConstant(const llvm::SCEVConstant *E);
+  PWACtx visitPtrToIntExpr(const llvm::SCEVPtrToIntExpr *E);
   PWACtx visitTruncateExpr(const llvm::SCEVTruncateExpr *E);
   PWACtx visitZeroExtendExpr(const llvm::SCEVZeroExtendExpr *E);
   PWACtx visitSignExtendExpr(const llvm::SCEVSignExtendExpr *E);

diff  --git a/polly/lib/Support/SCEVAffinator.cpp b/polly/lib/Support/SCEVAffinator.cpp
index 2c7dc8fa415f..9d2e7d9a6fcb 100644
--- a/polly/lib/Support/SCEVAffinator.cpp
+++ b/polly/lib/Support/SCEVAffinator.cpp
@@ -266,6 +266,10 @@ PWACtx SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
       isl::manage(isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v))));
 }
 
+PWACtx SCEVAffinator::visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
+  return visit(Expr->getOperand(0));
+}
+
 PWACtx SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
   // Truncate operations are basically modulo operations, thus we can
   // model them that way. However, for large types we assume the operand
@@ -538,8 +542,6 @@ PWACtx SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
     switch (I->getOpcode()) {
     case Instruction::IntToPtr:
       return visit(SE.getSCEVAtScope(I->getOperand(0), getScope()));
-    case Instruction::PtrToInt:
-      return visit(SE.getSCEVAtScope(I->getOperand(0), getScope()));
     case Instruction::SDiv:
       return visitSDivInstruction(I);
     case Instruction::SRem:

diff  --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp
index 501d7645831c..94b55167a9b4 100644
--- a/polly/lib/Support/SCEVValidator.cpp
+++ b/polly/lib/Support/SCEVValidator.cpp
@@ -161,6 +161,10 @@ struct SCEVValidator
     return ValidatorResult(SCEVType::PARAM, Expr);
   }
 
+  class ValidatorResult visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
+    return visit(Expr->getOperand());
+  }
+
   class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
     return visitZeroExtendOrTruncateExpr(Expr, Expr->getOperand());
   }
@@ -444,8 +448,6 @@ struct SCEVValidator
       switch (I->getOpcode()) {
       case Instruction::IntToPtr:
         return visit(SE.getSCEVAtScope(I->getOperand(0), Scope));
-      case Instruction::PtrToInt:
-        return visit(SE.getSCEVAtScope(I->getOperand(0), Scope));
       case Instruction::Load:
         return visitLoadInstruction(I, Expr);
       case Instruction::SDiv:

diff  --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp
index bf2d82e44660..a2010476b7be 100644
--- a/polly/lib/Support/ScopHelper.cpp
+++ b/polly/lib/Support/ScopHelper.cpp
@@ -341,6 +341,9 @@ struct ScopExpander : SCEVVisitor<ScopExpander, const SCEV *> {
   ///
   ///{
   const SCEV *visitConstant(const SCEVConstant *E) { return E; }
+  const SCEV *visitPtrToIntExpr(const SCEVPtrToIntExpr *E) {
+    return SE.getPtrToIntExpr(visit(E->getOperand()), E->getType());
+  }
   const SCEV *visitTruncateExpr(const SCEVTruncateExpr *E) {
     return SE.getTruncateExpr(visit(E->getOperand()), E->getType());
   }

diff  --git a/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll b/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
index a673ac77f4fb..7e69560d0df8 100644
--- a/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
+++ b/polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
@@ -1,7 +1,12 @@
 ; RUN: opt %loadPolly -polly-codegen -S < %s | FileCheck %s
 ;
-; CHECK:      polly.split_new_and_old:
-; CHECK-NEXT:   %pollysub.ptr.lhs.cast263 = ptrtoint i8* inttoptr (i64 1 to i8*) to i64
+; CHECK:      if.then260:
+; CHECK-NEXT:   %p.4 = getelementptr inbounds i8, i8* null, i64 1
+; CHECK-NEXT:   %sub.ptr.lhs.cast263 = ptrtoint i8* %p.4 to i64
+; CHECK-NEXT:   %sub.ptr.sub265 = sub i64 %sub.ptr.lhs.cast263, 0
+; CHECK-NEXT:   %div = udiv i64 0, %sub.ptr.sub265
+; CHECK-NEXT:   %cmp268 = icmp ult i64 0, %div
+; CHECK-NEXT:   br i1 %cmp268, label %cond.true270, label %while.cond.region_exiting
 ;
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 

diff  --git a/polly/test/ScopInfo/int2ptr_ptr2int.ll b/polly/test/ScopInfo/int2ptr_ptr2int.ll
index 350e6401d1f5..9618ea068e1b 100644
--- a/polly/test/ScopInfo/int2ptr_ptr2int.ll
+++ b/polly/test/ScopInfo/int2ptr_ptr2int.ll
@@ -17,21 +17,24 @@
 ; CHECK-NEXT:       [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
 ;
 ; IR:      polly.stmt.for.body:
-; IR-NEXT:   %p_tmp = ptrtoint i64* %scevgep to i64
-; IR-NEXT:   %p_add = add nsw i64 %p_tmp, 1
-; IR-NEXT:   %p_tmp1 = inttoptr i64 %[[r1:[a-zA-Z0-9]*]] to i64*
+; IR-NEXT:   %p_tmp1 = inttoptr i64 %0 to i64*
 ; IR-NEXT:   %p_add.ptr2 = getelementptr inbounds i64, i64* %p_tmp1, i64 1
 ; IR-NEXT:   %p_tmp2 = ptrtoint i64* %p_add.ptr2 to i64
 ; IR-NEXT:   %p_arrayidx = getelementptr inbounds i64, i64* %A, i64 %p_tmp2
-; IR-NEXT:   %tmp3_p_scalar_ = load i64, i64* %p_arrayidx
-; IR-NEXT:   %p_arrayidx3 = getelementptr inbounds i64, i64* %A, i64 %p_add
-; IR-NEXT:   %tmp4_p_scalar_ = load i64, i64* %p_arrayidx3
+; IR-NEXT:   %tmp3_p_scalar_ = load i64, i64* %p_arrayidx, align 8, !alias.scope !0, !noalias !2
+; IR-NEXT:   %tmp4_p_scalar_ = load i64, i64* %scevgep1, align 8, !alias.scope !0, !noalias !2
 ; IR-NEXT:   %p_add4 = add nsw i64 %tmp4_p_scalar_, %tmp3_p_scalar_
-; IR-NEXT:   store i64 %p_add4, i64* %p_arrayidx3
+; IR-NEXT:   store i64 %p_add4, i64* %scevgep1, align 8, !alias.scope !0, !noalias !2
+; IR-NEXT:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; IR-NEXT:   %polly.loop_cond = icmp sle i64 %polly.indvar_next, 99
+; IR-NEXT:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
 ;
 ; IR:      polly.loop_preheader:
+; IR-NEXT:   %0 = add i64 %val, 1
 ; IR-NEXT:   %scevgep = getelementptr i64, i64* %ptr, i32 1
-; IR-NEXT:   %[[r1]] = add i64 %val, 1
+; IR-NEXT:   %1 = ptrtoint i64* %scevgep to i32
+; IR-NEXT:   %2 = add i32 %1, 1
+; IR-NEXT:   %scevgep1 = getelementptr i64, i64* %A, i32 %2
 ; IR-NEXT:   br label %polly.loop_header
 ;
 target datalayout = "e-p:32:32:32-m:e-i64:64-f80:128-n8:16:32:64-S128"

diff  --git a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll
index 951f4930b68c..894f5f308a07 100644
--- a/polly/test/ScopInfo/int2ptr_ptr2int_2.ll
+++ b/polly/test/ScopInfo/int2ptr_ptr2int_2.ll
@@ -21,19 +21,21 @@
 ; CHECK-NEXT:       [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
 ;
 ; IR:      polly.stmt.for.body:
-; IR-NEXT:  %p_tmp = ptrtoint i64* %scevgep to i16
-; IR-NEXT:  %p_add = add nsw i16 %p_tmp, 1
-; IR-NEXT:  %p_arrayidx3 = getelementptr inbounds i64, i64* %A, i16 %p_add
-; IR-NEXT:  %tmp4_p_scalar_ = load i64, i64* %p_arrayidx3
-; IR-NEXT:  %p_add4 = add nsw i64 %tmp4_p_scalar_, %polly.preload.tmp3.merge
-; IR-NEXT:  store i64 %p_add4, i64* %p_arrayidx3
+; IR-NEXT:   %tmp4_p_scalar_ = load i64, i64* %scevgep13, align 8, !alias.scope !3, !noalias !4
+; IR-NEXT:   %p_add4 = add nsw i64 %tmp4_p_scalar_, %polly.preload.tmp3.merge
+; IR-NEXT:   store i64 %p_add4, i64* %scevgep13, align 8, !alias.scope !3, !noalias !4
+; IR-NEXT:   %polly.indvar_next = add nsw i64 %polly.indvar, 1
+; IR-NEXT:   %polly.loop_cond = icmp sle i64 %polly.indvar_next, 99
+; IR-NEXT:   br i1 %polly.loop_cond, label %polly.loop_header, label %polly.loop_exit
 ;
 ; IR:      polly.loop_preheader:
-; IR-NEXT:   %scevgep = getelementptr i64, i64* %ptr, i16 1
 ; IR-NEXT:   %35 = add i16 %val, 1
+; IR-NEXT:   %scevgep = getelementptr i64, i64* %ptr, i16 1
+; IR-NEXT:   %36 = ptrtoint i64* %scevgep to i16
+; IR-NEXT:   %37 = add i16 %36, 1
+; IR-NEXT:   %scevgep13 = getelementptr i64, i64* %A, i16 %37
 ; IR-NEXT:   br label %polly.loop_header
 ;
-;
 target datalayout = "e-p:16:16:16-m:e-i64:64-f80:128-n8:16:16:64-S128"
 
 define void @f(i64* %A, i64* %B, i64* %ptr, i16 %val) {


        


More information about the llvm-commits mailing list