1 /*
2  * Copyright (c) 2015, 2018, 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 
26 package org.graalvm.compiler.core.amd64;
27 
28 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
29 import org.graalvm.compiler.core.common.LIRKind;
30 import org.graalvm.compiler.core.common.type.IntegerStamp;
31 import org.graalvm.compiler.graph.NodeClass;
32 import org.graalvm.compiler.graph.spi.Simplifiable;
33 import org.graalvm.compiler.graph.spi.SimplifierTool;
34 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
35 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
36 import org.graalvm.compiler.nodeinfo.NodeInfo;
37 import org.graalvm.compiler.nodes.ConstantNode;
38 import org.graalvm.compiler.nodes.LoopBeginNode;
39 import org.graalvm.compiler.nodes.NodeView;
40 import org.graalvm.compiler.nodes.PhiNode;
41 import org.graalvm.compiler.nodes.ValueNode;
42 import org.graalvm.compiler.nodes.calc.AddNode;
43 import org.graalvm.compiler.nodes.memory.address.AddressNode;
44 import org.graalvm.compiler.nodes.spi.LIRLowerable;
45 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
46 
47 import jdk.vm.ci.meta.AllocatableValue;
48 import jdk.vm.ci.meta.Value;
49 
50 /**
51  * Represents an address of the form [base + index*scale + displacement]. Both base and index are
52  * optional.
53  */
54 @NodeInfo
55 public class AMD64AddressNode extends AddressNode implements Simplifiable, LIRLowerable {
56 
57     public static final NodeClass<AMD64AddressNode> TYPE = NodeClass.create(AMD64AddressNode.class);
58 
59     @OptionalInput private ValueNode base;
60 
61     @OptionalInput private ValueNode index;
62     private Scale scale;
63 
64     private int displacement;
65 
AMD64AddressNode(ValueNode base)66     public AMD64AddressNode(ValueNode base) {
67         this(base, null);
68     }
69 
AMD64AddressNode(ValueNode base, ValueNode index)70     public AMD64AddressNode(ValueNode base, ValueNode index) {
71         super(TYPE);
72         this.base = base;
73         this.index = index;
74         this.scale = Scale.Times1;
75     }
76 
canonicalizeIndex(SimplifierTool tool)77     public void canonicalizeIndex(SimplifierTool tool) {
78         if (index instanceof AddNode && ((IntegerStamp) index.stamp(NodeView.DEFAULT)).getBits() == 64) {
79             AddNode add = (AddNode) index;
80             ValueNode valX = add.getX();
81             if (valX instanceof PhiNode) {
82                 PhiNode phi = (PhiNode) valX;
83                 if (phi.merge() instanceof LoopBeginNode) {
84                     LoopBeginNode loopNode = (LoopBeginNode) phi.merge();
85                     if (!loopNode.isSimpleLoop()) {
86                         ValueNode valY = add.getY();
87                         if (valY instanceof ConstantNode) {
88                             int addBy = valY.asJavaConstant().asInt();
89                             displacement = displacement + scale.value * addBy;
90                             replaceFirstInput(index, phi);
91                             tool.addToWorkList(index);
92                         }
93                     }
94                 }
95             }
96         }
97     }
98 
99     @Override
generate(NodeLIRBuilderTool gen)100     public void generate(NodeLIRBuilderTool gen) {
101         LIRGeneratorTool tool = gen.getLIRGeneratorTool();
102 
103         AllocatableValue baseValue = base == null ? Value.ILLEGAL : tool.asAllocatable(gen.operand(base));
104         AllocatableValue indexValue = index == null ? Value.ILLEGAL : tool.asAllocatable(gen.operand(index));
105 
106         AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue);
107         AllocatableValue indexReference;
108         if (index == null) {
109             indexReference = null;
110         } else if (scale.equals(Scale.Times1)) {
111             indexReference = LIRKind.derivedBaseFromValue(indexValue);
112         } else {
113             if (LIRKind.isValue(indexValue)) {
114                 indexReference = null;
115             } else {
116                 indexReference = Value.ILLEGAL;
117             }
118         }
119 
120         LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp(NodeView.DEFAULT)), baseReference, indexReference);
121         gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement));
122     }
123 
124     @Override
getBase()125     public ValueNode getBase() {
126         return base;
127     }
128 
setBase(ValueNode base)129     public void setBase(ValueNode base) {
130         // allow modification before inserting into the graph
131         if (isAlive()) {
132             updateUsages(this.base, base);
133         }
134         this.base = base;
135     }
136 
137     @Override
getIndex()138     public ValueNode getIndex() {
139         return index;
140     }
141 
setIndex(ValueNode index)142     public void setIndex(ValueNode index) {
143         // allow modification before inserting into the graph
144         if (isAlive()) {
145             updateUsages(this.index, index);
146         }
147         this.index = index;
148     }
149 
getScale()150     public Scale getScale() {
151         return scale;
152     }
153 
setScale(Scale scale)154     public void setScale(Scale scale) {
155         this.scale = scale;
156     }
157 
getDisplacement()158     public int getDisplacement() {
159         return displacement;
160     }
161 
setDisplacement(int displacement)162     public void setDisplacement(int displacement) {
163         this.displacement = displacement;
164     }
165 
166     @Override
getMaxConstantDisplacement()167     public long getMaxConstantDisplacement() {
168         return displacement;
169     }
170 
171     @Override
simplify(SimplifierTool tool)172     public void simplify(SimplifierTool tool) {
173         canonicalizeIndex(tool);
174     }
175 }
176