StackMapLivenessAnalysis.cpp [plain text]
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
#define DEBUG_TYPE "stackmaps"
static cl::opt<bool> EnablePatchPointLiveness(
"enable-patchpoint-liveness", cl::Hidden, cl::init(true),
cl::desc("Enable PatchPoint Liveness Analysis Pass"));
STATISTIC(NumStackMapFuncVisited, "Number of functions visited");
STATISTIC(NumStackMapFuncSkipped, "Number of functions skipped");
STATISTIC(NumBBsVisited, "Number of basic blocks visited");
STATISTIC(NumBBsHaveNoStackmap, "Number of basic blocks with no stackmap");
STATISTIC(NumStackMaps, "Number of StackMaps visited");
namespace {
class StackMapLiveness : public MachineFunctionPass {
const TargetRegisterInfo *TRI;
LivePhysRegs LiveRegs;
public:
static char ID;
StackMapLiveness();
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &MF) override;
private:
bool calculateLiveness(MachineFunction &MF);
void addLiveOutSetToMI(MachineFunction &MF, MachineInstr &MI);
uint32_t *createRegisterMask(MachineFunction &MF) const;
};
}
char StackMapLiveness::ID = 0;
char &llvm::StackMapLivenessID = StackMapLiveness::ID;
INITIALIZE_PASS(StackMapLiveness, "stackmap-liveness",
"StackMap Liveness Analysis", false, false)
StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) {
initializeStackMapLivenessPass(*PassRegistry::getPassRegistry());
}
void StackMapLiveness::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool StackMapLiveness::runOnMachineFunction(MachineFunction &MF) {
if (!EnablePatchPointLiveness)
return false;
DEBUG(dbgs() << "********** COMPUTING STACKMAP LIVENESS: " << MF.getName()
<< " **********\n");
TRI = MF.getSubtarget().getRegisterInfo();
++NumStackMapFuncVisited;
if (!MF.getFrameInfo()->hasPatchPoint()) {
++NumStackMapFuncSkipped;
return false;
}
return calculateLiveness(MF);
}
bool StackMapLiveness::calculateLiveness(MachineFunction &MF) {
bool HasChanged = false;
for (auto &MBB : MF) {
DEBUG(dbgs() << "****** BB " << MBB.getName() << " ******\n");
LiveRegs.init(TRI);
LiveRegs.addLiveOuts(&MBB);
bool HasStackMap = false;
for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) {
if (I->getOpcode() == TargetOpcode::PATCHPOINT) {
addLiveOutSetToMI(MF, *I);
HasChanged = true;
HasStackMap = true;
++NumStackMaps;
}
DEBUG(dbgs() << " " << LiveRegs << " " << *I);
LiveRegs.stepBackward(*I);
}
++NumBBsVisited;
if (!HasStackMap)
++NumBBsHaveNoStackmap;
}
return HasChanged;
}
void StackMapLiveness::addLiveOutSetToMI(MachineFunction &MF,
MachineInstr &MI) {
uint32_t *Mask = createRegisterMask(MF);
MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask);
MI.addOperand(MF, MO);
}
uint32_t *StackMapLiveness::createRegisterMask(MachineFunction &MF) const {
uint32_t *Mask = MF.allocateRegisterMask(TRI->getNumRegs());
for (auto Reg : LiveRegs)
Mask[Reg / 32] |= 1U << (Reg % 32);
TRI->adjustStackMapLiveOutMask(Mask);
return Mask;
}