191 changes: 172 additions & 19 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -1013,6 +1033,86 @@ 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, Depth);

assert((isa<SCEVNAryExpr>(Op) || isa<SCEVUnknown>(Op)) &&
"We can only gen an nary expression, or an unknown here.");

Type *IntPtrTy = getDataLayout().getIntPtrType(Op->getType());

// If the input operand is not an unknown (and thus is an nary expression),
// sink the cast to operands, so that the operation is performed on integers,
// and we eventually end up with just an ptrtoint(unknown).
if (const SCEVNAryExpr *NaryExpr = dyn_cast<SCEVNAryExpr>(Op)) {
SmallVector<const SCEV *, 2> NewOps;
NewOps.reserve(NaryExpr->getNumOperands());
for (const SCEV *Op : NaryExpr->operands())
NewOps.push_back(Op->getType()->isPointerTy()
? getPtrToIntExpr(Op, IntPtrTy, Depth + 1)
: Op);
const SCEV *NewNaryExpr = nullptr;
switch (SCEVTypes SCEVType = NaryExpr->getSCEVType()) {
case scAddExpr:
NewNaryExpr = getAddExpr(NewOps, NaryExpr->getNoWrapFlags(), Depth + 1);
break;
case scAddRecExpr:
NewNaryExpr =
getAddRecExpr(NewOps, cast<SCEVAddRecExpr>(NaryExpr)->getLoop(),
NaryExpr->getNoWrapFlags());
break;
case scUMaxExpr:
case scSMaxExpr:
case scUMinExpr:
case scSMinExpr:
NewNaryExpr = getMinMaxExpr(SCEVType, NewOps);
break;

case scMulExpr:
NewNaryExpr = getMulExpr(NewOps, NaryExpr->getNoWrapFlags(), Depth + 1);
break;
case scUDivExpr:
NewNaryExpr = getUDivExpr(NewOps[0], NewOps[1]);
break;
case scConstant:
case scTruncate:
case scZeroExtend:
case scSignExtend:
case scPtrToInt:
case scUnknown:
case scCouldNotCompute:
llvm_unreachable("We can't get these types here.");
}
return getTruncateOrZeroExtend(NewNaryExpr, Ty, Depth);
}

// 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.
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, Depth);
}

const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, Type *Ty,
unsigned Depth) {
assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) &&
Expand Down Expand Up @@ -3528,15 +3628,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));
}

Expand Down Expand Up @@ -5007,8 +5110,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.
Expand Down Expand Up @@ -5266,6 +5376,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()));
Expand Down Expand Up @@ -5471,6 +5584,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,
Expand Down Expand Up @@ -6077,6 +6195,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());
Expand Down Expand Up @@ -6412,6 +6531,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))) &&
Expand All @@ -6426,11 +6568,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));

Expand Down Expand Up @@ -8090,6 +8227,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()))
Expand Down Expand Up @@ -8397,6 +8541,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!");
}

Expand Down Expand Up @@ -11973,10 +12124,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);

Expand Down Expand Up @@ -12080,10 +12232,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
Expand Down
16 changes: 13 additions & 3 deletions llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions llvm/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
237 changes: 163 additions & 74 deletions llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll

Large diffs are not rendered by default.

134 changes: 70 additions & 64 deletions llvm/test/Analysis/ScalarEvolution/ptrtoint.ll

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions llvm/test/Other/constant-fold-gep.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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*
Expand Down
54 changes: 26 additions & 28 deletions llvm/test/Transforms/LoopStrengthReduce/X86/expander-crashes.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,42 @@ target triple = "x86_64-apple-macosx10.15.0"
define i64 @blam(%struct.hoge* %start, %struct.hoge* %end, %struct.hoge* %ptr.2) {
; CHECK-LABEL: @blam(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[END16:%.*]] = bitcast %struct.hoge* [[END:%.*]] to i8*
; CHECK-NEXT: [[START17:%.*]] = ptrtoint %struct.hoge* [[START:%.*]] to i64
; CHECK-NEXT: [[SCEVGEP12:%.*]] = getelementptr [[STRUCT_HOGE:%.*]], %struct.hoge* [[START]], i64 0, i32 3
; CHECK-NEXT: [[SCEVGEP1213:%.*]] = bitcast i32* [[SCEVGEP12]] to %struct.hoge*
; CHECK-NEXT: [[TMP0:%.*]] = sub i64 0, [[START17]]
; CHECK-NEXT: [[UGLYGEP18:%.*]] = getelementptr i8, i8* [[END16]], i64 [[TMP0]]
; CHECK-NEXT: [[UGLYGEP1819:%.*]] = bitcast i8* [[UGLYGEP18]] to %struct.hoge*
; CHECK-NEXT: [[START9:%.*]] = ptrtoint %struct.hoge* [[START:%.*]] to i64
; CHECK-NEXT: [[START6:%.*]] = bitcast %struct.hoge* [[START]] to i8*
; CHECK-NEXT: [[END8:%.*]] = bitcast %struct.hoge* [[END:%.*]] to i8*
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint %struct.hoge* [[START]] to i64
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[START9]]
; CHECK-NEXT: [[UGLYGEP10:%.*]] = getelementptr i8, i8* [[END8]], i64 [[TMP1]]
; CHECK-NEXT: br label [[LOOP_1_HEADER:%.*]]
; CHECK: loop.1.header:
; CHECK-NEXT: [[LSR_IV20:%.*]] = phi %struct.hoge* [ [[SCEVGEP21:%.*]], [[LOOP_1_HEADER]] ], [ [[UGLYGEP1819]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[LSR_IV14:%.*]] = phi %struct.hoge* [ [[SCEVGEP15:%.*]], [[LOOP_1_HEADER]] ], [ [[SCEVGEP1213]], [[ENTRY]] ]
; CHECK-NEXT: [[SCEVGEP15]] = getelementptr [[STRUCT_HOGE]], %struct.hoge* [[LSR_IV14]], i64 1
; CHECK-NEXT: [[SCEVGEP21]] = getelementptr [[STRUCT_HOGE]], %struct.hoge* [[LSR_IV20]], i64 -1
; CHECK-NEXT: [[EC:%.*]] = icmp eq %struct.hoge* [[SCEVGEP21]], null
; CHECK-NEXT: [[LSR_IV4:%.*]] = phi i64 [ [[LSR_IV_NEXT5:%.*]], [[LOOP_1_HEADER]] ], [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[LSR_IV_NEXT5]] = add i64 [[LSR_IV4]], -16
; CHECK-NEXT: [[SCEVGEP11:%.*]] = getelementptr i8, i8* [[UGLYGEP10]], i64 [[LSR_IV_NEXT5]]
; CHECK-NEXT: [[SCEVGEP1112:%.*]] = bitcast i8* [[SCEVGEP11]] to %struct.hoge*
; CHECK-NEXT: [[EC:%.*]] = icmp eq %struct.hoge* [[SCEVGEP1112]], null
; CHECK-NEXT: br i1 [[EC]], label [[LOOP_2_PH:%.*]], label [[LOOP_1_HEADER]]
; CHECK: loop.2.ph:
; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[TMP0]], [[LSR_IV_NEXT5]]
; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[LSR_IV_NEXT5]], -1
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, i8* [[START6]], i64 [[TMP3]]
; CHECK-NEXT: [[UGLYGEP7:%.*]] = bitcast i8* [[UGLYGEP]] to %struct.hoge*
; CHECK-NEXT: br label [[LOOP_2_HEADER:%.*]]
; CHECK: loop.2.header:
; CHECK-NEXT: [[LSR_IV3:%.*]] = phi %struct.hoge* [ [[SCEVGEP4:%.*]], [[LOOP_2_LATCH:%.*]] ], [ [[SCEVGEP15]], [[LOOP_2_PH]] ]
; CHECK-NEXT: [[LSR_IV310:%.*]] = bitcast %struct.hoge* [[LSR_IV3]] to i32*
; CHECK-NEXT: [[LSR_IV37:%.*]] = bitcast %struct.hoge* [[LSR_IV3]] to i8*
; CHECK-NEXT: [[UGLYGEP8:%.*]] = getelementptr i8, i8* [[LSR_IV37]], i64 -12
; CHECK-NEXT: [[UGLYGEP89:%.*]] = bitcast i8* [[UGLYGEP8]] to %struct.hoge*
; CHECK-NEXT: [[LSR_IV35:%.*]] = bitcast %struct.hoge* [[LSR_IV3]] to i8*
; CHECK-NEXT: [[TMP8:%.*]] = ptrtoint i32* [[LSR_IV310]] to i64
; CHECK-NEXT: call void @use.i64(i64 [[TMP8]])
; CHECK-NEXT: [[SCEVGEP11:%.*]] = getelementptr i32, i32* [[LSR_IV310]], i64 -1
; CHECK-NEXT: store i32 10, i32* [[SCEVGEP11]], align 8
; CHECK-NEXT: [[EC_2:%.*]] = icmp ugt %struct.hoge* [[UGLYGEP89]], [[PTR_2:%.*]]
; CHECK-NEXT: [[LSR_IV1:%.*]] = phi i64 [ [[LSR_IV_NEXT2:%.*]], [[LOOP_2_LATCH:%.*]] ], [ [[TMP2]], [[LOOP_2_PH]] ]
; CHECK-NEXT: [[IV2:%.*]] = phi %struct.hoge* [ [[IV2_NEXT:%.*]], [[LOOP_2_LATCH]] ], [ [[UGLYGEP7]], [[LOOP_2_PH]] ]
; CHECK-NEXT: [[IV23:%.*]] = bitcast %struct.hoge* [[IV2]] to i32*
; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[LSR_IV1]], 12
; CHECK-NEXT: call void @use.i64(i64 [[TMP4]])
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i32, i32* [[IV23]], i64 2
; CHECK-NEXT: store i32 10, i32* [[SCEVGEP]], align 8
; CHECK-NEXT: [[EC_2:%.*]] = icmp ugt %struct.hoge* [[IV2]], [[PTR_2:%.*]]
; CHECK-NEXT: br i1 [[EC_2]], label [[LOOP_2_EXIT:%.*]], label [[LOOP_2_LATCH]]
; CHECK: loop.2.latch:
; CHECK-NEXT: [[SCEVGEP4]] = getelementptr [[STRUCT_HOGE]], %struct.hoge* [[LSR_IV3]], i64 1
; CHECK-NEXT: [[IV2_NEXT]] = getelementptr inbounds [[STRUCT_HOGE:%.*]], %struct.hoge* [[IV2]], i64 1
; CHECK-NEXT: [[LSR_IV_NEXT2]] = add i64 [[LSR_IV1]], 16
; CHECK-NEXT: br label [[LOOP_2_HEADER]]
; CHECK: loop.2.exit:
; CHECK-NEXT: [[UGLYGEP:%.*]] = getelementptr i8, i8* [[LSR_IV35]], i64 -12
; CHECK-NEXT: [[UGLYGEP6:%.*]] = bitcast i8* [[UGLYGEP]] to %struct.hoge*
; CHECK-NEXT: [[IV2_CAST:%.*]] = ptrtoint %struct.hoge* [[UGLYGEP6]] to i64
; CHECK-NEXT: ret i64 [[IV2_CAST]]
; CHECK-NEXT: ret i64 [[LSR_IV1]]
;
entry:
br label %loop.1.header
Expand Down
16 changes: 8 additions & 8 deletions llvm/test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions polly/include/polly/Support/SCEVAffinator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions polly/lib/Support/SCEVAffinator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 4 additions & 2 deletions polly/lib/Support/SCEVValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions polly/lib/Support/ScopHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
9 changes: 7 additions & 2 deletions polly/test/Isl/CodeGen/ptrtoint_as_parameter.ll
Original file line number Diff line number Diff line change
@@ -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"

Expand Down
21 changes: 12 additions & 9 deletions polly/test/ScopInfo/int2ptr_ptr2int.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,25 @@
; 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 %14 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* %scevgep, 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* %scevgep, 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: %scevgep = getelementptr i64, i64* %ptr, i32 1
; IR-NEXT: %[[r1]] = add i64 %val, 1
; IR-NEXT: %14 = add i64 %val, 1
; IR-NEXT: %15 = ptrtoint i64* %ptr to i32
; IR-NEXT: %16 = add i32 %15, 9
; IR-NEXT: %scevgep = getelementptr i64, i64* %A, i32 %16
; 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"

Expand Down
23 changes: 12 additions & 11 deletions polly/test/ScopInfo/int2ptr_ptr2int_2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,28 @@
;
; CHECK: ReadAccess := [Reduction Type: NONE] [Scalar: 0]
; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_B[9 + val] };
; CHECK-NEXT: Execution Context: [val, ptr] -> { : val <= 32766 }
; CHECK-NEXT: Execution Context: [val, ptr] -> { : -4097 <= val <= 4086 }
;
; CHECK: ReadAccess := [Reduction Type: +] [Scalar: 0]
; CHECK-NEXT: [val, ptr] -> { Stmt_for_body[i0] -> MemRef_A[9 + ptr] };
; CHECK-NEXT: MustWriteAccess := [Reduction Type: +] [Scalar: 0]
; 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* %scevgep, 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* %scevgep, 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: %41 = add i16 %val, 1
; IR-NEXT: %42 = ptrtoint i64* %ptr to i16
; IR-NEXT: %43 = add i16 %42, 9
; IR-NEXT: %scevgep = getelementptr i64, i64* %A, i16 %43
; 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) {
Expand Down