summaryrefslogtreecommitdiff
path: root/tools/bugpoint/ExtractFunction.cpp
blob: 4c671be62fae65b79253e901aa4a244f2a293775 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//===- ExtractFunction.cpp - Extract a function from Program --------------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file implements a method that extracts a function from program, cleans
// it up, and returns it as a new module.
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "llvm/Constant.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"


namespace llvm {

bool DisableSimplifyCFG = false;

} // End llvm namespace

using namespace llvm;

namespace {
  cl::opt<bool>
  NoADCE("disable-adce",
         cl::desc("Do not use the -adce pass to reduce testcases"));
  cl::opt<bool>
  NoDCE ("disable-dce",
         cl::desc("Do not use the -dce pass to reduce testcases"));
  cl::opt<bool, true>
  NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG),
         cl::desc("Do not use the -simplifycfg pass to reduce testcases"));
}

namespace llvm {

/// deleteInstructionFromProgram - This method clones the current Program and
/// deletes the specified instruction from the cloned module.  It then runs a
/// series of cleanup passes (ADCE and SimplifyCFG) to eliminate any code which
/// depends on the value.  The modified module is then returned.
///
Module *BugDriver::deleteInstructionFromProgram(Instruction *I,
                                                unsigned Simplification) const {
  Module *Result = CloneModule(Program);

  BasicBlock *PBB = I->getParent();
  Function *PF = PBB->getParent();

  Module::iterator RFI = Result->begin(); // Get iterator to corresponding fn
  std::advance(RFI, std::distance(Program->begin(), Module::iterator(PF)));

  Function::iterator RBI = RFI->begin();  // Get iterator to corresponding BB
  std::advance(RBI, std::distance(PF->begin(), Function::iterator(PBB)));

  BasicBlock::iterator RI = RBI->begin(); // Get iterator to corresponding inst
  std::advance(RI, std::distance(PBB->begin(), BasicBlock::iterator(I)));
  I = RI;                                 // Got the corresponding instruction!

  // If this instruction produces a value, replace any users with null values
  if (I->getType() != Type::VoidTy)
    I->replaceAllUsesWith(Constant::getNullValue(I->getType()));

  // Remove the instruction from the program.
  I->getParent()->getInstList().erase(I);

  // Spiff up the output a little bit.
  PassManager Passes;
  // Make sure that the appropriate target data is always used...
  Passes.add(new TargetData("bugpoint", Result));

  if (Simplification > 2 && !NoADCE)
    Passes.add(createAggressiveDCEPass());          // Remove dead code...
  //Passes.add(createInstructionCombiningPass());
  if (Simplification > 1 && !NoDCE)
    Passes.add(createDeadCodeEliminationPass());
  if (Simplification && !DisableSimplifyCFG)
    Passes.add(createCFGSimplificationPass());      // Delete dead control flow

  Passes.add(createVerifierPass());
  Passes.run(*Result);
  return Result;
}

static const PassInfo *getPI(Pass *P) {
  const PassInfo *PI = P->getPassInfo();
  delete P;
  return PI;
}

/// performFinalCleanups - This method clones the current Program and performs
/// a series of cleanups intended to get rid of extra cruft on the module
/// before handing it to the user...
///
Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
  // Make all functions external, so GlobalDCE doesn't delete them...
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    I->setLinkage(GlobalValue::ExternalLinkage);
  
  std::vector<const PassInfo*> CleanupPasses;
  CleanupPasses.push_back(getPI(createFunctionResolvingPass()));
  CleanupPasses.push_back(getPI(createGlobalDCEPass()));
  CleanupPasses.push_back(getPI(createDeadTypeEliminationPass()));
  CleanupPasses.push_back(getPI(createDeadArgHackingPass()));

  std::swap(Program, M);
  std::string Filename;
  bool Failed = runPasses(CleanupPasses, Filename);
  std::swap(Program, M);

  if (Failed) {
    std::cerr << "Final cleanups failed.  Sorry.  :(\n";
  } else {
    delete M;
    M = ParseInputFile(Filename);
    if (M == 0) {
      std::cerr << getToolName() << ": Error reading bytecode file '"
                << Filename << "'!\n";
      exit(1);
    }
  }
  return M;
}

} // End llvm namespace