1*0b57cec5SDimitry Andric //===-- StackMapLivenessAnalysis.cpp - StackMap live Out Analysis ----------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the StackMap Liveness analysis pass. The pass calculates 10*0b57cec5SDimitry Andric // the liveness for each basic block in a function and attaches the register 11*0b57cec5SDimitry Andric // live-out information to a stackmap or patchpoint intrinsic if present. 12*0b57cec5SDimitry Andric // 13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14*0b57cec5SDimitry Andric 15*0b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 22480093f4SDimitry Andric #include "llvm/InitializePasses.h" 23*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 24*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 25*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric using namespace llvm; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric #define DEBUG_TYPE "stackmaps" 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric static cl::opt<bool> EnablePatchPointLiveness( 32*0b57cec5SDimitry Andric "enable-patchpoint-liveness", cl::Hidden, cl::init(true), 33*0b57cec5SDimitry Andric cl::desc("Enable PatchPoint Liveness Analysis Pass")); 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric STATISTIC(NumStackMapFuncVisited, "Number of functions visited"); 36*0b57cec5SDimitry Andric STATISTIC(NumStackMapFuncSkipped, "Number of functions skipped"); 37*0b57cec5SDimitry Andric STATISTIC(NumBBsVisited, "Number of basic blocks visited"); 38*0b57cec5SDimitry Andric STATISTIC(NumBBsHaveNoStackmap, "Number of basic blocks with no stackmap"); 39*0b57cec5SDimitry Andric STATISTIC(NumStackMaps, "Number of StackMaps visited"); 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric namespace { 42*0b57cec5SDimitry Andric /// This pass calculates the liveness information for each basic block in 43*0b57cec5SDimitry Andric /// a function and attaches the register live-out information to a patchpoint 44*0b57cec5SDimitry Andric /// intrinsic if present. 45*0b57cec5SDimitry Andric /// 46*0b57cec5SDimitry Andric /// This pass can be disabled via the -enable-patchpoint-liveness=false flag. 47*0b57cec5SDimitry Andric /// The pass skips functions that don't have any patchpoint intrinsics. The 48*0b57cec5SDimitry Andric /// information provided by this pass is optional and not required by the 49*0b57cec5SDimitry Andric /// aformentioned intrinsic to function. 50*0b57cec5SDimitry Andric class StackMapLiveness : public MachineFunctionPass { 51*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 52*0b57cec5SDimitry Andric LivePhysRegs LiveRegs; 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric public: 55*0b57cec5SDimitry Andric static char ID; 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric /// Default construct and initialize the pass. 58*0b57cec5SDimitry Andric StackMapLiveness(); 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric /// Tell the pass manager which passes we depend on and what 61*0b57cec5SDimitry Andric /// information we preserve. 62*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override; 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 65*0b57cec5SDimitry Andric return MachineFunctionProperties().set( 66*0b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 67*0b57cec5SDimitry Andric } 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric /// Calculate the liveness information for the given machine function. 70*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric private: 73*0b57cec5SDimitry Andric /// Performs the actual liveness calculation for the function. 74*0b57cec5SDimitry Andric bool calculateLiveness(MachineFunction &MF); 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric /// Add the current register live set to the instruction. 77*0b57cec5SDimitry Andric void addLiveOutSetToMI(MachineFunction &MF, MachineInstr &MI); 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric /// Create a register mask and initialize it with the registers from 80*0b57cec5SDimitry Andric /// the register live set. 81*0b57cec5SDimitry Andric uint32_t *createRegisterMask(MachineFunction &MF) const; 82*0b57cec5SDimitry Andric }; 83*0b57cec5SDimitry Andric } // namespace 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric char StackMapLiveness::ID = 0; 86*0b57cec5SDimitry Andric char &llvm::StackMapLivenessID = StackMapLiveness::ID; 87*0b57cec5SDimitry Andric INITIALIZE_PASS(StackMapLiveness, "stackmap-liveness", 88*0b57cec5SDimitry Andric "StackMap Liveness Analysis", false, false) 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric /// Default construct and initialize the pass. 91*0b57cec5SDimitry Andric StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) { 92*0b57cec5SDimitry Andric initializeStackMapLivenessPass(*PassRegistry::getPassRegistry()); 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric /// Tell the pass manager which passes we depend on and what information we 96*0b57cec5SDimitry Andric /// preserve. 97*0b57cec5SDimitry Andric void StackMapLiveness::getAnalysisUsage(AnalysisUsage &AU) const { 98*0b57cec5SDimitry Andric // We preserve all information. 99*0b57cec5SDimitry Andric AU.setPreservesAll(); 100*0b57cec5SDimitry Andric AU.setPreservesCFG(); 101*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric /// Calculate the liveness information for the given machine function. 105*0b57cec5SDimitry Andric bool StackMapLiveness::runOnMachineFunction(MachineFunction &MF) { 106*0b57cec5SDimitry Andric if (!EnablePatchPointLiveness) 107*0b57cec5SDimitry Andric return false; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: " 110*0b57cec5SDimitry Andric << MF.getName() << " **********\n"); 111*0b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 112*0b57cec5SDimitry Andric ++NumStackMapFuncVisited; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric // Skip this function if there are no patchpoints to process. 115*0b57cec5SDimitry Andric if (!MF.getFrameInfo().hasPatchPoint()) { 116*0b57cec5SDimitry Andric ++NumStackMapFuncSkipped; 117*0b57cec5SDimitry Andric return false; 118*0b57cec5SDimitry Andric } 119*0b57cec5SDimitry Andric return calculateLiveness(MF); 120*0b57cec5SDimitry Andric } 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric /// Performs the actual liveness calculation for the function. 123*0b57cec5SDimitry Andric bool StackMapLiveness::calculateLiveness(MachineFunction &MF) { 124*0b57cec5SDimitry Andric bool HasChanged = false; 125*0b57cec5SDimitry Andric // For all basic blocks in the function. 126*0b57cec5SDimitry Andric for (auto &MBB : MF) { 127*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "****** BB " << MBB.getName() << " ******\n"); 128*0b57cec5SDimitry Andric LiveRegs.init(*TRI); 129*0b57cec5SDimitry Andric // FIXME: This should probably be addLiveOuts(). 130*0b57cec5SDimitry Andric LiveRegs.addLiveOutsNoPristines(MBB); 131*0b57cec5SDimitry Andric bool HasStackMap = false; 132*0b57cec5SDimitry Andric // Reverse iterate over all instructions and add the current live register 133*0b57cec5SDimitry Andric // set to an instruction if we encounter a patchpoint instruction. 1340eae32dcSDimitry Andric for (MachineInstr &MI : llvm::reverse(MBB)) { 1350eae32dcSDimitry Andric if (MI.getOpcode() == TargetOpcode::PATCHPOINT) { 1360eae32dcSDimitry Andric addLiveOutSetToMI(MF, MI); 137*0b57cec5SDimitry Andric HasChanged = true; 138*0b57cec5SDimitry Andric HasStackMap = true; 139*0b57cec5SDimitry Andric ++NumStackMaps; 140*0b57cec5SDimitry Andric } 1410eae32dcSDimitry Andric LLVM_DEBUG(dbgs() << " " << LiveRegs << " " << MI); 1420eae32dcSDimitry Andric LiveRegs.stepBackward(MI); 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric ++NumBBsVisited; 145*0b57cec5SDimitry Andric if (!HasStackMap) 146*0b57cec5SDimitry Andric ++NumBBsHaveNoStackmap; 147*0b57cec5SDimitry Andric } 148*0b57cec5SDimitry Andric return HasChanged; 149*0b57cec5SDimitry Andric } 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric /// Add the current register live set to the instruction. 152*0b57cec5SDimitry Andric void StackMapLiveness::addLiveOutSetToMI(MachineFunction &MF, 153*0b57cec5SDimitry Andric MachineInstr &MI) { 154*0b57cec5SDimitry Andric uint32_t *Mask = createRegisterMask(MF); 155*0b57cec5SDimitry Andric MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask); 156*0b57cec5SDimitry Andric MI.addOperand(MF, MO); 157*0b57cec5SDimitry Andric } 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric /// Create a register mask and initialize it with the registers from the 160*0b57cec5SDimitry Andric /// register live set. 161*0b57cec5SDimitry Andric uint32_t *StackMapLiveness::createRegisterMask(MachineFunction &MF) const { 162*0b57cec5SDimitry Andric // The mask is owned and cleaned up by the Machine Function. 163*0b57cec5SDimitry Andric uint32_t *Mask = MF.allocateRegMask(); 164*0b57cec5SDimitry Andric for (auto Reg : LiveRegs) 165*0b57cec5SDimitry Andric Mask[Reg / 32] |= 1U << (Reg % 32); 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric // Give the target a chance to adjust the mask. 168*0b57cec5SDimitry Andric TRI->adjustStackMapLiveOutMask(Mask); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric return Mask; 171*0b57cec5SDimitry Andric } 172