Remove function from module

How correctly remove function from module?
For example:

int f1(int x) {

a = f2(smth);

}
int f2 (int y) {

b = f1(smth);
…}

I need delete from module both f1 and f2. They haven’t uses in other part of module, but I can’t delete them with eraseFromParent, because they are use each other.

Yours sincerely,
Kadysev Mikhail

Михаил wrote:

How correctly remove function from module?
For example:

int f1(int x) {
...
a = f2(smth);
...
}
int f2 (int y) {
...
b = f1(smth);
...
}

I need delete from module both f1 and f2. They haven't uses in other
part of module, but I can't delete them with eraseFromParent, because
they are use each other.

Call X->replaceAllUsesWith(UndefValue::get(X->getType)) before calling X->eraseFromParent().

Nick

Hi Михаил,

You can also use GVExtractionPass:

  if (!strcmp(argv[1], "pass"))
  {
    PassManager manager;
    manager.add(new TargetData(m.get()));
    
    // Delete functions specified in list of functions.
    vector<GlobalValue*> functions;
    functions.push_back(m.get()->getFunction("f1"));
    functions.push_back(m.get()->getFunction("f2"));
    manager.add(createGVExtractionPass(functions, true));

    // Delete unreachable globals.
    manager.add(createGlobalDCEPass());
    
    // Remove dead debug info.
    manager.add(createStripDeadDebugInfoPass());
    
    // Remove dead func decls.
    manager.add(createStripDeadPrototypesPass());

    manager.run(*m.get());
  }

  if (!strcmp(argv[1], "manual"))
  {
    Function* f1 = m.get()->getFunction("f1");
    Function* f2 = m.get()->getFunction("f2");
    
    f1->replaceAllUsesWith(UndefValue::get((Type*)f1->getType()));
    f2->replaceAllUsesWith(UndefValue::get((Type*)f2->getType()));

    f1->eraseFromParent();
    f2->eraseFromParent();
  }

- D.

makefile (388 Bytes)

test.c (98 Bytes)

test.ll (1.71 KB)

transform.cxx (1.83 KB)

Thanks, but I replaceAllUsesWith() - works well, but I still get bug in eraseFromParent():

While deleting: i32 (%class.B*, i32)* %_ZN1B1xEi
An asserting value handle still pointed to this value!
UNREACHABLE executed at /Users/neonomaly/LLVM/LLVM/lib/VMCore/Value.cpp:561!

Yours sincerely,
Kadysev Mikhail

21.04.2012, в 23:45, Nick Lewycky написал(а):

Could you reproduce this assertion with my test program?

22 ÁÐÒÅÌÑ 2012šÇ. 0:09 ÐÏÌØÚÏ×ÁÔÅÌØ íÉÈÁÉÌ <neonomaly.x@gmail.com> ÎÁÐÉÓÁÌ:

It also occurs on several (different) test cases. I have founded that assershion rises in void ValueHandleBase::ValueIsDeleted(Value *V);

Code from function:

// All callbacks, weak references, and assertingVHs should be dropped by now.
if (V->HasValueHandle) {
#ifndef NDEBUG // Only in +Asserts mode…
dbgs() << “While deleting: " << *V->getType() << " %” << V->getNameStr()
<< “\n”;
if (pImpl->ValueHandles[V]->getKind() == Assert)
llvm_unreachable(“An asserting value handle still pointed to this
" value!”);

#endif
llvm_unreachable(“All references to V were not removed?”);
}

Yours sincerely,
Kadysev Mikhail

22.04.2012, в 1:41, Dmitry N. Mikushin написал(а):

íÉÈÁÉÌ wrote:

Thanks, but I replaceAllUsesWith() - works well, but I still get bug in
eraseFromParent():

While deleting: i32 (%class.B*, i32)* %_ZN1B1xEi
An asserting value handle still pointed to this value!
UNREACHABLE executed at /Users/neonomaly/LLVM/LLVM/lib/VMCore/Value.cpp:561!

The replaceAllUsesWith + eraseFromParent pattern remains correct, but there's more to the story than the parts we've focused on. This error means that there's some other code that is holding a pointer to the function you tried to delete, but is using AssertingVH to do so, so as to catch errors exactly like this producing a dangling pointer.

The error message doesn't tell us who owns the AssertingVH (indeed, the asserting-vh doesn't know, much like a pointer doesn't know who owns it).

So, under what circumstance are you doing this deletion? Is it inside a FunctionPass, or another kind of Pass? Are you using AssertingVH's or calling other code that is? Such as ValueMap's, or some llvm analysis pass which stores an AssertingVH?

Nick

It is ModulePass with AnalysisUsage of CallGraph

Yours sincerely,
Kadysev Mikhail

22.04.2012, в 5:20, Nick Lewycky написал(а):

Михаил wrote:

It is ModulePass with AnalysisUsage of CallGraph

Ah, then you'll need to update the CallGraph first. Use "CG.removeFunctionFromModule(F);" before deleting it.

Nick

Thanks.

I try to delete function like this (rta_IsFunctionVisited.find - set of good functions) :

// delete dead functions
for (Module::iterator Fx = M->begin(), FE = M->end(); Fx!=FE; Fx++) {
if (rta_IsFunctionVisited.find(Fx)==rta_IsFunctionVisited.end()) {
Fx->replaceAllUsesWith(UndefValue::get(Fx->getType()));
}
}

for (CallGraph::iterator CGN = CG.begin(); CGN!=CG.end(); CGN++) {
if (rta_IsFunctionVisited.find(CGN->second->getFunction())==rta_IsFunctionVisited.end()) {
CGN->second->removeAllCalledFunctions();
}
}

for (Module::iterator Fx = M->begin(), FE = M->end(); Fx!=FE;) {
if (rta_IsFunctionVisited.find(Fx)==rta_IsFunctionVisited.end()) {
CallGraphNode *CGN = CG.getOrInsertFunction(Fx);
CG.removeFunctionFromModule(Fx);
wasChanged=true;
Fx=M->begin();
} else Fx++;
}

return true;

But I still have a bug:

opt(63981) malloc: *** error for object 0x7ff1394050a0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
0 libLLVM-3.0.dylib 0x00000001082d7605 _ZL15PrintStackTracePv + 53
1 libLLVM-3.0.dylib 0x00000001082d7c6c _ZL13SignalHandleri + 364
2 libsystem_c.dylib 0x00007fff9152dcfa _sigtramp + 26
3 libsystem_c.dylib 0x00007fff66d6a878 _sigtramp + 18446744072996768664
4 libsystem_c.dylib 0x00007fff9152b84c free + 389
5 libLLVM-3.0.dylib 0x00000001083536b0 __gnu_cxx::new_allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> >::deallocate(std::pair<llvm::WeakVH, llvm::CallGraphNode*>, unsigned long) + 32
6 libLLVM-3.0.dylib 0x000000010835360e std::_Vector_base<std::pair<llvm::WeakVH, llvm::CallGraphNode
>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::_M_deallocate(std::pair<llvm::WeakVH, llvm::CallGraphNode*>, unsigned long) + 62
7 libLLVM-3.0.dylib 0x00000001083535bd std::_Vector_base<std::pair<llvm::WeakVH, llvm::CallGraphNode
>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::~_Vector_base() + 45
8 libLLVM-3.0.dylib 0x0000000108353509 std::vector<std::pair<llvm::WeakVH, llvm::CallGraphNode*>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::~vector() + 105
9 libLLVM-3.0.dylib 0x0000000108353495 std::vector<std::pair<llvm::WeakVH, llvm::CallGraphNode*>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::~vector() + 21
10 libLLVM-3.0.dylib 0x000000010852be3e llvm::CallGraphNode::~CallGraphNode() + 110
11 libLLVM-3.0.dylib 0x0000000108529d55 llvm::CallGraphNode::~CallGraphNode() + 21
12 libLLVM-3.0.dylib 0x0000000108528468 llvm::CallGraph::destroy() + 264
13 libLLVM-3.0.dylib 0x00000001085295f8 (anonymous namespace)::BasicCallGraph::destroy() + 120
14 libLLVM-3.0.dylib 0x0000000108529379 (anonymous namespace)::BasicCallGraph::releaseMemory() + 25
15 libLLVM-3.0.dylib 0x0000000107bf5d93 llvm::PMDataManager::freePass(llvm::Pass*, llvm::StringRef, llvm::PassDebuggingString) + 179
16 libLLVM-3.0.dylib 0x0000000107bf5c89 llvm::PMDataManager::removeDeadPasses(llvm::Pass*, llvm::StringRef, llvm::PassDebuggingString) + 505
17 libLLVM-3.0.dylib 0x0000000107bf8ee8 llvm::MPPassManager::runOnModule(llvm::Module&) + 1016
18 libLLVM-3.0.dylib 0x0000000107bf949c llvm::PassManagerImpl::run(llvm::Module&) + 172
19 libLLVM-3.0.dylib 0x0000000107bf997d llvm::PassManager::run(llvm::Module&) + 29
20 opt 0x000000010717f057 main + 6903
21 opt 0x000000010716d7b4 start + 52
22 opt 0x0000000000000007 start + 18446744069295646855

Yours sincerely,
Kadysev Mikhail

22.04.2012, в 23:30, Nick Lewycky написал(а):