diff --git a/llvm/lib/Transforms/IPO/ExtractGV.cpp b/llvm/lib/Transforms/IPO/ExtractGV.cpp --- a/llvm/lib/Transforms/IPO/ExtractGV.cpp +++ b/llvm/lib/Transforms/IPO/ExtractGV.cpp @@ -36,7 +36,7 @@ } // Map linkonce* to weak* so that llvm doesn't drop this GV. - switch(GV.getLinkage()) { + switch (GV.getLinkage()) { default: llvm_unreachable("Unexpected linkage"); case GlobalValue::LinkOnceAnyLinkage: @@ -48,10 +48,9 @@ } } - - /// If deleteS is true, this pass deletes the specified global values. - /// Otherwise, it deletes as much of the module as possible, except for the - /// global values specified. +/// If deleteS is true, this pass deletes the specified global values. +/// Otherwise, it deletes as much of the module as possible, except for the +/// global values specified. ExtractGVPass::ExtractGVPass(std::vector &GVs, bool deleteS, bool keepConstInit) : Named(GVs.begin(), GVs.end()), deleteStuff(deleteS), @@ -129,5 +128,22 @@ } } + // Visit the IFuncs. + for (GlobalIFunc &IF : llvm::make_early_inc_range(M.ifuncs())) { + bool Delete = deleteStuff == (bool)Named.count(&IF); + makeVisible(IF, Delete); + + if (!Delete) + continue; + + auto *FuncType = dyn_cast(IF.getValueType()); + IF.removeFromParent(); + llvm::Value *Declaration = + Function::Create(FuncType, GlobalValue::ExternalLinkage, + IF.getAddressSpace(), IF.getName(), &M); + IF.replaceAllUsesWith(Declaration); + delete &IF; + } + return PreservedAnalyses::none(); } diff --git a/llvm/test/tools/llvm-extract/delete-ifunc.ll b/llvm/test/tools/llvm-extract/delete-ifunc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-extract/delete-ifunc.ll @@ -0,0 +1,22 @@ +; RUN: llvm-extract -func foo -S %s | FileCheck %s + +; llvm-extract should not copy ifuncs into the new module, so make sure they +; are turned into declarations. + +; CHECK: define void @foo() { +; CHECK: call void @ifunc() +define void @foo() { + call void @ifunc() + ret void +} + +define void @ifunc_impl() { + ret void +} + +; CHECK: declare void @ifunc() +@ifunc = ifunc void (), ptr @ifunc_resolver + +define internal ptr @ifunc_resolver() { + ret ptr @ifunc_impl +}