43972
|
1 |
/*
|
46344
|
2 |
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
43972
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation.
|
|
8 |
*
|
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
13 |
* accompanied this code).
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License version
|
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 |
*
|
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
20 |
* or visit www.oracle.com if you need additional information or have any
|
|
21 |
* questions.
|
|
22 |
*/
|
|
23 |
|
|
24 |
package org.graalvm.compiler.hotspot.amd64;
|
|
25 |
|
|
26 |
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
|
|
27 |
|
48861
|
28 |
import org.graalvm.collections.EconomicMap;
|
43972
|
29 |
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
|
|
30 |
import org.graalvm.compiler.core.amd64.AMD64AddressNode;
|
48861
|
31 |
import org.graalvm.compiler.core.amd64.AMD64CompressAddressLowering;
|
46344
|
32 |
import org.graalvm.compiler.core.common.CompressEncoding;
|
48861
|
33 |
import org.graalvm.compiler.core.common.type.IntegerStamp;
|
43972
|
34 |
import org.graalvm.compiler.core.common.type.ObjectStamp;
|
48861
|
35 |
import org.graalvm.compiler.graph.Node;
|
43972
|
36 |
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
|
|
37 |
import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
|
|
38 |
import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
|
48861
|
39 |
import org.graalvm.compiler.loop.BasicInductionVariable;
|
|
40 |
import org.graalvm.compiler.loop.CountedLoopInfo;
|
|
41 |
import org.graalvm.compiler.loop.DerivedInductionVariable;
|
|
42 |
import org.graalvm.compiler.loop.InductionVariable;
|
|
43 |
import org.graalvm.compiler.loop.LoopEx;
|
|
44 |
import org.graalvm.compiler.loop.LoopsData;
|
46459
|
45 |
import org.graalvm.compiler.nodes.CompressionNode;
|
48861
|
46 |
import org.graalvm.compiler.nodes.ConstantNode;
|
48190
|
47 |
import org.graalvm.compiler.nodes.NodeView;
|
48861
|
48 |
import org.graalvm.compiler.nodes.PhiNode;
|
47798
|
49 |
import org.graalvm.compiler.nodes.StructuredGraph;
|
43972
|
50 |
import org.graalvm.compiler.nodes.ValueNode;
|
48861
|
51 |
import org.graalvm.compiler.nodes.calc.AddNode;
|
|
52 |
import org.graalvm.compiler.nodes.calc.SignExtendNode;
|
|
53 |
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
|
|
54 |
import org.graalvm.compiler.nodes.memory.address.AddressNode;
|
|
55 |
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
|
46344
|
56 |
import org.graalvm.compiler.options.OptionValues;
|
43972
|
57 |
|
|
58 |
import jdk.vm.ci.code.Register;
|
|
59 |
import jdk.vm.ci.meta.JavaKind;
|
|
60 |
|
48861
|
61 |
public class AMD64HotSpotAddressLowering extends AMD64CompressAddressLowering {
|
43972
|
62 |
|
48861
|
63 |
private static final int ADDRESS_BITS = 64;
|
|
64 |
private static final int INT_BITS = 32;
|
46344
|
65 |
|
43972
|
66 |
private final long heapBase;
|
|
67 |
private final Register heapBaseRegister;
|
|
68 |
private final GraalHotSpotVMConfig config;
|
46344
|
69 |
private final boolean generatePIC;
|
43972
|
70 |
|
46344
|
71 |
public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) {
|
|
72 |
this.heapBase = config.getOopEncoding().getBase();
|
43972
|
73 |
this.config = config;
|
46344
|
74 |
this.generatePIC = GeneratePIC.getValue(options);
|
|
75 |
if (heapBase == 0 && !generatePIC) {
|
43972
|
76 |
this.heapBaseRegister = null;
|
|
77 |
} else {
|
|
78 |
this.heapBaseRegister = heapBaseRegister;
|
|
79 |
}
|
|
80 |
}
|
|
81 |
|
|
82 |
@Override
|
48861
|
83 |
protected final boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) {
|
47798
|
84 |
CompressEncoding encoding = compression.getEncoding();
|
|
85 |
Scale scale = Scale.fromShift(encoding.getShift());
|
|
86 |
if (scale == null) {
|
|
87 |
return false;
|
|
88 |
}
|
|
89 |
|
|
90 |
if (heapBaseRegister != null && encoding.getBase() == heapBase) {
|
48190
|
91 |
if ((!generatePIC || compression.stamp(NodeView.DEFAULT) instanceof ObjectStamp) && other == null) {
|
47798
|
92 |
// With PIC it is only legal to do for oops since the base value may be
|
|
93 |
// different at runtime.
|
|
94 |
ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister));
|
|
95 |
addr.setBase(base);
|
|
96 |
} else {
|
43972
|
97 |
return false;
|
|
98 |
}
|
48190
|
99 |
} else if (encoding.getBase() != 0 || (generatePIC && compression.stamp(NodeView.DEFAULT) instanceof KlassPointerStamp)) {
|
47798
|
100 |
if (generatePIC) {
|
|
101 |
if (other == null) {
|
|
102 |
ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long));
|
43972
|
103 |
addr.setBase(base);
|
|
104 |
} else {
|
|
105 |
return false;
|
|
106 |
}
|
47798
|
107 |
} else {
|
48861
|
108 |
if (updateDisplacement(addr, encoding.getBase(), false)) {
|
47798
|
109 |
addr.setBase(other);
|
43972
|
110 |
} else {
|
47798
|
111 |
return false;
|
43972
|
112 |
}
|
|
113 |
}
|
47798
|
114 |
} else {
|
|
115 |
addr.setBase(other);
|
|
116 |
}
|
43972
|
117 |
|
47798
|
118 |
addr.setScale(scale);
|
|
119 |
addr.setIndex(compression.getValue());
|
|
120 |
return true;
|
43972
|
121 |
}
|
48861
|
122 |
|
|
123 |
@Override
|
|
124 |
public void preProcess(StructuredGraph graph) {
|
|
125 |
if (graph.hasLoops()) {
|
|
126 |
LoopsData loopsData = new LoopsData(graph);
|
|
127 |
loopsData.detectedCountedLoops();
|
|
128 |
for (LoopEx loop : loopsData.countedLoops()) {
|
|
129 |
for (OffsetAddressNode offsetAdressNode : loop.whole().nodes().filter(OffsetAddressNode.class)) {
|
|
130 |
tryOptimize(offsetAdressNode, loop);
|
|
131 |
}
|
|
132 |
}
|
|
133 |
}
|
|
134 |
}
|
|
135 |
|
|
136 |
@Override
|
|
137 |
public void postProcess(AddressNode lowered) {
|
|
138 |
// Allow implicit zero extend for always positive input. This
|
|
139 |
// assumes that the upper bits of the operand is zero out by
|
|
140 |
// the backend.
|
|
141 |
AMD64AddressNode address = (AMD64AddressNode) lowered;
|
|
142 |
address.setBase(tryImplicitZeroExtend(address.getBase()));
|
|
143 |
address.setIndex(tryImplicitZeroExtend(address.getIndex()));
|
|
144 |
}
|
|
145 |
|
|
146 |
private static void tryOptimize(OffsetAddressNode offsetAddress, LoopEx loop) {
|
|
147 |
EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
|
|
148 |
InductionVariable currentIV = ivs.get(offsetAddress.getOffset());
|
|
149 |
while (currentIV != null) {
|
|
150 |
if (!(currentIV instanceof DerivedInductionVariable)) {
|
|
151 |
break;
|
|
152 |
}
|
|
153 |
ValueNode currentValue = currentIV.valueNode();
|
|
154 |
if (currentValue.isDeleted()) {
|
|
155 |
break;
|
|
156 |
}
|
|
157 |
|
|
158 |
if (currentValue instanceof ZeroExtendNode) {
|
|
159 |
ZeroExtendNode zeroExtendNode = (ZeroExtendNode) currentValue;
|
|
160 |
if (applicableToImplicitZeroExtend(zeroExtendNode)) {
|
|
161 |
ValueNode input = zeroExtendNode.getValue();
|
|
162 |
if (input instanceof AddNode) {
|
|
163 |
AddNode add = (AddNode) input;
|
|
164 |
if (add.getX().isConstant()) {
|
|
165 |
optimizeAdd(zeroExtendNode, (ConstantNode) add.getX(), add.getY(), loop);
|
|
166 |
} else if (add.getY().isConstant()) {
|
|
167 |
optimizeAdd(zeroExtendNode, (ConstantNode) add.getY(), add.getX(), loop);
|
|
168 |
}
|
|
169 |
}
|
|
170 |
}
|
|
171 |
}
|
|
172 |
|
|
173 |
currentIV = ((DerivedInductionVariable) currentIV).getBase();
|
|
174 |
}
|
|
175 |
}
|
|
176 |
|
|
177 |
/**
|
|
178 |
* Given that Add(a, cst) is always positive, performs the following: ZeroExtend(Add(a, cst)) ->
|
|
179 |
* Add(SignExtend(a), SignExtend(cst)).
|
|
180 |
*/
|
|
181 |
private static void optimizeAdd(ZeroExtendNode zeroExtendNode, ConstantNode constant, ValueNode other, LoopEx loop) {
|
|
182 |
StructuredGraph graph = zeroExtendNode.graph();
|
|
183 |
AddNode addNode = graph.unique(new AddNode(signExtend(other, loop), ConstantNode.forLong(constant.asJavaConstant().asInt(), graph)));
|
|
184 |
zeroExtendNode.replaceAtUsages(addNode);
|
|
185 |
}
|
|
186 |
|
|
187 |
/**
|
|
188 |
* Create a sign extend for {@code input}, or zero extend if {@code input} can be proven
|
|
189 |
* positive.
|
|
190 |
*/
|
|
191 |
private static ValueNode signExtend(ValueNode input, LoopEx loop) {
|
|
192 |
StructuredGraph graph = input.graph();
|
|
193 |
if (input instanceof PhiNode) {
|
|
194 |
EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
|
|
195 |
InductionVariable inductionVariable = ivs.get(input);
|
|
196 |
if (inductionVariable != null && inductionVariable instanceof BasicInductionVariable) {
|
|
197 |
CountedLoopInfo countedLoopInfo = loop.counted();
|
|
198 |
IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
|
|
199 |
if (initStamp.isPositive()) {
|
|
200 |
if (inductionVariable.isConstantExtremum()) {
|
|
201 |
long init = inductionVariable.constantInit();
|
|
202 |
long stride = inductionVariable.constantStride();
|
|
203 |
long extremum = inductionVariable.constantExtremum();
|
|
204 |
|
|
205 |
if (init >= 0 && extremum >= 0) {
|
|
206 |
long shortestTrip = (extremum - init) / stride + 1;
|
|
207 |
if (shortestTrip == countedLoopInfo.constantMaxTripCount()) {
|
|
208 |
return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
|
|
209 |
}
|
|
210 |
}
|
|
211 |
}
|
|
212 |
if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) {
|
|
213 |
return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
|
|
214 |
}
|
|
215 |
}
|
|
216 |
}
|
|
217 |
}
|
|
218 |
return input.graph().maybeAddOrUnique(SignExtendNode.create(input, ADDRESS_BITS, NodeView.DEFAULT));
|
|
219 |
}
|
|
220 |
|
|
221 |
private static boolean applicableToImplicitZeroExtend(ZeroExtendNode zeroExtendNode) {
|
|
222 |
return zeroExtendNode.isInputAlwaysPositive() && zeroExtendNode.getInputBits() == INT_BITS && zeroExtendNode.getResultBits() == ADDRESS_BITS;
|
|
223 |
}
|
|
224 |
|
|
225 |
private static ValueNode tryImplicitZeroExtend(ValueNode input) {
|
|
226 |
if (input instanceof ZeroExtendNode) {
|
|
227 |
ZeroExtendNode zeroExtendNode = (ZeroExtendNode) input;
|
|
228 |
if (applicableToImplicitZeroExtend(zeroExtendNode)) {
|
|
229 |
return zeroExtendNode.getValue();
|
|
230 |
}
|
|
231 |
}
|
|
232 |
return input;
|
|
233 |
}
|
|
234 |
|
43972
|
235 |
}
|