<commit_before>//===- CodeExtractor.cpp - Pull code region into a new function -----------===//
//
//                     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 the interface to tear out a code region, such as an
// individual loop or a parallel section, into a new function, replacing it with
// a call to the new function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <set>
using namespace llvm;

// Provide a command-line option to aggregate function arguments into a struct
// for functions produced by the code extrator. This is useful when converting
// extracted functions to pthread-based code, as only one argument (void*) can
// be passed in to pthread_create().
static cl::opt<bool>
AggregateArgsOpt("aggregate-extracted-args", cl::Hidden,
                 cl::desc("Aggregate arguments to code-extracted functions"));

namespace {
  class VISIBILITY_HIDDEN CodeExtractor {
    typedef std::vector<Value*> Values;
    std::set<BasicBlock*> BlocksToExtract;
    ETForest *EF;
    DominatorTree* DT;
    bool AggregateArgs;
    unsigned NumExitBlocks;
    const Type *RetTy;
  public:
    CodeExtractor(ETForest *ef = 0, DominatorTree* dt = 0, bool AggArgs = false)
      : EF(ef), DT(dt), AggregateArgs(AggArgs||AggregateArgsOpt), NumExitBlocks(~0U) {}

    Function *ExtractCodeRegion(const std::vector<BasicBlock*> &code);

    bool isEligible(const std::vector<BasicBlock*> &code);

  private:
    /// definedInRegion - Return true if the specified value is defined in the
    /// extracted region.
    bool definedInRegion(Value *V) const {
      if (Instruction *I = dyn_cast<Instruction>(V))
        if (BlocksToExtract.count(I->getParent()))
          return true;
      return false;
    }

    /// definedInCaller - Return true if the specified value is defined in the
    /// function being code extracted, but not in the region being extracted.
    /// These values must be passed in as live-ins to the function.
    bool definedInCaller(Value *V) const {
      if (isa<Argument>(V)) return true;
      if (Instruction *I = dyn_cast<Instruction>(V))
        if (!BlocksToExtract.count(I->getParent()))
          return true;
      return false;
    }

    void severSplitPHINodes(BasicBlock *&Header);
    void splitReturnBlocks();
    void findInputsOutputs(Values &inputs, Values &outputs);

    Function *constructFunction(const Values &inputs,
                                const Values &outputs,
                                BasicBlock *header,
                                BasicBlock *newRootNode, BasicBlock *newHeader,
                                Function *oldFunction, Module *M);

    void moveCodeToFunction(Function *newFunction);

    void emitCallAndSwitchStatement(Function *newFunction,
                                    BasicBlock *newHeader,
                                    Values &inputs,
                                    Values &outputs);

  };
}

/// severSplitPHINodes - If a PHI node has multiple inputs from outside of the
/// region, we need to split the entry block of the region so that the PHI node
/// is easier to deal with.
void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) {
  bool HasPredsFromRegion = false;
  unsigned NumPredsOutsideRegion = 0;

  if (Header != &Header->getParent()->getEntryBlock()) {
    PHINode *PN = dyn_cast<PHINode>(Header->begin());
    if (!PN) return;  // No PHI nodes.

    // If the header node contains any PHI nodes, check to see if there is more
    // than one entry from outside the region.  If so, we need to sever the
    // header block into two.
    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
      if (BlocksToExtract.count(PN->getIncomingBlock(i)))
        HasPredsFromRegion = true;
      else
        ++NumPredsOutsideRegion;

    // If there is one (or fewer) predecessor from outside the region, we don't
    // need to do anything special.
    if (NumPredsOutsideRegion <= 1) return;
  }

  // Otherwise, we need to split the header block into two pieces: one
  // containing PHI nodes merging values from outside of the region, and a
  // second that contains all of the code for the block and merges back any
  // incoming values from inside of the region.
  BasicBlock::iterator AfterPHIs = Header->begin();
  while (isa<PHINode>(AfterPHIs)) ++AfterPHIs;
  BasicBlock *NewBB = Header->splitBasicBlock(AfterPHIs,
                                              Header->getName()+".ce");

  // We only want to code extract the second block now, and it becomes the new
  // header of the region.
  BasicBlock *OldPred = Header;
  BlocksToExtract.erase(OldPred);
  BlocksToExtract.insert(NewBB);
  Header = NewBB;

  // Okay, update dominator sets. The blocks that dominate the new one are the
  // blocks that dominate TIBB plus the new block itself.
  if (EF) {
    DominatorTree::Node* idom = DT->getNode(OldPred)->getIDom();
    DT->createNewNode(NewBB, idom);
    EF->addNewBlock(NewBB, idom->getBlock());

    // Additionally, NewBB replaces OldPred as the immediate dominator of blocks
    Function *F = Header->getParent();
    for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
      if (DT->getNode(I)->getIDom()->getBlock() == OldPred) {
        DT->changeImmediateDominator(DT->getNode(I), DT->getNode(NewBB));
        EF->setImmediateDominator(I, NewBB);
      }
  }

  // Okay, now we need to adjust the PHI nodes and any branches from within the
  // region to go to the new header block instead of the old header block.
  if (HasPredsFromRegion) {
    PHINode *PN = cast<PHINode>(OldPred->begin());
    // Loop over all of the predecessors of OldPred that are in the region,
    // changing them to branch to NewBB instead.
    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
      if (BlocksToExtract.count(PN->getIncomingBlock(i))) {
        TerminatorInst *TI = PN->getIncomingBlock(i)->getTerminator();
        TI->replaceUsesOfWith(OldPred, NewBB);
      }

    // Okay, everthing within the region is now branching to the right block, we
    // just have to update the PHI nodes now, inserting PHI nodes into NewBB.
    for (AfterPHIs = OldPred->begin(); isa<PHINode>(AfterPHIs); ++AfterPHIs) {<commit_msg>Use new ETForest accessor.<commit_after>//===- CodeExtractor.cpp - Pull code region into a new function -----------===//
//
//                     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 the interface to tear out a code region, such as an
// individual loop or a parallel section, into a new function, replacing it with
// a call to the new function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <set>
using namespace llvm;

// Provide a command-line option to aggregate function arguments into a struct
// for functions produced by the code extrator. This is useful when converting
// extracted functions to pthread-based code, as only one argument (void*) can
// be passed in to pthread_create().
static cl::opt<bool>
AggregateArgsOpt("aggregate-extracted-args", cl::Hidden,
                 cl::desc("Aggregate arguments to code-extracted functions"));

namespace {
  class VISIBILITY_HIDDEN CodeExtractor {
    typedef std::vector<Value*> Values;
    std::set<BasicBlock*> BlocksToExtract;
    ETForest *EF;
    DominatorTree* DT;
    bool AggregateArgs;
    unsigned NumExitBlocks;
    const Type *RetTy;
  public:
    CodeExtractor(ETForest *ef = 0, DominatorTree* dt = 0, bool AggArgs = false)
      : EF(ef), DT(dt), AggregateArgs(AggArgs||AggregateArgsOpt), NumExitBlocks(~0U) {}

    Function *ExtractCodeRegion(const std::vector<BasicBlock*> &code);

    bool isEligible(const std::vector<BasicBlock*> &code);

  private:
    /// definedInRegion - Return true if the specified value is defined in the
    /// extracted region.
    bool definedInRegion(Value *V) const {
      if (Instruction *I = dyn_cast<Instruction>(V))
        if (BlocksToExtract.count(I->getParent()))
          return true;
      return false;
    }

    /// definedInCaller - Return true if the specified value is defined in the
    /// function being code extracted, but not in the region being extracted.
    /// These values must be passed in as live-ins to the function.
    bool definedInCaller(Value *V) const {
      if (isa<Argument>(V)) return true;
      if (Instruction *I = dyn_cast<Instruction>(V))
        if (!BlocksToExtract.count(I->getParent()))
          return true;
      return false;
    }

    void severSplitPHINodes(BasicBlock *&Header);
    void splitReturnBlocks();
    void findInputsOutputs(Values &inputs, Values &outputs);

    Function *constructFunction(const Values &inputs,
                                const Values &outputs,
                                BasicBlock *header,
                                BasicBlock *newRootNode, BasicBlock *newHeader,
                                Function *oldFunction, Module *M);

    void moveCodeToFunction(Function *newFunction);

    void emitCallAndSwitchStatement(Function *newFunction,
                                    BasicBlock *newHeader,
                                    Values &inputs,
                                    Values &outputs);

  };
}

/// severSplitPHINodes - If a PHI node has multiple inputs from outside of the
/// region, we need to split the entry block of the region so that the PHI node
/// is easier to deal with.
void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) {
  bool HasPredsFromRegion = false;
  unsigned NumPredsOutsideRegion = 0;

  if (Header != &Header->getParent()->getEntryBlock()) {
    PHINode *PN = dyn_cast<PHINode>(Header->begin());
    if (!PN) return;  // No PHI nodes.

    // If the header node contains any PHI nodes, check to see if there is more
    // than one entry from outside the region.  If so, we need to sever the
    // header block into two.
    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
      if (BlocksToExtract.count(PN->getIncomingBlock(i)))
        HasPredsFromRegion = true;
      else
        ++NumPredsOutsideRegion;

    // If there is one (or fewer) predecessor from outside the region, we don't
    // need to do anything special.
    if (NumPredsOutsideRegion <= 1) return;
  }

  // Otherwise, we need to split the header block into two pieces: one
  // containing PHI nodes merging values from outside of the region, and a
  // second that contains all of the code for the block and merges back any
  // incoming values from inside of the region.
  BasicBlock::iterator AfterPHIs = Header->begin();
  while (isa<PHINode>(AfterPHIs)) ++AfterPHIs;
  BasicBlock *NewBB = Header->splitBasicBlock(AfterPHIs,
                                              Header->getName()+".ce");

  // We only want to code extract the second block now, and it becomes the new
  // header of the region.
  BasicBlock *OldPred = Header;
  BlocksToExtract.erase(OldPred);
  BlocksToExtract.insert(NewBB);
  Header = NewBB;

  // Okay, update dominator sets. The blocks that dominate the new one are the
  // blocks that dominate TIBB plus the new block itself.
  if (EF) {
    BasicBlock* idom = EF->getIDom(OldPred);
    DT->createNewNode(NewBB, DT->getNode(idom));
    EF->addNewBlock(NewBB, idom);

    // Additionally, NewBB replaces OldPred as the immediate dominator of blocks
    Function *F = Header->getParent();
    for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
      if (EF->getIDom(I) == OldPred) {
        DT->changeImmediateDominator(DT->getNode(I), DT->getNode(NewBB));
        EF->setImmediateDominator(I, NewBB);
      }
  }

  // Okay, now we need to adjust the PHI nodes and any branches from within the
  // region to go to the new header block instead of the old header block.
  if (HasPredsFromRegion) {
    PHINode *PN = cast<PHINode>(OldPred->begin());
    // Loop over all of the predecessors of OldPred that are in the region,
    // changing them to branch to NewBB instead.
    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
      if (BlocksToExtract.count(PN->getIncomingBlock(i))) {
        TerminatorInst *TI = PN->getIncomingBlock(i)->getTerminator();
        TI->replaceUsesOfWith(OldPred, NewBB);
      }

    // Okay, everthing within the region is now branching to the right block, we
    // just have to update the PHI nodes now, inserting PHI nodes into NewBB.
    for (AfterPHIs = OldPred->begin(); isa<PHINode>(AfterPHIs); ++AfterPHIs) {
{'fraction_non_alphanumeric': 0.1293867422899681, 'fraction_numerical': 0.0009925558312655087, 'mean_word_length': 2.716016859852476, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 92, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4425549', 'n_tokens_mistral': 4033, 'n_tokens_neox': 3941, 'n_words': 1365}