Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===-- Speculation.h - Speculative Compilation --*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Contains the definition to support speculative compilation when laziness is
10
// enabled.
11
//===----------------------------------------------------------------------===//
12
 
13
#ifndef LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
14
#define LLVM_EXECUTIONENGINE_ORC_SPECULATION_H
15
 
16
#include "llvm/ADT/DenseMap.h"
17
#include "llvm/ExecutionEngine/Orc/Core.h"
18
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
19
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
20
#include "llvm/Support/Debug.h"
21
#include <mutex>
22
#include <type_traits>
23
#include <utility>
24
 
25
namespace llvm {
26
namespace orc {
27
 
28
class Speculator;
29
 
30
// Track the Impls (JITDylib,Symbols) of Symbols while lazy call through
31
// trampolines are created. Operations are guarded by locks tp ensure that Imap
32
// stays in consistent state after read/write
33
 
34
class ImplSymbolMap {
35
  friend class Speculator;
36
 
37
public:
38
  using AliaseeDetails = std::pair<SymbolStringPtr, JITDylib *>;
39
  using Alias = SymbolStringPtr;
40
  using ImapTy = DenseMap<Alias, AliaseeDetails>;
41
  void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD);
42
 
43
private:
44
  // FIX ME: find a right way to distinguish the pre-compile Symbols, and update
45
  // the callsite
46
  std::optional<AliaseeDetails> getImplFor(const SymbolStringPtr &StubSymbol) {
47
    std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
48
    auto Position = Maps.find(StubSymbol);
49
    if (Position != Maps.end())
50
      return Position->getSecond();
51
    else
52
      return std::nullopt;
53
  }
54
 
55
  std::mutex ConcurrentAccess;
56
  ImapTy Maps;
57
};
58
 
59
// Defines Speculator Concept,
60
class Speculator {
61
public:
62
  using TargetFAddr = JITTargetAddress;
63
  using FunctionCandidatesMap = DenseMap<SymbolStringPtr, SymbolNameSet>;
64
  using StubAddrLikelies = DenseMap<TargetFAddr, SymbolNameSet>;
65
 
66
private:
67
  void registerSymbolsWithAddr(TargetFAddr ImplAddr,
68
                               SymbolNameSet likelySymbols) {
69
    std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
70
    GlobalSpecMap.insert({ImplAddr, std::move(likelySymbols)});
71
  }
72
 
73
  void launchCompile(JITTargetAddress FAddr) {
74
    SymbolNameSet CandidateSet;
75
    // Copy CandidateSet is necessary, to avoid unsynchronized access to
76
    // the datastructure.
77
    {
78
      std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
79
      auto It = GlobalSpecMap.find(FAddr);
80
      if (It == GlobalSpecMap.end())
81
        return;
82
      CandidateSet = It->getSecond();
83
    }
84
 
85
    SymbolDependenceMap SpeculativeLookUpImpls;
86
 
87
    for (auto &Callee : CandidateSet) {
88
      auto ImplSymbol = AliaseeImplTable.getImplFor(Callee);
89
      // try to distinguish already compiled & library symbols
90
      if (!ImplSymbol)
91
        continue;
92
      const auto &ImplSymbolName = ImplSymbol->first;
93
      JITDylib *ImplJD = ImplSymbol->second;
94
      auto &SymbolsInJD = SpeculativeLookUpImpls[ImplJD];
95
      SymbolsInJD.insert(ImplSymbolName);
96
    }
97
 
98
    DEBUG_WITH_TYPE("orc", {
99
      for (auto &I : SpeculativeLookUpImpls) {
100
        llvm::dbgs() << "\n In " << I.first->getName() << " JITDylib ";
101
        for (auto &N : I.second)
102
          llvm::dbgs() << "\n Likely Symbol : " << N;
103
      }
104
    });
105
 
106
    // for a given symbol, there may be no symbol qualified for speculatively
107
    // compile try to fix this before jumping to this code if possible.
108
    for (auto &LookupPair : SpeculativeLookUpImpls)
109
      ES.lookup(
110
          LookupKind::Static,
111
          makeJITDylibSearchOrder(LookupPair.first,
112
                                  JITDylibLookupFlags::MatchAllSymbols),
113
          SymbolLookupSet(LookupPair.second), SymbolState::Ready,
114
          [this](Expected<SymbolMap> Result) {
115
            if (auto Err = Result.takeError())
116
              ES.reportError(std::move(Err));
117
          },
118
          NoDependenciesToRegister);
119
  }
120
 
121
public:
122
  Speculator(ImplSymbolMap &Impl, ExecutionSession &ref)
123
      : AliaseeImplTable(Impl), ES(ref), GlobalSpecMap(0) {}
124
  Speculator(const Speculator &) = delete;
125
  Speculator(Speculator &&) = delete;
126
  Speculator &operator=(const Speculator &) = delete;
127
  Speculator &operator=(Speculator &&) = delete;
128
 
129
  /// Define symbols for this Speculator object (__orc_speculator) and the
130
  /// speculation runtime entry point symbol (__orc_speculate_for) in the
131
  /// given JITDylib.
132
  Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle);
133
 
134
  // Speculatively compile likely functions for the given Stub Address.
135
  // destination of __orc_speculate_for jump
136
  void speculateFor(TargetFAddr StubAddr) { launchCompile(StubAddr); }
137
 
138
  // FIXME : Register with Stub Address, after JITLink Fix.
139
  void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD) {
140
    for (auto &SymPair : Candidates) {
141
      auto Target = SymPair.first;
142
      auto Likely = SymPair.second;
143
 
144
      auto OnReadyFixUp = [Likely, Target,
145
                           this](Expected<SymbolMap> ReadySymbol) {
146
        if (ReadySymbol) {
147
          auto RAddr = (*ReadySymbol)[Target].getAddress();
148
          registerSymbolsWithAddr(RAddr, std::move(Likely));
149
        } else
150
          this->getES().reportError(ReadySymbol.takeError());
151
      };
152
      // Include non-exported symbols also.
153
      ES.lookup(
154
          LookupKind::Static,
155
          makeJITDylibSearchOrder(JD, JITDylibLookupFlags::MatchAllSymbols),
156
          SymbolLookupSet(Target, SymbolLookupFlags::WeaklyReferencedSymbol),
157
          SymbolState::Ready, OnReadyFixUp, NoDependenciesToRegister);
158
    }
159
  }
160
 
161
  ExecutionSession &getES() { return ES; }
162
 
163
private:
164
  static void speculateForEntryPoint(Speculator *Ptr, uint64_t StubId);
165
  std::mutex ConcurrentAccess;
166
  ImplSymbolMap &AliaseeImplTable;
167
  ExecutionSession &ES;
168
  StubAddrLikelies GlobalSpecMap;
169
};
170
 
171
class IRSpeculationLayer : public IRLayer {
172
public:
173
  using IRlikiesStrRef =
174
      std::optional<DenseMap<StringRef, DenseSet<StringRef>>>;
175
  using ResultEval = std::function<IRlikiesStrRef(Function &)>;
176
  using TargetAndLikelies = DenseMap<SymbolStringPtr, SymbolNameSet>;
177
 
178
  IRSpeculationLayer(ExecutionSession &ES, IRLayer &BaseLayer, Speculator &Spec,
179
                     MangleAndInterner &Mangle, ResultEval Interpreter)
180
      : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer),
181
        S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {}
182
 
183
  void emit(std::unique_ptr<MaterializationResponsibility> R,
184
            ThreadSafeModule TSM) override;
185
 
186
private:
187
  TargetAndLikelies
188
  internToJITSymbols(DenseMap<StringRef, DenseSet<StringRef>> IRNames) {
189
    assert(!IRNames.empty() && "No IRNames received to Intern?");
190
    TargetAndLikelies InternedNames;
191
    for (auto &NamePair : IRNames) {
192
      DenseSet<SymbolStringPtr> TargetJITNames;
193
      for (auto &TargetNames : NamePair.second)
194
        TargetJITNames.insert(Mangle(TargetNames));
195
      InternedNames[Mangle(NamePair.first)] = std::move(TargetJITNames);
196
    }
197
    return InternedNames;
198
  }
199
 
200
  IRLayer &NextLayer;
201
  Speculator &S;
202
  MangleAndInterner &Mangle;
203
  ResultEval QueryAnalysis;
204
};
205
 
206
} // namespace orc
207
} // namespace llvm
208
 
209
#endif // LLVM_EXECUTIONENGINE_ORC_SPECULATION_H