[llvm] [JITLink] Add GOT indirection optimization for SystemZ (PR #171919)

Ulrich Weigand via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 12 04:15:12 PST 2025


================
@@ -106,11 +106,51 @@ const char *getEdgeKindName(Edge::Kind R) {
     return "RequestGOTAndTransformToDelta32dbl";
   case RequestTLSDescInGOTAndTransformToDelta64FromGOT:
     return "RequestTLSDescInGOTAndTransformToDelta64FromGOT";
+  case Delta32dblToPtrJumpStubBypassable:
+    return "Delta32dblToPtrJumpStubBypassable";
   default:
     return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
   }
 }
 
+Error optimizeGOTAndStubAccesses(LinkGraph &G) {
+  LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
+
+  for (auto *B : G.blocks())
+    for (auto &E : B->edges()) {
+      if (E.getKind() == systemz::Delta32dblToPtrJumpStubBypassable) {
+        auto &StubBlock = E.getTarget().getBlock();
+        assert(StubBlock.getSize() == sizeof(Pointer64JumpStubContent) &&
+               "Stub block should be stub sized");
+        assert(StubBlock.edges_size() == 1 &&
+               "Stub block should only have one outgoing edge");
+
+        auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
+        assert(GOTBlock.getSize() == G.getPointerSize() &&
+               "GOT block should be pointer sized");
+        assert(GOTBlock.edges_size() == 1 &&
+               "GOT block should only have one outgoing edge");
+
+        auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
+        orc::ExecutorAddr EdgeAddr = B->getAddress() + E.getOffset();
+        orc::ExecutorAddr TargetAddr = GOTTarget.getAddress();
+
+        int64_t Displacement = TargetAddr - EdgeAddr;
----------------
uweigand wrote:

I think we need to take the addend into account here.  `R_390_PTL32DBL` relocations on a `brasl` instruction usually have an added of 2, as the instruction is a branch relative to the PC at the beginning of the instruction, but the relocation is computed as a delta relative to the field starting at 2 bytes into the instruction.  That's why in `applyFixup` we have:
```
  case DeltaPLT32dbl: {
    int64_t Value = S + A - P;
    if (!LLVM_UNLIKELY(isInt<33>(Value)))
      return makeTargetOutOfRangeError(G, B, E);
```
where `S` corresponds to `TargetAddr` here and `P` corresponds to `FixupAddr` here, but the `A` is missing.  This should be something like:
```
        int64_t Displacement = TargetAddr + E.getAddend() - EdgeAddr;
```

https://github.com/llvm/llvm-project/pull/171919


More information about the llvm-commits mailing list