This is an automated email from the ASF dual-hosted git repository.

mboehm7 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/systemds.git


The following commit(s) were added to refs/heads/master by this push:
     new 87e4d50  [SYSTEMDS-2801] New rewrite for removing (par)for loops w/o 
iterations
87e4d50 is described below

commit 87e4d502205919f1e3ee9aeb7838731e677e6ef0
Author: Patrick Damme <[email protected]>
AuthorDate: Sat Jan 23 19:58:32 2021 +0100

    [SYSTEMDS-2801] New rewrite for removing (par)for loops w/o iterations
    
    This commit adds a new StatementBlockRewriteRule removing (par)for-loops
    which are known to iterate over an empty sequence, and, thus, will not
    perform a single iteration. This works if the loop's from, to, and
    increment are constants (possibly DML script arguments, and after
    constant folding). Furthermore, OptimizerUtils has a new flag
    determining whether this rule shall be applied. In ProgramRewriter's
    default rule sequence, this new rule is inserted directly after the
    removal of unnecessary branches, since they have a lot in common.
    Merging subsequent blocks is done once afterwards if any of removing
    unnecessary branches or removing (par)for-loops shall be applied.
    
    Closes #1165.
---
 .../java/org/apache/sysds/hops/OptimizerUtils.java | 10 +++
 .../apache/sysds/hops/rewrite/ProgramRewriter.java |  8 +-
 .../rewrite/RewriteRemoveForLoopEmptySequence.java | 79 +++++++++++++++++++
 .../runtime/controlprogram/ForProgramBlock.java    | 36 ++++-----
 .../runtime/controlprogram/ParForProgramBlock.java | 23 +++---
 .../sysds/runtime/controlprogram/ProgramBlock.java |  2 +-
 .../apache/sysds/runtime/util/UtilFunctions.java   | 11 ++-
 .../rewrite/RewriteForLoopRemovalTest.java         | 91 ++++++++++++++++++++++
 src/test/scripts/functions/rewrite/removal_for.dml | 28 +++++++
 .../scripts/functions/rewrite/removal_parfor.dml   | 28 +++++++
 10 files changed, 283 insertions(+), 33 deletions(-)

diff --git a/src/main/java/org/apache/sysds/hops/OptimizerUtils.java 
b/src/main/java/org/apache/sysds/hops/OptimizerUtils.java
index 2d94b59..c05eaa3 100644
--- a/src/main/java/org/apache/sysds/hops/OptimizerUtils.java
+++ b/src/main/java/org/apache/sysds/hops/OptimizerUtils.java
@@ -124,6 +124,13 @@ public class OptimizerUtils
         */
        public static boolean ALLOW_BRANCH_REMOVAL = true;
        
+       /**
+        * Enables the removal of (par)for-loops when from, to, and increment 
are constants
+        * (original literals or results of constant folding) and lead to an 
empty sequence,
+        * i.e., (par)for-loops without a single iteration.
+        */
+       public static boolean ALLOW_FOR_LOOP_REMOVAL = true;
+
        public static boolean ALLOW_AUTO_VECTORIZATION = true;
        
        /**
@@ -300,6 +307,7 @@ public class OptimizerUtils
                                ALLOW_INTER_PROCEDURAL_ANALYSIS = false;
                                IPA_NUM_REPETITIONS = 1;
                                ALLOW_BRANCH_REMOVAL = false;
+                               ALLOW_FOR_LOOP_REMOVAL = false;
                                ALLOW_SUM_PRODUCT_REWRITES = false;
                                break;
                        // opt level 1: memory-based (no advanced rewrites)     
@@ -312,6 +320,7 @@ public class OptimizerUtils
                                ALLOW_INTER_PROCEDURAL_ANALYSIS = false;
                                IPA_NUM_REPETITIONS = 1;
                                ALLOW_BRANCH_REMOVAL = false;
+                               ALLOW_FOR_LOOP_REMOVAL = false;
                                ALLOW_SUM_PRODUCT_REWRITES = false;
                                ALLOW_LOOP_UPDATE_IN_PLACE = false;
                                break;
@@ -366,6 +375,7 @@ public class OptimizerUtils
                ALLOW_ALGEBRAIC_SIMPLIFICATION = true;
                ALLOW_AUTO_VECTORIZATION = true;
                ALLOW_BRANCH_REMOVAL = true;
+               ALLOW_FOR_LOOP_REMOVAL = true;
                ALLOW_CONSTANT_FOLDING = true;
                ALLOW_COMMON_SUBEXPRESSION_ELIMINATION = true;
                ALLOW_INTER_PROCEDURAL_ANALYSIS = true;
diff --git a/src/main/java/org/apache/sysds/hops/rewrite/ProgramRewriter.java 
b/src/main/java/org/apache/sysds/hops/rewrite/ProgramRewriter.java
index af81e86..5127384 100644
--- a/src/main/java/org/apache/sysds/hops/rewrite/ProgramRewriter.java
+++ b/src/main/java/org/apache/sysds/hops/rewrite/ProgramRewriter.java
@@ -90,10 +90,12 @@ public class ProgramRewriter
                        _dagRuleSet.add( new 
RewriteInjectSparkPReadCheckpointing()          ); //dependency: reblock
                        
                        //add statement block rewrite rules
-                       if( OptimizerUtils.ALLOW_BRANCH_REMOVAL ) {
+                       if( OptimizerUtils.ALLOW_BRANCH_REMOVAL )
                                _sbRuleSet.add(  new 
RewriteRemoveUnnecessaryBranches()          ); //dependency: constant folding
-                               _sbRuleSet.add(  new 
RewriteMergeBlockSequence()                 ); //dependency: remove branches
-                       }
+                       if( OptimizerUtils.ALLOW_FOR_LOOP_REMOVAL )
+                               _sbRuleSet.add(  new 
RewriteRemoveForLoopEmptySequence()         ); //dependency: constant folding
+                       if( OptimizerUtils.ALLOW_BRANCH_REMOVAL || 
OptimizerUtils.ALLOW_FOR_LOOP_REMOVAL )
+                               _sbRuleSet.add(  new 
RewriteMergeBlockSequence()                 ); //dependency: remove branches, 
remove for-loops
                        _sbRuleSet.add(      new RewriteCompressedReblock()     
             ); // Compression Rewrite
                        if( OptimizerUtils.ALLOW_SPLIT_HOP_DAGS )
                                _sbRuleSet.add(  new 
RewriteSplitDagUnknownCSVRead()             ); //dependency: reblock, merge 
blocks
diff --git 
a/src/main/java/org/apache/sysds/hops/rewrite/RewriteRemoveForLoopEmptySequence.java
 
b/src/main/java/org/apache/sysds/hops/rewrite/RewriteRemoveForLoopEmptySequence.java
new file mode 100644
index 0000000..82b5f0f
--- /dev/null
+++ 
b/src/main/java/org/apache/sysds/hops/rewrite/RewriteRemoveForLoopEmptySequence.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysds.hops.rewrite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sysds.hops.Hop;
+import org.apache.sysds.hops.LiteralOp;
+import org.apache.sysds.parser.ForStatementBlock;
+import org.apache.sysds.parser.StatementBlock;
+import org.apache.sysds.runtime.util.UtilFunctions;
+
+/**
+ * Rule: Simplify program structure by removing (par)for statements iterating 
over
+ * an empty sequence, i.e., (par)for-loops without a single iteration.
+ */
+public class RewriteRemoveForLoopEmptySequence extends 
StatementBlockRewriteRule {
+
+       @Override
+       public boolean createsSplitDag() {
+               return false;
+       }
+
+       @Override
+       public List<StatementBlock> rewriteStatementBlock(StatementBlock sb, 
ProgramRewriteStatus state) {
+               ArrayList<StatementBlock> ret = new ArrayList<>();
+               boolean apply = false;
+               
+               if( sb instanceof ForStatementBlock ) {
+                       ForStatementBlock fsb = (ForStatementBlock) sb;
+                       
+                       //consider rewrite if the increment was specified
+                       Hop from = fsb.getFromHops().getInput().get(0);
+                       Hop to = fsb.getToHops().getInput().get(0);
+                       Hop incr = (fsb.getIncrementHops() != null) ?
+                               fsb.getIncrementHops().getInput().get(0) : new 
LiteralOp(1);
+                       
+                       //consider rewrite if from, to, and incr are literal 
ops (constant values)
+                       if( from instanceof LiteralOp && to instanceof 
LiteralOp && incr instanceof LiteralOp ) {
+                               double dfrom = 
HopRewriteUtils.getDoubleValue((LiteralOp) from);
+                               double dto = 
HopRewriteUtils.getDoubleValue((LiteralOp) to);
+                               double dincr = 
HopRewriteUtils.getDoubleValue((LiteralOp) incr);
+                               if( dfrom > dto && dincr == 1 )
+                                       dincr = -1;
+                               apply = UtilFunctions.getSeqLength(dfrom, dto, 
dincr, false) <= 0;
+                       }
+               }
+               
+               if(apply) //remove for-loop (add nothing)
+                       LOG.debug("Applied removeForLoopEmptySequence (lines 
"+sb.getBeginLine()+"-"+sb.getEndLine()+").");
+               else //keep original sb (no for)
+                       ret.add( sb );
+               
+               return ret;
+       }
+
+       @Override
+       public List<StatementBlock> rewriteStatementBlocks(List<StatementBlock> 
sbs, ProgramRewriteStatus state) {
+               return sbs;
+       }
+}
diff --git 
a/src/main/java/org/apache/sysds/runtime/controlprogram/ForProgramBlock.java 
b/src/main/java/org/apache/sysds/runtime/controlprogram/ForProgramBlock.java
index 4f6f552..4faadff 100644
--- a/src/main/java/org/apache/sysds/runtime/controlprogram/ForProgramBlock.java
+++ b/src/main/java/org/apache/sysds/runtime/controlprogram/ForProgramBlock.java
@@ -36,6 +36,7 @@ import org.apache.sysds.runtime.instructions.cp.IntObject;
 import org.apache.sysds.runtime.instructions.cp.ScalarObject;
 import org.apache.sysds.runtime.lineage.Lineage;
 import org.apache.sysds.runtime.lineage.LineageDedupUtils;
+import org.apache.sysds.runtime.util.UtilFunctions;
 
 public class ForProgramBlock extends ProgramBlock
 {
@@ -100,15 +101,16 @@ public class ForProgramBlock extends ProgramBlock
        @Override
        public void execute(ExecutionContext ec) {
                // evaluate from, to, incr only once (assumption: known at for 
entry)
-               IntObject from = executePredicateInstructions( 1, 
_fromInstructions, ec );
-               IntObject to   = executePredicateInstructions( 2, 
_toInstructions, ec );
-               IntObject incr = (_incrementInstructions == null || 
_incrementInstructions.isEmpty()) ? 
+               ScalarObject from = executePredicateInstructions( 1, 
_fromInstructions, ec, false);
+               ScalarObject to   = executePredicateInstructions( 2, 
_toInstructions, ec, false);
+               ScalarObject incr = (_incrementInstructions == null || 
_incrementInstructions.isEmpty()) ? 
                        new IntObject((from.getLongValue()<=to.getLongValue()) 
? 1 : -1) :
-                       executePredicateInstructions( 3, 
_incrementInstructions, ec );
+                       executePredicateInstructions( 3, 
_incrementInstructions, ec, false);
                
-               if ( incr.getLongValue() == 0 ) //would produce infinite loop
-                       throw new DMLRuntimeException(printBlockErrorLocation() 
+  "Expression for increment "
-                               + "of variable '" + _iterPredVar + "' must 
evaluate to a non-zero value.");
+               long numIterations = UtilFunctions.getSeqLength(
+                       from.getDoubleValue(), to.getDoubleValue(), 
incr.getDoubleValue(), false);
+               if( numIterations <= 0 )
+                       return;
                
                // execute for loop
                try
@@ -166,10 +168,10 @@ public class ForProgramBlock extends ProgramBlock
                executeExitInstructions(_exitInstruction, "for", ec);
        }
 
-       protected IntObject executePredicateInstructions( int pos, 
ArrayList<Instruction> instructions, ExecutionContext ec )
+       protected ScalarObject executePredicateInstructions( int pos, 
ArrayList<Instruction> instructions, ExecutionContext ec, boolean downCast )
        {
-               ScalarObject tmp = null;
-               IntObject ret = null;
+               ScalarObject ret = null;
+               ValueType vt = downCast ? ValueType.INT64 : null;
                
                try
                {
@@ -190,10 +192,10 @@ public class ForProgramBlock extends ProgramBlock
                                        predHops = fsb.getIncrementHops();
                                        recompile = 
fsb.requiresIncrementRecompilation();
                                }
-                               tmp = executePredicate(instructions, predHops, 
recompile, ValueType.INT64, ec);
+                               ret = executePredicate(instructions, predHops, 
recompile, vt, ec);
                        }
                        else
-                               tmp = executePredicate(instructions, null, 
false, ValueType.INT64, ec);
+                               ret = executePredicate(instructions, null, 
false, vt, ec);
                }
                catch(Exception ex) {
                        String predNameStr = null;
@@ -205,10 +207,8 @@ public class ForProgramBlock extends ProgramBlock
                }
                
                //final check of resulting int object (guaranteed to be 
non-null, see executePredicate)
-               if( tmp instanceof IntObject )
-                       ret = (IntObject)tmp;
-               else //downcast to int if necessary
-                       ret = new IntObject(tmp.getLongValue());
+               if(downCast && !(ret instanceof IntObject)) //downcast to int 
if necessary
+                       ret = new IntObject(ret.getLongValue());
                
                return ret;
        }
@@ -228,7 +228,7 @@ public class ForProgramBlock extends ProgramBlock
                private long _incr = -1;
                private boolean _inuse = false;
                
-               protected SequenceIterator(IntObject from, IntObject to, 
IntObject incr) {
+               protected SequenceIterator(ScalarObject from, ScalarObject to, 
ScalarObject incr) {
                        _cur = from.getLongValue();
                        _to = to.getLongValue();
                        _incr = incr.getLongValue();
@@ -259,4 +259,4 @@ public class ForProgramBlock extends ProgramBlock
                        throw new RuntimeException("Unsupported remove on 
iterator.");
                }
        }
-}
\ No newline at end of file
+}
diff --git 
a/src/main/java/org/apache/sysds/runtime/controlprogram/ParForProgramBlock.java 
b/src/main/java/org/apache/sysds/runtime/controlprogram/ParForProgramBlock.java
index d95512f..f11d795 100644
--- 
a/src/main/java/org/apache/sysds/runtime/controlprogram/ParForProgramBlock.java
+++ 
b/src/main/java/org/apache/sysds/runtime/controlprogram/ParForProgramBlock.java
@@ -77,6 +77,7 @@ import org.apache.sysds.runtime.instructions.cp.Data;
 import org.apache.sysds.runtime.instructions.cp.DoubleObject;
 import org.apache.sysds.runtime.instructions.cp.IntObject;
 import org.apache.sysds.runtime.instructions.cp.ListObject;
+import org.apache.sysds.runtime.instructions.cp.ScalarObject;
 import org.apache.sysds.runtime.instructions.cp.StringObject;
 import org.apache.sysds.runtime.instructions.cp.VariableCPInstruction;
 import org.apache.sysds.runtime.lineage.Lineage;
@@ -558,22 +559,26 @@ public class ParForProgramBlock extends ForProgramBlock
                ParForStatementBlock sb = 
(ParForStatementBlock)getStatementBlock();
 
                // evaluate from, to, incr only once (assumption: known at for 
entry)
-               IntObject from = executePredicateInstructions( 1, 
_fromInstructions, ec );
-               IntObject to   = executePredicateInstructions( 2, 
_toInstructions, ec );
-               IntObject incr = (_incrementInstructions == null || 
_incrementInstructions.isEmpty()) ? 
-                       new IntObject((from.getLongValue()<=to.getLongValue()) 
? 1 : -1) :
-                       executePredicateInstructions( 3, 
_incrementInstructions, ec );
+               ScalarObject from0 = executePredicateInstructions(1, 
_fromInstructions, ec, false);
+               ScalarObject to0   = executePredicateInstructions(2, 
_toInstructions, ec, false);
+               ScalarObject incr0 = (_incrementInstructions == null || 
_incrementInstructions.isEmpty()) ? 
+                       new 
IntObject((from0.getLongValue()<=to0.getLongValue()) ? 1 : -1) :
+                       executePredicateInstructions( 3, 
_incrementInstructions, ec, false);
                
-               if ( incr.getLongValue() == 0 ) //would produce infinite loop
+               if ( incr0.getLongValue() == 0 ) //would produce infinite loop
                        throw new 
DMLRuntimeException(this.printBlockErrorLocation() + "Expression for increment "
                                + "of variable '" + _iterPredVar + "' must 
evaluate to a non-zero value.");
                
-               //early exit on num iterations = zero
-               _numIterations = UtilFunctions.getSeqLength(
-                       from.getDoubleValue(), to.getDoubleValue(), 
incr.getDoubleValue());
+               //early exit on num iterations (e.g., for invalid loop bounds)
+               _numIterations = UtilFunctions.getSeqLength( 
+                       from0.getDoubleValue(), to0.getDoubleValue(), 
incr0.getDoubleValue(), false);
                if( _numIterations <= 0 )
                        return; //avoid unnecessary optimization/initialization
                
+               IntObject from = new IntObject(from0.getLongValue());
+               IntObject to = new IntObject(to0.getLongValue());
+               IntObject incr = new IntObject(incr0.getLongValue());
+               
                ///////
                //OPTIMIZATION of ParFOR body (incl all child parfor PBs)
                ///////
diff --git 
a/src/main/java/org/apache/sysds/runtime/controlprogram/ProgramBlock.java 
b/src/main/java/org/apache/sysds/runtime/controlprogram/ProgramBlock.java
index a555a5d..0ee6553 100644
--- a/src/main/java/org/apache/sysds/runtime/controlprogram/ProgramBlock.java
+++ b/src/main/java/org/apache/sysds/runtime/controlprogram/ProgramBlock.java
@@ -217,7 +217,7 @@ public abstract class ProgramBlock implements ParseInfo
                ScalarObject ret = ec.getScalarInput(PRED_VAR, retType, false);
 
                //check and correct scalar ret type (incl save double to int)
-               if( ret.getValueType() != retType )
+               if( retType != null && retType != ret.getValueType() )
                        switch( retType ) {
                                case BOOLEAN: ret = new 
BooleanObject(ret.getBooleanValue()); break;
                                case INT64:   ret = new 
IntObject(ret.getLongValue()); break;
diff --git a/src/main/java/org/apache/sysds/runtime/util/UtilFunctions.java 
b/src/main/java/org/apache/sysds/runtime/util/UtilFunctions.java
index 5c8ed95..6f578c4 100644
--- a/src/main/java/org/apache/sysds/runtime/util/UtilFunctions.java
+++ b/src/main/java/org/apache/sysds/runtime/util/UtilFunctions.java
@@ -405,9 +405,12 @@ public class UtilFunctions {
                //a very small increment. Hence, we use a different formulation 
                //that exhibits better numerical stability by avoiding the 
subtraction
                //of numbers of different magnitude.
-               if( check && (Double.isNaN(from) || Double.isNaN(to) || 
Double.isNaN(incr) 
+               if( (isSpecial(from) || isSpecial(to) || isSpecial(incr) 
                        || (from > to && incr > 0) || (from < to && incr < 0)) 
) {
-                       throw new RuntimeException("Invalid seq parameters: 
("+from+", "+to+", "+incr+")");
+                       if( check )
+                               throw new RuntimeException("Invalid seq 
parameters: ("+from+", "+to+", "+incr+")");
+                       else
+                               return 0; // invalid loop configuration
                }
                return 1L + (long) Math.floor(to/incr - from/incr);
        }
@@ -590,6 +593,10 @@ public class UtilFunctions {
                return true;
        }
        
+       public static boolean isSpecial(double value) {
+               return Double.isNaN(value) || Double.isInfinite(value);
+       }
+       
        public static int[] getSortedSampleIndexes(int range, int sampleSize) {
                return getSortedSampleIndexes(range, sampleSize, -1);
        }
diff --git 
a/src/test/java/org/apache/sysds/test/functions/rewrite/RewriteForLoopRemovalTest.java
 
b/src/test/java/org/apache/sysds/test/functions/rewrite/RewriteForLoopRemovalTest.java
new file mode 100644
index 0000000..1187948
--- /dev/null
+++ 
b/src/test/java/org/apache/sysds/test/functions/rewrite/RewriteForLoopRemovalTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sysds.test.functions.rewrite;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.sysds.hops.OptimizerUtils;
+import org.apache.sysds.test.AutomatedTestBase;
+import org.apache.sysds.test.TestConfiguration;
+import org.apache.sysds.utils.Statistics;
+
+public class RewriteForLoopRemovalTest extends AutomatedTestBase
+{
+       private final static String TEST_NAME1 = "removal_for";
+       private final static String TEST_NAME2 = "removal_parfor";
+       private final static String TEST_DIR = "functions/rewrite/";
+       private final static String TEST_CLASS_DIR = TEST_DIR + 
RewriteForLoopRemovalTest.class.getSimpleName() + "/";
+       
+       private final static int rows = 10;
+       private final static int cols = 15;
+       
+       @Override
+       public void setUp() {
+               addTestConfiguration(TEST_NAME1, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME1, new String[] {"R"}) );
+               addTestConfiguration(TEST_NAME2, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME2, new String[] {"R"}) );
+       }
+       
+       @Test
+       public void runForLoopRemovalTest() {
+               runLoopRemovalTest(TEST_NAME1, true);
+       }
+       
+       @Test
+       public void runParForLoopRemovalTest() {
+               runLoopRemovalTest(TEST_NAME2, true);
+       }
+       
+       @Test
+       public void runForLoopRemovalNoRewriteTest() {
+               runLoopRemovalTest(TEST_NAME1, false);
+       }
+       
+       @Test
+       public void runParForLoopRemovalNoRewriteTest() {
+               runLoopRemovalTest(TEST_NAME2, false);
+       }
+       
+       private void runLoopRemovalTest(String testname, boolean rewrites)
+       {
+               boolean rewritesOld = OptimizerUtils.ALLOW_FOR_LOOP_REMOVAL;
+               OptimizerUtils.ALLOW_FOR_LOOP_REMOVAL = rewrites;
+               
+               try {
+                       TestConfiguration config = 
getTestConfiguration(testname);
+                       loadTestConfiguration(config);
+                       
+                       String HOME = SCRIPT_DIR + TEST_DIR;
+                       fullDMLScriptName = HOME + testname + ".dml";
+                       programArgs = new String[]{"-explain", "-stats", 
"-args",
+                               Integer.toString(rows), Integer.toString(cols)};
+                       
+                       runTest(true, false, null, -1);
+                       
+                       //check for applied rewrite (which enabled CSE of sum)
+                       long cnt = Statistics.getCPHeavyHitterCount("uak+");
+                       long expected = rewrites ? 1 : 2;
+                       Assert.assertEquals(expected, cnt);
+               }
+               finally {
+                       OptimizerUtils.ALLOW_FOR_LOOP_REMOVAL = rewritesOld;
+               }
+       }
+}
diff --git a/src/test/scripts/functions/rewrite/removal_for.dml 
b/src/test/scripts/functions/rewrite/removal_for.dml
new file mode 100644
index 0000000..6da6588
--- /dev/null
+++ b/src/test/scripts/functions/rewrite/removal_for.dml
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = rand(rows=$1, cols=$2);
+print(sum(X));
+
+for(i in seq(NaN,1))
+  print("Iteration "+i)
+
+print(sum(X))
diff --git a/src/test/scripts/functions/rewrite/removal_parfor.dml 
b/src/test/scripts/functions/rewrite/removal_parfor.dml
new file mode 100644
index 0000000..2c32c5f
--- /dev/null
+++ b/src/test/scripts/functions/rewrite/removal_parfor.dml
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+X = rand(rows=$1, cols=$2);
+print(sum(X));
+
+parfor(i in seq(NaN,1))
+  print("Iteration "+i)
+
+print(sum(X))

Reply via email to