<commit_before>//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
// The code in this file for handling inlines through invoke
// instructions preserves semantics only under some assumptions about
// the behavior of unwinders which correspond to gcc-style libUnwind
// exception personality functions.  Eventually the IR will be
// improved to make this unnecessary, but until then, this code is
// marked [LIBUNWIND].
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Intrinsics.h"
#include "llvm/Attributes.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/IRBuilder.h"
using namespace llvm;

bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI) {
  return InlineFunction(CallSite(CI), IFI);
}
bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI) {
  return InlineFunction(CallSite(II), IFI);
}

/// [LIBUNWIND] Find the (possibly absent) call to @llvm.eh.selector in
/// the given landing pad.
static EHSelectorInst *findSelectorForLandingPad(BasicBlock *lpad) {
  // The llvm.eh.exception call is required to be in the landing pad.
  for (BasicBlock::iterator i = lpad->begin(), e = lpad->end(); i != e; i++) {
    EHExceptionInst *exn = dyn_cast<EHExceptionInst>(i);
    if (!exn) continue;

    EHSelectorInst *selector = 0;
    for (Instruction::use_iterator
           ui = exn->use_begin(), ue = exn->use_end(); ui != ue; ++ui) {
      EHSelectorInst *sel = dyn_cast<EHSelectorInst>(*ui);
      if (!sel) continue;

      // Immediately accept an eh.selector in the landing pad.
      if (sel->getParent() == lpad) return sel;

      // Otherwise, use the first selector we see.
      if (!selector) selector = sel;
    }

    return selector;
  }

  return 0;
}

namespace {
  /// A class for recording information about inlining through an invoke.
  class InvokeInliningInfo {
    BasicBlock *OuterUnwindDest;
    EHSelectorInst *OuterSelector;
    BasicBlock *InnerUnwindDest;
    PHINode *InnerExceptionPHI;
    PHINode *InnerSelectorPHI;
    SmallVector<Value*, 8> UnwindDestPHIValues;

  public:
    InvokeInliningInfo(InvokeInst *II) :
      OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
      InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) {

      // If there are PHI nodes in the unwind destination block, we
      // need to keep track of which values came into them from the
      // invoke before removing the edge from this block.
      llvm::BasicBlock *invokeBB = II->getParent();
      for (BasicBlock::iterator I = OuterUnwindDest->begin();
             isa<PHINode>(I); ++I) {
        // Save the value to use for this edge.
        PHINode *phi = cast<PHINode>(I);
        UnwindDestPHIValues.push_back(phi->getIncomingValueForBlock(invokeBB));
      }
    }

    /// The outer unwind destination is the target of unwind edges
    /// introduced for calls within the inlined function.
    BasicBlock *getOuterUnwindDest() const {
      return OuterUnwindDest;
    }

    EHSelectorInst *getOuterSelector() {
      if (!OuterSelector)
        OuterSelector = findSelectorForLandingPad(OuterUnwindDest);
      return OuterSelector;
    }

    BasicBlock *getInnerUnwindDest();

    bool forwardEHResume(CallInst *call, BasicBlock *src);

    /// Add incoming-PHI values to the unwind destination block for
    /// the given basic block, using the values for the original
    /// invoke's source block.
    void addIncomingPHIValuesFor(BasicBlock *BB) const {
      addIncomingPHIValuesForInto(BB, OuterUnwindDest);
    }

    void addIncomingPHIValuesForInto(BasicBlock *src, BasicBlock *dest) const {
      BasicBlock::iterator I = dest->begin();
      for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
        PHINode *phi = cast<PHINode>(I);
        phi->addIncoming(UnwindDestPHIValues[i], src);
      }
    }
  };
}

/// Replace all the instruction uses of a value with a different value.
/// This has the advantage of not screwing up the CallGraph.
static void replaceAllInsnUsesWith(Instruction *insn, Value *replacement) {
  for (Value::use_iterator i = insn->use_begin(), e = insn->use_end();
       i != e; ) {
    Use &use = i.getUse();
    ++i;
    if (isa<Instruction>(use.getUser()))
      use.set(replacement);
  }
}

/// Get or create a target for the branch out of rewritten calls to
/// llvm.eh.resume.
BasicBlock *InvokeInliningInfo::getInnerUnwindDest() {
  if (InnerUnwindDest) return InnerUnwindDest;

  // Find and hoist the llvm.eh.exception and llvm.eh.selector calls
  // in the outer landing pad to immediately following the phis.
  EHSelectorInst *selector = getOuterSelector();
  if (!selector) return 0;

  // The call to llvm.eh.exception *must* be in the landing pad.
  Instruction *exn = cast<Instruction>(selector->getArgOperand(0));
  assert(exn->getParent() == OuterUnwindDest);

  // TODO: recognize when we've already done this, so that we don't
  // get a linear number of these when inlining calls into lots of
  // invokes with the same landing pad.

  // Do the hoisting.
  Instruction *splitPoint = exn->getParent()->getFirstNonPHI();
  assert(splitPoint != selector && "selector-on-exception dominance broken!");
  if (splitPoint == exn) {
    selector->removeFromParent();
    selector->insertAfter(exn);
    splitPoint = selector->getNextNode();
  } else {
    exn->moveBefore(splitPoint);
    selector->moveBefore(splitPoint);
  }

  // Split the landing pad.
  InnerUnwindDest = OuterUnwindDest->splitBasicBlock(splitPoint,
                                        OuterUnwindDest->getName() + ".body");

  // The number of incoming edges we expect to the inner landing pad.
  const unsigned phiCapacity = 2;

  // Create corresponding new phis for all the phis in the outer landing pad.
  BasicBlock::iterator insertPoint = InnerUnwindDest->begin();
  BasicBlock::iterator I = OuterUnwindDest->begin();
  for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
    PHINode *outerPhi = cast<PHINode>(I);
    PHINode *innerPhi = PHINode::Create(outerPhi->getType(), phiCapacity,
                                        outerPhi->getName() + ".lpad-body",
                                        insertPoint);
    innerPhi->addIncoming(outerPhi, OuterUnwindDest);<commit_msg>Fix this to work correctly with phis;  test case to follow if this successfully fixes self-host.<commit_after>//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
// The code in this file for handling inlines through invoke
// instructions preserves semantics only under some assumptions about
// the behavior of unwinders which correspond to gcc-style libUnwind
// exception personality functions.  Eventually the IR will be
// improved to make this unnecessary, but until then, this code is
// marked [LIBUNWIND].
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Intrinsics.h"
#include "llvm/Attributes.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/IRBuilder.h"
using namespace llvm;

bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI) {
  return InlineFunction(CallSite(CI), IFI);
}
bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI) {
  return InlineFunction(CallSite(II), IFI);
}

/// [LIBUNWIND] Find the (possibly absent) call to @llvm.eh.selector in
/// the given landing pad.
static EHSelectorInst *findSelectorForLandingPad(BasicBlock *lpad) {
  // The llvm.eh.exception call is required to be in the landing pad.
  for (BasicBlock::iterator i = lpad->begin(), e = lpad->end(); i != e; i++) {
    EHExceptionInst *exn = dyn_cast<EHExceptionInst>(i);
    if (!exn) continue;

    EHSelectorInst *selector = 0;
    for (Instruction::use_iterator
           ui = exn->use_begin(), ue = exn->use_end(); ui != ue; ++ui) {
      EHSelectorInst *sel = dyn_cast<EHSelectorInst>(*ui);
      if (!sel) continue;

      // Immediately accept an eh.selector in the landing pad.
      if (sel->getParent() == lpad) return sel;

      // Otherwise, use the first selector we see.
      if (!selector) selector = sel;
    }

    return selector;
  }

  return 0;
}

namespace {
  /// A class for recording information about inlining through an invoke.
  class InvokeInliningInfo {
    BasicBlock *OuterUnwindDest;
    EHSelectorInst *OuterSelector;
    BasicBlock *InnerUnwindDest;
    PHINode *InnerExceptionPHI;
    PHINode *InnerSelectorPHI;
    SmallVector<Value*, 8> UnwindDestPHIValues;

  public:
    InvokeInliningInfo(InvokeInst *II) :
      OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
      InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) {

      // If there are PHI nodes in the unwind destination block, we
      // need to keep track of which values came into them from the
      // invoke before removing the edge from this block.
      llvm::BasicBlock *invokeBB = II->getParent();
      for (BasicBlock::iterator I = OuterUnwindDest->begin();
             isa<PHINode>(I); ++I) {
        // Save the value to use for this edge.
        PHINode *phi = cast<PHINode>(I);
        UnwindDestPHIValues.push_back(phi->getIncomingValueForBlock(invokeBB));
      }
    }

    /// The outer unwind destination is the target of unwind edges
    /// introduced for calls within the inlined function.
    BasicBlock *getOuterUnwindDest() const {
      return OuterUnwindDest;
    }

    EHSelectorInst *getOuterSelector() {
      if (!OuterSelector)
        OuterSelector = findSelectorForLandingPad(OuterUnwindDest);
      return OuterSelector;
    }

    BasicBlock *getInnerUnwindDest();

    bool forwardEHResume(CallInst *call, BasicBlock *src);

    /// Add incoming-PHI values to the unwind destination block for
    /// the given basic block, using the values for the original
    /// invoke's source block.
    void addIncomingPHIValuesFor(BasicBlock *BB) const {
      addIncomingPHIValuesForInto(BB, OuterUnwindDest);
    }

    void addIncomingPHIValuesForInto(BasicBlock *src, BasicBlock *dest) const {
      BasicBlock::iterator I = dest->begin();
      for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
        PHINode *phi = cast<PHINode>(I);
        phi->addIncoming(UnwindDestPHIValues[i], src);
      }
    }
  };
}

/// Replace all the instruction uses of a value with a different value.
/// This has the advantage of not screwing up the CallGraph.
static void replaceAllInsnUsesWith(Instruction *insn, Value *replacement) {
  for (Value::use_iterator i = insn->use_begin(), e = insn->use_end();
       i != e; ) {
    Use &use = i.getUse();
    ++i;
    if (isa<Instruction>(use.getUser()))
      use.set(replacement);
  }
}

/// Get or create a target for the branch out of rewritten calls to
/// llvm.eh.resume.
BasicBlock *InvokeInliningInfo::getInnerUnwindDest() {
  if (InnerUnwindDest) return InnerUnwindDest;

  // Find and hoist the llvm.eh.exception and llvm.eh.selector calls
  // in the outer landing pad to immediately following the phis.
  EHSelectorInst *selector = getOuterSelector();
  if (!selector) return 0;

  // The call to llvm.eh.exception *must* be in the landing pad.
  Instruction *exn = cast<Instruction>(selector->getArgOperand(0));
  assert(exn->getParent() == OuterUnwindDest);

  // TODO: recognize when we've already done this, so that we don't
  // get a linear number of these when inlining calls into lots of
  // invokes with the same landing pad.

  // Do the hoisting.
  Instruction *splitPoint = exn->getParent()->getFirstNonPHI();
  assert(splitPoint != selector && "selector-on-exception dominance broken!");
  if (splitPoint == exn) {
    selector->removeFromParent();
    selector->insertAfter(exn);
    splitPoint = selector->getNextNode();
  } else {
    exn->moveBefore(splitPoint);
    selector->moveBefore(splitPoint);
  }

  // Split the landing pad.
  InnerUnwindDest = OuterUnwindDest->splitBasicBlock(splitPoint,
                                        OuterUnwindDest->getName() + ".body");

  // The number of incoming edges we expect to the inner landing pad.
  const unsigned phiCapacity = 2;

  // Create corresponding new phis for all the phis in the outer landing pad.
  BasicBlock::iterator insertPoint = InnerUnwindDest->begin();
  BasicBlock::iterator I = OuterUnwindDest->begin();
  for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
    PHINode *outerPhi = cast<PHINode>(I);
    PHINode *innerPhi = PHINode::Create(outerPhi->getType(), phiCapacity,
                                        outerPhi->getName() + ".lpad-body",
                                        insertPoint);
    outerPhi->replaceAllUsesWith(innerPhi);
    innerPhi->addIncoming(outerPhi, OuterUnwindDest);
{'fraction_non_alphanumeric': 0.1361596354346475, 'fraction_numerical': 0.001657115238555548, 'mean_word_length': 3.0605550883095036, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3616259', 'n_tokens_mistral': 4326, 'n_tokens_neox': 4212, 'n_words': 1273}