001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.nodes.extended; 024 025import com.oracle.graal.compiler.common.type.*; 026import com.oracle.graal.graph.*; 027import com.oracle.graal.graph.spi.*; 028import com.oracle.graal.nodeinfo.*; 029import com.oracle.graal.nodes.*; 030import com.oracle.graal.nodes.calc.*; 031import com.oracle.graal.nodes.memory.*; 032import com.oracle.graal.nodes.spi.*; 033import com.oracle.graal.nodes.util.*; 034import com.oracle.graal.nodes.virtual.*; 035 036/** 037 * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph. 038 */ 039@NodeInfo(allowedUsageTypes = {InputType.Anchor, InputType.Guard}) 040public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, AnchoringNode, GuardingNode { 041 042 public static final NodeClass<ValueAnchorNode> TYPE = NodeClass.create(ValueAnchorNode.class); 043 @OptionalInput(InputType.Guard) ValueNode anchored; 044 045 public ValueAnchorNode(ValueNode value) { 046 super(TYPE, StampFactory.forVoid()); 047 this.anchored = value; 048 } 049 050 @Override 051 public void generate(NodeLIRBuilderTool gen) { 052 // Nothing to emit, since this node is used for structural purposes only. 053 } 054 055 public ValueNode getAnchoredNode() { 056 return anchored; 057 } 058 059 @Override 060 public void simplify(SimplifierTool tool) { 061 while (next() instanceof ValueAnchorNode) { 062 ValueAnchorNode nextAnchor = (ValueAnchorNode) next(); 063 if (nextAnchor.anchored == anchored || nextAnchor.anchored == null) { 064 // two anchors for the same anchored -> coalesce 065 // nothing anchored on the next anchor -> coalesce 066 nextAnchor.replaceAtUsages(this); 067 GraphUtil.removeFixedWithUnusedInputs(nextAnchor); 068 } else { 069 break; 070 } 071 } 072 if (tool.allUsagesAvailable() && hasNoUsages() && next() instanceof FixedAccessNode) { 073 FixedAccessNode currentNext = (FixedAccessNode) next(); 074 if (currentNext.getGuard() == anchored) { 075 GraphUtil.removeFixedWithUnusedInputs(this); 076 return; 077 } else if (currentNext.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) { 078 // coalesce null check guards into subsequent read/write 079 currentNext.setGuard((GuardingNode) anchored); 080 tool.addToWorkList(next()); 081 return; 082 } 083 } 084 085 if (anchored != null && (anchored.isConstant() || anchored instanceof FixedNode)) { 086 // anchoring fixed nodes and constants is useless 087 removeAnchoredNode(); 088 } 089 090 if (anchored == null && hasNoUsages()) { 091 // anchor is not necessary any more => remove. 092 GraphUtil.removeFixedWithUnusedInputs(this); 093 } 094 } 095 096 @Override 097 public void virtualize(VirtualizerTool tool) { 098 if (anchored == null || anchored instanceof AbstractBeginNode) { 099 tool.delete(); 100 } else { 101 ValueNode alias = tool.getAlias(anchored); 102 if (alias instanceof VirtualObjectNode) { 103 tool.delete(); 104 } 105 } 106 } 107 108 public void removeAnchoredNode() { 109 this.updateUsages(anchored, null); 110 this.anchored = null; 111 } 112}