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