Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/z/codegen/J9CodeGenerator.hpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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
21
*******************************************************************************/
22
23
#ifndef J9_Z_CODEGENERATOR_INCL
24
#define J9_Z_CODEGENERATOR_INCL
25
26
/*
27
* The following #define and typedef must appear before any #includes in this file
28
*/
29
#ifndef J9_CODEGENERATOR_CONNECTOR
30
#define J9_CODEGENERATOR_CONNECTOR
31
namespace J9 { namespace Z { class CodeGenerator; } }
32
namespace J9 { typedef J9::Z::CodeGenerator CodeGeneratorConnector; }
33
#else
34
#error J9::Z::CodeGenerator expected to be a primary connector, but a J9 connector is already defined
35
#endif
36
37
#include "compiler/codegen/J9CodeGenerator.hpp"
38
#include "j9cfg.h"
39
40
namespace TR { class S390EyeCatcherDataSnippet; }
41
namespace TR { class Node; }
42
43
44
namespace J9
45
{
46
47
namespace Z
48
{
49
50
class OMR_EXTENSIBLE CodeGenerator : public J9::CodeGenerator
51
{
52
53
protected:
54
55
CodeGenerator(TR::Compilation *comp);
56
57
public:
58
59
void initialize();
60
61
TR::Recompilation *allocateRecompilationInfo();
62
63
bool doInlineAllocate(TR::Node *node);
64
65
TR::Linkage *createLinkage(TR_LinkageConventions lc);
66
67
void lowerTreesPreChildrenVisit(TR::Node * parent, TR::TreeTop * treeTop, vcount_t visitCount);
68
void lowerTreesPostChildrenVisit(TR::Node * parent, TR::TreeTop * treeTop, vcount_t visitCount);
69
70
void lowerTreeIfNeeded(TR::Node *node, int32_t childNumber, TR::Node *parent, TR::TreeTop *tt);
71
72
TR::S390EyeCatcherDataSnippet *CreateEyeCatcher(TR::Node *);
73
74
void genZeroLeftMostUnicodeBytes(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t bytesToClear, TR::MemoryReference *targetMR);
75
void widenZonedSignLeadingEmbedded(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t bytesToClear, TR::MemoryReference *targetMR);
76
void widenUnicodeSignLeadingSeparate(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t bytesToClear, TR::MemoryReference *targetMR);
77
void widenZonedSignLeadingSeparate(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t bytesToClear, TR::MemoryReference *targetMR);
78
void genZeroLeftMostZonedBytes(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t bytesToClear, TR::MemoryReference *targetMR);
79
80
bool alwaysGeneratesAKnownCleanSign(TR::Node *node);
81
bool alwaysGeneratesAKnownPositiveCleanSign(TR::Node *node);
82
bool canUseRelativeLongInstructions(int64_t value);
83
TR_RawBCDSignCode alwaysGeneratedSign(TR::Node *node);
84
85
uint32_t getPDMulEncodedSize(TR::Node *pdmul, TR_PseudoRegister *multiplicand, TR_PseudoRegister *multiplier);
86
uint32_t getPDMulEncodedSize(TR::Node *pdmul);
87
uint32_t getPDMulEncodedSize(TR::Node *pdmul, int32_t exponent);
88
int32_t getPDMulEncodedPrecision(TR::Node *pdmul, TR_PseudoRegister *multiplicand, TR_PseudoRegister *multiplier);
89
int32_t getPDMulEncodedPrecision(TR::Node *pdmul);
90
int32_t getPDMulEncodedPrecision(TR::Node *pdmul, int32_t exponent);
91
bool callUsesHelperImplementation(TR::Symbol *sym);
92
93
uint32_t getLongToPackedFixedSize() { return TR_LONG_TO_PACKED_SIZE; }
94
uint32_t getIntegerToPackedFixedSize() { return TR_INTEGER_TO_PACKED_SIZE; }
95
uint32_t getPackedToLongFixedSize() { return TR_PACKED_TO_LONG_SIZE; }
96
uint32_t getPackedToIntegerFixedSize() { return TR_PACKED_TO_INTEGER_SIZE; }
97
uint32_t getPackedToUnicodeFixedSourceSize() { return TR_PACKED_TO_UNICODE_SOURCE_SIZE; }
98
uint32_t getUnicodeToPackedFixedResultSize() { return TR_UNICODE_TO_PACKED_RESULT_SIZE; }
99
uint32_t getAsciiToPackedFixedResultSize() { return TR_ASCII_TO_PACKED_RESULT_SIZE; }
100
uint32_t getPDDivEncodedSize(TR::Node *node);
101
uint32_t getPDDivEncodedSize(TR::Node *node, TR_PseudoRegister *dividendReg, TR_PseudoRegister *divisorReg);
102
uint32_t getPDAddSubEncodedSize(TR::Node *node);
103
uint32_t getPDAddSubEncodedSize(TR::Node *node, TR_PseudoRegister *firstReg);
104
int32_t getPDAddSubEncodedPrecision(TR::Node *node);
105
int32_t getPDAddSubEncodedPrecision(TR::Node *node, TR_PseudoRegister *firstReg);
106
int32_t getPDDivEncodedPrecisionCommon(TR::Node *node, int32_t dividendPrecision, int32_t divisorPrecision, bool isDivisorEvenPrecision);
107
int32_t getPDDivEncodedPrecision(TR::Node *node);
108
int32_t getPDDivEncodedPrecision(TR::Node *node, TR_PseudoRegister *dividendReg, TR_PseudoRegister *divisorReg);
109
110
bool supportsPackedShiftRight(int32_t resultPrecision, TR::Node *shiftSource, int32_t shiftAmount);
111
bool canGeneratePDBinaryIntrinsic(TR::ILOpCodes opCode, TR::Node * op1PrecNode, TR::Node * op2PrecNode, TR::Node * resultPrecNode);
112
113
bool constLoadNeedsLiteralFromPool(TR::Node *node);
114
115
bool supportsTrapsInTMRegion();
116
117
using J9::CodeGenerator::addAllocatedRegister;
118
void addAllocatedRegister(TR_PseudoRegister * temp);
119
120
TR_OpaquePseudoRegister * allocateOpaquePseudoRegister(TR::DataType dt);
121
TR_OpaquePseudoRegister * allocateOpaquePseudoRegister(TR_OpaquePseudoRegister *reg);
122
TR_PseudoRegister * allocatePseudoRegister(TR::DataType dt);
123
TR_PseudoRegister * allocatePseudoRegister(TR_PseudoRegister *reg);
124
125
TR_OpaquePseudoRegister * evaluateOPRNode(TR::Node* node);
126
TR_PseudoRegister * evaluateBCDNode(TR::Node * node);
127
128
// --------------------------------------------------------------------------
129
// Storage references
130
//
131
bool getAddStorageReferenceHints() { return _cgFlags.testAny(S390CG_addStorageReferenceHints);}
132
void setAddStorageReferenceHints() { _cgFlags.set(S390CG_addStorageReferenceHints);}
133
134
bool storageReferencesMatch(TR_StorageReference *ref1, TR_StorageReference *ref2);
135
void processUnusedStorageRef(TR_StorageReference *ref);
136
void freeUnusedTemporaryBasedHint(TR::Node *node);
137
138
139
140
/**
141
* Will a BCD left shift always leave the sign code unchanged and thus
142
* allow it to be propagated through and upwards
143
*/
144
bool propagateSignThroughBCDLeftShift(TR::DataType type)
145
{
146
if (type.isAnyPacked())
147
return false; // may use SRP that will always generate a 0xC or 0xD
148
else
149
return true;
150
}
151
152
bool isAcceptableDestructivePDModPrecision(TR::Node *storeNode, TR::Node *nodeForAliasing);
153
bool isAcceptableDestructivePDShiftRight(TR::Node *storeNode, TR::Node *nodeForAliasing);
154
155
bool validateAddressOneToAddressOffset(int32_t expectedOffset, TR::Node *addr1, int64_t addr1ExtraOffset, TR::Node *addr2, int64_t addr2ExtraOffset, TR::list<TR::Node*> *_baseLoadsThatAreNotKilled, bool trace);
156
void getAddressOneToAddressTwoOffset(bool *canGetOffset, TR::Node *addr1, int64_t addr1ExtraOffset, TR::Node *addr2, int64_t addr2ExtraOffset, int32_t *offset, TR::list<TR::Node*> *_baseLoadsThatAreNotKilled, bool trace);
157
158
template <class TR_AliasSetInterface>
159
bool canUseSingleStoreAsAnAccumulator(TR::Node *parent,
160
TR::Node *node,
161
TR::Node *store,
162
TR_AliasSetInterface &storeAliases,
163
TR::list<TR::Node*> *conflictingAddressNodes,
164
bool justLookForConflictingAddressNodes,
165
bool isChainOfFirstChildren,
166
bool mustCheckAllNodes);
167
168
TR::Node *getAddressLoadVar(TR::Node *node, bool trace);
169
170
void markStoreAsAnAccumulator(TR::Node *node);
171
void addStorageReferenceHints(TR::Node *node);
172
void examineNode(TR::Node *parent, TR::Node *node, TR::Node *&bestNode, int32_t &storeSize, TR::list<TR::Node*> &leftMostNodesList);
173
void processNodeList(TR::Node *&bestNode, int32_t &storeSize, TR::list<TR::Node*> &leftMostNodesList);
174
175
void correctBadSign(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, TR::MemoryReference *memRef);
176
177
int32_t genSignCodeSetting(TR::Node *node, TR_PseudoRegister *targetReg, int32_t endByte, TR::MemoryReference *signCodeMR, int32_t sign, TR_PseudoRegister *srcReg, int32_t digitsToClear, bool numericNibbleIsZero);
178
179
void widenBCDValue(TR::Node *node, TR_PseudoRegister *reg, int32_t startByte, int32_t endByte, TR::MemoryReference *targetMR);
180
181
void widenBCDValueIfNeeded(TR::Node *node, TR_PseudoRegister *reg, int32_t startByte, int32_t endByte, TR::MemoryReference *targetMR);
182
void genZeroLeftMostDigitsIfNeeded(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t digitsToClear, TR::MemoryReference *targetMR, bool widenOnLeft=false);
183
void clearByteRangeIfNeeded(TR::Node *node, TR_PseudoRegister *reg, TR::MemoryReference *targetMR, int32_t startByte, int32_t endByte, bool widenOnLeft=false);
184
void genZeroLeftMostPackedDigits(TR::Node *node, TR_PseudoRegister *reg, int32_t endByte, int32_t digitsToClear, TR::MemoryReference *targetMR, int32_t memRefOffset=0);
185
186
void initializeStorageReference(TR::Node *node,
187
TR_OpaquePseudoRegister *destReg,
188
TR::MemoryReference *destMR,
189
int32_t destSize,
190
TR::Node *srcNode,
191
TR_OpaquePseudoRegister *srcReg,
192
TR::MemoryReference *sourceMR,
193
int32_t sourceSize,
194
bool performExplicitWidening,
195
bool alwaysLegalToCleanSign,
196
bool trackSignState);
197
198
TR_StorageReference *initializeNewTemporaryStorageReference(TR::Node *node,
199
TR_OpaquePseudoRegister *destReg,
200
int32_t destSize,
201
TR::Node *srcNode,
202
TR_OpaquePseudoRegister *srcReg,
203
int32_t sourceSize,
204
TR::MemoryReference *sourceMR,
205
bool performExplicitWidening,
206
bool alwaysLegalToCleanSign,
207
bool trackSignState);
208
209
TR_OpaquePseudoRegister *privatizePseudoRegister(TR::Node *node, TR_OpaquePseudoRegister *reg, TR_StorageReference *storageRef, size_t sizeOverride = 0);
210
TR_OpaquePseudoRegister *privatizePseudoRegisterIfNeeded(TR::Node *parent, TR::Node *child, TR_OpaquePseudoRegister *childReg);
211
212
TR_StorageReference *privatizeStorageReference(TR::Node *node, TR_OpaquePseudoRegister *reg, TR::MemoryReference *sourceMR);
213
TR_PseudoRegister *privatizeBCDRegisterIfNeeded(TR::Node *parent, TR::Node *child, TR_OpaquePseudoRegister *childReg);
214
215
TR::MemoryReference *materializeFullBCDValue(TR::Node *node, TR_PseudoRegister *&reg, int32_t resultSize, int32_t clearSize=0, bool updateStorageReference=false, bool alwaysEnforceSSLimits=true);
216
217
bool useMoveImmediateCommon(TR::Node *node,
218
char *srcLiteral,
219
size_t srcSize,
220
TR::Node *srcNode,
221
size_t destSize,
222
intptr_t destBaseOffset,
223
size_t destLeftMostByte,
224
TR::MemoryReference *destMR);
225
226
bool checkFieldAlignmentForAtomicLong();
227
228
bool canCopyWithOneOrTwoInstrs(char *lit, size_t size);
229
bool inlineSmallLiteral(size_t srcSize, char *srcLiteral, size_t destSize, bool trace);
230
231
#if defined(J9VM_JIT_FREE_SYSTEM_STACK_POINTER)
232
/** \brief
233
* Determines whether the JIT supports freeing up the system stack pointer (SSP) for register allocation.
234
*
235
* \return
236
* <c>true</c> if <c>J9VM_JIT_FREE_SYSTEM_STACK_POINTER</c> is defined; <c>false</c> otherwise.
237
*
238
* \note
239
* <c>J9VM_JIT_FREE_SYSTEM_STACK_POINTER</c> is currently only defined on z/OS. For exception handling,
240
* additional frames are typically allocated on the system stack. Hence, the OS needs to be able to locate
241
* the system stack at all times in case of interrupts. In case of z/OS, we have the mechanism to save the
242
* SSP in a memory location (off <c>J9VMThread</c>) that is registered with the OS. We don't have such
243
* support on Linux, and hence, this is z/OS specific at the moment.
244
*/
245
bool supportsJITFreeSystemStackPointer()
246
{
247
return true;
248
}
249
#endif
250
251
bool suppressInliningOfRecognizedMethod(TR::RecognizedMethod method);
252
253
bool inlineDirectCall(TR::Node *node, TR::Register *&resultReg);
254
255
#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION
256
bool inlineCryptoMethod(TR::Node *node, TR::Register *&resultReg);
257
#endif
258
259
void incRefCountForOpaquePseudoRegister(TR::Node * node);
260
261
/** \brief
262
* Generates a VM call helper sequence along with the necessary metadata in the instruction stream which when
263
* executed reverts the execution of this JIT body back to the interpreter.
264
*
265
* \param cursor
266
* The cursor to which the generated instructions will be appended.
267
*
268
* \param vmCallHelperSnippetLabel
269
* The label which is used to call this snippet.
270
*
271
* \return
272
* The last generated instruction.
273
*/
274
TR::Instruction* generateVMCallHelperSnippet(TR::Instruction* cursor, TR::LabelSymbol* vmCallHelperSnippetLabel);
275
276
/** \brief
277
* Generates a VM call helper preprologue using \see generateVMCallHelperSnippet and generates the necessary
278
* metadata as well as data constants needed for invoking the snippet.
279
*
280
* \param cursor
281
* The cursor to which the generated instructions will be appended.
282
*
283
* \return
284
* The last generated instruction.
285
*/
286
TR::Instruction* generateVMCallHelperPrePrologue(TR::Instruction* cursor);
287
288
/**
289
* \brief
290
* The number of nodes between a monexit and the next monent before transforming
291
* a monitored region with transactional lock elision. On Z, 25-30 cycles are
292
* required between transactions or else the latter transaction will be aborted
293
* (with significant penalty).
294
*
295
* \return
296
* 45. This is an estimate based on CPI of 1.5-2 and an average of 1 instruction
297
* per node.
298
*/
299
int32_t getMinimumNumberOfNodesBetweenMonitorsForTLE() { return 45; }
300
301
/** \brief
302
* Sets whether decimal overflow or fixed point overflow checks should be generated for instructions which
303
* support such by-passes.
304
*
305
* \note
306
* This is applicable to z15 hardware accelerated vector packed decimal operations and is typically used to
307
* control whether the ignore overflow mask (IOM) bit is set in vector packed decimal instructions.
308
*/
309
void setIgnoreDecimalOverflowException(bool v)
310
{
311
_ignoreDecimalOverflowException = v;
312
}
313
314
/** \brief
315
* Gets whether decimal overflow or fixed point overflow checks should be generated for instructions which
316
* support such by-passes.
317
*
318
* \note
319
* This is applicable to z15 hardware accelerated vector packed decimal operations and is typically used to
320
* control whether the ignore overflow mask (IOM) bit is set in vector packed decimal instructions.
321
*/
322
bool getIgnoreDecimalOverflowException()
323
{
324
return _ignoreDecimalOverflowException;
325
}
326
327
// LL: move to .cpp
328
bool arithmeticNeedsLiteralFromPool(TR::Node *node);
329
330
/**
331
* \brief Determines whether the code generator supports stack allocations
332
*/
333
bool supportsStackAllocations() { return true; }
334
335
// See J9::CodeGenerator::guaranteesResolvedDirectDispatchForSVM
336
bool guaranteesResolvedDirectDispatchForSVM() { return true; }
337
338
private:
339
340
/** \brief
341
* Determines whether decimal overflow or fixed point overflow checks should be generated for instructions which
342
* support such by-passes.
343
*/
344
bool _ignoreDecimalOverflowException;
345
};
346
347
}
348
349
}
350
351
#endif
352
353