view graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java @ 5563:6a2671066204

added NewInstanceSnippets for lowering NewInstanceNodes (currently disabled by default) added Word type and WordTypeRewriterPhase to support programming against machine word values in snippets without duplicating the code for 32 and 64 bit platforms added GraphUtil.approxSourceLocation() utility method for getting an approximate source code location for a node
author Doug Simon <doug.simon@oracle.com>
date Mon, 11 Jun 2012 15:39:57 +0200
parents a891c53a295b
children a63ed5993987
line wrap: on
line source

/*
 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.graal.nodes;

import java.util.*;

import com.oracle.graal.api.meta.*;
import com.oracle.graal.nodes.spi.*;
import com.oracle.graal.nodes.spi.types.*;
import com.oracle.graal.nodes.type.*;

/**
 * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome of a
 * comparison.
 */
public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, SplitTypeFeedbackProvider, Negatable {
    public static final int TRUE_EDGE = 0;
    public static final int FALSE_EDGE = 1;

    @Input private BooleanNode compare;

    public BooleanNode compare() {
        return compare;
    }

    public void setCompare(BooleanNode x) {
        updateUsages(compare, x);
        compare = x;
    }

    public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability) {
        super(StampFactory.forVoid(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability});
        this.compare = condition;
    }

    /**
     * Gets the true successor.
     *
     * @return the true successor
     */
    public BeginNode trueSuccessor() {
        return blockSuccessor(0);
    }

    /**
     * Gets the false successor.
     *
     * @return the false successor
     */
    public BeginNode falseSuccessor() {
        return blockSuccessor(1);
    }

    public void setTrueSuccessor(BeginNode node) {
        setBlockSuccessor(0, node);
    }

    public void setFalseSuccessor(BeginNode node) {
        setBlockSuccessor(1, node);
    }

    /**
     * Gets the node corresponding to the specified outcome of the branch.
     *
     * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
     * @return the corresponding successor
     */
    public BeginNode successor(boolean istrue) {
        return blockSuccessor(istrue ? 0 : 1);
    }

    @Override
    public void generate(LIRGeneratorTool gen) {
        gen.emitIf(this);
    }

    @Override
    public boolean verify() {
        assertTrue(compare() != null, "missing compare");
        assertTrue(trueSuccessor() != null, "missing trueSuccessor");
        assertTrue(falseSuccessor() != null, "missing falseSuccessor");
        return super.verify();
    }

    @Override
    public void simplify(SimplifierTool tool) {
        if (compare() instanceof ConstantNode) {
            ConstantNode c = (ConstantNode) compare();
            if (c.asConstant().asBoolean()) {
                tool.deleteBranch(falseSuccessor());
                tool.addToWorkList(trueSuccessor());
                ((StructuredGraph) graph()).removeSplit(this, TRUE_EDGE);
            } else {
                tool.deleteBranch(trueSuccessor());
                tool.addToWorkList(falseSuccessor());
                ((StructuredGraph) graph()).removeSplit(this, FALSE_EDGE);
            }
        } else if (trueSuccessor().guards().isEmpty() && falseSuccessor().guards().isEmpty()) {
            if (trueSuccessor().next() instanceof EndNode && falseSuccessor().next() instanceof EndNode) {
                EndNode trueEnd = (EndNode) trueSuccessor().next();
                EndNode falseEnd = (EndNode) falseSuccessor().next();
                MergeNode merge = trueEnd.merge();
                if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) {
                    Iterator<PhiNode> phis = merge.phis().iterator();
                    if (!phis.hasNext()) {
                        // empty if construct with no phis: remove it
                        removeEmptyIf(tool);
                    } else {
                        PhiNode singlePhi = phis.next();
                        if (!phis.hasNext()) {
                            // one phi at the merge of an otherwise empty if construct: try to convert into a MaterializeNode
                            boolean inverted = trueEnd == merge.forwardEndAt(FALSE_EDGE);
                            ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0);
                            ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1);
                            if (trueValue.kind() != falseValue.kind()) {
                                return;
                            }
                            if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) {
                                return;
                            }
                            if (trueValue.isConstant() && falseValue.isConstant()) {
                                MaterializeNode materialize = MaterializeNode.create(compare(), graph(), trueValue, falseValue);
                                ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize);
                                removeEmptyIf(tool);
                            }
                        }
                    }
                }
            }
        }
    }

    private void removeEmptyIf(SimplifierTool tool) {
        BeginNode trueSuccessor = trueSuccessor();
        BeginNode falseSuccessor = falseSuccessor();
        assert trueSuccessor.next() instanceof EndNode && falseSuccessor.next() instanceof EndNode;

        EndNode trueEnd = (EndNode) trueSuccessor.next();
        EndNode falseEnd = (EndNode) falseSuccessor.next();
        assert trueEnd.merge() == falseEnd.merge();

        FixedWithNextNode pred = (FixedWithNextNode) predecessor();
        MergeNode merge = trueEnd.merge();
        merge.prepareDelete(pred);
        assert merge.usages().isEmpty();
        trueSuccessor.prepareDelete();
        falseSuccessor.prepareDelete();

        FixedNode next = merge.next();
        merge.setNext(null);
        setTrueSuccessor(null);
        setFalseSuccessor(null);
        pred.setNext(next);
        safeDelete();
        trueSuccessor.safeDelete();
        falseSuccessor.safeDelete();
        merge.safeDelete();
        trueEnd.safeDelete();
        falseEnd.safeDelete();
        tool.addToWorkList(next);
    }

    @Override
    public void typeFeedback(int blockSuccessor, TypeFeedbackTool tool) {
        if (compare instanceof ConditionalTypeFeedbackProvider) {
            ((ConditionalTypeFeedbackProvider) compare).typeFeedback(blockSuccessor == TRUE_EDGE ? tool : tool.negate());
        }
    }

    @Override
    public Negatable negate() {
        BeginNode trueSucc = trueSuccessor();
        BeginNode falseSucc = falseSuccessor();
        setTrueSuccessor(null);
        setFalseSuccessor(null);
        setTrueSuccessor(falseSucc);
        setFalseSuccessor(trueSucc);
        double prop = branchProbability[TRUE_EDGE];
        branchProbability[TRUE_EDGE] = branchProbability[FALSE_EDGE];
        branchProbability[FALSE_EDGE] = prop;
        return this;
    }
}