================ @@ -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@toc node (for the + // variable offset), and the .__tls_get_mod node is being tuned + // here. It is better to put the LoadOffset@toc node after the call, + // since the LoadOffset@toc node can use clobbers r4/r5. Search for + // the pattern of two Load@toc nodes (either for the variable offset + // or for the module handle), and then move the LoadOffset@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@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@toc node + // for the InReg. Otherwise, Temp probably pointed to the + // LoadOffset@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@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. ---------------- orcguru wrote:
Emm, according to the document (assembler-AIX-72.pdf), "region handle" and "region offset" are used to describe parameters for the __tls_get_addr() function. https://github.com/llvm/llvm-project/pull/66316 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits