1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
|
//===---------- PPCTLSDynamicCall.cpp - TLS Dynamic Call Fixup ------------===//
//
// 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 expands ADDItls{ld,gd}LADDR[32] machine instructions into
// separate ADDItls[gd]L[32] and GETtlsADDR[32] instructions, both of
// which define GPR3. A copy is added from GPR3 to the target virtual
// register of the original instruction. The GETtlsADDR[32] is really
// a call instruction, so its target register is constrained to be GPR3.
// This is not true of ADDItls[gd]L[32], but there is a legacy linker
// optimization bug that requires the target register of the addi of
// a local- or general-dynamic TLS access sequence to be GPR3.
//
// This is done in a late pass so that TLS variable accesses can be
// fully commoned by MachineCSE.
//
//===----------------------------------------------------------------------===//
#include "PPC.h"
#include "PPCInstrBuilder.h"
#include "PPCInstrInfo.h"
#include "PPCTargetMachine.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "ppc-tls-dynamic-call"
namespace {
struct PPCTLSDynamicCall : public MachineFunctionPass {
static char ID;
PPCTLSDynamicCall() : MachineFunctionPass(ID) {
initializePPCTLSDynamicCallPass(*PassRegistry::getPassRegistry());
}
const PPCInstrInfo *TII;
protected:
bool processBlock(MachineBasicBlock &MBB) {
bool Changed = false;
bool NeedFence = true;
const PPCSubtarget &Subtarget =
MBB.getParent()->getSubtarget<PPCSubtarget>();
bool Is64Bit = Subtarget.isPPC64();
bool IsAIX = Subtarget.isAIXABI();
bool IsLargeModel =
Subtarget.getTargetMachine().getCodeModel() == CodeModel::Large;
bool IsPCREL = false;
MachineFunction *MF = MBB.getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
I != IE;) {
MachineInstr &MI = *I;
IsPCREL = isPCREL(MI);
// There are a number of slight differences in code generation
// when we call .__get_tpointer (32-bit AIX TLS).
bool IsTLSTPRelMI = MI.getOpcode() == PPC::GETtlsTpointer32AIX;
bool IsTLSLDAIXMI = (MI.getOpcode() == PPC::TLSLDAIX8 ||
MI.getOpcode() == PPC::TLSLDAIX);
if (MI.getOpcode() != PPC::ADDItlsgdLADDR &&
MI.getOpcode() != PPC::ADDItlsldLADDR &&
MI.getOpcode() != PPC::ADDItlsgdLADDR32 &&
MI.getOpcode() != PPC::ADDItlsldLADDR32 &&
MI.getOpcode() != PPC::TLSGDAIX &&
MI.getOpcode() != PPC::TLSGDAIX8 && !IsTLSTPRelMI && !IsPCREL &&
!IsTLSLDAIXMI) {
// Although we create ADJCALLSTACKDOWN and ADJCALLSTACKUP
// as scheduling fences, we skip creating fences if we already
// have existing ADJCALLSTACKDOWN/UP to avoid nesting,
// which causes verification error with -verify-machineinstrs.
if (MI.getOpcode() == PPC::ADJCALLSTACKDOWN)
NeedFence = false;
else if (MI.getOpcode() == PPC::ADJCALLSTACKUP)
NeedFence = true;
++I;
continue;
}
LLVM_DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n " << MI);
Register OutReg = MI.getOperand(0).getReg();
Register InReg = PPC::NoRegister;
Register GPR3 = Is64Bit ? PPC::X3 : PPC::R3;
Register GPR4 = Is64Bit ? PPC::X4 : PPC::R4;
if (!IsPCREL && !IsTLSTPRelMI)
InReg = MI.getOperand(1).getReg();
DebugLoc DL = MI.getDebugLoc();
unsigned Opc1, Opc2;
switch (MI.getOpcode()) {
default:
llvm_unreachable("Opcode inconsistency error");
case PPC::ADDItlsgdLADDR:
Opc1 = PPC::ADDItlsgdL;
Opc2 = PPC::GETtlsADDR;
break;
case PPC::ADDItlsldLADDR:
Opc1 = PPC::ADDItlsldL;
Opc2 = PPC::GETtlsldADDR;
break;
case PPC::ADDItlsgdLADDR32:
Opc1 = PPC::ADDItlsgdL32;
Opc2 = PPC::GETtlsADDR32;
break;
case PPC::ADDItlsldLADDR32:
Opc1 = PPC::ADDItlsldL32;
Opc2 = PPC::GETtlsldADDR32;
break;
case PPC::TLSLDAIX:
// TLSLDAIX is expanded to one copy and GET_TLS_MOD, so we only set
// Opc2 here.
Opc2 = PPC::GETtlsMOD32AIX;
break;
case PPC::TLSLDAIX8:
// TLSLDAIX8 is expanded to one copy and GET_TLS_MOD, so we only set
// Opc2 here.
Opc2 = PPC::GETtlsMOD64AIX;
break;
case PPC::TLSGDAIX8:
// TLSGDAIX8 is expanded to two copies and GET_TLS_ADDR, so we only
// set Opc2 here.
Opc2 = PPC::GETtlsADDR64AIX;
break;
case PPC::TLSGDAIX:
// TLSGDAIX is expanded to two copies and GET_TLS_ADDR, so we only
// set Opc2 here.
Opc2 = PPC::GETtlsADDR32AIX;
break;
case PPC::GETtlsTpointer32AIX:
// GETtlsTpointer32AIX is expanded to a call to GET_TPOINTER on AIX
// 32-bit mode within PPCAsmPrinter. This instruction does not need
// to change, so Opc2 is set to the same instruction opcode.
Opc2 = PPC::GETtlsTpointer32AIX;
break;
case PPC::PADDI8pc:
assert(IsPCREL && "Expecting General/Local Dynamic PCRel");
Opc1 = PPC::PADDI8pc;
Opc2 = MI.getOperand(2).getTargetFlags() ==
PPCII::MO_GOT_TLSGD_PCREL_FLAG
? PPC::GETtlsADDRPCREL
: PPC::GETtlsldADDRPCREL;
}
// We create ADJCALLSTACKUP and ADJCALLSTACKDOWN around _tls_get_addr
// as scheduling fence to avoid it is scheduled before
// mflr in the prologue and the address in LR is clobbered (PR25839).
// We don't really need to save data to the stack - the clobbered
// registers are already saved when the SDNode (e.g. PPCaddiTlsgdLAddr)
// gets translated to the pseudo instruction (e.g. ADDItlsgdLADDR).
if (NeedFence) {
MBB.getParent()->getFrameInfo().setAdjustsStack(true);
BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKDOWN)).addImm(0)
.addImm(0);
}
if (IsAIX) {
if (IsTLSLDAIXMI) {
// The relative order between the node that loads the variable
// offset from the TOC, and the .__tls_get_mod node is being tuned
// here. It is better to put the variable offset TOC load after the
// call, since this node can use clobbers r4/r5.
// Search for the pattern of the two nodes that load from the TOC
// (either for the variable offset or for the module handle), and
// then move the variable offset TOC load right before the node that
// uses the OutReg of the .__tls_get_mod node.
unsigned LDTocOp =
Is64Bit ? (IsLargeModel ? PPC::LDtocL : PPC::LDtoc)
: (IsLargeModel ? PPC::LWZtocL : PPC::LWZtoc);
if (!RegInfo.use_empty(OutReg)) {
std::set<MachineInstr *> Uses;
// Collect all instructions that use the OutReg.
for (MachineOperand &MO : RegInfo.use_operands(OutReg))
Uses.insert(MO.getParent());
// Find the first user (e.g.: lwax/stfdx) of the OutReg within the
// current BB.
MachineBasicBlock::iterator UseIter = MBB.begin();
for (MachineBasicBlock::iterator IE = MBB.end(); UseIter != IE;
++UseIter)
if (Uses.count(&*UseIter))
break;
// Additional handling is required when UserIter (the first user
// of OutReg) is pointing to a valid node that loads from the TOC.
// Check the pattern and do the movement if the pattern matches.
if (UseIter != MBB.end()) {
// Collect all associated nodes that load from the TOC. Use
// hasOneDef() to guard against unexpected scenarios.
std::set<MachineInstr *> LoadFromTocs;
for (MachineOperand &MO : UseIter->operands())
if (MO.isReg() && MO.isUse()) {
Register MOReg = MO.getReg();
if (RegInfo.hasOneDef(MOReg)) {
MachineInstr *Temp =
RegInfo.getOneDef(MOReg)->getParent();
// For the current TLSLDAIX node, get the corresponding
// node that loads from the TOC for the InReg. Otherwise,
// Temp probably pointed to the variable offset TOC load
// we would like to move.
if (Temp == &MI && RegInfo.hasOneDef(InReg))
Temp = RegInfo.getOneDef(InReg)->getParent();
if (Temp->getOpcode() == LDTocOp)
LoadFromTocs.insert(Temp);
} else {
// FIXME: analyze this scenario if there is one.
LoadFromTocs.clear();
break;
}
}
// Check the two nodes that loaded from the TOC: one should be
// "_$TLSML", and the other will be moved before the node that
// uses the OutReg of the .__tls_get_mod node.
if (LoadFromTocs.size() == 2) {
MachineBasicBlock::iterator TLSMLIter = MBB.end();
MachineBasicBlock::iterator OffsetIter = MBB.end();
// Make sure the two nodes that loaded from the TOC are within
// the current BB, and that one of them is from the "_$TLSML"
// pseudo symbol, while the other is from the variable.
for (MachineBasicBlock::iterator I = MBB.begin(),
IE = MBB.end();
I != IE; ++I)
if (LoadFromTocs.count(&*I)) {
MachineOperand MO = I->getOperand(1);
if (MO.isGlobal() && MO.getGlobal()->hasName() &&
MO.getGlobal()->getName() == "_$TLSML")
TLSMLIter = I;
else
OffsetIter = I;
}
// Perform the movement when the desired scenario has been
// identified, which should be when both of the iterators are
// valid.
if (TLSMLIter != MBB.end() && OffsetIter != MBB.end())
OffsetIter->moveBefore(&*UseIter);
}
}
}
// The module-handle is copied into r3. The copy is followed by
// GETtlsMOD32AIX/GETtlsMOD64AIX.
BuildMI(MBB, I, DL, TII->get(TargetOpcode::COPY), GPR3)
.addReg(InReg);
// The call to .__tls_get_mod.
BuildMI(MBB, I, DL, TII->get(Opc2), GPR3).addReg(GPR3);
} else if (!IsTLSTPRelMI) {
// The variable offset and region handle (for TLSGD) are copied in
// r4 and r3. The copies are followed by
// GETtlsADDR32AIX/GETtlsADDR64AIX.
BuildMI(MBB, I, DL, TII->get(TargetOpcode::COPY), GPR4)
.addReg(MI.getOperand(1).getReg());
BuildMI(MBB, I, DL, TII->get(TargetOpcode::COPY), GPR3)
.addReg(MI.getOperand(2).getReg());
BuildMI(MBB, I, DL, TII->get(Opc2), GPR3).addReg(GPR3).addReg(GPR4);
} else
// The opcode of GETtlsTpointer32AIX does not change, because later
// this instruction will be expanded into a call to .__get_tpointer,
// which will return the thread pointer into r3.
BuildMI(MBB, I, DL, TII->get(Opc2), GPR3);
} else {
MachineInstr *Addi;
if (IsPCREL) {
Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addImm(0);
} else {
// Expand into two ops built prior to the existing instruction.
assert(InReg != PPC::NoRegister && "Operand must be a register");
Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addReg(InReg);
}
Addi->addOperand(MI.getOperand(2));
MachineInstr *Call =
(BuildMI(MBB, I, DL, TII->get(Opc2), GPR3).addReg(GPR3));
if (IsPCREL)
Call->addOperand(MI.getOperand(2));
else
Call->addOperand(MI.getOperand(3));
}
if (NeedFence)
BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKUP)).addImm(0).addImm(0);
BuildMI(MBB, I, DL, TII->get(TargetOpcode::COPY), OutReg)
.addReg(GPR3);
// Move past the original instruction and remove it.
++I;
MI.removeFromParent();
Changed = true;
}
return Changed;
}
public:
bool isPCREL(const MachineInstr &MI) {
return (MI.getOpcode() == PPC::PADDI8pc) &&
(MI.getOperand(2).getTargetFlags() ==
PPCII::MO_GOT_TLSGD_PCREL_FLAG ||
MI.getOperand(2).getTargetFlags() ==
PPCII::MO_GOT_TLSLD_PCREL_FLAG);
}
bool runOnMachineFunction(MachineFunction &MF) override {
TII = MF.getSubtarget<PPCSubtarget>().getInstrInfo();
bool Changed = false;
for (MachineBasicBlock &B : llvm::make_early_inc_range(MF))
if (processBlock(B))
Changed = true;
return Changed;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<LiveIntervalsWrapperPass>();
AU.addRequired<SlotIndexesWrapperPass>();
MachineFunctionPass::getAnalysisUsage(AU);
}
};
}
INITIALIZE_PASS_BEGIN(PPCTLSDynamicCall, DEBUG_TYPE,
"PowerPC TLS Dynamic Call Fixup", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)
INITIALIZE_PASS_END(PPCTLSDynamicCall, DEBUG_TYPE,
"PowerPC TLS Dynamic Call Fixup", false, false)
char PPCTLSDynamicCall::ID = 0;
FunctionPass*
llvm::createPPCTLSDynamicCallPass() { return new PPCTLSDynamicCall(); }
|