001/*
002 * Copyright (c) 2013, 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.phases.common;
024
025import java.util.*;
026
027import com.oracle.graal.graph.*;
028import com.oracle.graal.nodes.*;
029import com.oracle.graal.nodes.extended.*;
030import com.oracle.graal.phases.*;
031import com.oracle.graal.phases.graph.*;
032
033/**
034 * This phase performs a bit of hygiene on {@link ValueAnchorNode} by removing inputs that have
035 * already been anchored in a dominating value anchor. Value anchors that lose their last input,
036 * have no usages and are not marked as permanent are removed.
037 */
038public class ValueAnchorCleanupPhase extends Phase {
039
040    private static class State extends MergeableState<State> implements Cloneable {
041
042        private final Set<Node> anchoredValues;
043
044        public State() {
045            anchoredValues = Node.newSet();
046        }
047
048        public State(State other) {
049            anchoredValues = Node.newSet(other.anchoredValues);
050        }
051
052        @Override
053        public boolean merge(AbstractMergeNode merge, List<State> withStates) {
054            for (State other : withStates) {
055                anchoredValues.retainAll(other.anchoredValues);
056            }
057            return true;
058        }
059
060        @Override
061        public State clone() {
062            return new State(this);
063        }
064    }
065
066    private static class CleanupValueAnchorsClosure extends SinglePassNodeIterator<State> {
067
068        public CleanupValueAnchorsClosure(StartNode start) {
069            super(start, new State());
070        }
071
072        @Override
073        protected void node(FixedNode node) {
074            if (node instanceof ValueAnchorNode) {
075                ValueAnchorNode anchor = (ValueAnchorNode) node;
076                ValueNode anchored = anchor.getAnchoredNode();
077                if (anchored != null) {
078                    if (state.anchoredValues.contains(anchored)) {
079                        anchor.removeAnchoredNode();
080                    } else {
081                        state.anchoredValues.add(anchored);
082                    }
083                }
084                if (anchor.getAnchoredNode() == null && anchor.hasNoUsages()) {
085                    node.graph().removeFixed(anchor);
086                }
087            }
088        }
089    }
090
091    @Override
092    protected void run(StructuredGraph graph) {
093        CleanupValueAnchorsClosure closure = new CleanupValueAnchorsClosure(graph.start());
094        closure.apply();
095    }
096}