[clang] [llvm] [PowerPC] Support local-dynamic TLS relocation on AIX (PR #66316)
Amy Kwan via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 12 20:11:51 PST 2024
================
@@ -145,9 +164,94 @@ namespace {
.addImm(0);
if (IsAIX) {
- // The variable offset and region handle are copied in r4 and r3. The
- // copies are followed by GETtlsADDR32AIX/GETtlsADDR64AIX.
- if (!IsTLSTPRelMI) {
+ if (IsTLSLDAIXMI) {
+ // The relative order between the LoadOffset at toc node (for the
+ // variable offset), and the .__tls_get_mod node is being tuned
+ // here. It is better to put the LoadOffset at toc node after the call,
+ // since the LoadOffset at toc node can use clobbers r4/r5. Search for
+ // the pattern of two Load at toc nodes (either for the variable offset
+ // or for the module handle), and then move the LoadOffset at toc node
+ // 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. Check the pattern and
+ // do the movement if the pattern matches.
+ if (UseIter != MBB.end()) {
+ // Collect associated Load at toc nodes. 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 Load at toc node
+ // for the InReg. Otherwise, Temp probably pointed to the
+ // LoadOffset at toc node that 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 Load at 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 LoadFromTocs are within current BB, and
+ // one of them from the "_$TLSML" pseudo symbol, while the
+ // other 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;
+ }
+ // If both two iterators are valid, we should have identified
+ // the scenario, and do the movement.
+ 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 are copied in r4 and r3.
----------------
amy-kwan wrote:
nit: We use module handle in the other places but region handle here. I think we should use the same terminology.
https://github.com/llvm/llvm-project/pull/66316
More information about the cfe-commits
mailing list