changeset 15520:4cdc787681d4

add support for more nodes inputs
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Mon, 05 May 2014 16:13:49 -0700
parents f8cf483ba31e
children 76213c9350ad
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java
diffstat 7 files changed, 155 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Mon May 05 16:13:49 2014 -0700
@@ -455,7 +455,7 @@
         return null;
     }
 
-    @MatchRule("(Write Narrow=narrow value)")
+    @MatchRule("(Write Narrow=narrow location value)")
     public ComplexMatchResult writeNarrow(WriteNode root, NarrowNode narrow) {
         return builder -> {
             PlatformKind writeKind = getLIRGeneratorTool().getPlatformKind(root.value().stamp());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/GraalMatchableNodes.java	Mon May 05 16:13:49 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.match;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -30,19 +31,19 @@
  * Helper class to describe the matchable nodes in the core Graal IR. These could possibly live in
  * their respective classes but for simplicity in the {@link MatchProcessor} they are grouped here.
  */
-@MatchableNode(nodeClass = ConstantNode.class, inputs = 0)
+@MatchableNode(nodeClass = ConstantNode.class, inputs = 0, shareable = true)
 @MatchableNode(nodeClass = FloatConvertNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
 @MatchableNode(nodeClass = FloatSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
-@MatchableNode(nodeClass = FloatingReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class)
+@MatchableNode(nodeClass = FloatingReadNode.class, inputs = 2, adapter = GraalMatchableNodes.AccessAdapter.class)
 @MatchableNode(nodeClass = IfNode.class, inputs = 1, adapter = GraalMatchableNodes.IfNodeAdapter.class)
 @MatchableNode(nodeClass = IntegerSubNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
 @MatchableNode(nodeClass = LeftShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
 @MatchableNode(nodeClass = NarrowNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
-@MatchableNode(nodeClass = ReadNode.class, inputs = 1, adapter = GraalMatchableNodes.ReadNodeAdapter.class)
+@MatchableNode(nodeClass = ReadNode.class, inputs = 2, adapter = GraalMatchableNodes.AccessAdapter.class)
 @MatchableNode(nodeClass = ReinterpretNode.class, inputs = 1, adapter = GraalMatchableNodes.ReinterpretNodeAdapter.class)
 @MatchableNode(nodeClass = SignExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
 @MatchableNode(nodeClass = UnsignedRightShiftNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class)
-@MatchableNode(nodeClass = WriteNode.class, inputs = 2, adapter = GraalMatchableNodes.WriteNodeAdapter.class)
+@MatchableNode(nodeClass = WriteNode.class, inputs = 3, adapter = GraalMatchableNodes.WriteNodeAdapter.class)
 @MatchableNode(nodeClass = ZeroExtendNode.class, inputs = 1, adapter = GraalMatchableNodes.ConvertNodeAdapter.class)
 @MatchableNode(nodeClass = AndNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
 @MatchableNode(nodeClass = FloatAddNode.class, inputs = 2, adapter = GraalMatchableNodes.BinaryNodeAdapter.class, commutative = true)
@@ -61,71 +62,87 @@
 public class GraalMatchableNodes {
     public static class BinaryNodeAdapter extends MatchNodeAdapter {
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((BinaryNode) node).x();
-        }
-
-        @Override
-        protected ValueNode getSecondInput(ValueNode node) {
-            return ((BinaryNode) node).y();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((BinaryNode) node).x();
+            }
+            if (input == 1) {
+                return ((BinaryNode) node).y();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     public static class WriteNodeAdapter extends MatchNodeAdapter {
-
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((WriteNode) node).object();
-        }
-
-        @Override
-        protected ValueNode getSecondInput(ValueNode node) {
-            return ((WriteNode) node).value();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((WriteNode) node).object();
+            }
+            if (input == 1) {
+                return ((WriteNode) node).location();
+            }
+            if (input == 2) {
+                return ((WriteNode) node).value();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     public static class ConvertNodeAdapter extends MatchNodeAdapter {
-
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((ConvertNode) node).getInput();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((ConvertNode) node).getInput();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     public static class ReinterpretNodeAdapter extends MatchNodeAdapter {
-
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((ReinterpretNode) node).value();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((ReinterpretNode) node).value();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     public static class IfNodeAdapter extends MatchNodeAdapter {
-
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((IfNode) node).condition();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((IfNode) node).condition();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
-    public static class ReadNodeAdapter extends MatchNodeAdapter {
+    public static class AccessAdapter extends MatchNodeAdapter {
 
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((Access) node).object();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((Access) node).object();
+            }
+            if (input == 1) {
+                return ((Access) node).accessLocation();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 
     public static class BinaryOpLogicNodeAdapter extends MatchNodeAdapter {
-
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((BinaryOpLogicNode) node).x();
-        }
-
-        @Override
-        protected ValueNode getSecondInput(ValueNode node) {
-            return ((BinaryOpLogicNode) node).y();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((BinaryOpLogicNode) node).x();
+            }
+            if (input == 1) {
+                return ((BinaryOpLogicNode) node).y();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchNodeAdapter.java	Mon May 05 16:13:49 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.compiler.match;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -31,12 +32,7 @@
  */
 public class MatchNodeAdapter {
     @SuppressWarnings("unused")
-    protected ValueNode getFirstInput(ValueNode node) {
-        throw new InternalError();
-    }
-
-    @SuppressWarnings("unused")
-    protected ValueNode getSecondInput(ValueNode node) {
-        throw new InternalError();
+    public ValueNode getInput(int input, ValueNode node) {
+        throw GraalInternalError.shouldNotReachHere();
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java	Mon May 05 16:13:49 2014 -0700
@@ -111,23 +111,25 @@
      * The expected type of the node. It must match exactly.
      */
     private final Class<? extends ValueNode> nodeClass;
+
     /**
      * An optional name for this node. A name can occur multiple times in a match and that name must
      * always refer to the same node of the match will fail.
      */
     private final String name;
+
     /**
-     * An optional pattern for the first input.
+     * Patterns to match the inputs.
      */
-    private final MatchPattern first;
-    /**
-     * An optional pattern for the second input.
-     */
-    private final MatchPattern second;
+    private final MatchPattern[] patterns;
+
     /**
      * Helper class to visit the inputs.
      */
     private final MatchNodeAdapter adapter;
+
+    private static final MatchPattern[] EMPTY_PATTERNS = new MatchPattern[0];
+
     /**
      * Can there only be one user of the node. Constant nodes can be matched even if there are other
      * users.
@@ -135,23 +137,44 @@
     private final boolean singleUser;
 
     public MatchPattern(String name, boolean singleUser) {
-        this(null, name, null, null, null, singleUser);
+        this(null, name, singleUser);
     }
 
     public MatchPattern(Class<? extends ValueNode> nodeClass, String name, boolean singleUser) {
-        this(nodeClass, name, null, null, null, singleUser);
+        this.nodeClass = nodeClass;
+        this.name = name;
+        this.singleUser = singleUser;
+        this.patterns = EMPTY_PATTERNS;
+        this.adapter = null;
     }
 
     public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchNodeAdapter adapter, boolean singleUser) {
-        this(nodeClass, name, first, null, adapter, singleUser);
+        this.nodeClass = nodeClass;
+        this.name = name;
+        this.singleUser = singleUser;
+        this.patterns = new MatchPattern[1];
+        patterns[0] = first;
+        this.adapter = adapter;
     }
 
     public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchNodeAdapter adapter, boolean singleUser) {
         this.nodeClass = nodeClass;
         this.name = name;
         this.singleUser = singleUser;
-        this.first = first;
-        this.second = second;
+        this.patterns = new MatchPattern[2];
+        patterns[0] = first;
+        patterns[1] = second;
+        this.adapter = adapter;
+    }
+
+    public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, MatchNodeAdapter adapter, boolean singleUser) {
+        this.nodeClass = nodeClass;
+        this.name = name;
+        this.singleUser = singleUser;
+        this.patterns = new MatchPattern[3];
+        patterns[0] = first;
+        patterns[1] = second;
+        patterns[2] = third;
         this.adapter = adapter;
     }
 
@@ -197,10 +220,10 @@
             result = context.captureNamedValue(name, nodeClass, node);
         }
 
-        if (first != null) {
-            result = first.matchUsage(adapter.getFirstInput(node), context, false);
-            if (result == Result.OK && second != null) {
-                result = second.matchUsage(adapter.getSecondInput(node), context, false);
+        for (int input = 0; input < patterns.length; input++) {
+            result = patterns[input].matchUsage(adapter.getInput(input, node), context, false);
+            if (result != Result.OK) {
+                return result;
             }
         }
 
@@ -231,10 +254,10 @@
             }
         }
 
-        if (first != null) {
-            result = first.matchShape(adapter.getFirstInput(node), statement, false);
-            if (result == Result.OK && second != null) {
-                result = second.matchShape(adapter.getSecondInput(node), statement, false);
+        for (int input = 0; input < patterns.length; input++) {
+            result = patterns[input].matchShape(adapter.getInput(input, node), statement, false);
+            if (result != Result.OK) {
+                return result;
             }
         }
 
@@ -248,10 +271,18 @@
      */
     public String formatMatch(ValueNode root) {
         String result = String.format("%s", root);
-        if (first == null && second == null) {
+        if (patterns.length == 0) {
             return result;
         } else {
-            return "(" + result + (first != null ? " " + first.formatMatch(adapter.getFirstInput(root)) : "") + (second != null ? " " + second.formatMatch(adapter.getSecondInput(root)) : "") + ")";
+            StringBuilder sb = new StringBuilder();
+            sb.append("(");
+            sb.append(result);
+            for (int input = 0; input < patterns.length; input++) {
+                sb.append(" ");
+                sb.append(patterns[input].formatMatch(adapter.getInput(input, root)));
+            }
+            sb.append(")");
+            return sb.toString();
         }
     }
 
@@ -260,11 +291,21 @@
         if (nodeClass == null) {
             return name;
         } else {
-            String pre = first != null || second != null ? "(" : "";
-            String post = first != null || second != null ? ")" : "";
             String nodeName = nodeClass.getSimpleName();
             nodeName = nodeName.substring(0, nodeName.length() - 4);
-            return pre + nodeName + (name != null ? "=" + name : "") + (first != null ? (" " + first.toString()) : "") + (second != null ? (" " + second.toString()) : "") + post;
+            if (patterns.length == 0) {
+                return nodeName + (name != null ? "=" + name : "");
+            } else {
+                StringBuilder sb = new StringBuilder();
+                sb.append("(");
+                sb.append(nodeName);
+                for (int index = 0; index < patterns.length; index++) {
+                    sb.append(" ");
+                    sb.append(patterns[index].toString());
+                }
+                sb.append(")");
+                return sb.toString();
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchProcessor.java	Mon May 05 16:13:49 2014 -0700
@@ -237,11 +237,11 @@
          * Can multiple users of this node subsume it. Constants can be swallowed into a match even
          * if there are multiple users.
          */
-        final boolean cloneable;
+        final boolean shareable;
 
         final Set<Element> originatingElements = new HashSet<>();
 
-        TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative) {
+        TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative, boolean shareable) {
             this.mirror = mirror;
             this.shortName = shortName;
             this.nodeClass = nodeClass;
@@ -249,7 +249,7 @@
             this.inputs = inputs;
             this.adapter = adapter;
             this.commutative = commutative;
-            this.cloneable = (nodePackage + "." + nodeClass).equals(ConstantNode.class.getName());
+            this.shareable = shareable;
             assert !commutative || inputs == 2;
         }
     }
@@ -270,8 +270,8 @@
     private Map<ExecutableElement, MethodInvokerItem> invokers = new LinkedHashMap<>();
     private TypeDescriptor valueType;
 
-    private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative, Element element) {
-        TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, adapter, commutative);
+    private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, int inputs, String adapter, boolean commutative, boolean shareable, Element element) {
+        TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, adapter, commutative, shareable);
         descriptor.originatingElements.add(element);
         knownTypes.put(shortName, descriptor);
         if (!requiredPackages.contains(descriptor.nodePackage)) {
@@ -315,7 +315,15 @@
             String prefix = formatPrefix();
             String suffix = formatSuffix();
             ArrayList<String> variants = new ArrayList<>();
-            if (inputs.length == 2) {
+            if (inputs.length == 3) {
+                for (String first : inputs[0].generateVariants()) {
+                    for (String second : inputs[1].generateVariants()) {
+                        for (String third : inputs[2].generateVariants()) {
+                            variants.add(prefix + ", " + first + ", " + second + ", " + third + suffix);
+                        }
+                    }
+                }
+            } else if (inputs.length == 2) {
                 // Generate this version and a swapped version
                 for (String first : inputs[0].generateVariants()) {
                     for (String second : inputs[1].generateVariants()) {
@@ -330,6 +338,7 @@
                     variants.add(prefix + ", " + first + suffix);
                 }
             } else {
+                assert inputs.length == 0;
                 variants.add(prefix + suffix);
             }
             return variants;
@@ -349,9 +358,9 @@
                     return ", true)";
                 } else {
                     if (nodeType.adapter != null) {
-                        return ", " + nodeType.adapter + "," + !nodeType.cloneable + ")";
+                        return ", " + nodeType.adapter + "," + !nodeType.shareable + ")";
                     }
-                    if (nodeType.cloneable) {
+                    if (nodeType.shareable) {
                         return ", false)";
                     }
                 }
@@ -561,7 +570,7 @@
             // Define a TypeDescriptor the generic node but don't enter it into the nodeTypes table
             // since it shouldn't mentioned in match rules.
             TypeMirror mirror = processingEnv.getElementUtils().getTypeElement(ValueNode.class.getName()).asType();
-            valueType = new TypeDescriptor(mirror, "Value", ValueNode.class.getSimpleName(), ValueNode.class.getPackage().getName(), 0, null, false);
+            valueType = new TypeDescriptor(mirror, "Value", ValueNode.class.getSimpleName(), ValueNode.class.getPackage().getName(), 0, null, false, false);
 
             // Import default definitions
             processMatchableNode(processingEnv.getElementUtils().getTypeElement(GraalMatchableNodes.class.getName()));
@@ -644,7 +653,7 @@
                         nodeAdapter = String.format("new %s()", nodeAdapterMirror.toString());
                     }
 
-                    declareType(nodeClassMirror, shortName, nodeClass, nodePackage, matchable.inputs(), nodeAdapter, matchable.commutative(), element);
+                    declareType(nodeClassMirror, shortName, nodeClass, nodePackage, matchable.inputs(), nodeAdapter, matchable.commutative(), matchable.shareable(), element);
                 }
             } catch (Throwable t) {
                 reportExceptionThrow(element, t);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchableNode.java	Mon May 05 16:13:49 2014 -0700
@@ -57,4 +57,9 @@
      * patterns to be automatically generated.
      */
     boolean commutative() default false;
+
+    /**
+     * Can a node with multiple users be safely match by a rule.
+     */
+    boolean shareable() default false;
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java	Mon May 05 16:13:41 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotMatchableNodes.java	Mon May 05 16:13:49 2014 -0700
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.match.*;
 import com.oracle.graal.nodes.*;
 
@@ -29,8 +30,11 @@
 public class HotSpotMatchableNodes {
     public static class CompressionNodeAdapter extends MatchNodeAdapter {
         @Override
-        protected ValueNode getFirstInput(ValueNode node) {
-            return ((CompressionNode) node).getInput();
+        public ValueNode getInput(int input, ValueNode node) {
+            if (input == 0) {
+                return ((CompressionNode) node).getInput();
+            }
+            throw GraalInternalError.shouldNotReachHere();
         }
     }