diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2173,14 +2173,15 @@ Matched = true; } - if (Matched) { - // Canonicalize (gep i8* X, (ptrtoint Y)-(ptrtoint X)) - // to (bitcast Y) - Value *Y; - if (match(V, m_Sub(m_PtrToInt(m_Value(Y)), - m_PtrToInt(m_Specific(GEP.getOperand(0)))))) - return CastInst::CreatePointerBitCastOrAddrSpaceCast(Y, GEPType); - } + // Canonicalize (gep i8* X, (ptrtoint Y)-(ptrtoint X)) to (bitcast Y), but + // only if both point to the same underlying object (otherwise provenance + // is not necessarily retained). + Value *Y; + Value *X = GEP.getOperand(0); + if (Matched && + match(V, m_Sub(m_PtrToInt(m_Value(Y)), m_PtrToInt(m_Specific(X)))) && + getUnderlyingObject(X) == getUnderlyingObject(Y)) + return CastInst::CreatePointerBitCastOrAddrSpaceCast(Y, GEPType); } } diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -1087,7 +1087,11 @@ define %struct.C* @test45(%struct.C* %c1, %struct.C** %c2) { ; CHECK-LABEL: @test45( -; CHECK-NEXT: [[GEP:%.*]] = bitcast %struct.C** [[C2:%.*]] to %struct.C* +; CHECK-NEXT: [[PTRTOINT1:%.*]] = ptrtoint %struct.C* [[C1:%.*]] to i64 +; CHECK-NEXT: [[PTRTOINT2:%.*]] = ptrtoint %struct.C** [[C2:%.*]] to i64 +; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[PTRTOINT2]], [[PTRTOINT1]] +; CHECK-NEXT: [[SHR:%.*]] = sdiv i64 [[SUB]], 7 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], %struct.C* [[C1]], i64 [[SHR]] ; CHECK-NEXT: ret %struct.C* [[GEP]] ; %ptrtoint1 = ptrtoint %struct.C* %c1 to i64