191bc56edSDimitry Andric //===-- StackMapLivenessAnalysis.cpp - StackMap live Out Analysis ----------===// 291bc56edSDimitry Andric // 391bc56edSDimitry Andric // The LLVM Compiler Infrastructure 491bc56edSDimitry Andric // 591bc56edSDimitry Andric // This file is distributed under the University of Illinois Open Source 691bc56edSDimitry Andric // License. See LICENSE.TXT for details. 791bc56edSDimitry Andric // 891bc56edSDimitry Andric //===----------------------------------------------------------------------===// 991bc56edSDimitry Andric // 1091bc56edSDimitry Andric // This file implements the StackMap Liveness analysis pass. The pass calculates 1191bc56edSDimitry Andric // the liveness for each basic block in a function and attaches the register 1291bc56edSDimitry Andric // live-out information to a stackmap or patchpoint intrinsic if present. 1391bc56edSDimitry Andric // 1491bc56edSDimitry Andric //===----------------------------------------------------------------------===// 1591bc56edSDimitry Andric 1691bc56edSDimitry Andric #include "llvm/ADT/Statistic.h" 17ff0cc061SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 1891bc56edSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 1991bc56edSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 20ff0cc061SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 2191bc56edSDimitry Andric #include "llvm/CodeGen/Passes.h" 222cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 2391bc56edSDimitry Andric #include "llvm/Support/CommandLine.h" 2491bc56edSDimitry Andric #include "llvm/Support/Debug.h" 25ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h" 2691bc56edSDimitry Andric 2791bc56edSDimitry Andric using namespace llvm; 2891bc56edSDimitry Andric 2991bc56edSDimitry Andric #define DEBUG_TYPE "stackmaps" 3091bc56edSDimitry Andric 31ff0cc061SDimitry Andric static cl::opt<bool> EnablePatchPointLiveness( 32ff0cc061SDimitry Andric "enable-patchpoint-liveness", cl::Hidden, cl::init(true), 3391bc56edSDimitry Andric cl::desc("Enable PatchPoint Liveness Analysis Pass")); 3491bc56edSDimitry Andric 3591bc56edSDimitry Andric STATISTIC(NumStackMapFuncVisited, "Number of functions visited"); 3691bc56edSDimitry Andric STATISTIC(NumStackMapFuncSkipped, "Number of functions skipped"); 3791bc56edSDimitry Andric STATISTIC(NumBBsVisited, "Number of basic blocks visited"); 3891bc56edSDimitry Andric STATISTIC(NumBBsHaveNoStackmap, "Number of basic blocks with no stackmap"); 3991bc56edSDimitry Andric STATISTIC(NumStackMaps, "Number of StackMaps visited"); 4091bc56edSDimitry Andric 41ff0cc061SDimitry Andric namespace { 42ff0cc061SDimitry Andric /// \brief This pass calculates the liveness information for each basic block in 43ff0cc061SDimitry Andric /// a function and attaches the register live-out information to a patchpoint 44ff0cc061SDimitry Andric /// intrinsic if present. 45ff0cc061SDimitry Andric /// 46ff0cc061SDimitry Andric /// This pass can be disabled via the -enable-patchpoint-liveness=false flag. 47ff0cc061SDimitry Andric /// The pass skips functions that don't have any patchpoint intrinsics. The 48ff0cc061SDimitry Andric /// information provided by this pass is optional and not required by the 49ff0cc061SDimitry Andric /// aformentioned intrinsic to function. 50ff0cc061SDimitry Andric class StackMapLiveness : public MachineFunctionPass { 51ff0cc061SDimitry Andric const TargetRegisterInfo *TRI; 52ff0cc061SDimitry Andric LivePhysRegs LiveRegs; 53ff0cc061SDimitry Andric 54ff0cc061SDimitry Andric public: 55ff0cc061SDimitry Andric static char ID; 56ff0cc061SDimitry Andric 57ff0cc061SDimitry Andric /// \brief Default construct and initialize the pass. 58ff0cc061SDimitry Andric StackMapLiveness(); 59ff0cc061SDimitry Andric 60ff0cc061SDimitry Andric /// \brief Tell the pass manager which passes we depend on and what 61ff0cc061SDimitry Andric /// information we preserve. 62ff0cc061SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 63ff0cc061SDimitry Andric 643ca95b02SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 653ca95b02SDimitry Andric return MachineFunctionProperties().set( 66d88c1a5aSDimitry Andric MachineFunctionProperties::Property::NoVRegs); 673ca95b02SDimitry Andric } 683ca95b02SDimitry Andric 69ff0cc061SDimitry Andric /// \brief Calculate the liveness information for the given machine function. 70ff0cc061SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 71ff0cc061SDimitry Andric 72ff0cc061SDimitry Andric private: 73ff0cc061SDimitry Andric /// \brief Performs the actual liveness calculation for the function. 74875ed548SDimitry Andric bool calculateLiveness(MachineFunction &MF); 75ff0cc061SDimitry Andric 76ff0cc061SDimitry Andric /// \brief Add the current register live set to the instruction. 77875ed548SDimitry Andric void addLiveOutSetToMI(MachineFunction &MF, MachineInstr &MI); 78ff0cc061SDimitry Andric 79ff0cc061SDimitry Andric /// \brief Create a register mask and initialize it with the registers from 80ff0cc061SDimitry Andric /// the register live set. 81875ed548SDimitry Andric uint32_t *createRegisterMask(MachineFunction &MF) const; 82ff0cc061SDimitry Andric }; 83ff0cc061SDimitry Andric } // namespace 84ff0cc061SDimitry Andric 8591bc56edSDimitry Andric char StackMapLiveness::ID = 0; 8691bc56edSDimitry Andric char &llvm::StackMapLivenessID = StackMapLiveness::ID; 8791bc56edSDimitry Andric INITIALIZE_PASS(StackMapLiveness, "stackmap-liveness", 8891bc56edSDimitry Andric "StackMap Liveness Analysis", false, false) 8991bc56edSDimitry Andric 9091bc56edSDimitry Andric /// Default construct and initialize the pass. 9191bc56edSDimitry Andric StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) { 9291bc56edSDimitry Andric initializeStackMapLivenessPass(*PassRegistry::getPassRegistry()); 9391bc56edSDimitry Andric } 9491bc56edSDimitry Andric 9591bc56edSDimitry Andric /// Tell the pass manager which passes we depend on and what information we 9691bc56edSDimitry Andric /// preserve. 9791bc56edSDimitry Andric void StackMapLiveness::getAnalysisUsage(AnalysisUsage &AU) const { 9891bc56edSDimitry Andric // We preserve all information. 9991bc56edSDimitry Andric AU.setPreservesAll(); 10091bc56edSDimitry Andric AU.setPreservesCFG(); 101875ed548SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 10291bc56edSDimitry Andric } 10391bc56edSDimitry Andric 10491bc56edSDimitry Andric /// Calculate the liveness information for the given machine function. 105ff0cc061SDimitry Andric bool StackMapLiveness::runOnMachineFunction(MachineFunction &MF) { 10691bc56edSDimitry Andric if (!EnablePatchPointLiveness) 10791bc56edSDimitry Andric return false; 10891bc56edSDimitry Andric 109ff0cc061SDimitry Andric DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: " << MF.getName() 110ff0cc061SDimitry Andric << " **********\n"); 111ff0cc061SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 11291bc56edSDimitry Andric ++NumStackMapFuncVisited; 11391bc56edSDimitry Andric 11491bc56edSDimitry Andric // Skip this function if there are no patchpoints to process. 115d88c1a5aSDimitry Andric if (!MF.getFrameInfo().hasPatchPoint()) { 11691bc56edSDimitry Andric ++NumStackMapFuncSkipped; 11791bc56edSDimitry Andric return false; 11891bc56edSDimitry Andric } 119875ed548SDimitry Andric return calculateLiveness(MF); 12091bc56edSDimitry Andric } 12191bc56edSDimitry Andric 12291bc56edSDimitry Andric /// Performs the actual liveness calculation for the function. 123875ed548SDimitry Andric bool StackMapLiveness::calculateLiveness(MachineFunction &MF) { 12491bc56edSDimitry Andric bool HasChanged = false; 12591bc56edSDimitry Andric // For all basic blocks in the function. 126875ed548SDimitry Andric for (auto &MBB : MF) { 127875ed548SDimitry Andric DEBUG(dbgs() << "****** BB " << MBB.getName() << " ******\n"); 128d88c1a5aSDimitry Andric LiveRegs.init(*TRI); 1293ca95b02SDimitry Andric // FIXME: This should probably be addLiveOuts(). 1303ca95b02SDimitry Andric LiveRegs.addLiveOutsNoPristines(MBB); 13191bc56edSDimitry Andric bool HasStackMap = false; 13291bc56edSDimitry Andric // Reverse iterate over all instructions and add the current live register 13391bc56edSDimitry Andric // set to an instruction if we encounter a patchpoint instruction. 134875ed548SDimitry Andric for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) { 13591bc56edSDimitry Andric if (I->getOpcode() == TargetOpcode::PATCHPOINT) { 136875ed548SDimitry Andric addLiveOutSetToMI(MF, *I); 13791bc56edSDimitry Andric HasChanged = true; 13891bc56edSDimitry Andric HasStackMap = true; 13991bc56edSDimitry Andric ++NumStackMaps; 14091bc56edSDimitry Andric } 14191bc56edSDimitry Andric DEBUG(dbgs() << " " << LiveRegs << " " << *I); 14291bc56edSDimitry Andric LiveRegs.stepBackward(*I); 14391bc56edSDimitry Andric } 14491bc56edSDimitry Andric ++NumBBsVisited; 14591bc56edSDimitry Andric if (!HasStackMap) 14691bc56edSDimitry Andric ++NumBBsHaveNoStackmap; 14791bc56edSDimitry Andric } 14891bc56edSDimitry Andric return HasChanged; 14991bc56edSDimitry Andric } 15091bc56edSDimitry Andric 15191bc56edSDimitry Andric /// Add the current register live set to the instruction. 152875ed548SDimitry Andric void StackMapLiveness::addLiveOutSetToMI(MachineFunction &MF, 153875ed548SDimitry Andric MachineInstr &MI) { 154875ed548SDimitry Andric uint32_t *Mask = createRegisterMask(MF); 15591bc56edSDimitry Andric MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask); 156875ed548SDimitry Andric MI.addOperand(MF, MO); 15791bc56edSDimitry Andric } 15891bc56edSDimitry Andric 15991bc56edSDimitry Andric /// Create a register mask and initialize it with the registers from the 16091bc56edSDimitry Andric /// register live set. 161875ed548SDimitry Andric uint32_t *StackMapLiveness::createRegisterMask(MachineFunction &MF) const { 16291bc56edSDimitry Andric // The mask is owned and cleaned up by the Machine Function. 163875ed548SDimitry Andric uint32_t *Mask = MF.allocateRegisterMask(TRI->getNumRegs()); 164875ed548SDimitry Andric for (auto Reg : LiveRegs) 165875ed548SDimitry Andric Mask[Reg / 32] |= 1U << (Reg % 32); 16639d628a0SDimitry Andric 167875ed548SDimitry Andric // Give the target a chance to adjust the mask. 16839d628a0SDimitry Andric TRI->adjustStackMapLiveOutMask(Mask); 169875ed548SDimitry Andric 17091bc56edSDimitry Andric return Mask; 17191bc56edSDimitry Andric } 172