1 /*
2  * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 
25 package org.graalvm.compiler.nodes;
26 
27 import java.util.Map;
28 
29 import org.graalvm.compiler.core.common.type.Stamp;
30 import org.graalvm.compiler.core.common.type.StampFactory;
31 import org.graalvm.compiler.graph.NodeClass;
32 import org.graalvm.compiler.graph.NodeInputList;
33 import org.graalvm.compiler.nodeinfo.NodeInfo;
34 import org.graalvm.compiler.nodes.type.StampTool;
35 import org.graalvm.util.CollectionsUtil;
36 
37 /**
38  * Value {@link PhiNode}s merge data flow values at control flow merges.
39  */
40 @NodeInfo(nameTemplate = "Phi({i#values}, {p#valueDescription})")
41 public class ValuePhiNode extends PhiNode {
42 
43     public static final NodeClass<ValuePhiNode> TYPE = NodeClass.create(ValuePhiNode.class);
44     @Input protected NodeInputList<ValueNode> values;
45 
ValuePhiNode(Stamp stamp, AbstractMergeNode merge)46     public ValuePhiNode(Stamp stamp, AbstractMergeNode merge) {
47         this(TYPE, stamp, merge);
48     }
49 
ValuePhiNode(NodeClass<? extends ValuePhiNode> c, Stamp stamp, AbstractMergeNode merge)50     protected ValuePhiNode(NodeClass<? extends ValuePhiNode> c, Stamp stamp, AbstractMergeNode merge) {
51         super(c, stamp, merge);
52         assert stamp != StampFactory.forVoid();
53         values = new NodeInputList<>(this);
54     }
55 
ValuePhiNode(Stamp stamp, AbstractMergeNode merge, ValueNode[] values)56     public ValuePhiNode(Stamp stamp, AbstractMergeNode merge, ValueNode[] values) {
57         super(TYPE, stamp, merge);
58         assert stamp != StampFactory.forVoid();
59         this.values = new NodeInputList<>(this, values);
60     }
61 
62     @Override
values()63     public NodeInputList<ValueNode> values() {
64         return values;
65     }
66 
67     @Override
inferStamp()68     public boolean inferStamp() {
69         /*
70          * Meet all the values feeding this Phi but don't use the stamp of this Phi since that's
71          * what's being computed.
72          */
73         Stamp valuesStamp = StampTool.meetOrNull(values(), this);
74         if (valuesStamp == null) {
75             valuesStamp = stamp;
76         } else if (stamp.isCompatible(valuesStamp)) {
77             valuesStamp = stamp.join(valuesStamp);
78         }
79         return updateStamp(valuesStamp);
80     }
81 
82     @Override
verify()83     public boolean verify() {
84         Stamp s = null;
85         for (ValueNode input : values()) {
86             assert input != null;
87             if (s == null) {
88                 s = input.stamp(NodeView.DEFAULT);
89             } else {
90                 if (!s.isCompatible(input.stamp(NodeView.DEFAULT))) {
91                     fail("Phi Input Stamps are not compatible. Phi:%s inputs:%s", this,
92                                     CollectionsUtil.mapAndJoin(values(), x -> x.toString() + ":" + x.stamp(NodeView.DEFAULT), ", "));
93                 }
94             }
95         }
96         return super.verify();
97     }
98 
99     @Override
valueDescription()100     protected String valueDescription() {
101         return stamp(NodeView.DEFAULT).unrestricted().toString();
102     }
103 
104     @Override
getDebugProperties(Map<Object, Object> map)105     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
106         Map<Object, Object> properties = super.getDebugProperties(map);
107         properties.put("valueDescription", valueDescription());
108         return properties;
109     }
110 }
111