diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -1908,6 +1908,12 @@ getContext().pImpl->DSOLocalEquivalents.erase(getGlobalValue()); NewEquiv = this; setOperand(0, Func); + + if (Func->getType() != getType()) { + // It is ok to mutate the type here because this constant should always + // reflect the type of the function it's holding. + mutateType(Func->getType()); + } return nullptr; } diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp --- a/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -412,6 +412,20 @@ if (BlockAddress *BA = dyn_cast(C)) return mapBlockAddress(*BA); + if (const auto *Equiv = dyn_cast(C)) { + auto *Val = mapValue(Equiv->getGlobalValue()); + GlobalValue *GV = dyn_cast(Val); + if (GV) + return getVM()[Equiv] = DSOLocalEquivalent::get(GV); + + auto *Func = cast(Val->stripPointerCastsAndAliases()); + Type *NewTy = Equiv->getType(); + if (TypeMapper) + NewTy = TypeMapper->remapType(NewTy); + return getVM()[Equiv] = llvm::ConstantExpr::getBitCast( + DSOLocalEquivalent::get(Func), NewTy); + } + auto mapValueOrNull = [this](Value *V) { auto Mapped = mapValue(V); assert((Mapped || (Flags & RF_NullMapMissingGlobalValues)) &&