diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt --- a/llvm/lib/Target/X86/CMakeLists.txt +++ b/llvm/lib/Target/X86/CMakeLists.txt @@ -28,6 +28,7 @@ X86CallLowering.cpp X86CmovConversion.cpp X86CondBrFolding.cpp + X86CountMIAnalysis.cpp X86DomainReassignment.cpp X86DiscriminateMemOps.cpp X86ExpandPseudo.cpp diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h --- a/llvm/lib/Target/X86/X86.h +++ b/llvm/lib/Target/X86/X86.h @@ -123,6 +123,10 @@ /// This pass applies profiling information to insert cache prefetches. FunctionPass *createX86InsertPrefetchPass(); +/// Return a pass that avoids creating store forward block issues in the +/// hardware. +FunctionPass *createX86CountMIAnalysis(); + InstructionSelector *createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &, X86RegisterBankInfo &); @@ -144,6 +148,8 @@ void initializeX86FlagsCopyLoweringPassPass(PassRegistry &); void initializeX86OptimizeLEAPassPass(PassRegistry &); void initializeX86SpeculativeLoadHardeningPassPass(PassRegistry &); +void initializeX86CountMIPass(PassRegistry &); + } // End llvm namespace #endif diff --git a/llvm/lib/Target/X86/X86CountMIAnalysis.cpp b/llvm/lib/Target/X86/X86CountMIAnalysis.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/X86/X86CountMIAnalysis.cpp @@ -0,0 +1,218 @@ +//===-- CountMIAnalysis.cpp - Count specific MachineInstrs 000000----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This implements a machine function analysis pass that visits every machine +// function, every machine basic block, every machine instruction, +// and counts how many branches and conditional moves there are. +// +//===----------------------------------------------------------------------===// + +#include "X86InstrInfo.h" +#include "X86Subtarget.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "x86-mi-counting" + +STATISTIC(NumMachineFunctions, "Number of machine functions"); +STATISTIC(NumMachineBasicBlocks, "Number of machine basic blocks"); +STATISTIC(NumMachineInstructions, "Number of machine instructions"); +STATISTIC(NumUncondBR, "Number of unconditional branch instructions"); +STATISTIC(NumCondBR, "Number of conditional branch instructions"); +STATISTIC(NumCMOV, "Number of conditional move instructions"); +STATISTIC(NumVecCMOV, "Number of vector conditional move instructions"); + +namespace { + +class X86CountMI : public MachineFunctionPass { +public: + static char ID; + + /// Default construct and initialize the pass. + X86CountMI() : MachineFunctionPass(ID) {} + + /// Tell the pass manager which passes we depend on and what information we + /// preserve. + void getAnalysisUsage(AnalysisUsage &AU) const override { + // We preserve all information. + AU.setPreservesAll(); + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// Perform the counting of the interesting instructions + /// in the given machine function. + bool runOnMachineFunction(MachineFunction &MF) override; + +private: + /// Perform the counting of the interesting instructions + /// in the given machine basic block. + void runOnMachineBasicBlock(const MachineBasicBlock &MBB); + + /// Perform the counting of the interesting instructions, + /// given the machine instruction. + void runOnMachineInstruction(const MachineInstr &MI); +}; + +} // namespace + +char X86CountMI::ID = 0; + +INITIALIZE_PASS(X86CountMI, DEBUG_TYPE, "X86 Machine Instruction counting", + false, false) + +bool X86CountMI::runOnMachineFunction(MachineFunction &MF) { + LLVM_DEBUG(dbgs() << "********** COUNT MACHINE INSTRUCTIONS: " << MF.getName() + << " **********\n"); + ++NumMachineFunctions; + + for (const MachineBasicBlock &MBB : MF) + runOnMachineBasicBlock(MBB); + + return false; // No changes done. +} + +void X86CountMI::runOnMachineBasicBlock(const MachineBasicBlock &MBB) { + ++NumMachineBasicBlocks; + + for (const MachineInstr &MI : MBB) + runOnMachineInstruction(MI); +} + +void X86CountMI::runOnMachineInstruction(const MachineInstr &MI) { + ++NumMachineInstructions; + + switch (MI.getOpcode()) { + case X86::JMP16m: + case X86::JMP16m_NT: + case X86::JMP16r: + case X86::JMP16r_NT: + case X86::JMP32m: + case X86::JMP32m_NT: + case X86::JMP32r: + case X86::JMP32r_NT: + case X86::JMP64m: + case X86::JMP64m_NT: + case X86::JMP64m_REX: + case X86::JMP64r: + case X86::JMP64r_NT: + case X86::JMP64r_REX: + case X86::JMP_1: + case X86::JMP_2: + case X86::JMP_4: + case X86::TAILJMPd: + case X86::TAILJMPd64: + case X86::TAILJMPm: + case X86::TAILJMPm64: + case X86::TAILJMPm64_REX: + case X86::TAILJMPr: + case X86::TAILJMPr64: + case X86::TAILJMPr64_REX: + LLVM_DEBUG(dbgs() << "Found unconditional branch instruction: " << MI + << "\n"); + ++NumUncondBR; + break; + case X86::JCXZ: + case X86::JECXZ: + case X86::JRCXZ: + case X86::TAILJMPd64_CC: + case X86::TAILJMPd_CC: + case X86::JCC_1: + case X86::JCC_2: + case X86::JCC_4: + LLVM_DEBUG(dbgs() << "Found conditional branch instruction: " << MI + << "\n"); + ++NumCondBR; + break; + case X86::CMOV16rm: + case X86::CMOV16rr: + case X86::CMOV32rm: + case X86::CMOV32rr: + case X86::CMOV64rm: + case X86::CMOV64rr: + case X86::CMOVBE_F: + case X86::CMOVBE_Fp32: + case X86::CMOVBE_Fp64: + case X86::CMOVBE_Fp80: + case X86::CMOVB_F: + case X86::CMOVB_Fp32: + case X86::CMOVB_Fp64: + case X86::CMOVB_Fp80: + case X86::CMOVE_F: + case X86::CMOVE_Fp32: + case X86::CMOVE_Fp64: + case X86::CMOVE_Fp80: + case X86::CMOVNBE_F: + case X86::CMOVNBE_Fp32: + case X86::CMOVNBE_Fp64: + case X86::CMOVNBE_Fp80: + case X86::CMOVNB_F: + case X86::CMOVNB_Fp32: + case X86::CMOVNB_Fp64: + case X86::CMOVNB_Fp80: + case X86::CMOVNE_F: + case X86::CMOVNE_Fp32: + case X86::CMOVNE_Fp64: + case X86::CMOVNE_Fp80: + case X86::CMOVNP_F: + case X86::CMOVNP_Fp32: + case X86::CMOVNP_Fp64: + case X86::CMOVNP_Fp80: + case X86::CMOVP_F: + case X86::CMOVP_Fp32: + case X86::CMOVP_Fp64: + case X86::CMOVP_Fp80: + case X86::CMOV_FR32: + case X86::CMOV_FR32X: + case X86::CMOV_FR64: + case X86::CMOV_FR64X: + case X86::CMOV_GR16: + case X86::CMOV_GR32: + case X86::CMOV_GR8: + case X86::CMOV_RFP32: + case X86::CMOV_RFP64: + case X86::CMOV_RFP80: + LLVM_DEBUG(dbgs() << "Found conditional move: " << MI << "\n"); + ++NumCMOV; + break; + case X86::CMOV_VK16: + case X86::CMOV_VK2: + case X86::CMOV_VK32: + case X86::CMOV_VK4: + case X86::CMOV_VK64: + case X86::CMOV_VK8: + case X86::CMOV_VR128: + case X86::CMOV_VR128X: + case X86::CMOV_VR256: + case X86::CMOV_VR256X: + case X86::CMOV_VR512: + case X86::VPCLMULQDQrr: + case X86::VPCMOVYrmr: + case X86::VPCMOVYrrm: + case X86::VPCMOVYrrr: + case X86::VPCMOVYrrr_REV: + case X86::VPCMOVrmr: + case X86::VPCMOVrrm: + case X86::VPCMOVrrr: + case X86::VPCMOVrrr_REV: + case X86::VPCMPBZ128rmi: + LLVM_DEBUG(dbgs() << "Found vector conditional move: " << MI << "\n"); + ++NumVecCMOV; + break; + } +} + +FunctionPass *llvm::createX86CountMIAnalysis() { return new X86CountMI(); } diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -528,6 +528,8 @@ (!TT.isOSWindows() || MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI)) addPass(createCFIInstrInserter()); + + addPass(createX86CountMIAnalysis()); } std::unique_ptr X86PassConfig::getCSEConfig() const {