< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java

Print this page
rev 56282 : [mq]: graal

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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.

@@ -68,25 +68,28 @@
     }
 
     /**
      * Get a property of an induction variable.
      */
-    private static int get(@SuppressWarnings("unused") IVProperty property, @SuppressWarnings("unused") StaticIVProperty staticProperty, @SuppressWarnings("unused") IVPredicate constantCheck,
-                    int iv) {
+    @SuppressWarnings("unused")
+    private static int get(IVProperty property, StaticIVProperty staticProperty, IVPredicate constantCheck, int iv) {
         return iv;
     }
 
-    private static int get(@SuppressWarnings("unused") IVProperty property, int iv) {
+    @SuppressWarnings("unused")
+    private static int get(IVProperty property, int iv) {
         return iv;
     }
 
-    private static long get(@SuppressWarnings("unused") IVProperty property, @SuppressWarnings("unused") StaticIVProperty staticProperty, @SuppressWarnings("unused") IVPredicate constantCheck,
+    @SuppressWarnings("unused")
+    private static long get(IVProperty property, StaticIVProperty staticProperty, IVPredicate constantCheck,
                     long iv) {
         return iv;
     }
 
-    private static long get(@SuppressWarnings("unused") IVProperty property, long iv) {
+    @SuppressWarnings("unused")
+    private static long get(IVProperty property, long iv) {
         return iv;
     }
 
     private static class Result {
         public long extremum;

@@ -148,16 +151,16 @@
         testCounted("incrementSnippet", -10, 1, Integer.MAX_VALUE);
     }
 
     @Test
     public void increment5() {
-        testCounted("incrementSnippet", 256, 256, 1);
+        testRemovableCounted("incrementSnippet", 256, 256, 1);
     }
 
     @Test
     public void increment6() {
-        testCounted("incrementSnippet", 257, 256, 1);
+        testRemovableCounted("incrementSnippet", 257, 256, 1);
     }
 
     @Test
     public void increment7() {
         testCounted("incrementSnippet", -10, Integer.MAX_VALUE, 1);

@@ -205,11 +208,11 @@
         testCounted("incrementEqSnippet", 256, 256, 1);
     }
 
     @Test
     public void incrementEq6() {
-        testCounted("incrementEqSnippet", 257, 256, 1);
+        testRemovableCounted("incrementEqSnippet", 257, 256, 1);
     }
 
     @Test
     public void incrementEq7() {
         testCounted("incrementEqSnippet", -10, Integer.MAX_VALUE - 1, 1);

@@ -218,10 +221,20 @@
     @Test
     public void incrementEq8() {
         testCounted("incrementEqSnippet", -10, Integer.MAX_VALUE - 2, 2);
     }
 
+    @Test
+    public void incrementEq9() {
+        testCounted("incrementEqSnippet", 0, 0, 1);
+    }
+
+    @Test
+    public void incrementEq10() {
+        testCounted("incrementEqSnippet", 0, 0, 3);
+    }
+
     public static Result decrementSnippet(int start, int limit, int step) {
         int i;
         int dec = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive
         Result ret = new Result();
         for (i = start; i > limit; i -= dec) {

@@ -284,11 +297,11 @@
         testCounted("decrementEqSnippet", 256, 0, 3);
     }
 
     @Test
     public void decrementEq4() {
-        testCounted("decrementEqSnippet", -10, 0, Integer.MAX_VALUE);
+        testRemovableCounted("decrementEqSnippet", -10, 0, Integer.MAX_VALUE);
     }
 
     @Test
     public void decrementEq5() {
         testCounted("decrementEqSnippet", Integer.MAX_VALUE, -10, 1);

@@ -297,10 +310,20 @@
     @Test
     public void decrementEq6() {
         testCounted("decrementEqSnippet", Integer.MAX_VALUE, -10, 2);
     }
 
+    @Test
+    public void decrementEq7() {
+        testCounted("decrementEqSnippet", 10, 10, 1);
+    }
+
+    @Test
+    public void decrementEq8() {
+        testCounted("decrementEqSnippet", 10, 10, 3);
+    }
+
     public static Result twoVariablesSnippet() {
         Result ret = new Result();
         int j = 0;
         for (int i = 0; i < 1024; i++) {
             j += 5;

@@ -382,50 +405,180 @@
         testCounted("incrementLongSnippet", -10L, 1L, Long.MAX_VALUE);
     }
 
     @Test
     public void incrementLong5() {
-        testCounted("incrementLongSnippet", 256L, 256L, 1L);
+        testRemovableCounted("incrementLongSnippet", 256L, 256L, 1L);
     }
 
     @Test
     public void incrementLong6() {
-        testCounted("incrementLongSnippet", 257L, 256L, 1L);
+        testRemovableCounted("incrementLongSnippet", 257L, 256L, 1L);
+    }
+
+    public static Result incrementUnsignedSnippet(int start, int limit, int step) {
+        int i;
+        int inc = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive
+        Result ret = new Result();
+        for (i = start; Integer.compareUnsigned(i, limit) < 0; i += inc) {
+            GraalDirectives.controlFlowAnchor();
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
+        }
+        ret.exitValue = get(InductionVariable::exitValueNode, i);
+        return ret;
+    }
+
+    @Test
+    public void incrementUnsigned1() {
+        testCounted("incrementUnsignedSnippet", 0, 256, 1);
+    }
+
+    @Test
+    public void incrementUnsigned2() {
+        testCounted("incrementUnsignedSnippet", 0, 256, 2);
+    }
+
+    @Test
+    public void incrementUnsigned3() {
+        testCounted("incrementUnsignedSnippet", 0, 256, 3);
+    }
+
+    @Test
+    public void incrementUnsigned4() {
+        testCounted("incrementUnsignedSnippet", 1, Integer.MAX_VALUE + 10, Integer.MAX_VALUE);
+    }
+
+    @Test
+    public void incrementUnsigned5() {
+        testRemovableCounted("incrementUnsignedSnippet", 256, 256, 1);
+    }
+
+    @Test
+    public void incrementUnsigned6() {
+        testRemovableCounted("incrementUnsignedSnippet", 257, 256, 1);
+    }
+
+    @Test
+    public void incrementUnsigned7() {
+        testCounted("incrementUnsignedSnippet", 0, Integer.MAX_VALUE + 10, 1);
+    }
+
+    @Test
+    public void incrementUnsigned8a() {
+        testCounted("incrementUnsignedSnippet", 0, Integer.MAX_VALUE + 11, 2);
+    }
+
+    @Test
+    public void incrementUnsigned8b() {
+        testCounted("incrementUnsignedSnippet", 0, Integer.MAX_VALUE + 10, 2);
+    }
+
+    @Test
+    public void incrementUnsigned9() {
+        testCounted("incrementUnsignedSnippet", Integer.MAX_VALUE - 1, Integer.MAX_VALUE + 10, 1);
+    }
+
+    @Test
+    public void incrementUnsigned10() {
+        testCounted("incrementUnsignedSnippet", Integer.MAX_VALUE - 1, Integer.MAX_VALUE + 10, 2);
+    }
+
+    public static Result decrementUnsignedSnippet(int start, int limit, int step) {
+        int dec = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive
+        Result ret = new Result();
+        int i;
+        for (i = start; Integer.compareUnsigned(i, limit) > 0; i -= dec) {
+            GraalDirectives.controlFlowAnchor();
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
+        }
+        ret.exitValue = get(InductionVariable::exitValueNode, i);
+        return ret;
+    }
+
+    @Test
+    public void decrementUnsigned1() {
+        testCounted("decrementUnsignedSnippet", 256, 0, 1);
+    }
+
+    @Test
+    public void decrementUnsigned2() {
+        testCounted("decrementUnsignedSnippet", 256, 0, 2);
+    }
+
+    @Test
+    public void decrementUnsigned3() {
+        testCounted("decrementUnsignedSnippet", 256, 2, 3);
+    }
+
+    @Test
+    public void decrementUnsigned5() {
+        testRemovableCounted("decrementUnsignedSnippet", 256, 256, 1);
+    }
+
+    @Test
+    public void decrementUnsigned6() {
+        testRemovableCounted("decrementUnsignedSnippet", 256, 257, 1);
+    }
+
+    @Test
+    public void decrementUnsigned7() {
+        testCounted("decrementUnsignedSnippet", Integer.MAX_VALUE + 10, 0, 1);
+    }
+
+    @Test
+    public void decrementUnsigned8() {
+        testCounted("decrementUnsignedSnippet", Integer.MAX_VALUE + 11, 0, 2);
+    }
+
+    @Test
+    public void decrementUnsigned9() {
+        testCounted("decrementUnsignedSnippet", Integer.MAX_VALUE + 10, Integer.MAX_VALUE - 1, 1);
+    }
+
+    @Test
+    public void decrementUnsigned10() {
+        testCounted("decrementUnsignedSnippet", Integer.MAX_VALUE + 10, Integer.MAX_VALUE - 1, 2);
     }
 
     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
     private static class IVPropertyNode extends FloatingNode implements LIRLowerable {
-
         public static final NodeClass<IVPropertyNode> TYPE = NodeClass.create(IVPropertyNode.class);
 
         private final IVProperty property;
         private final StaticIVProperty staticProperty;
         private final IVPredicate staticCheck;
+        private final boolean loopCanBeRemoved;
         @Input private ValueNode iv;
 
-        protected IVPropertyNode(IVProperty property, StaticIVProperty staticProperty, IVPredicate staticCheck, ValueNode iv) {
+        protected IVPropertyNode(IVProperty property, StaticIVProperty staticProperty, IVPredicate staticCheck, ValueNode iv, boolean loopCanBeRemoved) {
             super(TYPE, iv.stamp(NodeView.DEFAULT).unrestricted());
             this.property = property;
             this.staticProperty = staticProperty;
             this.staticCheck = staticCheck;
             this.iv = iv;
+            this.loopCanBeRemoved = loopCanBeRemoved;
         }
 
         public void rewrite(LoopsData loops) {
             InductionVariable inductionVariable = loops.getInductionVariable(iv);
-            assert inductionVariable != null;
-            assertTrue(inductionVariable.getLoop().isCounted(), "must be counted");
             ValueNode node = null;
+            if (inductionVariable == null) {
+                assert loopCanBeRemoved;
+                assert loops.loops().isEmpty();
+                node = iv;
+            } else {
+                assertTrue(inductionVariable.getLoop().isCounted(), "must be counted");
             if (staticCheck != null) {
                 assert staticProperty != null;
                 if (staticCheck.test(inductionVariable)) {
                     node = ConstantNode.forLong(staticProperty.get(inductionVariable), graph());
                 }
             }
             if (node == null) {
                 node = property.get(inductionVariable);
             }
+            }
             replaceAtUsagesAndDelete(node);
         }
 
         @Override
         public void generate(NodeLIRBuilderTool gen) {

@@ -448,11 +601,11 @@
                 IVProperty property = null;
                 if (arg1.isConstant()) {
                     property = getSnippetReflection().asObject(IVProperty.class, arg1.asJavaConstant());
                 }
                 if (property != null) {
-                    b.addPush(ivKind, new IVPropertyNode(property, null, null, arg2));
+                    b.addPush(ivKind, new IVPropertyNode(property, null, null, arg2, loopCanBeRemoved));
                     return true;
                 } else {
                     return false;
                 }
             }

@@ -471,11 +624,11 @@
                 }
                 if (arg3.isConstant()) {
                     staticCheck = getSnippetReflection().asObject(IVPredicate.class, arg3.asJavaConstant());
                 }
                 if (property != null && staticProperty != null && staticCheck != null) {
-                    b.addPush(ivKind, new IVPropertyNode(property, staticProperty, staticCheck, arg4));
+                    b.addPush(ivKind, new IVPropertyNode(property, staticProperty, staticCheck, arg4, loopCanBeRemoved));
                     return true;
                 } else {
                     return false;
                 }
             }

@@ -497,18 +650,42 @@
         // Don't convert unreached paths into Guard
         return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE);
     }
 
     private Object[] argsToBind;
+    private boolean loopCanBeRemoved;
 
     @Override
     protected Object[] getArgumentToBind() {
         return argsToBind;
     }
 
     public void testCounted(String snippetName, Object... args) {
+        this.loopCanBeRemoved = false;
+        test(snippetName, args);
+        this.argsToBind = args;
+        test(snippetName, args);
+        this.argsToBind = null;
+    }
+
+    public void testCounted(String snippetName, Object start, Object limit, Object step) {
+        testCounted(false, snippetName, start, limit, step);
+    }
+
+    public void testRemovableCounted(String snippetName, Object start, Object limit, Object step) {
+        testCounted(true, snippetName, start, limit, step);
+    }
+
+    public void testCounted(boolean removable, String snippetName, Object start, Object limit, Object step) {
+        this.loopCanBeRemoved = removable;
+        Object[] args = {start, limit, step};
+        test(snippetName, args);
+        this.argsToBind = args;
+        test(snippetName, args);
+        this.argsToBind = new Object[]{NO_BIND, NO_BIND, step};
         test(snippetName, args);
-        argsToBind = args;
+        this.argsToBind = new Object[]{start, NO_BIND, step};
         test(snippetName, args);
-        argsToBind = null;
+        this.argsToBind = null;
+        this.loopCanBeRemoved = false;
     }
 }
< prev index next >