<commit_before>//===- ProfileVerifierPass.cpp - LLVM Pass to estimate profile info -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass that checks profiling information for
// plausibility.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "profile-verifier"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Debug.h"
#include <set>
using namespace llvm;

static cl::opt<bool,false>
ProfileVerifierDisableAssertions("profile-verifier-noassert",
     cl::desc("Disable assertions"));

namespace llvm {
  template<class FType, class BType>
  class ProfileVerifierPassT : public FunctionPass {

    struct DetailedBlockInfo {
      const BType *BB;
      double      BBWeight;
      double      inWeight;
      int         inCount;
      double      outWeight;
      int         outCount;
    };

    ProfileInfoT<FType, BType> *PI;
    std::set<const BType*> BBisVisited;
    std::set<const FType*>   FisVisited;
    bool DisableAssertions;

    // When debugging is enabled, the verifier prints a whole slew of debug
    // information, otherwise its just the assert. These are all the helper
    // functions.
    bool PrintedDebugTree;
    std::set<const BType*> BBisPrinted;
    void debugEntry(DetailedBlockInfo*);
    void printDebugInfo(const BType *BB);

  public:
    static char ID; // Class identification, replacement for typeinfo

    explicit ProfileVerifierPassT () : FunctionPass(&ID) {
      DisableAssertions = ProfileVerifierDisableAssertions;
    }
    explicit ProfileVerifierPassT (bool da) : FunctionPass(&ID),
                                              DisableAssertions(da) {
    }

    void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
      AU.addRequired<ProfileInfoT<FType, BType> >();
    }

    const char *getPassName() const {
      return "Profiling information verifier";
    }

    /// run - Verify the profile information.
    bool runOnFunction(FType &F);
    void recurseBasicBlock(const BType*);

    bool   exitReachable(const FType*);
    double ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge);
    void   CheckValue(bool, const char*, DetailedBlockInfo*);
  };

  typedef ProfileVerifierPassT<Function, BasicBlock> ProfileVerifierPass;

  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::printDebugInfo(const BType *BB) {

    if (BBisPrinted.find(BB) != BBisPrinted.end()) return;

    double BBWeight = PI->getExecutionCount(BB);
    if (BBWeight == ProfileInfoT<FType, BType>::MissingValue) { BBWeight = 0; }
    double inWeight = 0;
    int inCount = 0;
    std::set<const BType*> ProcessedPreds;
    for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
          bbi != bbe; ++bbi ) {
      if (ProcessedPreds.insert(*bbi).second) {
        typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(*bbi,BB);
        double EdgeWeight = PI->getEdgeWeight(E);
        if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
        errs() << "calculated in-edge " << E << ": "
               << format("%20.20g",EdgeWeight) << "\n";
        inWeight += EdgeWeight;
        inCount++;
      }
    }
    double outWeight = 0;
    int outCount = 0;
    std::set<const BType*> ProcessedSuccs;
    for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
          bbi != bbe; ++bbi ) {
      if (ProcessedSuccs.insert(*bbi).second) {
        typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(BB,*bbi);
        double EdgeWeight = PI->getEdgeWeight(E);
        if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
        errs() << "calculated out-edge " << E << ": "
               << format("%20.20g",EdgeWeight) << "\n";
        outWeight += EdgeWeight;
        outCount++;
      }
    }
    errs() << "Block " << BB->getNameStr()                << " in "
           << BB->getParent()->getNameStr()               << ":"
           << "BBWeight="  << format("%20.20g",BBWeight)  << ","
           << "inWeight="  << format("%20.20g",inWeight)  << ","
           << "inCount="   << inCount                     << ","
           << "outWeight=" << format("%20.20g",outWeight) << ","
           << "outCount"   << outCount                    << "\n";

    // mark as visited and recurse into subnodes
    BBisPrinted.insert(BB);
    for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
          bbi != bbe; ++bbi ) {
      printDebugInfo(*bbi);
    }
  }

  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::debugEntry (DetailedBlockInfo *DI) {
    errs() << "TROUBLE: Block " << DI->BB->getNameStr()       << " in "
           << DI->BB->getParent()->getNameStr()               << ":"
           << "BBWeight="  << format("%20.20g",DI->BBWeight)  << ","
           << "inWeight="  << format("%20.20g",DI->inWeight)  << ","
           << "inCount="   << DI->inCount                     << ","
           << "outWeight=" << format("%20.20g",DI->outWeight) << ","
           << "outCount="  << DI->outCount                    << "\n";
    if (!PrintedDebugTree) {
      PrintedDebugTree = true;
      printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
    }
  }

  // This compares A and B for equality.
  static bool Equals(double A, double B) {
    return A == B;
  }

  // This checks if the function "exit" is reachable from an given function
  // via calls, this is necessary to check if a profile is valid despite the
  // counts not fitting exactly.
  template<class FType, class BType>
  bool ProfileVerifierPassT<FType, BType>::exitReachable(const FType *F) {
    if (!F) return false;

    if (FisVisited.count(F)) return false;

    FType *Exit = F->getParent()->getFunction("exit");
    if (Exit == F) {
      return true;
    }

    FisVisited.insert(F);
    bool exits = false;
    for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      if (const CallInst *CI = dyn_cast<CallInst>(&*I)) {
        FType *F = CI->getCalledFunction();
        if (F) {
          exits |= exitReachable(F);
        } else {
          // This is a call to a pointer, all bets are off...
          exits = true;
        }
        if (exits) break;
      }
    }
    return exits;
  }

  #define ASSERTMESSAGE(M) \
    { errs() << "ASSERT:" << (M) << "\n"; \
      if (!DisableAssertions) assert(0 && (M)); }

  template<class FType, class BType>
  double ProfileVerifierPassT<FType, BType>::ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge E) {
    double EdgeWeight = PI->getEdgeWeight(E);
    if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) {
      errs() << "Edge " << E << " in Function "
             << ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": ";
      ASSERTMESSAGE("Edge has missing value");
      return 0;
    } else {
      if (EdgeWeight < 0) {
        errs() << "Edge " << E << " in Function "
               << ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": ";
        ASSERTMESSAGE("Edge has negative value");
      }
      return EdgeWeight;
    }
  }

  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::CheckValue(bool Error,
                                                      const char *Message,
                                                      DetailedBlockInfo *DI) {
    if (Error) {
      DEBUG(debugEntry(DI));
      errs() << "Block " << DI->BB->getNameStr() << " in Function "
             << DI->BB->getParent()->getNameStr() << ": ";
      ASSERTMESSAGE(Message);
    }
    return;
  }

  // This calculates the Information for a block and then recurses into the
  // successors.
  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::recurseBasicBlock(const BType *BB) {

    // Break the recursion by remembering all visited blocks.
    if (BBisVisited.find(BB) != BBisVisited.end()) return;

    // Use a data structure to store all the information, this can then be handed
    // to debug printers.
    DetailedBlockInfo DI;
    DI.BB = BB;
    DI.outCount = DI.inCount = 0;
    DI.inWeight = DI.outWeight = 0;

    // Read predecessors.
    std::set<const BType*> ProcessedPreds;
    pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
    // If there are none, check for (0,BB) edge.
    if (bpi == bpe) {
      DI.inWeight += ReadOrAssert(PI->getEdge(0,BB));
      DI.inCount++;
    }
    for (;bpi != bpe; ++bpi) {
      if (ProcessedPreds.insert(*bpi).second) {
        DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB));
        DI.inCount++;
      }
    }

    // Read successors.
    std::set<const BType*> ProcessedSuccs;
    succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
    // If there is an (0,BB) edge, consider it too. (This is done not only when
    // there are no successors, but every time; not every function contains
    // return blocks with no successors (think loop latch as return block)).
    double w = PI->getEdgeWeight(PI->getEdge(BB,0));
    if (w != ProfileInfoT<FType, BType>::MissingValue) {
      DI.outWeight += w;
      DI.outCount++;
    }
    for (;bbi != bbe; ++bbi) {
      if (ProcessedSuccs.insert(*bbi).second) {
        DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
        DI.outCount++;
      }
    }

    // Read block weight.
    DI.BBWeight = PI->getExecutionCount(BB);
    CheckValue(DI.BBWeight == ProfileInfoT<FType, BType>::MissingValue,
               "BasicBlock has missing value", &DI);
    CheckValue(DI.BBWeight < 0,
               "BasicBlock has negative value", &DI);

    // Check if this block is a setjmp target.
    bool isSetJmpTarget = false;
    if (DI.outWeight > DI.inWeight) {
      for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
           i != ie; ++i) {
        if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
          FType *F = CI->getCalledFunction();
          if (F && (F->getNameStr() == "_setjmp")) {
            isSetJmpTarget = true; break;
          }
        }
      }
    }
    // Check if this block is eventually reaching exit.
    bool isExitReachable = false;
    if (DI.inWeight > DI.outWeight) {
      for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
           i != ie; ++i) {
        if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
          FType *F = CI->getCalledFunction();
          if (F) {
            FisVisited.clear();
            isExitReachable |= exitReachable(F);
          } else {
            // This is a call to a pointer, all bets are off...
            isExitReachable = true;
          }
          if (isExitReachable) break;
        }
      }
    }

    if (DI.inCount > 0 && DI.outCount == 0) {
       // If this is a block with no successors.
      if (!isSetJmpTarget) {
        CheckValue(!Equals(DI.inWeight,DI.BBWeight),
                   "inWeight and BBWeight do not match", &DI);
      }
    } else if (DI.inCount == 0 && DI.outCount > 0) {
      // If this is a block with no predecessors.
      if (!isExitReachable)
        CheckValue(!Equals(DI.BBWeight,DI.outWeight),
                   "BBWeight and outWeight do not match", &DI);
    } else {
      // If this block has successors and predecessors.
      if (DI.inWeight > DI.outWeight && !isExitReachable)
        CheckValue(!Equals(DI.inWeight,DI.outWeight),
                   "inWeight and outWeight do not match", &DI);
      if (DI.inWeight < DI.outWeight && !isSetJmpTarget)
        CheckValue(!Equals(DI.inWeight,DI.outWeight),
                   "inWeight and outWeight do not match", &DI);
    }

    // Mark this block as visited, rescurse into successors.
    BBisVisited.insert(BB);
    for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
          bbi != bbe; ++bbi ) {
      recurseBasicBlock(*bbi);
    }
  }

  template<class FType, class BType>
  bool ProfileVerifierPassT<FType, BType>::runOnFunction(FType &F) {
    PI = getAnalysisIfAvailable<ProfileInfoT<FType, BType> >();
    if (!PI)
      ASSERTMESSAGE("No ProfileInfo available");

    // Prepare global variables.
    PrintedDebugTree = false;
    BBisVisited.clear();

    // Fetch entry block and recurse into it.
    const BType *entry = &F.getEntryBlock();
    recurseBasicBlock(entry);

    if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry))
      ASSERTMESSAGE("Function count and entry block count do not match");

    return false;
  }

  template<class FType, class BType>
  char ProfileVerifierPassT<FType, BType>::ID = 0;
}

static RegisterPass<ProfileVerifierPass>
X("profile-verifier", "Verify profiling information", false, true);

namespace llvm {
  FunctionPass *createProfileVerifierPass() {
    return new ProfileVerifierPass(ProfileVerifierDisableAssertions);
  }
}

<commit_msg><commit_after>//===- ProfileVerifierPass.cpp - LLVM Pass to estimate profile info -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass that checks profiling information for
// plausibility.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "profile-verifier"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Debug.h"
#include <set>
using namespace llvm;

static cl::opt<bool,false>
ProfileVerifierDisableAssertions("profile-verifier-noassert",
     cl::desc("Disable assertions"));

namespace llvm {
  template<class FType, class BType>
  class ProfileVerifierPassT : public FunctionPass {

    struct DetailedBlockInfo {
      const BType *BB;
      double      BBWeight;
      double      inWeight;
      int         inCount;
      double      outWeight;
      int         outCount;
    };

    ProfileInfoT<FType, BType> *PI;
    std::set<const BType*> BBisVisited;
    std::set<const FType*>   FisVisited;
    bool DisableAssertions;

    // When debugging is enabled, the verifier prints a whole slew of debug
    // information, otherwise its just the assert. These are all the helper
    // functions.
    bool PrintedDebugTree;
    std::set<const BType*> BBisPrinted;
    void debugEntry(DetailedBlockInfo*);
    void printDebugInfo(const BType *BB);

  public:
    static char ID; // Class identification, replacement for typeinfo

    explicit ProfileVerifierPassT () : FunctionPass(&ID) {
      DisableAssertions = ProfileVerifierDisableAssertions;
    }
    explicit ProfileVerifierPassT (bool da) : FunctionPass(&ID),
                                              DisableAssertions(da) {
    }

    void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
      AU.addRequired<ProfileInfoT<FType, BType> >();
    }

    const char *getPassName() const {
      return "Profiling information verifier";
    }

    /// run - Verify the profile information.
    bool runOnFunction(FType &F);
    void recurseBasicBlock(const BType*);

    bool   exitReachable(const FType*);
    double ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge);
    void   CheckValue(bool, const char*, DetailedBlockInfo*);
  };

  typedef ProfileVerifierPassT<Function, BasicBlock> ProfileVerifierPass;

  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::printDebugInfo(const BType *BB) {

    if (BBisPrinted.find(BB) != BBisPrinted.end()) return;

    double BBWeight = PI->getExecutionCount(BB);
    if (BBWeight == ProfileInfoT<FType, BType>::MissingValue) { BBWeight = 0; }
    double inWeight = 0;
    int inCount = 0;
    std::set<const BType*> ProcessedPreds;
    for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
          bbi != bbe; ++bbi ) {
      if (ProcessedPreds.insert(*bbi).second) {
        typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(*bbi,BB);
        double EdgeWeight = PI->getEdgeWeight(E);
        if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
        dbgs() << "calculated in-edge " << E << ": "
               << format("%20.20g",EdgeWeight) << "\n";
        inWeight += EdgeWeight;
        inCount++;
      }
    }
    double outWeight = 0;
    int outCount = 0;
    std::set<const BType*> ProcessedSuccs;
    for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
          bbi != bbe; ++bbi ) {
      if (ProcessedSuccs.insert(*bbi).second) {
        typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(BB,*bbi);
        double EdgeWeight = PI->getEdgeWeight(E);
        if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
        dbgs() << "calculated out-edge " << E << ": "
               << format("%20.20g",EdgeWeight) << "\n";
        outWeight += EdgeWeight;
        outCount++;
      }
    }
    dbgs() << "Block " << BB->getNameStr()                << " in "
           << BB->getParent()->getNameStr()               << ":"
           << "BBWeight="  << format("%20.20g",BBWeight)  << ","
           << "inWeight="  << format("%20.20g",inWeight)  << ","
           << "inCount="   << inCount                     << ","
           << "outWeight=" << format("%20.20g",outWeight) << ","
           << "outCount"   << outCount                    << "\n";

    // mark as visited and recurse into subnodes
    BBisPrinted.insert(BB);
    for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
          bbi != bbe; ++bbi ) {
      printDebugInfo(*bbi);
    }
  }

  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::debugEntry (DetailedBlockInfo *DI) {
    dbgs() << "TROUBLE: Block " << DI->BB->getNameStr()       << " in "
           << DI->BB->getParent()->getNameStr()               << ":"
           << "BBWeight="  << format("%20.20g",DI->BBWeight)  << ","
           << "inWeight="  << format("%20.20g",DI->inWeight)  << ","
           << "inCount="   << DI->inCount                     << ","
           << "outWeight=" << format("%20.20g",DI->outWeight) << ","
           << "outCount="  << DI->outCount                    << "\n";
    if (!PrintedDebugTree) {
      PrintedDebugTree = true;
      printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
    }
  }

  // This compares A and B for equality.
  static bool Equals(double A, double B) {
    return A == B;
  }

  // This checks if the function "exit" is reachable from an given function
  // via calls, this is necessary to check if a profile is valid despite the
  // counts not fitting exactly.
  template<class FType, class BType>
  bool ProfileVerifierPassT<FType, BType>::exitReachable(const FType *F) {
    if (!F) return false;

    if (FisVisited.count(F)) return false;

    FType *Exit = F->getParent()->getFunction("exit");
    if (Exit == F) {
      return true;
    }

    FisVisited.insert(F);
    bool exits = false;
    for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
      if (const CallInst *CI = dyn_cast<CallInst>(&*I)) {
        FType *F = CI->getCalledFunction();
        if (F) {
          exits |= exitReachable(F);
        } else {
          // This is a call to a pointer, all bets are off...
          exits = true;
        }
        if (exits) break;
      }
    }
    return exits;
  }

  #define ASSERTMESSAGE(M) \
    { dbgs() << "ASSERT:" << (M) << "\n"; \
      if (!DisableAssertions) assert(0 && (M)); }

  template<class FType, class BType>
  double ProfileVerifierPassT<FType, BType>::ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge E) {
    double EdgeWeight = PI->getEdgeWeight(E);
    if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) {
      dbgs() << "Edge " << E << " in Function "
             << ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": ";
      ASSERTMESSAGE("Edge has missing value");
      return 0;
    } else {
      if (EdgeWeight < 0) {
        dbgs() << "Edge " << E << " in Function "
               << ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": ";
        ASSERTMESSAGE("Edge has negative value");
      }
      return EdgeWeight;
    }
  }

  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::CheckValue(bool Error,
                                                      const char *Message,
                                                      DetailedBlockInfo *DI) {
    if (Error) {
      DEBUG(debugEntry(DI));
      dbgs() << "Block " << DI->BB->getNameStr() << " in Function "
             << DI->BB->getParent()->getNameStr() << ": ";
      ASSERTMESSAGE(Message);
    }
    return;
  }

  // This calculates the Information for a block and then recurses into the
  // successors.
  template<class FType, class BType>
  void ProfileVerifierPassT<FType, BType>::recurseBasicBlock(const BType *BB) {

    // Break the recursion by remembering all visited blocks.
    if (BBisVisited.find(BB) != BBisVisited.end()) return;

    // Use a data structure to store all the information, this can then be handed
    // to debug printers.
    DetailedBlockInfo DI;
    DI.BB = BB;
    DI.outCount = DI.inCount = 0;
    DI.inWeight = DI.outWeight = 0;

    // Read predecessors.
    std::set<const BType*> ProcessedPreds;
    pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
    // If there are none, check for (0,BB) edge.
    if (bpi == bpe) {
      DI.inWeight += ReadOrAssert(PI->getEdge(0,BB));
      DI.inCount++;
    }
    for (;bpi != bpe; ++bpi) {
      if (ProcessedPreds.insert(*bpi).second) {
        DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB));
        DI.inCount++;
      }
    }

    // Read successors.
    std::set<const BType*> ProcessedSuccs;
    succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
    // If there is an (0,BB) edge, consider it too. (This is done not only when
    // there are no successors, but every time; not every function contains
    // return blocks with no successors (think loop latch as return block)).
    double w = PI->getEdgeWeight(PI->getEdge(BB,0));
    if (w != ProfileInfoT<FType, BType>::MissingValue) {
      DI.outWeight += w;
      DI.outCount++;
    }
    for (;bbi != bbe; ++bbi) {
      if (ProcessedSuccs.insert(*bbi).second) {
        DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
        DI.outCount++;
      }
    }

    // Read block weight.
    DI.BBWeight = PI->getExecutionCount(BB);
    CheckValue(DI.BBWeight == ProfileInfoT<FType, BType>::MissingValue,
               "BasicBlock has missing value", &DI);
    CheckValue(DI.BBWeight < 0,
               "BasicBlock has negative value", &DI);

    // Check if this block is a setjmp target.
    bool isSetJmpTarget = false;
    if (DI.outWeight > DI.inWeight) {
      for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
           i != ie; ++i) {
        if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
          FType *F = CI->getCalledFunction();
          if (F && (F->getNameStr() == "_setjmp")) {
            isSetJmpTarget = true; break;
          }
        }
      }
    }
    // Check if this block is eventually reaching exit.
    bool isExitReachable = false;
    if (DI.inWeight > DI.outWeight) {
      for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
           i != ie; ++i) {
        if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
          FType *F = CI->getCalledFunction();
          if (F) {
            FisVisited.clear();
            isExitReachable |= exitReachable(F);
          } else {
            // This is a call to a pointer, all bets are off...
            isExitReachable = true;
          }
          if (isExitReachable) break;
        }
      }
    }

    if (DI.inCount > 0 && DI.outCount == 0) {
       // If this is a block with no successors.
      if (!isSetJmpTarget) {
        CheckValue(!Equals(DI.inWeight,DI.BBWeight),
                   "inWeight and BBWeight do not match", &DI);
      }
    } else if (DI.inCount == 0 && DI.outCount > 0) {
      // If this is a block with no predecessors.
      if (!isExitReachable)
        CheckValue(!Equals(DI.BBWeight,DI.outWeight),
                   "BBWeight and outWeight do not match", &DI);
    } else {
      // If this block has successors and predecessors.
      if (DI.inWeight > DI.outWeight && !isExitReachable)
        CheckValue(!Equals(DI.inWeight,DI.outWeight),
                   "inWeight and outWeight do not match", &DI);
      if (DI.inWeight < DI.outWeight && !isSetJmpTarget)
        CheckValue(!Equals(DI.inWeight,DI.outWeight),
                   "inWeight and outWeight do not match", &DI);
    }

    // Mark this block as visited, rescurse into successors.
    BBisVisited.insert(BB);
    for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
          bbi != bbe; ++bbi ) {
      recurseBasicBlock(*bbi);
    }
  }

  template<class FType, class BType>
  bool ProfileVerifierPassT<FType, BType>::runOnFunction(FType &F) {
    PI = getAnalysisIfAvailable<ProfileInfoT<FType, BType> >();
    if (!PI)
      ASSERTMESSAGE("No ProfileInfo available");

    // Prepare global variables.
    PrintedDebugTree = false;
    BBisVisited.clear();

    // Fetch entry block and recurse into it.
    const BType *entry = &F.getEntryBlock();
    recurseBasicBlock(entry);

    if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry))
      ASSERTMESSAGE("Function count and entry block count do not match");

    return false;
  }

  template<class FType, class BType>
  char ProfileVerifierPassT<FType, BType>::ID = 0;
}

static RegisterPass<ProfileVerifierPass>
X("profile-verifier", "Verify profiling information", false, true);

namespace llvm {
  FunctionPass *createProfileVerifierPass() {
    return new ProfileVerifierPass(ProfileVerifierDisableAssertions);
  }
}

<|endoftext|>


<commit_before>#pragma once

#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>

// ----------------------------------------------------------------------

enum class report_time { No, Yes };

class Timeit
{
 public:
    inline Timeit(std::string msg, report_time aReport = report_time::Yes, std::ostream& out = std::cerr)
        : message(msg), out_stream(out), mReport(aReport), start(std::chrono::steady_clock::now()) {}

    inline ~Timeit() { report(); }

    inline void report()
        {
            if (mReport == report_time::Yes) {
                const auto total = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
                const decltype(total) s = total / 1000;
                const decltype(total) ms = total % 1000;
                out_stream << message;
                out_stream << s << '.' << std::setw(3) << std::setfill('0') << ms << std::setw(0) << '\n';
                mReport = report_time::No;
            }
        }

    inline void message_append(std::string to_append) { message += to_append; }

 private:
    std::string message;
    std::ostream& out_stream;
    report_time mReport;
    decltype(std::chrono::steady_clock::now()) start;
};

inline report_time do_report_time(bool do_report) { return do_report ? report_time::Yes : report_time::No; }

// ----------------------------------------------------------------------

namespace acmacs
{
    using timestamp_t = decltype(std::chrono::steady_clock::now());
    inline timestamp_t timestamp() { return std::chrono::steady_clock::now(); }
    inline double elapsed(timestamp_t start)
    {
        const auto diff = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - start).count();
        const decltype(diff) sec = diff / std::nano::den;
        const decltype(diff) nanosec = diff % std::nano::den;
        return static_cast<double>(sec) + static_cast<double>(nanosec) / double{std::nano::den};
    }

} // namespace acmacs

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>duration format<commit_after>#pragma once

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <chrono>

// ----------------------------------------------------------------------

namespace acmacs
{
    using timestamp_t = decltype(std::chrono::high_resolution_clock::now());
    using duration_t = std::chrono::nanoseconds;

    inline timestamp_t timestamp() { return std::chrono::high_resolution_clock::now(); }

    inline duration_t elapsed(timestamp_t start) { return std::chrono::duration_cast<duration_t>(timestamp() - start); }
      //inline auto days(duration_t duration) { return std::chrono::duration_cast<std::chrono::days>(duration); }
    // inline auto hours(duration_t duration) { return std::chrono::duration_cast<std::chrono::hours>(duration); }

    inline std::string format(duration_t duration)
    {
        std::stringstream result;
        auto hours = std::chrono::duration_cast<std::chrono::hours>(duration).count();
        if (hours > 24) {
            result << (hours / 24) << "d:";
            hours %= 24;
        }
        auto format_val = [](auto& target, auto val, char terminator) {
            if (val || target.tellg())
                target << std::setw(2) << std::setfill('0') << val << terminator;
        };
        format_val(result, hours, ':');
        const auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration % std::chrono::hours(1)).count();
        format_val(result, minutes, ':');
        const auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration % std::chrono::minutes(1)).count();
        if (result.tellg())
            result << std::setw(2) << std::setfill('0');
        result << seconds << '.';
        const auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(duration % std::chrono::seconds(1)).count();
        result << std::setw(6) << std::setfill('0') << microseconds;
        return result.str();
    }

    inline double elapsed_seconds(timestamp_t start)
    {
        const auto diff = elapsed(start).count();
        const decltype(diff) sec = diff / std::nano::den;
        const decltype(diff) nanosec = diff % std::nano::den;
        return static_cast<double>(sec) + static_cast<double>(nanosec) / double{std::nano::den};
    }

} // namespace acmacs

// ----------------------------------------------------------------------

enum class report_time { No, Yes };

class Timeit
{
 public:
    inline Timeit(std::string msg, report_time aReport = report_time::Yes, std::ostream& out = std::cerr)
        : message(msg), out_stream(out), mReport(aReport), start(acmacs::timestamp()) {}

    inline ~Timeit() { report(); }

    inline void report()
        {
            if (mReport == report_time::Yes) {
                  // const auto total = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
                const auto total = std::chrono::duration_cast<std::chrono::milliseconds>(acmacs::elapsed(start)).count();
                const decltype(total) s = total / 1000;
                const decltype(total) ms = total % 1000;
                out_stream << message;
                out_stream << s << '.' << std::setw(3) << std::setfill('0') << ms << std::setw(0) << '\n';
                mReport = report_time::No;
            }
        }

    inline void message_append(std::string to_append) { message += to_append; }

 private:
    std::string message;
    std::ostream& out_stream;
    report_time mReport;
    acmacs::timestamp_t start;
};

inline report_time do_report_time(bool do_report) { return do_report ? report_time::Yes : report_time::No; }

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <catch.hpp>
#include <luwra.hpp>

#include <iostream>

using namespace luwra;

TEST_CASE("RefHandle") {
	StateWrapper state;
	state.loadStandardLibrary();

	state["didCollect"] = false;

	REQUIRE(state.runString(
		"return setmetatable({}, {\n"
			"__gc = function () didCollect = true end"
		"})"
	) == LUA_OK);

	bool didCollect = state["didCollect"];
	REQUIRE(!didCollect);

	{
		RefLifecycle ref(state, -1);
		lua_pop(state, 1);

		didCollect = state["didCollect"];
		REQUIRE(!didCollect);

		lua_gc(state, LUA_GCCOLLECT, 0);

		didCollect = state["didCollect"];
		REQUIRE(!didCollect);
	}

	lua_gc(state, LUA_GCCOLLECT, 0);

	didCollect = state["didCollect"];
	REQUIRE(didCollect);
}
<commit_msg>tests: Fix tests for 'RefLifecycle'<commit_after>#include <catch.hpp>
#include <luwra.hpp>

#include <iostream>

using namespace luwra;

// Set the referenced boolean to true upon garbage collection
struct GCTrigger {
	bool& target;

	GCTrigger(bool& target): target(target) {
		target = false;
	}

	~GCTrigger() {
		target = true;
	}
};

TEST_CASE("RefLifecycle") {
	StateWrapper state;

	state.loadStandardLibrary();
	state.registerUserType<GCTrigger>();

	bool didCollect;

	// We instantiate a type which will set didCollect to true upon garbage collection
	construct<GCTrigger>(state, didCollect);

	// didCollect starts off as false
	REQUIRE(!didCollect);

	{
		// Create the reference
		RefLifecycle refLife(state, -1);

		// Remove the user data from the stack and perform a full garbage collection cycle
		lua_pop(state, 1);
		lua_gc(state, LUA_GCCOLLECT, 0);

		// Since the reference still exists, the user data must not have been collected
		REQUIRE(!didCollect);
	}

	// Our reference goes out of scope, therefore making the user data unreachable. In order to
	// trigger the finalizers, we must collect the dead user data.
	lua_gc(state, LUA_GCCOLLECT, 0);

	// At this point, the finalizer should have been invoked
	REQUIRE(didCollect);
}
<|endoftext|>


<commit_before>#include "itkCommandLineArgumentParser.h"

#include "itkImage.h"
#include "itkRescaleIntensityImageFilter.h"
//#include "itkNumericTraits.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

//-------------------------------------------------------------------------------------

/** run: A macro to call a function. */
#define run(function,type,dim) \
if ( PixelType == #type && Dimension == #dim ) \
{ \
    typedef  itk::Image< type, dim >   InputImageType; \
    function< InputImageType >( inputFileName, outputFileName, minimum, maximum ); \
}

//-------------------------------------------------------------------------------------

/** Declare resizeImage. */
template< class InputImageType >
void rescaleIntensity( std::string inputFileName, std::string outputFileName, double minimum, double maximum );

//-------------------------------------------------------------------------------------

int main( int argc, char **argv )
{
	/** Check number of arguments. */
	if ( argc < 3 || argc > 11 || argv[ 1 ] == "--help" )
	{
		std::cout << "Usage:" << std::endl;
		std::cout << "\tpxrescaleintensityimagefilter -in inputfilename [-out outputfilename] [-mm minimum maximum] [-dim Dimension] [-pt PixelType]" << std::endl;
		std::cout << "Defaults: Dimension = 2, PixelType = short, out = in + INTENSITYRESCALED." << std::endl;
		std::cout << "Supported: 2D, 3D, (unsigned) short, (unsigned) char." << std::endl;
		return 1;
	}

	/** Create a command line argument parser. */
	itk::CommandLineArgumentParser::Pointer parser = itk::CommandLineArgumentParser::New();
	parser->SetCommandLineArguments( argc, argv );

	/** Get arguments. */
	std::string	inputFileName = "";
	bool ret1 = parser->GetCommandLineArgument( "-in", inputFileName );

	std::string	outputFileName = inputFileName.substr( 0, inputFileName.rfind( "." ) );
	outputFileName += "INTENSITYRESCALED.mhd";
	bool ret2 = parser->GetCommandLineArgument( "-out", outputFileName );

	std::vector<double> extrema(2);
	extrema[ 0 ] = 0.0; extrema[ 1 ] = 0.0;
	bool ret3 = parser->GetCommandLineArgument( "-mm", extrema );
	double minimum = extrema[ 0 ];
	double maximum = extrema[ 1 ];

	std::string	Dimension = "2";
	bool ret4 = parser->GetCommandLineArgument( "-dim", Dimension );

	std::string	PixelType = "short";
	bool ret5 = parser->GetCommandLineArgument( "-pt", PixelType );

	/** Check if the required arguments are given. */
	if ( !ret1 )
	{
		std::cerr << "ERROR: You should specify \"-in\"." << std::endl;
		return 1;
	}

	/** Check if the extrema are given (correctly). */
	if ( ret3 )
	{
		if ( extrema.size() != 2 )
		{
			std::cerr << "ERROR: You should specify \"-mm\" with two values." << std::endl;
			return 1;
		}
		if ( extrema[ 1 ] <= extrema[ 0 ] )
		{
			std::cerr << "ERROR: You should specify \"-mm\" with two values:" << std::endl;
			std::cerr << "minimum maximum, where it should hold that maximum > minimum." << std::endl;
			return 1;
		}
	}

	/** Get rid of the possible "_" in PixelType. */
	std::basic_string<char>::size_type pos = PixelType.find( "_" );
	static const std::basic_string<char>::size_type npos = std::basic_string<char>::npos;
	if ( pos != npos )
	{
		PixelType.replace( pos, 1, " " );
	}

	/** Run the program. */
	try
	{
		run(rescaleIntensity,unsigned char,2);
		run(rescaleIntensity,unsigned char,3);
		run(rescaleIntensity,char,2);
		run(rescaleIntensity,char,3);
		run(rescaleIntensity,unsigned short,2);
		run(rescaleIntensity,unsigned short,3);
		run(rescaleIntensity,short,2);
		run(rescaleIntensity,short,3);
	}
	catch( itk::ExceptionObject &e )
	{
		std::cerr << "Caught ITK exception: " << e << std::endl;
		return 1;
	}

	/** End program. */
	return 0;

} // end main

	/**
	 * ******************* resizeImage *******************
	 *
	 * The rescaleIntensity function templated over the input pixel type.
	 */

template< class InputImageType >
void rescaleIntensity( std::string inputFileName, std::string outputFileName, double minimum, double maximum )
{
	/** TYPEDEF's. */
	typedef itk::RescaleIntensityImageFilter< InputImageType, InputImageType >	RescalerType;
	typedef itk::ImageFileReader< InputImageType >			ReaderType;
	typedef itk::ImageFileWriter< InputImageType >			WriterType;
	typedef typename InputImageType::PixelType					PixelType;

	/** DECLARATION'S. */
	typename RescalerType::Pointer rescaler = RescalerType::New();
	typename ReaderType::Pointer reader = ReaderType::New();
	typename WriterType::Pointer writer = WriterType::New();

	/** Define the extrema. */
	PixelType min, max;
	if ( minimum == 0.0 && maximum == 0.0 )
	{
		min = itk::NumericTraits<PixelType>::min();
		max = itk::NumericTraits<PixelType>::max();
	}
	else
	{
		min = static_cast<PixelType>( minimum );
		max = static_cast<PixelType>( maximum );
	}

	/** Read in the inputImage. */
	reader->SetFileName( inputFileName.c_str() );

	/** Setup the rescaler. */
	rescaler->SetInput( reader->GetOutput() );
	rescaler->SetOutputMinimum( min );
	rescaler->SetOutputMaximum( max );

	/** Write the output image. */
	writer->SetFileName( outputFileName.c_str() );
	writer->SetInput( rescaler->GetOutput() );
	writer->Update();

} // end rescaleIntensity

<commit_msg>SK:<commit_after>#include "itkCommandLineArgumentParser.h"

#include "itkImage.h"
#include "itkRescaleIntensityImageFilter.h"
//#include "itkNumericTraits.h"

#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

//-------------------------------------------------------------------------------------

/** run: A macro to call a function. */
#define run(function,type,dim) \
if ( PixelType == #type && Dimension == #dim ) \
{ \
    typedef  itk::Image< type, dim >   InputImageType; \
    function< InputImageType >( inputFileName, outputFileName, minimum, maximum ); \
}

//-------------------------------------------------------------------------------------

/** Declare resizeImage. */
template< class InputImageType >
void rescaleIntensity( std::string inputFileName, std::string outputFileName, double minimum, double maximum );

//-------------------------------------------------------------------------------------

int main( int argc, char **argv )
{
	/** Check number of arguments. */
	if ( argc < 3 || argc > 12 || argv[ 1 ] == "--help" )
	{
		std::cout << "Usage:" << std::endl;
		std::cout << "\tpxrescaleintensityimagefilter -in inputfilename [-out outputfilename] [-mm minimum maximum] [-dim Dimension] [-pt PixelType]" << std::endl;
		std::cout << "Defaults: Dimension = 2, PixelType = short, out = in + INTENSITYRESCALED." << std::endl;
		std::cout << "Supported: 2D, 3D, (unsigned) short, (unsigned) char." << std::endl;
		return 1;
	}

	/** Create a command line argument parser. */
	itk::CommandLineArgumentParser::Pointer parser = itk::CommandLineArgumentParser::New();
	parser->SetCommandLineArguments( argc, argv );

	/** Get arguments. */
	std::string	inputFileName = "";
	bool ret1 = parser->GetCommandLineArgument( "-in", inputFileName );

	std::string	outputFileName = inputFileName.substr( 0, inputFileName.rfind( "." ) );
	outputFileName += "INTENSITYRESCALED.mhd";
	bool ret2 = parser->GetCommandLineArgument( "-out", outputFileName );

	std::vector<double> extrema(2);
	extrema[ 0 ] = 0.0; extrema[ 1 ] = 0.0;
	bool ret3 = parser->GetCommandLineArgument( "-mm", extrema );
	double minimum = extrema[ 0 ];
	double maximum = extrema[ 1 ];

	std::string	Dimension = "2";
	bool ret4 = parser->GetCommandLineArgument( "-dim", Dimension );

	std::string	PixelType = "short";
	bool ret5 = parser->GetCommandLineArgument( "-pt", PixelType );

	/** Check if the required arguments are given. */
	if ( !ret1 )
	{
		std::cerr << "ERROR: You should specify \"-in\"." << std::endl;
		return 1;
	}

	/** Check if the extrema are given (correctly). */
	if ( ret3 )
	{
		if ( extrema.size() != 2 )
		{
			std::cerr << "ERROR: You should specify \"-mm\" with two values." << std::endl;
			return 1;
		}
		if ( extrema[ 1 ] <= extrema[ 0 ] )
		{
			std::cerr << "ERROR: You should specify \"-mm\" with two values:" << std::endl;
			std::cerr << "minimum maximum, where it should hold that maximum > minimum." << std::endl;
			return 1;
		}
	}

	/** Get rid of the possible "_" in PixelType. */
	std::basic_string<char>::size_type pos = PixelType.find( "_" );
	static const std::basic_string<char>::size_type npos = std::basic_string<char>::npos;
	if ( pos != npos )
	{
		PixelType.replace( pos, 1, " " );
	}

	/** Run the program. */
	try
	{
		run(rescaleIntensity,unsigned char,2);
		run(rescaleIntensity,unsigned char,3);
		run(rescaleIntensity,char,2);
		run(rescaleIntensity,char,3);
		run(rescaleIntensity,unsigned short,2);
		run(rescaleIntensity,unsigned short,3);
		run(rescaleIntensity,short,2);
		run(rescaleIntensity,short,3);
	}
	catch( itk::ExceptionObject &e )
	{
		std::cerr << "Caught ITK exception: " << e << std::endl;
		return 1;
	}

	/** End program. */
	return 0;

} // end main

	/**
	 * ******************* resizeImage *******************
	 *
	 * The rescaleIntensity function templated over the input pixel type.
	 */

template< class InputImageType >
void rescaleIntensity( std::string inputFileName, std::string outputFileName, double minimum, double maximum )
{
	/** TYPEDEF's. */
	typedef itk::RescaleIntensityImageFilter< InputImageType, InputImageType >	RescalerType;
	typedef itk::ImageFileReader< InputImageType >			ReaderType;
	typedef itk::ImageFileWriter< InputImageType >			WriterType;
	typedef typename InputImageType::PixelType					PixelType;

	/** DECLARATION'S. */
	typename RescalerType::Pointer rescaler = RescalerType::New();
	typename ReaderType::Pointer reader = ReaderType::New();
	typename WriterType::Pointer writer = WriterType::New();

	/** Define the extrema. */
	PixelType min, max;
	if ( minimum == 0.0 && maximum == 0.0 )
	{
		min = itk::NumericTraits<PixelType>::min();
		max = itk::NumericTraits<PixelType>::max();
	}
	else
	{
		min = static_cast<PixelType>( minimum );
		max = static_cast<PixelType>( maximum );
	}

	/** Read in the inputImage. */
	reader->SetFileName( inputFileName.c_str() );

	/** Setup the rescaler. */
	rescaler->SetInput( reader->GetOutput() );
	rescaler->SetOutputMinimum( min );
	rescaler->SetOutputMaximum( max );

	/** Write the output image. */
	writer->SetFileName( outputFileName.c_str() );
	writer->SetInput( rescaler->GetOutput() );
	writer->Update();

} // end rescaleIntensity

<|endoftext|>


<commit_before>//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in 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 pass is responsible for finalizing the functions frame layout, saving
// callee saved registers, and for emitting prolog & epilog code for the
// function.
//
// This pass must be run after register allocation.  After this pass is
// executed, it is illegal to construct MO_FrameIndex operands.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

namespace {
  struct VISIBILITY_HIDDEN PEI : public MachineFunctionPass {
    const char *getPassName() const {
      return "Prolog/Epilog Insertion & Frame Finalization";
    }

    /// runOnMachineFunction - Insert prolog/epilog code and replace abstract
    /// frame indexes with appropriate references.
    ///
    bool runOnMachineFunction(MachineFunction &Fn) {
      // Get MachineDebugInfo so that we can track the construction of the
      // frame.
      if (MachineDebugInfo *DI = getAnalysisToUpdate<MachineDebugInfo>()) {
        Fn.getFrameInfo()->setMachineDebugInfo(DI);
      }

      // Scan the function for modified caller saved registers and insert spill
      // code for any caller saved registers that are modified.  Also calculate
      // the MaxCallFrameSize and HasCalls variables for the function's frame
      // information and eliminates call frame pseudo instructions.
      calculateCallerSavedRegisters(Fn);

      // Add the code to save and restore the caller saved registers
      saveCallerSavedRegisters(Fn);

      // Allow the target machine to make final modifications to the function
      // before the frame layout is finalized.
      Fn.getTarget().getRegisterInfo()->processFunctionBeforeFrameFinalized(Fn);

      // Calculate actual frame offsets for all of the abstract stack objects...
      calculateFrameObjectOffsets(Fn);

      // Add prolog and epilog code to the function.  This function is required
      // to align the stack frame as necessary for any stack variables or
      // called functions.  Because of this, calculateCallerSavedRegisters
      // must be called before this function in order to set the HasCalls
      // and MaxCallFrameSize variables.
      insertPrologEpilogCode(Fn);

      // Replace all MO_FrameIndex operands with physical register references
      // and actual offsets.
      //
      replaceFrameIndices(Fn);

      return true;
    }

  private:
    void calculateCallerSavedRegisters(MachineFunction &Fn);
    void saveCallerSavedRegisters(MachineFunction &Fn);
    void calculateFrameObjectOffsets(MachineFunction &Fn);
    void replaceFrameIndices(MachineFunction &Fn);
    void insertPrologEpilogCode(MachineFunction &Fn);
  };
}

/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }

/// calculateCallerSavedRegisters - Scan the function for modified caller saved
/// registers.  Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
void PEI::calculateCallerSavedRegisters(MachineFunction &Fn) {
  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();

  // Get the function call frame set-up and tear-down instruction opcode
  int FrameSetupOpcode   = RegInfo->getCallFrameSetupOpcode();
  int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode();

  // Early exit for targets which have no callee saved registers and no call
  // frame setup/destroy pseudo instructions.
  if ((CSRegs == 0 || CSRegs[0] == 0) &&
      FrameSetupOpcode == -1 && FrameDestroyOpcode == -1)
    return;

  unsigned MaxCallFrameSize = 0;
  bool HasCalls = false;

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
      if (I->getOpcode() == FrameSetupOpcode ||
          I->getOpcode() == FrameDestroyOpcode) {
        assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo"
               " instructions should have a single immediate argument!");
        unsigned Size = I->getOperand(0).getImmedValue();
        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
        HasCalls = true;
        RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
      } else {
        ++I;
      }

  MachineFrameInfo *FFI = Fn.getFrameInfo();
  FFI->setHasCalls(HasCalls);
  FFI->setMaxCallFrameSize(MaxCallFrameSize);

  // Now figure out which *callee saved* registers are modified by the current
  // function, thus needing to be saved and restored in the prolog/epilog.
  //
  const bool *PhysRegsUsed = Fn.getUsedPhysregs();
  const TargetRegisterClass* const *CSRegClasses =
    RegInfo->getCalleeSaveRegClasses();
  std::vector<CalleeSavedInfo> CSI;
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (PhysRegsUsed[Reg]) {
        // If the reg is modified, save it!
      CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too.
        if (PhysRegsUsed[*AliasSet]) {
          CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
          break;
        }
      }
    }
  }

  if (CSI.empty())
    return;   // Early exit if no caller saved registers are modified!

  unsigned NumFixedSpillSlots;
  const std::pair<unsigned,int> *FixedSpillSlots =
    TFI->getCalleeSaveSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    unsigned Reg = CSI[i].getReg();
    const TargetRegisterClass *RC = CSI[i].getRegClass();

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->first != Reg)
      ++FixedSlot;

    int FrameIdx;
    if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      FrameIdx = FFI->CreateStackObject(RC->getSize(), RC->getAlignment());
    } else {
      // Spill it to the stack where we must.
      FrameIdx = FFI->CreateFixedObject(RC->getSize(), FixedSlot->second);
    }
    CSI[i].setFrameIdx(FrameIdx);
  }

  FFI->setCalleeSavedInfo(CSI);
}

/// saveCallerSavedRegisters -  Insert spill code for any caller saved registers
/// that are modified in the function.
///
void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
  // Get callee saved register information.
  MachineFrameInfo *FFI = Fn.getFrameInfo();
  const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo();

  // Early exit if no caller saved registers are modified!
  if (CSI.empty())
    return;

  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();

  // Now that we have a stack slot for each register to be saved, insert spill
  // code into the entry block.
  MachineBasicBlock *MBB = Fn.begin();
  MachineBasicBlock::iterator I = MBB->begin();
  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    // Insert the spill to the stack frame.
    RegInfo->storeRegToStackSlot(*MBB, I, CSI[i].getReg(), CSI[i].getFrameIdx(),
                                 CSI[i].getRegClass());
  }

  // Add code to restore the callee-save registers in each exiting block.
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI)
    // If last instruction is a return instruction, add an epilogue.
    if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
      MBB = FI;
      I = MBB->end(); --I;

      // Skip over all terminator instructions, which are part of the return
      // sequence.
      MachineBasicBlock::iterator I2 = I;
      while (I2 != MBB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
        I = I2;

      bool AtStart = I == MBB->begin();
      MachineBasicBlock::iterator BeforeI = I;
      if (!AtStart)
        --BeforeI;

      // Restore all registers immediately before the return and any terminators
      // that preceed it.
      for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
        RegInfo->loadRegFromStackSlot(*MBB, I, CSI[i].getReg(),
                                      CSI[i].getFrameIdx(),
                                      CSI[i].getRegClass());
        assert(I != MBB->begin() &&
               "loadRegFromStackSlot didn't insert any code!");
        // Insert in reverse order.  loadRegFromStackSlot can insert multiple
        // instructions.
        if (AtStart)
          I = MBB->begin();
        else {
          I = BeforeI;
          ++I;
        }
      }
    }
}

/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
/// abstract stack objects.
///
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
  const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();

  bool StackGrowsDown =
    TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown;

  // Loop over all of the stack objects, assigning sequential addresses...
  MachineFrameInfo *FFI = Fn.getFrameInfo();

  unsigned StackAlignment = TFI.getStackAlignment();
  unsigned MaxAlign = 0;

  // Start at the beginning of the local area.
  // The Offset is the distance from the stack top in the direction
  // of stack growth -- so it's always positive.
  int Offset = TFI.getOffsetOfLocalArea();
  if (StackGrowsDown)
    Offset = -Offset;
  assert(Offset >= 0
         && "Local area offset should be in direction of stack growth");

  // If there are fixed sized objects that are preallocated in the local area,
  // non-fixed objects can't be allocated right at the start of local area.
  // We currently don't support filling in holes in between fixed sized objects,
  // so we adjust 'Offset' to point to the end of last fixed sized
  // preallocated object.
  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
    int FixedOff;
    if (StackGrowsDown) {
      // The maximum distance from the stack pointer is at lower address of
      // the object -- which is given by offset. For down growing stack
      // the offset is negative, so we negate the offset to get the distance.
      FixedOff = -FFI->getObjectOffset(i);
    } else {
      // The maximum distance from the start pointer is at the upper
      // address of the object.
      FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i);
    }
    if (FixedOff > Offset) Offset = FixedOff;
  }

  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
    // If stack grows down, we need to add size of find the lowest
    // address of the object.
    if (StackGrowsDown)
      Offset += FFI->getObjectSize(i);

    unsigned Align = FFI->getObjectAlignment(i);
    // If the alignment of this object is greater than that of the stack, then
    // increase the stack alignment to match.
    MaxAlign = std::max(MaxAlign, Align);
    // Adjust to alignment boundary
    Offset = (Offset+Align-1)/Align*Align;

    if (StackGrowsDown) {
      FFI->setObjectOffset(i, -Offset);        // Set the computed offset
    } else {
      FFI->setObjectOffset(i, Offset);
      Offset += FFI->getObjectSize(i);
    }
  }

  // Align the final stack pointer offset, but only if there are calls in the
  // function.  This ensures that any calls to subroutines have their stack
  // frames suitable aligned.
  if (FFI->hasCalls())
    Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;

  // Set the final value of the stack pointer...
  FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());

  // Remember the required stack alignment in case targets need it to perform
  // dynamic stack alignment.
  assert(FFI->getMaxAlignment() == MaxAlign &&
         "Stack alignment calculation broken!");
}

/// insertPrologEpilogCode - Scan the function for modified caller saved
/// registers, insert spill code for these caller saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
  // Add prologue to the function...
  Fn.getTarget().getRegisterInfo()->emitPrologue(Fn);

  // Add epilogue to restore the callee-save registers in each exiting block
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
    // If last instruction is a return instruction, add an epilogue
    if (!I->empty() && TII.isReturn(I->back().getOpcode()))
      Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
  }
}

/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
/// register references and actual offsets.
///
void PEI::replaceFrameIndices(MachineFunction &Fn) {
  if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do?

  const TargetMachine &TM = Fn.getTarget();
  assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!");
  const MRegisterInfo &MRI = *TM.getRegisterInfo();

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
        if (I->getOperand(i).isFrameIndex()) {
          // If this instruction has a FrameIndex operand, we need to use that
          // target machine register info object to eliminate it.
          MRI.eliminateFrameIndex(I);
          break;
        }
}
<commit_msg>Rename function. It's determining which callee-save registers to save.<commit_after>//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in 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 pass is responsible for finalizing the functions frame layout, saving
// callee saved registers, and for emitting prolog & epilog code for the
// function.
//
// This pass must be run after register allocation.  After this pass is
// executed, it is illegal to construct MO_FrameIndex operands.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

namespace {
  struct VISIBILITY_HIDDEN PEI : public MachineFunctionPass {
    const char *getPassName() const {
      return "Prolog/Epilog Insertion & Frame Finalization";
    }

    /// runOnMachineFunction - Insert prolog/epilog code and replace abstract
    /// frame indexes with appropriate references.
    ///
    bool runOnMachineFunction(MachineFunction &Fn) {
      // Get MachineDebugInfo so that we can track the construction of the
      // frame.
      if (MachineDebugInfo *DI = getAnalysisToUpdate<MachineDebugInfo>()) {
        Fn.getFrameInfo()->setMachineDebugInfo(DI);
      }

      // Scan the function for modified callee saved registers and insert spill
      // code for any callee saved registers that are modified.  Also calculate
      // the MaxCallFrameSize and HasCalls variables for the function's frame
      // information and eliminates call frame pseudo instructions.
      calculateCalleeSavedRegisters(Fn);

      // Add the code to save and restore the caller saved registers
      saveCallerSavedRegisters(Fn);

      // Allow the target machine to make final modifications to the function
      // before the frame layout is finalized.
      Fn.getTarget().getRegisterInfo()->processFunctionBeforeFrameFinalized(Fn);

      // Calculate actual frame offsets for all of the abstract stack objects...
      calculateFrameObjectOffsets(Fn);

      // Add prolog and epilog code to the function.  This function is required
      // to align the stack frame as necessary for any stack variables or
      // called functions.  Because of this, calculateCalleeSavedRegisters
      // must be called before this function in order to set the HasCalls
      // and MaxCallFrameSize variables.
      insertPrologEpilogCode(Fn);

      // Replace all MO_FrameIndex operands with physical register references
      // and actual offsets.
      //
      replaceFrameIndices(Fn);

      return true;
    }

  private:
    void calculateCalleeSavedRegisters(MachineFunction &Fn);
    void saveCallerSavedRegisters(MachineFunction &Fn);
    void calculateFrameObjectOffsets(MachineFunction &Fn);
    void replaceFrameIndices(MachineFunction &Fn);
    void insertPrologEpilogCode(MachineFunction &Fn);
  };
}

/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }

/// calculateCalleeSavedRegisters - Scan the function for modified caller saved
/// registers.  Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();

  // Get the function call frame set-up and tear-down instruction opcode
  int FrameSetupOpcode   = RegInfo->getCallFrameSetupOpcode();
  int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode();

  // Early exit for targets which have no callee saved registers and no call
  // frame setup/destroy pseudo instructions.
  if ((CSRegs == 0 || CSRegs[0] == 0) &&
      FrameSetupOpcode == -1 && FrameDestroyOpcode == -1)
    return;

  unsigned MaxCallFrameSize = 0;
  bool HasCalls = false;

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
      if (I->getOpcode() == FrameSetupOpcode ||
          I->getOpcode() == FrameDestroyOpcode) {
        assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo"
               " instructions should have a single immediate argument!");
        unsigned Size = I->getOperand(0).getImmedValue();
        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
        HasCalls = true;
        RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
      } else {
        ++I;
      }

  MachineFrameInfo *FFI = Fn.getFrameInfo();
  FFI->setHasCalls(HasCalls);
  FFI->setMaxCallFrameSize(MaxCallFrameSize);

  // Now figure out which *callee saved* registers are modified by the current
  // function, thus needing to be saved and restored in the prolog/epilog.
  //
  const bool *PhysRegsUsed = Fn.getUsedPhysregs();
  const TargetRegisterClass* const *CSRegClasses =
    RegInfo->getCalleeSaveRegClasses();
  std::vector<CalleeSavedInfo> CSI;
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (PhysRegsUsed[Reg]) {
        // If the reg is modified, save it!
      CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too.
        if (PhysRegsUsed[*AliasSet]) {
          CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
          break;
        }
      }
    }
  }

  if (CSI.empty())
    return;   // Early exit if no caller saved registers are modified!

  unsigned NumFixedSpillSlots;
  const std::pair<unsigned,int> *FixedSpillSlots =
    TFI->getCalleeSaveSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    unsigned Reg = CSI[i].getReg();
    const TargetRegisterClass *RC = CSI[i].getRegClass();

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->first != Reg)
      ++FixedSlot;

    int FrameIdx;
    if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      FrameIdx = FFI->CreateStackObject(RC->getSize(), RC->getAlignment());
    } else {
      // Spill it to the stack where we must.
      FrameIdx = FFI->CreateFixedObject(RC->getSize(), FixedSlot->second);
    }
    CSI[i].setFrameIdx(FrameIdx);
  }

  FFI->setCalleeSavedInfo(CSI);
}

/// saveCallerSavedRegisters -  Insert spill code for any caller saved registers
/// that are modified in the function.
///
void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
  // Get callee saved register information.
  MachineFrameInfo *FFI = Fn.getFrameInfo();
  const std::vector<CalleeSavedInfo> &CSI = FFI->getCalleeSavedInfo();

  // Early exit if no caller saved registers are modified!
  if (CSI.empty())
    return;

  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();

  // Now that we have a stack slot for each register to be saved, insert spill
  // code into the entry block.
  MachineBasicBlock *MBB = Fn.begin();
  MachineBasicBlock::iterator I = MBB->begin();
  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    // Insert the spill to the stack frame.
    RegInfo->storeRegToStackSlot(*MBB, I, CSI[i].getReg(), CSI[i].getFrameIdx(),
                                 CSI[i].getRegClass());
  }

  // Add code to restore the callee-save registers in each exiting block.
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI)
    // If last instruction is a return instruction, add an epilogue.
    if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
      MBB = FI;
      I = MBB->end(); --I;

      // Skip over all terminator instructions, which are part of the return
      // sequence.
      MachineBasicBlock::iterator I2 = I;
      while (I2 != MBB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
        I = I2;

      bool AtStart = I == MBB->begin();
      MachineBasicBlock::iterator BeforeI = I;
      if (!AtStart)
        --BeforeI;

      // Restore all registers immediately before the return and any terminators
      // that preceed it.
      for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
        RegInfo->loadRegFromStackSlot(*MBB, I, CSI[i].getReg(),
                                      CSI[i].getFrameIdx(),
                                      CSI[i].getRegClass());
        assert(I != MBB->begin() &&
               "loadRegFromStackSlot didn't insert any code!");
        // Insert in reverse order.  loadRegFromStackSlot can insert multiple
        // instructions.
        if (AtStart)
          I = MBB->begin();
        else {
          I = BeforeI;
          ++I;
        }
      }
    }
}

/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
/// abstract stack objects.
///
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
  const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();

  bool StackGrowsDown =
    TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown;

  // Loop over all of the stack objects, assigning sequential addresses...
  MachineFrameInfo *FFI = Fn.getFrameInfo();

  unsigned StackAlignment = TFI.getStackAlignment();
  unsigned MaxAlign = 0;

  // Start at the beginning of the local area.
  // The Offset is the distance from the stack top in the direction
  // of stack growth -- so it's always positive.
  int Offset = TFI.getOffsetOfLocalArea();
  if (StackGrowsDown)
    Offset = -Offset;
  assert(Offset >= 0
         && "Local area offset should be in direction of stack growth");

  // If there are fixed sized objects that are preallocated in the local area,
  // non-fixed objects can't be allocated right at the start of local area.
  // We currently don't support filling in holes in between fixed sized objects,
  // so we adjust 'Offset' to point to the end of last fixed sized
  // preallocated object.
  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
    int FixedOff;
    if (StackGrowsDown) {
      // The maximum distance from the stack pointer is at lower address of
      // the object -- which is given by offset. For down growing stack
      // the offset is negative, so we negate the offset to get the distance.
      FixedOff = -FFI->getObjectOffset(i);
    } else {
      // The maximum distance from the start pointer is at the upper
      // address of the object.
      FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i);
    }
    if (FixedOff > Offset) Offset = FixedOff;
  }

  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
    // If stack grows down, we need to add size of find the lowest
    // address of the object.
    if (StackGrowsDown)
      Offset += FFI->getObjectSize(i);

    unsigned Align = FFI->getObjectAlignment(i);
    // If the alignment of this object is greater than that of the stack, then
    // increase the stack alignment to match.
    MaxAlign = std::max(MaxAlign, Align);
    // Adjust to alignment boundary
    Offset = (Offset+Align-1)/Align*Align;

    if (StackGrowsDown) {
      FFI->setObjectOffset(i, -Offset);        // Set the computed offset
    } else {
      FFI->setObjectOffset(i, Offset);
      Offset += FFI->getObjectSize(i);
    }
  }

  // Align the final stack pointer offset, but only if there are calls in the
  // function.  This ensures that any calls to subroutines have their stack
  // frames suitable aligned.
  if (FFI->hasCalls())
    Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;

  // Set the final value of the stack pointer...
  FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());

  // Remember the required stack alignment in case targets need it to perform
  // dynamic stack alignment.
  assert(FFI->getMaxAlignment() == MaxAlign &&
         "Stack alignment calculation broken!");
}

/// insertPrologEpilogCode - Scan the function for modified caller saved
/// registers, insert spill code for these caller saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
  // Add prologue to the function...
  Fn.getTarget().getRegisterInfo()->emitPrologue(Fn);

  // Add epilogue to restore the callee-save registers in each exiting block
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
    // If last instruction is a return instruction, add an epilogue
    if (!I->empty() && TII.isReturn(I->back().getOpcode()))
      Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
  }
}

/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
/// register references and actual offsets.
///
void PEI::replaceFrameIndices(MachineFunction &Fn) {
  if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do?

  const TargetMachine &TM = Fn.getTarget();
  assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!");
  const MRegisterInfo &MRI = *TM.getRegisterInfo();

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
        if (I->getOperand(i).isFrameIndex()) {
          // If this instruction has a FrameIndex operand, we need to use that
          // target machine register info object to eliminate it.
          MRI.eliminateFrameIndex(I);
          break;
        }
}
<|endoftext|>


<commit_before>//===- StrongPhiElimination.cpp - Eliminate PHI nodes by inserting copies -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Owen Anderson and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates machine instruction PHI nodes by inserting copy
// instructions, using an intelligent copy-folding technique based on
// dominator information.  This is technique is derived from:
//
//    Budimlic, et al. Fast copy coalescing and live-range identification.
//    In Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language
//    Design and Implementation (Berlin, Germany, June 17 - 19, 2002).
//    PLDI '02. ACM, New York, NY, 25-32.
//    DOI= http://doi.acm.org/10.1145/512529.512534
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "strongphielim"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

namespace {
  struct VISIBILITY_HIDDEN StrongPHIElimination : public MachineFunctionPass {
    static char ID; // Pass identification, replacement for typeid
    StrongPHIElimination() : MachineFunctionPass((intptr_t)&ID) {}

    bool runOnMachineFunction(MachineFunction &Fn);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<LiveVariables>();
      AU.addPreservedID(PHIEliminationID);
      AU.addRequired<MachineDominatorTree>();
      AU.addRequired<LiveVariables>();
      AU.setPreservesAll();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

    virtual void releaseMemory() {
      preorder.clear();
      maxpreorder.clear();

      waiting.clear();
    }

  private:
    struct DomForestNode {
    private:
      std::vector<DomForestNode*> children;
      unsigned reg;

      void addChild(DomForestNode* DFN) { children.push_back(DFN); }

    public:
      typedef std::vector<DomForestNode*>::iterator iterator;

      DomForestNode(unsigned r, DomForestNode* parent) : reg(r) {
        if (parent)
          parent->addChild(this);
      }

      ~DomForestNode() {
        for (iterator I = begin(), E = end(); I != E; ++I)
          delete *I;
      }

      inline unsigned getReg() { return reg; }

      inline DomForestNode::iterator begin() { return children.begin(); }
      inline DomForestNode::iterator end() { return children.end(); }
    };

    DenseMap<MachineBasicBlock*, unsigned> preorder;
    DenseMap<MachineBasicBlock*, unsigned> maxpreorder;

    DenseMap<MachineBasicBlock*, std::vector<MachineInstr*> > waiting;

    void computeDFS(MachineFunction& MF);
    void processBlock(MachineBasicBlock* MBB);

    std::vector<DomForestNode*> computeDomForest(std::set<unsigned>& instrs);

  };

  char StrongPHIElimination::ID = 0;
  RegisterPass<StrongPHIElimination> X("strong-phi-node-elimination",
                  "Eliminate PHI nodes for register allocation, intelligently");
}

const PassInfo *llvm::StrongPHIEliminationID = X.getPassInfo();

/// computeDFS - Computes the DFS-in and DFS-out numbers of the dominator tree
/// of the given MachineFunction.  These numbers are then used in other parts
/// of the PHI elimination process.
void StrongPHIElimination::computeDFS(MachineFunction& MF) {
  SmallPtrSet<MachineDomTreeNode*, 8> frontier;
  SmallPtrSet<MachineDomTreeNode*, 8> visited;

  unsigned time = 0;

  MachineDominatorTree& DT = getAnalysis<MachineDominatorTree>();

  MachineDomTreeNode* node = DT.getRootNode();

  std::vector<MachineDomTreeNode*> worklist;
  worklist.push_back(node);

  while (!worklist.empty()) {
    MachineDomTreeNode* currNode = worklist.back();

    if (!frontier.count(currNode)) {
      frontier.insert(currNode);
      ++time;
      preorder.insert(std::make_pair(currNode->getBlock(), time));
    }

    bool inserted = false;
    for (MachineDomTreeNode::iterator I = node->begin(), E = node->end();
         I != E; ++I)
      if (!frontier.count(*I) && !visited.count(*I)) {
        worklist.push_back(*I);
        inserted = true;
        break;
      }

    if (!inserted) {
      frontier.erase(currNode);
      visited.insert(currNode);
      maxpreorder.insert(std::make_pair(currNode->getBlock(), time));

      worklist.pop_back();
    }
  }
}

/// PreorderSorter - a helper class that is used to sort registers
/// according to the preorder number of their defining blocks
class PreorderSorter {
private:
  DenseMap<MachineBasicBlock*, unsigned>& preorder;
  LiveVariables& LV;

public:
  PreorderSorter(DenseMap<MachineBasicBlock*, unsigned>& p,
                LiveVariables& L) : preorder(p), LV(L) { }

  bool operator()(unsigned A, unsigned B) {
    if (A == B)
      return false;

    MachineBasicBlock* ABlock = LV.getVarInfo(A).DefInst->getParent();
    MachineBasicBlock* BBlock = LV.getVarInfo(A).DefInst->getParent();

    if (preorder[ABlock] < preorder[BBlock])
      return true;
    else if (preorder[ABlock] > preorder[BBlock])
      return false;

    assert(0 && "Error sorting by dominance!");
    return false;
  }
};

/// computeDomForest - compute the subforest of the DomTree corresponding
/// to the defining blocks of the registers in question
std::vector<StrongPHIElimination::DomForestNode*>
StrongPHIElimination::computeDomForest(std::set<unsigned>& regs) {
  LiveVariables& LV = getAnalysis<LiveVariables>();

  DomForestNode* VirtualRoot = new DomForestNode(0, 0);
  maxpreorder.insert(std::make_pair((MachineBasicBlock*)0, ~0UL));

  std::vector<unsigned> worklist;
  worklist.reserve(regs.size());
  for (std::set<unsigned>::iterator I = regs.begin(), E = regs.end();
       I != E; ++I)
    worklist.push_back(*I);

  PreorderSorter PS(preorder, LV);
  std::sort(worklist.begin(), worklist.end(), PS);

  DomForestNode* CurrentParent = VirtualRoot;
  std::vector<DomForestNode*> stack;
  stack.push_back(VirtualRoot);

  for (std::vector<unsigned>::iterator I = worklist.begin(), E = worklist.end();
       I != E; ++I) {
    unsigned pre = preorder[LV.getVarInfo(*I).DefInst->getParent()];
    MachineBasicBlock* parentBlock =
      LV.getVarInfo(CurrentParent->getReg()).DefInst->getParent();

    while (pre > maxpreorder[parentBlock]) {
      stack.pop_back();
      CurrentParent = stack.back();

      parentBlock = LV.getVarInfo(CurrentParent->getReg()).DefInst->getParent();
    }

    DomForestNode* child = new DomForestNode(*I, CurrentParent);
    stack.push_back(child);
    CurrentParent = child;
  }

  std::vector<DomForestNode*> ret;
  ret.insert(ret.end(), VirtualRoot->begin(), VirtualRoot->end());
  return ret;
}

/// isLiveIn - helper method that determines, from a VarInfo, if a register
/// is live into a block
bool isLiveIn(LiveVariables::VarInfo& V, MachineBasicBlock* MBB) {
  if (V.AliveBlocks.test(MBB->getNumber()))
    return true;

  for (std::vector<MachineInstr*>::iterator I = V.Kills.begin(),
       E = V.Kills.end(); I != E; ++I)
    if ((*I)->getParent() == MBB)
      return true;

  return false;
}

/// isLiveOut - help method that determines, from a VarInfo, if a register is
/// live out of a block.
bool isLiveOut(LiveVariables::VarInfo& V, MachineBasicBlock* MBB) {
  if (V.AliveBlocks.test(MBB->getNumber()))
    return true;

  if (V.DefInst->getParent() == MBB)
    return true;

  return false;
}

/// processBlock - Eliminate PHIs in the given block
void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) {
  LiveVariables& LV = getAnalysis<LiveVariables>();

  // Holds names that have been added to a set in any PHI within this block
  // before the current one.
  std::set<unsigned> ProcessedNames;

  MachineBasicBlock::iterator P = MBB->begin();
  while (P->getOpcode() == TargetInstrInfo::PHI) {
    LiveVariables::VarInfo& PHIInfo = LV.getVarInfo(P->getOperand(0).getReg());

    // Hold the names that are currently in the candidate set.
    std::set<unsigned> PHIUnion;
    std::set<MachineBasicBlock*> UnionedBlocks;

    for (int i = P->getNumOperands() - 1; i >= 2; i-=2) {
      unsigned SrcReg = P->getOperand(i-1).getReg();
      LiveVariables::VarInfo& SrcInfo = LV.getVarInfo(SrcReg);

      if (isLiveIn(SrcInfo, P->getParent())) {
        // add a copy from a_i to p in Waiting[From[a_i]]
      } else if (isLiveOut(PHIInfo, SrcInfo.DefInst->getParent())) {
        // add a copy to Waiting[From[a_i]]
      } else if (PHIInfo.DefInst->getOpcode() == TargetInstrInfo::PHI &&
                 isLiveIn(PHIInfo, SrcInfo.DefInst->getParent())) {
        // add a copy to Waiting[From[a_i]]
      } else if (ProcessedNames.count(SrcReg)) {
        // add a copy to Waiting[From[a_i]]
      } else if (UnionedBlocks.count(SrcInfo.DefInst->getParent())) {
        // add a copy to Waiting[From[a_i]]
      } else {
        PHIUnion.insert(SrcReg);
        UnionedBlocks.insert(SrcInfo.DefInst->getParent());

        // DO STUFF HERE

      }

      ProcessedNames.insert(PHIUnion.begin(), PHIUnion.end());
    }

    ++P;
  }
}

bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) {
  computeDFS(Fn);

  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
    if (!I->empty() &&
        I->begin()->getOpcode() == TargetInstrInfo::PHI)
      processBlock(I);

  return false;
}
<commit_msg>Take another stab at getting isLiveIn() and isLiveOut() right.<commit_after>//===- StrongPhiElimination.cpp - Eliminate PHI nodes by inserting copies -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Owen Anderson and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates machine instruction PHI nodes by inserting copy
// instructions, using an intelligent copy-folding technique based on
// dominator information.  This is technique is derived from:
//
//    Budimlic, et al. Fast copy coalescing and live-range identification.
//    In Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language
//    Design and Implementation (Berlin, Germany, June 17 - 19, 2002).
//    PLDI '02. ACM, New York, NY, 25-32.
//    DOI= http://doi.acm.org/10.1145/512529.512534
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "strongphielim"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

namespace {
  struct VISIBILITY_HIDDEN StrongPHIElimination : public MachineFunctionPass {
    static char ID; // Pass identification, replacement for typeid
    StrongPHIElimination() : MachineFunctionPass((intptr_t)&ID) {}

    bool runOnMachineFunction(MachineFunction &Fn);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<LiveVariables>();
      AU.addPreservedID(PHIEliminationID);
      AU.addRequired<MachineDominatorTree>();
      AU.addRequired<LiveVariables>();
      AU.setPreservesAll();
      MachineFunctionPass::getAnalysisUsage(AU);
    }

    virtual void releaseMemory() {
      preorder.clear();
      maxpreorder.clear();

      waiting.clear();
    }

  private:
    struct DomForestNode {
    private:
      std::vector<DomForestNode*> children;
      unsigned reg;

      void addChild(DomForestNode* DFN) { children.push_back(DFN); }

    public:
      typedef std::vector<DomForestNode*>::iterator iterator;

      DomForestNode(unsigned r, DomForestNode* parent) : reg(r) {
        if (parent)
          parent->addChild(this);
      }

      ~DomForestNode() {
        for (iterator I = begin(), E = end(); I != E; ++I)
          delete *I;
      }

      inline unsigned getReg() { return reg; }

      inline DomForestNode::iterator begin() { return children.begin(); }
      inline DomForestNode::iterator end() { return children.end(); }
    };

    DenseMap<MachineBasicBlock*, unsigned> preorder;
    DenseMap<MachineBasicBlock*, unsigned> maxpreorder;

    DenseMap<MachineBasicBlock*, std::vector<MachineInstr*> > waiting;

    void computeDFS(MachineFunction& MF);
    void processBlock(MachineBasicBlock* MBB);

    std::vector<DomForestNode*> computeDomForest(std::set<unsigned>& instrs);

  };

  char StrongPHIElimination::ID = 0;
  RegisterPass<StrongPHIElimination> X("strong-phi-node-elimination",
                  "Eliminate PHI nodes for register allocation, intelligently");
}

const PassInfo *llvm::StrongPHIEliminationID = X.getPassInfo();

/// computeDFS - Computes the DFS-in and DFS-out numbers of the dominator tree
/// of the given MachineFunction.  These numbers are then used in other parts
/// of the PHI elimination process.
void StrongPHIElimination::computeDFS(MachineFunction& MF) {
  SmallPtrSet<MachineDomTreeNode*, 8> frontier;
  SmallPtrSet<MachineDomTreeNode*, 8> visited;

  unsigned time = 0;

  MachineDominatorTree& DT = getAnalysis<MachineDominatorTree>();

  MachineDomTreeNode* node = DT.getRootNode();

  std::vector<MachineDomTreeNode*> worklist;
  worklist.push_back(node);

  while (!worklist.empty()) {
    MachineDomTreeNode* currNode = worklist.back();

    if (!frontier.count(currNode)) {
      frontier.insert(currNode);
      ++time;
      preorder.insert(std::make_pair(currNode->getBlock(), time));
    }

    bool inserted = false;
    for (MachineDomTreeNode::iterator I = node->begin(), E = node->end();
         I != E; ++I)
      if (!frontier.count(*I) && !visited.count(*I)) {
        worklist.push_back(*I);
        inserted = true;
        break;
      }

    if (!inserted) {
      frontier.erase(currNode);
      visited.insert(currNode);
      maxpreorder.insert(std::make_pair(currNode->getBlock(), time));

      worklist.pop_back();
    }
  }
}

/// PreorderSorter - a helper class that is used to sort registers
/// according to the preorder number of their defining blocks
class PreorderSorter {
private:
  DenseMap<MachineBasicBlock*, unsigned>& preorder;
  LiveVariables& LV;

public:
  PreorderSorter(DenseMap<MachineBasicBlock*, unsigned>& p,
                LiveVariables& L) : preorder(p), LV(L) { }

  bool operator()(unsigned A, unsigned B) {
    if (A == B)
      return false;

    MachineBasicBlock* ABlock = LV.getVarInfo(A).DefInst->getParent();
    MachineBasicBlock* BBlock = LV.getVarInfo(A).DefInst->getParent();

    if (preorder[ABlock] < preorder[BBlock])
      return true;
    else if (preorder[ABlock] > preorder[BBlock])
      return false;

    assert(0 && "Error sorting by dominance!");
    return false;
  }
};

/// computeDomForest - compute the subforest of the DomTree corresponding
/// to the defining blocks of the registers in question
std::vector<StrongPHIElimination::DomForestNode*>
StrongPHIElimination::computeDomForest(std::set<unsigned>& regs) {
  LiveVariables& LV = getAnalysis<LiveVariables>();

  DomForestNode* VirtualRoot = new DomForestNode(0, 0);
  maxpreorder.insert(std::make_pair((MachineBasicBlock*)0, ~0UL));

  std::vector<unsigned> worklist;
  worklist.reserve(regs.size());
  for (std::set<unsigned>::iterator I = regs.begin(), E = regs.end();
       I != E; ++I)
    worklist.push_back(*I);

  PreorderSorter PS(preorder, LV);
  std::sort(worklist.begin(), worklist.end(), PS);

  DomForestNode* CurrentParent = VirtualRoot;
  std::vector<DomForestNode*> stack;
  stack.push_back(VirtualRoot);

  for (std::vector<unsigned>::iterator I = worklist.begin(), E = worklist.end();
       I != E; ++I) {
    unsigned pre = preorder[LV.getVarInfo(*I).DefInst->getParent()];
    MachineBasicBlock* parentBlock =
      LV.getVarInfo(CurrentParent->getReg()).DefInst->getParent();

    while (pre > maxpreorder[parentBlock]) {
      stack.pop_back();
      CurrentParent = stack.back();

      parentBlock = LV.getVarInfo(CurrentParent->getReg()).DefInst->getParent();
    }

    DomForestNode* child = new DomForestNode(*I, CurrentParent);
    stack.push_back(child);
    CurrentParent = child;
  }

  std::vector<DomForestNode*> ret;
  ret.insert(ret.end(), VirtualRoot->begin(), VirtualRoot->end());
  return ret;
}

/// isLiveIn - helper method that determines, from a VarInfo, if a register
/// is live into a block
bool isLiveIn(LiveVariables::VarInfo& V, MachineBasicBlock* MBB) {
  if (V.AliveBlocks.test(MBB->getNumber()))
    return true;

  if (V.DefInst->getParent() != MBB &&
      V.UsedBlocks.test(MBB->getNumber()))
    return true;

  return false;
}

/// isLiveOut - help method that determines, from a VarInfo, if a register is
/// live out of a block.
bool isLiveOut(LiveVariables::VarInfo& V, MachineBasicBlock* MBB) {
  if (MBB == V.DefInst->getParent() ||
      V.UsedBlocks.test(MBB->getNumber())) {
    for (std::vector<MachineInstr*>::iterator I = V.Kills.begin(),
         E = V.Kills.end(); I != E; ++I)
      if ((*I)->getParent() == MBB)
        return false;

    return true;
  }

  return false;
}

/// processBlock - Eliminate PHIs in the given block
void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) {
  LiveVariables& LV = getAnalysis<LiveVariables>();

  // Holds names that have been added to a set in any PHI within this block
  // before the current one.
  std::set<unsigned> ProcessedNames;

  MachineBasicBlock::iterator P = MBB->begin();
  while (P->getOpcode() == TargetInstrInfo::PHI) {
    LiveVariables::VarInfo& PHIInfo = LV.getVarInfo(P->getOperand(0).getReg());

    // Hold the names that are currently in the candidate set.
    std::set<unsigned> PHIUnion;
    std::set<MachineBasicBlock*> UnionedBlocks;

    for (int i = P->getNumOperands() - 1; i >= 2; i-=2) {
      unsigned SrcReg = P->getOperand(i-1).getReg();
      LiveVariables::VarInfo& SrcInfo = LV.getVarInfo(SrcReg);

      if (isLiveIn(SrcInfo, P->getParent())) {
        // add a copy from a_i to p in Waiting[From[a_i]]
      } else if (isLiveOut(PHIInfo, SrcInfo.DefInst->getParent())) {
        // add a copy to Waiting[From[a_i]]
      } else if (PHIInfo.DefInst->getOpcode() == TargetInstrInfo::PHI &&
                 isLiveIn(PHIInfo, SrcInfo.DefInst->getParent())) {
        // add a copy to Waiting[From[a_i]]
      } else if (ProcessedNames.count(SrcReg)) {
        // add a copy to Waiting[From[a_i]]
      } else if (UnionedBlocks.count(SrcInfo.DefInst->getParent())) {
        // add a copy to Waiting[From[a_i]]
      } else {
        PHIUnion.insert(SrcReg);
        UnionedBlocks.insert(SrcInfo.DefInst->getParent());

        // DO STUFF HERE

      }

      ProcessedNames.insert(PHIUnion.begin(), PHIUnion.end());
    }

    ++P;
  }
}

bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) {
  computeDFS(Fn);

  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
    if (!I->empty() &&
        I->begin()->getOpcode() == TargetInstrInfo::PHI)
      processBlock(I);

  return false;
}
<|endoftext|>