-
Notifications
You must be signed in to change notification settings - Fork 392
/
OptimizationPlan.hpp
301 lines (262 loc) · 14.6 KB
/
OptimizationPlan.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at http://eclipse.org/legal/epl-2.0
* or the Apache License, Version 2.0 which accompanies this distribution
* and is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License, v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception [1] and GNU General Public
* License, version 2 with the OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
#ifndef OPTIMIZATION_PLAN_INCL
#define OPTIMIZATION_PLAN_INCL
#include "optimizer/Optimizer.hpp"
#include <stddef.h>
#include <stdint.h>
#include "compile/CompilationTypes.hpp"
#include "env/FilePointerDecl.hpp"
#include "env/TRMemory.hpp"
#include "il/DataTypes.hpp"
#include "infra/Assert.hpp"
#include "infra/Flags.hpp"
namespace TR { class CompilationInfo; }
class TR_MethodEvent;
namespace TR { class Recompilation; }
namespace TR { class Monitor; }
struct TR_MethodToBeCompiled;
#if defined(__IBMCPP__)
// GCC (and other compilers) may assume that operator new cannot return null
// unless a nothrow specification is provided. For other reasons, we build
// Testarossa with -qnoeh / -fnoeh to disable exceptions. This is all fine,
// except that XLC doesn't wan't to be using the nothrow specification
// when -qnoeh is effect. As a result, we use it everywhere exept on XLC
#define NOTHROW
#else
#define NOTHROW throw()
#endif
///////////////////////////////////////////////////////////////////////
// TR_OptimizationPlan
// Will be used by Continuous Program Optimization (CPO) framework
// to control the behaviour of TR optimizations.
///////////////////////////////////////////////////////////////////////
class TR_OptimizationPlan
{
public:
TR_PERSISTENT_ALLOC(TR_Memory::OptimizationPlan)
// Eliminate explicit constructors so that we do not crash
// when calling new TR_OptimizationPlan(..) and don't have the memory
static TR_OptimizationPlan *alloc(TR_Hotness optLevel)
{
TR_ASSERT(optLevel != unknownHotness, "Cannot create a plan with unknown hotness");
TR_OptimizationPlan *plan = new TR_OptimizationPlan();
if (plan)
plan->init(optLevel);
return plan;
}
static TR_OptimizationPlan *alloc(TR_Hotness optLevel, bool insertInstrumentation, bool useSampling)
{
TR_ASSERT(optLevel != unknownHotness, "Cannot create a plan with unknown hotness");
TR_OptimizationPlan *plan = alloc(optLevel);
if (plan)
{
plan->setInsertInstrumentation(insertInstrumentation);
plan->setUseSampling(useSampling);
}
return plan;
}
void clone(const TR_OptimizationPlan* otherPlan)
{
_optLevel = otherPlan->_optLevel;
_flags = otherPlan->_flags;
_perceivedCPUUtil = otherPlan->_perceivedCPUUtil;
_hwpDoReducedWarm = otherPlan->_hwpDoReducedWarm;
// no need to copy the _next pointer
}
void init(TR_Hotness optLevel)
{
_next = 0;
setOptLevel(optLevel);
_flags.clear();
setUseSampling(true);
setInUse(true);
_perceivedCPUUtil = 0;
//getInsertEpilogueYieldpoints();
_hwpDoReducedWarm = false;
}
TR_Hotness getOptLevel() const { return _optLevel; }
void setOptLevel(TR_Hotness optLevel) { _optLevel = optLevel; TR_ASSERT(optLevel != unknownHotness, "Cannot set unknown hotness in a plan");}
int insertInstrumentation() const { return _flags.testAny(InsertInstrumentation); }
void setInsertInstrumentation(bool b) { _flags.set(InsertInstrumentation, b); }
int getUseSampling() const { return _flags.testAny(UseSampling); }
void setUseSampling(bool b) { _flags.set(UseSampling, b); }
bool isOptLevelDowngraded() const { return _flags.testAny(OptLevelDowngraded); }
void setOptLevelDowngraded(bool b) { _flags.set(OptLevelDowngraded, b); }
bool isDowngradedDueToSamplingJProfiling() const { return _flags.testAny(DowngradedDueToSamplingJProfiling); }
void setDowngradedDueToSamplingJProfiling(bool b) { _flags.set(DowngradedDueToSamplingJProfiling, b); }
// Insert epilogue yieldpoints if the method is being sampled
bool getInsertEpilogueYieldpoints() const { return _flags.testAny(UseSampling); }
bool isLogCompilation() const { return _flags.testAny(LogCompilation); }
void setLogCompilation(TR::FILE *f) { _flags.set(LogCompilation); _logFile = f; }
TR::FILE *getLogCompilation() { return _logFile; }
bool shouldAddToUpgradeQueue() const { return _flags.testAny(AddToUpgradeQueue); }
void setAddToUpgradeQueue() { _flags.set(AddToUpgradeQueue); }
void resetAddToUpgradeQueue() { _flags.set(AddToUpgradeQueue, false); }
bool inUse() const { return _flags.testAny(InUse); }
void setInUse(bool b) { _flags.set(InUse, b); }
int32_t getPerceivedCPUUtil() const { return _perceivedCPUUtil; }
void setPerceivedCPUUtil(int32_t v) { _perceivedCPUUtil = v; }
void setDisableCHOpts(bool b = true) { _flags.set(DisableCHOpts, b); }
bool disableCHOpts() { return _flags.testAny(DisableCHOpts); }
void setDisableGCR(bool b = true) { _flags.set(DisableGCR, b); }
bool disableGCR() { return _flags.testAny(DisableGCR); }
void setIsUpgradeRecompilation(bool b = true) { _flags.set(IsUpgradeRecompilation, b); }
bool isUpgradeRecompilation() { return _flags.testAny(IsUpgradeRecompilation); }
void setIsExplicitCompilation(bool b = true) { _flags.set(IsExplicitCompilation, b); }
bool isExplicitCompilation() { return _flags.testAny(IsExplicitCompilation); }
void setReduceMaxPeekedBytecode(uint32_t val) { val &= ReduceMaxPeekedBytecodeMask;
_flags.setValue(ReduceMaxPeekedBytecodeMask, val); }
uint32_t getReduceMaxPeekedBytecode() const { return _flags.getValue(ReduceMaxPeekedBytecodeMask); }
bool getDoNotSwitchToProfiling() const { return _flags.testAny(doNotSwitchToProfiling); }
void setDoNotSwitchToProfiling(bool b) { _flags.set(doNotSwitchToProfiling, b); }
bool getIsStackAllocated() const { return _flags.testAny(IsStackAllocated); }
void setIsStackAllocated() { _flags.set(IsStackAllocated, true); }
bool getIsAotLoad() const { return _flags.testAny(IsAotLoad); }
void setIsAotLoad(bool b) { _flags.set(IsAotLoad, b); }
bool getDontFailOnPurpose() const { return _flags.testAny(DontFailOnPurpose); }
void setDontFailOnPurpose(bool b) { _flags.set(DontFailOnPurpose, b); }
bool getRelaxedCompilationLimits() const { return _flags.testAny(RelaxedCompilationLimits); }
void setRelaxedCompilationLimits(bool b) { _flags.set(RelaxedCompilationLimits, b); }
bool isHwpDoReducedWarm() {return _hwpDoReducedWarm; }
void setIsHwpDoReducedWarm (bool b) { _hwpDoReducedWarm = b; }
bool isInducedByDLT() const { return _flags.testAny(InducedByDLT); }
void setInducedByDLT(bool b) { _flags.set(InducedByDLT, b); }
bool getDisableEDO() const { return _flags.testAny(DisableEDO); }
void setDisableEDO(bool b) { _flags.set(DisableEDO, b); }
// --------------------------------------------------------------------------
// GPU
//
void setIsGPUCompilation(bool b = true) { _flags.set(IsGPUCompilation, b); }
bool isGPUCompilation() { return _flags.testAny(IsGPUCompilation); }
void setIsGPUParallelStream(bool b = true) { _flags.set(IsGPUParallelStream, b); }
bool isGPUParallelStream() { return _flags.testAny(IsGPUParallelStream); }
void setIsGPUCompileCPUCode(bool b = true) { _flags.set(IsGPUCompileCPUCode, b); }
bool isGPUCompileCPUCode() { return _flags.testAny(IsGPUCompileCPUCode); }
void setGPUBlockDimX(int32_t dim) { _gpuBlockDimX = dim; }
int32_t getGPUBlockDimX() { return _gpuBlockDimX; }
void setGPUParms(void * parms) { _gpuParms = parms; }
void *getGPUParms() { return _gpuParms; }
void setGPUIR(char * ir) { _gpuIR = ir; }
char *getGPUIR() { return _gpuIR; }
void setGPUResult(int32_t result) { _gpuResult = result; }
int32_t getGPUResult() { return _gpuResult; }
enum { // list of flags
// First 2 bits are used as a value to divide the MAX_PEEKED_BYTECODE_SIZE
// to avoid future compilation failures. This allows us a better implementation of setter/getter
// NOTE: If we change the position of the mask, then we need to change the setter/getter above
ReduceMaxPeekedBytecodeMask = 0x0003,
InsertInstrumentation = 0x00000010,
UseSampling = 0x00000020,
OptLevelDowngraded = 0x00000040, // set if we downgrade the compilation to a lower level
LogCompilation = 0x00000080, // special compilation for method that crashed (to produce log)
AddToUpgradeQueue = 0x00000100, // flag to add request to the low priority upgrade queue
InUse = 0x00000200, // set this flag when allocating a plan; reset when dealocating it
DisableGCR = 0x00000400, // Do not generate a GCR body for this method
DisableCHOpts = 0x00000800, // do not use CHTable opts because it's likely to fail this compilation
IsUpgradeRecompilation = 0x00001000, // This is a recompilation request which upgrades a
// previously downgraded method
doNotSwitchToProfiling = 0x00002000, // Prevent the optimizer to switch to profiling on the fly
IsExplicitCompilation = 0x00004000,
IsStackAllocated = 0x00008000, // Plan is allocated on the stack. Only used in emergency situations
// when we run out of native memory and cannot allocate a plan
// using persistent memory, yet the compilation must be performed
IsAotLoad = 0x00010000, // AOT loads have a compilation object now
// This flag will allow the compilation object know that it is only
// used for relocation, so that some of the structures that are not
// needed will be skipped (e.g. jittedBodyInfo, persistentMethodInfo)
IsGPUCompilation = 0x00020000, // requested by GPU library
IsGPUParallelStream = 0x00040000, // requested by parallel stream
IsGPUCompileCPUCode = 0x00080000, // compile CPU code using system linkage
DontFailOnPurpose = 0x00100000, // Mostly needed to avoid failing for the purpose of upgrading to a higher opt level
RelaxedCompilationLimits= 0x00200000, // Compilation can use larger limits because method is very very hot
DowngradedDueToSamplingJProfiling=0x00400000, // Compilation was downgraded to cold just because we wanted to do JProfiling
InducedByDLT = 0x00800000, // Compilation that follows a DLT compilation
DisableEDO = 0x01000000, // Do not insert EDO profiling trees for this compilation
};
private:
TR_OptimizationPlan *_next; // to link events in the pool
TR_Hotness _optLevel;
flags32_t _flags;
int32_t _perceivedCPUUtil; // percentage*10 (so that we can use fractional values)
// Will be set only for recompilations. <=0 means no info
bool _hwpDoReducedWarm;
TR::FILE *_logFile;
static TR_OptimizationPlan *_pool;
static unsigned long _totalNumAllocatedPlans; // number of elements in the system
static unsigned long _poolSize; // number of elements currently in the pool
static unsigned long _numAllocOp; // statistics
static unsigned long _numFreeOp; // statistics
#define POOL_THRESHOLD 32
public:
static TR::Monitor *_optimizationPlanMonitor;
static void freeOptimizationPlan(TR_OptimizationPlan *plan);
static int32_t freeEntirePool();
void * operator new(size_t) NOTHROW;
int32_t _gpuBlockDimX;
void * _gpuParms;
char * _gpuIR;
int32_t _gpuResult;
};
//---------------------------- TR::CompilationStrategy ---------------------------
// Abstract class. Must derive strategies from it. The only pure virtual method
// is processEevent() which needs to be defined in the derived classes.
//-------------------------------------------------------------------------------
namespace TR
{
class CompilationStrategy
{
public:
virtual TR_OptimizationPlan *processEvent(TR_MethodEvent *event, bool *newPlanCreated) = 0;
virtual bool adjustOptimizationPlan(TR_MethodToBeCompiled *entry, int32_t adj) {return false;}
virtual void beforeCodeGen(TR_OptimizationPlan *plan, TR::Recompilation *recomp) {}
virtual void postCompilation(TR_OptimizationPlan *plan, TR::Recompilation *recomp) {}
virtual void shutdown() {} // called at shutdown time; useful for stats
virtual bool enableSwitchToProfiling() { return false; } // turn profiling on during optimizations
};
} // namespace TR
//------------------------------- TR::CompilationController ------------------------
// All methods and fields are static. The most important field is _compilationStrategy
// that store the compilation strategy in use.
//---------------------------------------------------------------------------------
namespace TR
{
class CompilationController
{
public:
enum {LEVEL1=1, LEVEL2, LEVEL3}; // verbosity levels;
enum {DEFAULT, THRESHOLD}; // strategy codes
static bool init(TR::CompilationInfo *);
static void shutdown();
static bool useController() { return _useController; }
static int32_t verbose() { return _verbose; }
static void setVerbose(int32_t v) { _verbose = v; }
static TR::CompilationStrategy * getCompilationStrategy() { return _compilationStrategy; }
static TR::CompilationInfo * getCompilationInfo() { return _compInfo; }
private:
static TR::CompilationStrategy *_compilationStrategy;
static TR::CompilationInfo *_compInfo; // stored here for convenience
static int32_t _verbose;
static bool _useController;
static bool _tlsCompObjCreated;
};
} // namespace TR
#endif