[llvm] [AIX][TLS] Optimize the small local-exec access sequence for non-zero offsets (PR #71485)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 22 15:55:58 PST 2024
================
@@ -1547,6 +1613,67 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
}
+// For non-TOC-based local-exec variables that have a non-zero offset,
+// we need to create a new MCExpr that adds the non-zero offset to the address
+// of the local-exec variable that will be used in either an addi, load or
+// store. However, the final displacement for these instructions must be
+// between [-32768, 32768), so if the TLS address + its non-zero offset is
+// greater than 32KB, a new MCExpr is produced to accommodate this situation.
+const MCExpr *PPCAsmPrinter::getAdjustedLocalExecExpr(const MachineOperand &MO,
+ int64_t Offset) {
+ // Non-zero offsets (for loads, stores or `addi`) require additional handling.
+ // When the offset is zero, there is no need to create an adjusted MCExpr.
+ if (!Offset)
+ return nullptr;
+
+ assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");
+ const GlobalValue *GValue = MO.getGlobal();
+ assert(TM.getTLSModel(GValue) == TLSModel::LocalExec &&
+ "Only local-exec accesses are handled!");
+
+ bool IsGlobalADeclaration = GValue->isDeclarationForLinker();
+ // Find the GlobalVariable that corresponds to the particular TLS variable
+ // in the TLS variable-to-address mapping. All TLS variables should exist
+ // within this map, with the exception of TLS variables marked as extern.
+ const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(GValue);
+ if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())
+ assert(IsGlobalADeclaration &&
+ "Only expecting to find extern TLS variables not present in the TLS "
+ "variable-to-address map!");
+
+ unsigned TLSVarAddress =
+ IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;
+ ptrdiff_t FinalAddress = (TLSVarAddress + Offset);
+ // If the address of the TLS variable + the offset is less than 32KB,
+ // or if the TLS variable is extern, we simply produce an MCExpr to add the
+ // non-zero offset to the TLS variable address.
+ // For when TLS variables are extern, this is safe to do because we can
+ // assume that the address of extern TLS variables are zero.
+ const MCExpr *Expr = MCSymbolRefExpr::create(
+ getSymbol(GValue), MCSymbolRefExpr::VK_PPC_AIX_TLSLE, OutContext);
+ Expr = MCBinaryExpr::createAdd(
+ Expr, MCConstantExpr::create(Offset, OutContext), OutContext);
+ if (FinalAddress >= 32768) {
+ // Handle the written offset for cases where:
+ // TLS variable address + Offset > 32KB.
+
+ // The assembly that is printed will look like:
+ // TLSVar at le + Offset - Delta
+ // where Delta is a multiple of 64KB: ((FinalAddress + 32768) & ~0xFFFF).
----------------
diggerlin wrote:
I am curiously that
`TLSVar[storageMappingClass]@le + Offset - (Multiple of 64KB) (r13)`
multiple of 64K means that we can have 128K ? is `1TLSVar[storageMappingClass]@le + Offset - 128K` out of the maximum displacement `-32K` of instruction ?
https://github.com/llvm/llvm-project/pull/71485
More information about the llvm-commits
mailing list