Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/optimizer/J9LocalCSE.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2019 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
#include "env/VMJ9.h"
24
#include "codegen/InstOpCode.hpp"
25
#include "codegen/CodeGenerator.hpp"
26
#include "il/Block.hpp"
27
#include "il/Node.hpp"
28
#include "il/Node_inlines.hpp"
29
#include "il/StaticSymbol.hpp"
30
#include "optimizer/LocalCSE.hpp"
31
#include "optimizer/Optimization_inlines.hpp"
32
33
bool
34
J9::LocalCSE::shouldTransformBlock(TR::Block *block)
35
{
36
if (!OMR::LocalCSE::shouldTransformBlock(block))
37
return false;
38
39
if (self()->comp()->getMethodHotness() < warm &&
40
block->getFrequency() < TR::Options::_localCSEFrequencyThreshold &&
41
!self()->comp()->compileRelocatableCode())
42
return false;
43
44
return true;
45
}
46
47
bool
48
J9::LocalCSE::shouldCommonNode(TR::Node *parent, TR::Node *node)
49
{
50
if (!OMR::LocalCSE::shouldCommonNode(parent, node))
51
return false;
52
53
if (parent != NULL)
54
{
55
// Commoning NULL pointers under a guard might result in dereferencing a NULL pointer
56
if (parent->isNopableInlineGuard() && node->getOpCode().hasSymbolReference())
57
{
58
TR::Symbol* symbol = node->getSymbolReference()->getSymbol();
59
60
if (symbol->isStatic() && symbol->getStaticSymbol()->getStaticAddress() == NULL)
61
{
62
return false;
63
}
64
}
65
66
// Prevent commoning of the first child of BCDCHK if the recognized DAA API checkOverflow argument is true.
67
//
68
// The BCDCHK node is well structured. Its first child represents a BCD operation that may raise a hardware
69
// interrupt if malformed input is provided. The evaluation of BCDCHK creates an OOL path to which we branch to
70
// from the signal handler if a hardware interrupt was caught. This OOL path simply reconstructs the original
71
// Java call to the DAA API and delegates the respective computation.
72
//
73
// Some DAA APIs have a conditional parameter called checkOverflow which lets the user control whether the
74
// respective API will raise a Java exception if overflow is detected. Thus if the checkOverflow argument is
75
// true then the evaluation of BCDCHK may or may not raise a Java exception. The issue with this is the following
76
// example scenario:
77
//
78
// n1n BCDCHK
79
// n2n pdshl
80
// ...
81
// ...
82
// n3n iconst 0
83
// ...
84
// n4n BCDCHK
85
// n5n pdshl
86
// ...
87
// ...
88
// n6n iconst 1
89
//
90
// Assuming n2n and n5n represent the same operation local CSE will attempt to common n2n with n5n. However given
91
// the above this can result in unwanted behavior. Commoning n5n with n2n is incorrect because the BCDCHK at n4n
92
// had checkOverflow argument as true (n6n) and thus the original DAA Java calls were in fact different. Assuming
93
// the BCDCHKs at n1n and n4n both raised hardware interrupts the fallback OOL path in case of n1n would have not
94
// raised a Java exception and the execution would resume as normal. However in case on n6n the fallback OOL path
95
// may or may not raise a Java exception so execution could in fact diverge to a different path. Hence it is not
96
// correct to common n5n and n2n in such cases.
97
//
98
// The following block of code checks for the above case and prevents commoning of n5n with n2n.
99
//
100
// NOTE: if n4n came before n1n in the treetop order then the commoning from n5n to n2n would be in fact valid,
101
// and the current implementation will allow it. However if between two BCDCHK treetops which both do overflow
102
// checking (i.e. two distinct instances of n4n) the current implementation will not allow the commoning to
103
// happen even though it is valid. Enabling the commoning is such cases is a lot more complicated from an
104
// implementation perspective and is likely not worth the return on investment.
105
if (parent->getOpCodeValue() == TR::BCDCHK && parent->getFirstChild() == node)
106
{
107
TR::MethodSymbol* bcdchkMethodSymbol = parent->getSymbolReference()->getSymbol()->getMethodSymbol();
108
109
TR_ASSERT(bcdchkMethodSymbol != NULL, "BCDCHK should always have a resolved method symbol since it was reduced in DataAccessAccelerator optimization");
110
111
switch(bcdchkMethodSymbol->getRecognizedMethod())
112
{
113
case TR::com_ibm_dataaccess_PackedDecimal_lessThanPackedDecimal_:
114
case TR::com_ibm_dataaccess_PackedDecimal_lessThanOrEqualsPackedDecimal_:
115
case TR::com_ibm_dataaccess_PackedDecimal_greaterThanPackedDecimal_:
116
case TR::com_ibm_dataaccess_PackedDecimal_greaterThanOrEqualsPackedDecimal_:
117
case TR::com_ibm_dataaccess_PackedDecimal_equalsPackedDecimal_:
118
case TR::com_ibm_dataaccess_PackedDecimal_notEqualsPackedDecimal_:
119
case TR::com_ibm_dataaccess_PackedDecimal_checkPackedDecimal_:
120
case TR::com_ibm_dataaccess_DecimalData_convertExternalDecimalToPackedDecimal_:
121
case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToExternalDecimal_:
122
case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToUnicodeDecimal_:
123
case TR::com_ibm_dataaccess_DecimalData_convertUnicodeDecimalToPackedDecimal_:
124
{
125
// No optional checkOverflow parameter on these APIs
126
break;
127
}
128
129
case TR::com_ibm_dataaccess_PackedDecimal_addPackedDecimal_:
130
case TR::com_ibm_dataaccess_PackedDecimal_subtractPackedDecimal_:
131
case TR::com_ibm_dataaccess_PackedDecimal_multiplyPackedDecimal_:
132
case TR::com_ibm_dataaccess_PackedDecimal_dividePackedDecimal_:
133
case TR::com_ibm_dataaccess_PackedDecimal_remainderPackedDecimal_:
134
case TR::com_ibm_dataaccess_PackedDecimal_shiftLeftPackedDecimal_:
135
case TR::com_ibm_dataaccess_PackedDecimal_shiftRightPackedDecimal_:
136
case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToInteger_:
137
case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToInteger_ByteBuffer_:
138
case TR::com_ibm_dataaccess_DecimalData_convertIntegerToPackedDecimal_:
139
case TR::com_ibm_dataaccess_DecimalData_convertIntegerToPackedDecimal_ByteBuffer_:
140
case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToLong_:
141
case TR::com_ibm_dataaccess_DecimalData_convertPackedDecimalToLong_ByteBuffer_:
142
case TR::com_ibm_dataaccess_DecimalData_convertLongToPackedDecimal_:
143
case TR::com_ibm_dataaccess_DecimalData_convertLongToPackedDecimal_ByteBuffer_:
144
{
145
TR::Node* checkOverflowNode = parent->getLastChild();
146
147
if (!(checkOverflowNode->getOpCode().isLoadConst() && checkOverflowNode->getConstValue() == 0))
148
{
149
traceMsg(comp(), "Skipping propagation of %s [%p] into the first child of %s [%p] because of potential overflow checking\n", node->getOpCode().getName(), node, parent->getOpCode().getName(), parent);
150
151
return false;
152
}
153
154
break;
155
}
156
157
default:
158
{
159
TR_ASSERT_FATAL(false, "Unrecognized DAA method symbol in BCDCHK [%p]\n", parent);
160
161
return false;
162
}
163
}
164
}
165
}
166
167
return true;
168
}
169
170
bool
171
J9::LocalCSE::shouldCopyPropagateNode(TR::Node *parent, TR::Node *node, int32_t childNum, TR::Node *storeNode)
172
{
173
if (!OMR::LocalCSE::shouldCopyPropagateNode(parent, node, childNum, storeNode))
174
return false;
175
176
// External float types come in as aggregates and an effort during ilgen (extFloatFixup) is made to fix
177
// up all the aggr types to extFloat.
178
// However due to late arrayOp scalarization there is a chance that CSE may create incorrect types during propagation
179
// so prevent these transformations from happening.
180
// The cost of adding a conversion to make things type correct is too high here (a runtime call) so disallow these.
181
182
int32_t childAdjust = storeNode->getOpCode().isWrtBar() ? 2 : 1;
183
int32_t maxChild = storeNode->getNumChildren() - childAdjust;
184
TR::Node *rhsOfStoreDefNode = storeNode->getChild(maxChild);
185
bool propagationIsTypeCorrect = true;
186
187
if (parent && parent->getChild(childNum))
188
{
189
TR::Node *oldNode = parent->getChild(childNum);
190
TR::DataType oldType = oldNode->getType();
191
TR::DataType newType = rhsOfStoreDefNode->getType();
192
if (oldType.isBCD() != newType.isBCD() ||
193
oldType.isFloatingPoint() != newType.isFloatingPoint())
194
propagationIsTypeCorrect = false;
195
196
if (!propagationIsTypeCorrect && (comp()->cg()->traceBCDCodeGen() || trace()))
197
{
198
int32_t lineNumber = comp()->getLineNumber(rhsOfStoreDefNode);
199
traceMsg(comp(),"z^z : skipping type invalid propagation : parent %s (%p), rhsOfStoreDefNode %s (%p) line_no=%d (offset %06X)\n",
200
parent->getOpCode().getName(),parent,rhsOfStoreDefNode->getOpCode().getName(),rhsOfStoreDefNode,lineNumber,lineNumber);
201
}
202
203
if (!propagationIsTypeCorrect)
204
return false;
205
}
206
207
return true;
208
}
209
210