diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4349,40 +4349,32 @@ // doesn't truncate the pointers. if (Ops[1]->getType()->getScalarSizeInBits() == Q.DL.getPointerSizeInBits(AS)) { - auto PtrToInt = [GEPTy](Value *P) -> Value * { - Value *Temp; - if (match(P, m_PtrToInt(m_Value(Temp)))) - if (Temp->getType() == GEPTy) - return Temp; - return nullptr; + auto CanSimplify = [GEPTy, &P, V = Ops[0]]() -> bool { + return P->getType() == GEPTy && + getUnderlyingObject(P) == getUnderlyingObject(V); }; - - // FIXME: The following transforms are only legal if P and V have the - // same provenance (PR44403). Check whether getUnderlyingObject() is - // the same? - // getelementptr V, (sub P, V) -> P if P points to a type of size 1. if (TyAllocSize == 1 && - match(Ops[1], m_Sub(m_Value(P), m_PtrToInt(m_Specific(Ops[0]))))) - if (Value *R = PtrToInt(P)) - return R; - - // 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_Value(P), m_PtrToInt(m_Specific(Ops[0]))), - m_ConstantInt(C))) && - TyAllocSize == 1ULL << C) - if (Value *R = PtrToInt(P)) - return R; - - // 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_Value(P), m_PtrToInt(m_Specific(Ops[0]))), - m_SpecificInt(TyAllocSize)))) - if (Value *R = PtrToInt(P)) - return R; + match(Ops[1], m_Sub(m_PtrToInt(m_Value(P)), + m_PtrToInt(m_Specific(Ops[0])))) && + CanSimplify()) + return P; + + // getelementptr V, (ashr (sub P, V), C) -> P 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))) && + TyAllocSize == 1ULL << C && CanSimplify()) + return P; + + // getelementptr V, (sdiv (sub P, V), C) -> P 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))) && + CanSimplify()) + return P; } } } diff --git a/llvm/test/Transforms/InstSimplify/gep.ll b/llvm/test/Transforms/InstSimplify/gep.ll --- a/llvm/test/Transforms/InstSimplify/gep.ll +++ b/llvm/test/Transforms/InstSimplify/gep.ll @@ -7,7 +7,12 @@ define %struct.A* @test1(%struct.A* %b, %struct.A* %e) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: ret %struct.A* [[E:%.*]] +; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint %struct.A* [[E:%.*]] to i64 +; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint %struct.A* [[B:%.*]] to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] +; CHECK-NEXT: [[SDIV:%.*]] = sdiv exact i64 [[SUB]], 7 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[B]], i64 [[SDIV]] +; CHECK-NEXT: ret %struct.A* [[GEP]] ; %e_ptr = ptrtoint %struct.A* %e to i64 %b_ptr = ptrtoint %struct.A* %b to i64 @@ -19,7 +24,11 @@ define i8* @test2(i8* %b, i8* %e) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: ret i8* [[E:%.*]] +; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint i8* [[E:%.*]] to i64 +; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint i8* [[B:%.*]] to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[B]], i64 [[SUB]] +; CHECK-NEXT: ret i8* [[GEP]] ; %e_ptr = ptrtoint i8* %e to i64 %b_ptr = ptrtoint i8* %b to i64 @@ -30,7 +39,12 @@ define i64* @test3(i64* %b, i64* %e) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: ret i64* [[E:%.*]] +; CHECK-NEXT: [[E_PTR:%.*]] = ptrtoint i64* [[E:%.*]] to i64 +; CHECK-NEXT: [[B_PTR:%.*]] = ptrtoint i64* [[B:%.*]] to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[E_PTR]], [[B_PTR]] +; CHECK-NEXT: [[ASHR:%.*]] = ashr exact i64 [[SUB]], 3 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, i64* [[B]], i64 [[ASHR]] +; CHECK-NEXT: ret i64* [[GEP]] ; %e_ptr = ptrtoint i64* %e to i64 %b_ptr = ptrtoint i64* %b to i64