text: //===--- InstCount.cpp - Collects the count of all instructions -----------===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  //
  // This pass collects the count of all instructions and reports them
  //
  //===----------------------------------------------------------------------===//
  
  #define DEBUG_TYPE "sil-instcount"
  #include "swift/SILOptimizer/PassManager/Passes.h"
  #include "swift/SILOptimizer/PassManager/PassManager.h"
  #include "swift/SILOptimizer/PassManager/Transforms.h"
  #include "swift/SIL/SILModule.h"
  #include "swift/SIL/SILVisitor.h"
  #include "llvm/ADT/Statistic.h"
  
  using namespace swift;
  
  //===----------------------------------------------------------------------===//
  //                                 Statistics
  //===----------------------------------------------------------------------===//
  
  // Local aggregate statistics
  STATISTIC(TotalInsts, "Number of instructions (of all types) in non-external "
                        "functions");
  STATISTIC(TotalBlocks, "Number of basic blocks in non-external functions");
  STATISTIC(TotalFuncs , "Number of non-external functions");
  
  // External aggregate statistics
  STATISTIC(TotalExternalFuncInsts, "Number of instructions (of all types) in "
                                    "external functions");
  STATISTIC(TotalExternalFuncBlocks, "Number of basic blocks in external "
                                     "functions");
  STATISTIC(TotalExternalFuncDefs, "Number of external funcs definitions");
  STATISTIC(TotalExternalFuncDecls, "Number of external funcs declarations");
  
  // Linkage statistics
  STATISTIC(TotalPublicFuncs, "Number of public funcs");
  STATISTIC(TotalPublicNonABIFuncs, "Number of public non-ABI funcs");
  STATISTIC(TotalHiddenFuncs, "Number of hidden funcs");
  STATISTIC(TotalPrivateFuncs, "Number of private funcs");
  STATISTIC(TotalSharedFuncs, "Number of shared funcs");
  STATISTIC(TotalPublicExternalFuncs, "Number of public external funcs");
  STATISTIC(TotalHiddenExternalFuncs, "Number of hidden external funcs");
  STATISTIC(TotalPrivateExternalFuncs, "Number of private external funcs");
  STATISTIC(TotalSharedExternalFuncs, "Number of shared external funcs");
  
  // Individual instruction statistics
  #define INST(Id, Parent) \
    STATISTIC(Num##Id, "Number of " #Id);
  #include "swift/SIL/SILNodes.def"
  
  namespace {
  
  struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
    // We store these locally so that we do not continually check if the function
    // is external or not. Instead, we just check once at the end and accumulate.
    unsigned InstCount = 0;
    unsigned BlockCount = 0;
  
    void visitSILBasicBlock(SILBasicBlock *BB) {
      BlockCount++;
      SILInstructionVisitor<InstCountVisitor>::visitSILBasicBlock(BB);
    }
  
    void visitSILFunction(SILFunction *F) {
      SILInstructionVisitor<InstCountVisitor>::visitSILFunction(F);
    }
  
    void visitValueBase(ValueBase *V) { }
  
  #define INST(Id, Parent)                                                       \
    void visit##Id(Id *I) {                                                      \
      ++Num##Id;                                                                 \
      ++InstCount;                                                               \
    }
  #include "swift/SIL/SILNodes.def"
  
  };
  
  } // end anonymous namespace
  
  //===----------------------------------------------------------------------===//
  //                              Top Level Driver
  //===----------------------------------------------------------------------===//
  
  namespace {
  class InstCount : public SILFunctionTransform {
  
    /// The entry point to the transformation.
    void run() override {
      SILFunction *F = getFunction();
      InstCountVisitor V;
      V.visitSILFunction(F);
      if (F->isAvailableExternally()) {
        if (F->isDefinition()) {
          TotalExternalFuncInsts += V.InstCount;
          TotalExternalFuncBlocks += V.BlockCount;
          TotalExternalFuncDefs++;
        } else {
          TotalExternalFuncDecls++;
        }
      } else {
        TotalInsts += V.InstCount;
        TotalBlocks += V.BlockCount;
        TotalFuncs++;
      }
  
      switch (F->getLinkage()) {
      case SILLinkage::Public:
        ++TotalPublicFuncs;
        break;
      case SILLinkage::PublicNonABI:
        ++TotalPublicNonABIFuncs;
        break;
      case SILLinkage::Hidden:
        ++TotalHiddenFuncs;
        break;
      case SILLinkage::Shared:
        ++TotalSharedFuncs;
        break;
      case SILLinkage::Private:
        ++TotalPrivateFuncs;
        break;
      case SILLinkage::PublicExternal:
        ++TotalPublicExternalFuncs;
        break;
      case SILLinkage::HiddenExternal:
        ++TotalHiddenExternalFuncs;
        break;
      case SILLinkage::SharedExternal:
        ++TotalSharedExternalFuncs;
        break;
      case SILLinkage::PrivateExternal:
        ++TotalPrivateExternalFuncs;
        break;
      }
    }
  };
  
  } // end anonymous namespace
  
  SILTransform *swift::createInstCount() {
    return new InstCount();
  }
  
  void swift::performSILInstCount(SILModule *M) {
    SILPassManager PrinterPM(M);
    PrinterPM.executePassPipelinePlan(
        SILPassPipelinePlan::getInstCountPassPipeline());
  }
  