001/*
002 * Copyright (c) 2009, 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.calc;
024
025import jdk.internal.jvmci.meta.*;
026
027import com.oracle.graal.compiler.common.type.*;
028import com.oracle.graal.graph.*;
029import com.oracle.graal.graph.spi.*;
030import com.oracle.graal.nodeinfo.*;
031import com.oracle.graal.nodes.*;
032import com.oracle.graal.nodes.spi.*;
033import com.oracle.graal.nodes.type.*;
034
035/**
036 * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
037 */
038@NodeInfo
039public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable {
040
041    public static final NodeClass<IsNullNode> TYPE = NodeClass.create(IsNullNode.class);
042
043    public IsNullNode(ValueNode object) {
044        super(TYPE, object);
045    }
046
047    @Override
048    public void generate(NodeLIRBuilderTool gen) {
049        // Nothing to do.
050    }
051
052    @Override
053    public boolean verify() {
054        assertTrue(getValue() != null, "is null input must not be null");
055        assertTrue(getValue().stamp() instanceof AbstractPointerStamp, "input must be a pointer not %s", getValue().stamp());
056        return super.verify();
057    }
058
059    @Override
060    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
061        if (StampTool.isPointerAlwaysNull(forValue)) {
062            return LogicConstantNode.tautology();
063        } else if (StampTool.isPointerNonNull(forValue)) {
064            return LogicConstantNode.contradiction();
065        }
066        return this;
067    }
068
069    @Override
070    public void virtualize(VirtualizerTool tool) {
071        ValueNode alias = tool.getAlias(getValue());
072        TriState fold = tryFold(alias.stamp());
073        if (fold != TriState.UNKNOWN) {
074            tool.replaceWithValue(LogicConstantNode.forBoolean(fold.isTrue(), graph()));
075        }
076    }
077
078    @Override
079    public boolean push(PiNode parent) {
080        if (parent.stamp() instanceof ObjectStamp && parent.object().stamp() instanceof ObjectStamp) {
081            ObjectStamp piStamp = (ObjectStamp) parent.stamp();
082            ObjectStamp piValueStamp = (ObjectStamp) parent.object().stamp();
083            if (piStamp.nonNull() == piValueStamp.nonNull() && piStamp.alwaysNull() == piValueStamp.alwaysNull()) {
084                replaceFirstInput(parent, parent.object());
085                return true;
086            }
087        }
088        return false;
089    }
090
091    @NodeIntrinsic
092    public static native IsNullNode isNull(Object object);
093
094    @Override
095    public Stamp getSucceedingStampForValue(boolean negated) {
096        return negated ? StampFactory.objectNonNull() : StampFactory.alwaysNull();
097    }
098
099    @Override
100    public TriState tryFold(Stamp valueStamp) {
101        if (valueStamp instanceof ObjectStamp) {
102            ObjectStamp objectStamp = (ObjectStamp) valueStamp;
103            if (objectStamp.alwaysNull()) {
104                return TriState.TRUE;
105            } else if (objectStamp.nonNull()) {
106                return TriState.FALSE;
107            }
108        }
109        return TriState.UNKNOWN;
110    }
111}