use of org.graalvm.compiler.nodes.PhiNode in project graal by oracle.
the class MultiTypeGuardInlineInfo method inlineMultipleMethods.
private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers) {
int numberOfMethods = concretes.size();
FixedNode continuation = invoke.next();
// setup merge and phi nodes for results and exceptions
AbstractMergeNode returnMerge = graph.add(new MergeNode());
returnMerge.setStateAfter(invoke.stateAfter());
PhiNode returnValuePhi = null;
if (invoke.asNode().getStackKind() != JavaKind.Void) {
returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp(NodeView.DEFAULT).unrestricted(), returnMerge));
}
AbstractMergeNode exceptionMerge = null;
PhiNode exceptionObjectPhi = null;
if (invoke instanceof InvokeWithExceptionNode) {
InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithException.exceptionEdge();
exceptionMerge = graph.add(new MergeNode());
FixedNode exceptionSux = exceptionEdge.next();
graph.addBeforeFixed(exceptionSux, exceptionMerge);
exceptionObjectPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(JavaKind.Object), exceptionMerge));
exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, JavaKind.Object, new JavaKind[] { JavaKind.Object }, new ValueNode[] { exceptionObjectPhi }));
}
// create one separate block for each invoked method
AbstractBeginNode[] successors = new AbstractBeginNode[numberOfMethods + 1];
for (int i = 0; i < numberOfMethods; i++) {
successors[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, true);
}
// create the successor for an unknown type
FixedNode unknownTypeSux;
if (shouldFallbackToInvoke()) {
unknownTypeSux = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, false);
} else {
unknownTypeSux = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated));
}
successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
// replace the invoke exception edge
if (invoke instanceof InvokeWithExceptionNode) {
InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invoke;
ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithExceptionNode.exceptionEdge();
exceptionEdge.replaceAtUsages(exceptionObjectPhi);
exceptionEdge.setNext(null);
GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
}
assert invoke.asNode().isAlive();
// replace the invoke with a switch on the type of the actual receiver
boolean methodDispatch = createDispatchOnTypeBeforeInvoke(graph, successors, false, providers.getStampProvider(), providers.getConstantReflection());
assert invoke.next() == continuation;
invoke.setNext(null);
returnMerge.setNext(continuation);
if (returnValuePhi != null) {
invoke.asNode().replaceAtUsages(returnValuePhi);
}
invoke.asNode().safeDelete();
ArrayList<PiNode> replacementNodes = new ArrayList<>();
// prepare the anchors for the invokes
for (int i = 0; i < numberOfMethods; i++) {
AbstractBeginNode node = successors[i];
Invoke invokeForInlining = (Invoke) node.next();
ResolvedJavaType commonType;
if (methodDispatch) {
commonType = concretes.get(i).getDeclaringClass();
} else {
commonType = getLeastCommonType(i);
}
ValueNode receiver = ((MethodCallTargetNode) invokeForInlining.callTarget()).receiver();
boolean exact = (getTypeCount(i) == 1 && !methodDispatch);
PiNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, node, commonType, receiver, exact);
invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
assert !anchoredReceiver.isDeleted() : anchoredReceiver;
replacementNodes.add(anchoredReceiver);
}
if (shouldFallbackToInvoke()) {
replacementNodes.add(null);
}
EconomicSet<Node> canonicalizeNodes = EconomicSet.create(Equivalence.DEFAULT);
// do the actual inlining for every invoke
for (int i = 0; i < numberOfMethods; i++) {
Invoke invokeForInlining = (Invoke) successors[i].next();
canonicalizeNodes.addAll(doInline(i, invokeForInlining));
}
if (returnValuePhi != null) {
canonicalizeNodes.add(returnValuePhi);
}
return canonicalizeNodes;
}
use of org.graalvm.compiler.nodes.PhiNode in project graal by oracle.
the class GraphUtil method checkRedundantPhi.
public static void checkRedundantPhi(PhiNode phiNode) {
if (phiNode.isDeleted() || phiNode.valueCount() == 1) {
return;
}
ValueNode singleValue = phiNode.singleValueOrThis();
if (singleValue != phiNode) {
Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot();
Collection<ProxyNode> proxyUsages = phiNode.usages().filter(ProxyNode.class).snapshot();
phiNode.replaceAtUsagesAndDelete(singleValue);
for (PhiNode phi : phiUsages) {
checkRedundantPhi(phi);
}
for (ProxyNode proxy : proxyUsages) {
checkRedundantProxy(proxy);
}
}
}
use of org.graalvm.compiler.nodes.PhiNode in project graal by oracle.
the class UnsafeEATest method testMergedDouble.
@Test
public void testMergedDouble() {
testEscapeAnalysis("testMergedDoubleSnippet", null, false);
Assert.assertEquals(1, returnNodes.size());
Assert.assertTrue(returnNodes.get(0).result() instanceof ValuePhiNode);
PhiNode phi = (PhiNode) returnNodes.get(0).result();
Assert.assertTrue(phi.valueAt(0) instanceof LoadFieldNode);
Assert.assertTrue(phi.valueAt(1) instanceof LoadFieldNode);
}
use of org.graalvm.compiler.nodes.PhiNode in project graal by oracle.
the class EAMergingTest method testSimpleMerge.
@Test
public void testSimpleMerge() {
testEscapeAnalysis("simpleMergeSnippet", null, false);
assertDeepEquals(1, returnNodes.size());
assertTrue(returnNodes.get(0).result() instanceof ValuePhiNode);
PhiNode phi = (PhiNode) returnNodes.get(0).result();
assertTrue(phi.valueAt(0) instanceof ParameterNode);
assertTrue(phi.valueAt(1) instanceof ParameterNode);
}
use of org.graalvm.compiler.nodes.PhiNode in project graal by oracle.
the class NodeLIRBuilder method createPhiOut.
private Value[] createPhiOut(AbstractMergeNode merge, AbstractEndNode pred) {
List<Value> values = new ArrayList<>();
for (PhiNode phi : merge.valuePhis()) {
ValueNode node = phi.valueAt(pred);
Value value = operand(node);
assert value != null;
if (isRegister(value)) {
/*
* Fixed register intervals are not allowed at block boundaries so we introduce a
* new Variable.
*/
value = gen.emitMove(value);
} else if (!allowObjectConstantToStackMove() && node instanceof ConstantNode && !LIRKind.isValue(value)) {
/*
* Some constants are not allowed as inputs for PHIs in certain backends. Explicitly
* create a copy of this value to force it into a register. The new variable is only
* used in the PHI.
*/
Variable result = gen.newVariable(value.getValueKind());
gen.emitMove(result, value);
value = result;
}
values.add(value);
}
return values.toArray(new Value[values.size()]);
}
Aggregations