From 8058ffeb18cd91196602b4675e30fb781e424358 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 26 Aug 2014 07:08:03 +0000 Subject: [PATCH] InstSimplify: Fold gep X, (sub 0, ptrtoint(X)) to null Save InstCombine some work if we can perform this fold during InstSimplify. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216441 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InstructionSimplify.cpp | 53 +++++++++++++++++----------- test/Transforms/InstSimplify/gep.ll | 29 +++++++++++++++ 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index c9c9eede435..666e7f2fa96 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -2789,14 +2789,14 @@ static Value *SimplifyGEPInst(ArrayRef Ops, const Query &Q, unsigned) { if (Ops.size() == 1) return Ops[0]; - if (isa(Ops[0])) { - // Compute the (pointer) type returned by the GEP instruction. - Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, Ops.slice(1)); - Type *GEPTy = PointerType::get(LastType, AS); - if (VectorType *VT = dyn_cast(Ops[0]->getType())) - GEPTy = VectorType::get(GEPTy, VT->getNumElements()); + // Compute the (pointer) type returned by the GEP instruction. + Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, Ops.slice(1)); + Type *GEPTy = PointerType::get(LastType, AS); + if (VectorType *VT = dyn_cast(Ops[0]->getType())) + GEPTy = VectorType::get(GEPTy, VT->getNumElements()); + + if (isa(Ops[0])) return UndefValue::get(GEPTy); - } if (Ops.size() == 2) { // getelementptr P, 0 -> P. @@ -2816,26 +2816,37 @@ static Value *SimplifyGEPInst(ArrayRef Ops, const Query &Q, unsigned) { // doesn't truncate the pointers. if (Ops[1]->getType()->getScalarSizeInBits() == Q.DL->getPointerSizeInBits(AS)) { - // getelementptr P, (sub Q, P) -> Q if P points to a type of size 1. + auto PtrToIntOrZero = [GEPTy](Value *P) -> Value * { + if (match(P, m_Zero())) + return Constant::getNullValue(GEPTy); + Value *Temp; + if (match(P, m_PtrToInt(m_Value(Temp)))) + return Temp; + return nullptr; + }; + + // getelementptr V, (sub P, V) -> P if P points to a type of size 1. if (TyAllocSize == 1 && - match(Ops[1], m_Sub(m_PtrToInt(m_Value(P)), - m_PtrToInt(m_Specific(Ops[0]))))) - return P; + match(Ops[1], m_Sub(m_Value(P), m_PtrToInt(m_Specific(Ops[0]))))) + if (Value *R = PtrToIntOrZero(P)) + return R; - // getelementptr P, (ashr (sub Q, P), C) -> Q + // getelementptr V, (ashr (sub P, V), C) -> Q // if P points to a type of size 1 << C. - if (match(Ops[1], m_AShr(m_Sub(m_PtrToInt(m_Value(P)), - m_PtrToInt(m_Specific(Ops[0]))), - m_ConstantInt(C))) && + if (match(Ops[1], + m_AShr(m_Sub(m_Value(P), m_PtrToInt(m_Specific(Ops[0]))), + m_ConstantInt(C))) && TyAllocSize == 1ULL << C) - return P; + if (Value *R = PtrToIntOrZero(P)) + return R; - // getelementptr P, (sdiv (sub Q, P), C) -> Q + // getelementptr V, (sdiv (sub P, V), C) -> Q // if P points to a type of size C. - if (match(Ops[1], m_SDiv(m_Sub(m_PtrToInt(m_Value(P)), - m_PtrToInt(m_Specific(Ops[0]))), - m_SpecificInt(TyAllocSize)))) - return P; + if (match(Ops[1], + m_SDiv(m_Sub(m_Value(P), m_PtrToInt(m_Specific(Ops[0]))), + m_SpecificInt(TyAllocSize)))) + if (Value *R = PtrToIntOrZero(P)) + return R; } } } diff --git a/test/Transforms/InstSimplify/gep.ll b/test/Transforms/InstSimplify/gep.ll index 4bc39754af2..d1704bf80bc 100644 --- a/test/Transforms/InstSimplify/gep.ll +++ b/test/Transforms/InstSimplify/gep.ll @@ -35,3 +35,32 @@ define i64* @test3(i64* %b, i64* %e) { ; CHECK-LABEL: @test3 ; CHECK-NEXT: ret i64* %e } + +define %struct.A* @test4(%struct.A* %b) { + %b_ptr = ptrtoint %struct.A* %b to i64 + %sub = sub i64 0, %b_ptr + %sdiv = sdiv exact i64 %sub, 7 + %gep = getelementptr inbounds %struct.A* %b, i64 %sdiv + ret %struct.A* %gep +; CHECK-LABEL: @test4 +; CHECK-NEXT: ret %struct.A* null +} + +define i8* @test5(i8* %b) { + %b_ptr = ptrtoint i8* %b to i64 + %sub = sub i64 0, %b_ptr + %gep = getelementptr inbounds i8* %b, i64 %sub + ret i8* %gep +; CHECK-LABEL: @test5 +; CHECK-NEXT: ret i8* null +} + +define i64* @test6(i64* %b) { + %b_ptr = ptrtoint i64* %b to i64 + %sub = sub i64 0, %b_ptr + %ashr = ashr exact i64 %sub, 3 + %gep = getelementptr inbounds i64* %b, i64 %ashr + ret i64* %gep +; CHECK-LABEL: @test6 +; CHECK-NEXT: ret i64* null +}