Port x86-cleanup-local-dynamic-tls to the new pass manager. I moved LDTLSCleanup to a new llvm/lib/Target/X86/X86CleanupLocalDynamicTLS.cpp file and renamed it to X86CleanupLocalDynamicTLSPass. Then I renamed the legacy pass, and adding a NewPM wrapper around the impl. No test coverage added for now as there are no MIR->MIR tests exercising this pass and we do not have enough ported to run any end to end tests.
166 lines
5.7 KiB
C++
166 lines
5.7 KiB
C++
//===- X86CleanupLocalDynamicTLS.cpp - Cleanup local dynamic TLS access ---===//
|
|
//
|
|
// 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 pass combines multiple accesses to local-dynamic TLS variables so that
|
|
// the TLS base address for the module is only fetched once per execution path
|
|
// through the function.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "X86.h"
|
|
#include "X86InstrInfo.h"
|
|
#include "X86MachineFunctionInfo.h"
|
|
#include "X86Subtarget.h"
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/InitializePasses.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "x86-cleanup-local-dynamic-tls"
|
|
|
|
namespace {
|
|
class X86CleanupLocalDynamicTLSLegacy : public MachineFunctionPass {
|
|
public:
|
|
static char ID;
|
|
|
|
X86CleanupLocalDynamicTLSLegacy() : MachineFunctionPass(ID) {}
|
|
|
|
StringRef getPassName() const override {
|
|
return "Local Dynamic TLS Access Clean-up";
|
|
}
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
AU.setPreservesCFG();
|
|
AU.addRequired<MachineDominatorTreeWrapperPass>();
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
char X86CleanupLocalDynamicTLSLegacy::ID = 0;
|
|
|
|
FunctionPass *llvm::createCleanupLocalDynamicTLSLegacyPass() {
|
|
return new X86CleanupLocalDynamicTLSLegacy();
|
|
}
|
|
|
|
// Replace the TLS_base_addr instruction I with a copy from
|
|
// TLSBaseAddrReg, returning the new instruction.
|
|
static MachineInstr *ReplaceTLSBaseAddrCall(MachineInstr &I,
|
|
Register TLSBaseAddrReg) {
|
|
MachineFunction *MF = I.getParent()->getParent();
|
|
const X86Subtarget &STI = MF->getSubtarget<X86Subtarget>();
|
|
const bool is64Bit = STI.is64Bit();
|
|
const X86InstrInfo *TII = STI.getInstrInfo();
|
|
|
|
// Insert a Copy from TLSBaseAddrReg to RAX/EAX.
|
|
MachineInstr *Copy =
|
|
BuildMI(*I.getParent(), I, I.getDebugLoc(), TII->get(TargetOpcode::COPY),
|
|
is64Bit ? X86::RAX : X86::EAX)
|
|
.addReg(TLSBaseAddrReg);
|
|
|
|
// Erase the TLS_base_addr instruction.
|
|
I.eraseFromParent();
|
|
|
|
return Copy;
|
|
}
|
|
|
|
// Create a virtual register in *TLSBaseAddrReg, and populate it by
|
|
// inserting a copy instruction after I. Returns the new instruction.
|
|
static MachineInstr *SetRegister(MachineInstr &I, Register *TLSBaseAddrReg) {
|
|
MachineFunction *MF = I.getParent()->getParent();
|
|
const X86Subtarget &STI = MF->getSubtarget<X86Subtarget>();
|
|
const bool is64Bit = STI.is64Bit();
|
|
const X86InstrInfo *TII = STI.getInstrInfo();
|
|
|
|
// Create a virtual register for the TLS base address.
|
|
MachineRegisterInfo &RegInfo = MF->getRegInfo();
|
|
*TLSBaseAddrReg = RegInfo.createVirtualRegister(is64Bit ? &X86::GR64RegClass
|
|
: &X86::GR32RegClass);
|
|
|
|
// Insert a copy from RAX/EAX to TLSBaseAddrReg.
|
|
MachineInstr *Next = I.getNextNode();
|
|
MachineInstr *Copy = BuildMI(*I.getParent(), Next, I.getDebugLoc(),
|
|
TII->get(TargetOpcode::COPY), *TLSBaseAddrReg)
|
|
.addReg(is64Bit ? X86::RAX : X86::EAX);
|
|
|
|
return Copy;
|
|
}
|
|
|
|
// Visit the dominator subtree rooted at Node in pre-order.
|
|
// If TLSBaseAddrReg is non-null, then use that to replace any
|
|
// TLS_base_addr instructions. Otherwise, create the register
|
|
// when the first such instruction is seen, and then use it
|
|
// as we encounter more instructions.
|
|
static bool VisitNode(MachineDomTreeNode *Node, Register TLSBaseAddrReg) {
|
|
MachineBasicBlock *BB = Node->getBlock();
|
|
bool Changed = false;
|
|
|
|
// Traverse the current block.
|
|
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;
|
|
++I) {
|
|
switch (I->getOpcode()) {
|
|
case X86::TLS_base_addr32:
|
|
case X86::TLS_base_addr64:
|
|
if (TLSBaseAddrReg)
|
|
I = ReplaceTLSBaseAddrCall(*I, TLSBaseAddrReg);
|
|
else
|
|
I = SetRegister(*I, &TLSBaseAddrReg);
|
|
Changed = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Visit the children of this block in the dominator tree.
|
|
for (MachineDomTreeNode *I : Node->children())
|
|
Changed |= VisitNode(I, TLSBaseAddrReg);
|
|
|
|
return Changed;
|
|
}
|
|
|
|
static bool cleanupLocalDynamicTLS(MachineDominatorTree &DT) {
|
|
return VisitNode(DT.getRootNode(), Register());
|
|
}
|
|
|
|
static bool shouldSkipLocalDynamicTLS(MachineFunction &MF) {
|
|
X86MachineFunctionInfo *MFI = MF.getInfo<X86MachineFunctionInfo>();
|
|
if (MFI->getNumLocalDynamicTLSAccesses() < 2) {
|
|
// No point folding accesses if there isn't at least two.
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool X86CleanupLocalDynamicTLSLegacy::runOnMachineFunction(
|
|
MachineFunction &MF) {
|
|
if (skipFunction(MF.getFunction()) || shouldSkipLocalDynamicTLS(MF))
|
|
return false;
|
|
|
|
MachineDominatorTree &DT =
|
|
getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
|
|
return cleanupLocalDynamicTLS(DT);
|
|
}
|
|
|
|
PreservedAnalyses
|
|
X86CleanupLocalDynamicTLSPass::run(MachineFunction &MF,
|
|
MachineFunctionAnalysisManager &MFAM) {
|
|
if (shouldSkipLocalDynamicTLS(MF))
|
|
return PreservedAnalyses::all();
|
|
|
|
MachineDominatorTree &DT = MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
|
|
return cleanupLocalDynamicTLS(DT) ? getMachineFunctionPassPreservedAnalyses()
|
|
.preserveSet<CFGAnalyses>()
|
|
: PreservedAnalyses::all();
|
|
}
|