aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/InstructionSimplify.cpp28
-rw-r--r--test/Transforms/InstSimplify/ptr_diff.ll11
2 files changed, 29 insertions, 10 deletions
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index e296215442..34ff64d900 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -667,9 +667,9 @@ Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
/// This is very similar to GetPointerBaseWithConstantOffset except it doesn't
/// follow non-inbounds geps. This allows it to remain usable for icmp ult/etc.
/// folding.
-static ConstantInt *stripAndComputeConstantOffsets(const DataLayout *TD,
- Value *&V) {
- assert(V->getType()->isPointerTy());
+static Constant *stripAndComputeConstantOffsets(const DataLayout *TD,
+ Value *&V) {
+ assert(V->getType()->getScalarType()->isPointerTy());
// Without DataLayout, just be conservative for now. Theoretically, more could
// be done in this case.
@@ -697,11 +697,16 @@ static ConstantInt *stripAndComputeConstantOffsets(const DataLayout *TD,
} else {
break;
}
- assert(V->getType()->isPointerTy() && "Unexpected operand type!");
+ assert(V->getType()->getScalarType()->isPointerTy() &&
+ "Unexpected operand type!");
} while (Visited.insert(V));
Type *IntPtrTy = TD->getIntPtrType(V->getContext());
- return cast<ConstantInt>(ConstantInt::get(IntPtrTy, Offset));
+ Constant *OffsetIntPtr = ConstantInt::get(IntPtrTy, Offset);
+ if (V->getType()->isVectorTy())
+ return ConstantVector::getSplat(V->getType()->getVectorNumElements(),
+ OffsetIntPtr);
+ return OffsetIntPtr;
}
/// \brief Compute the constant difference between two pointer values.
@@ -1758,8 +1763,8 @@ static Constant *computePointerICmp(const DataLayout *TD,
// numerous hazards. AliasAnalysis and its utilities rely on special rules
// governing loads and stores which don't apply to icmps. Also, AliasAnalysis
// doesn't need to guarantee pointer inequality when it says NoAlias.
- ConstantInt *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
- ConstantInt *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
+ Constant *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
+ Constant *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
// If LHS and RHS are related via constant offsets to the same base
// value, we can replace it with an icmp which just compares the offsets.
@@ -1799,11 +1804,14 @@ static Constant *computePointerICmp(const DataLayout *TD,
// address, due to canonicalization and constant folding.
if (isa<AllocaInst>(LHS) &&
(isa<AllocaInst>(RHS) || isa<GlobalVariable>(RHS))) {
+ ConstantInt *LHSOffsetCI = dyn_cast<ConstantInt>(LHSOffset);
+ ConstantInt *RHSOffsetCI = dyn_cast<ConstantInt>(RHSOffset);
uint64_t LHSSize, RHSSize;
- if (getObjectSize(LHS, LHSSize, TD, TLI) &&
+ if (LHSOffsetCI && RHSOffsetCI &&
+ getObjectSize(LHS, LHSSize, TD, TLI) &&
getObjectSize(RHS, RHSSize, TD, TLI)) {
- const APInt &LHSOffsetValue = LHSOffset->getValue();
- const APInt &RHSOffsetValue = RHSOffset->getValue();
+ const APInt &LHSOffsetValue = LHSOffsetCI->getValue();
+ const APInt &RHSOffsetValue = RHSOffsetCI->getValue();
if (!LHSOffsetValue.isNegative() &&
!RHSOffsetValue.isNegative() &&
LHSOffsetValue.ult(LHSSize) &&
diff --git a/test/Transforms/InstSimplify/ptr_diff.ll b/test/Transforms/InstSimplify/ptr_diff.ll
index 1eb1fd4c09..8651628069 100644
--- a/test/Transforms/InstSimplify/ptr_diff.ll
+++ b/test/Transforms/InstSimplify/ptr_diff.ll
@@ -46,3 +46,14 @@ define i64 @ptrdiff3(i8* %ptr) {
%diff = sub i64 %last.int, %first.int
ret i64 %diff
}
+
+define <4 x i32> @ptrdiff4(<4 x i8*> %arg) nounwind {
+; Handle simple cases of vectors of pointers.
+; CHECK: @ptrdiff4
+; CHECK: ret <4 x i32> zeroinitializer
+ %p1 = ptrtoint <4 x i8*> %arg to <4 x i32>
+ %bc = bitcast <4 x i8*> %arg to <4 x i32*>
+ %p2 = ptrtoint <4 x i32*> %bc to <4 x i32>
+ %sub = sub <4 x i32> %p1, %p2
+ ret <4 x i32> %sub
+}