Przeglądaj źródła

HPCC-10534 Optimize IF(PROJECT, PROJECT)

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 11 lat temu
rodzic
commit
db9d7a6321

+ 2 - 0
ecl/hql/hqlatoms.cpp

@@ -80,6 +80,7 @@ IAtom * assertConstAtom;
 IAtom * atmostAtom;
 IAtom * aveAtom;
 IAtom * backupAtom;
+IAtom * balancedAtom;
 IAtom * bcdAtom;
 IAtom * beforeAtom;
 IAtom * bestAtom;
@@ -485,6 +486,7 @@ MODULE_INIT(INIT_PRIORITY_HQLATOM)
     MAKEATOM(atmost);
     MAKEATOM(ave);
     MAKEATOM(backup);
+    MAKEATOM(balanced);
     MAKEATOM(bcd);
     MAKEATOM(before);
     MAKEATOM(best);

+ 1 - 0
ecl/hql/hqlatoms.hpp

@@ -82,6 +82,7 @@ extern HQL_API IAtom * assertConstAtom;
 extern HQL_API IAtom * atmostAtom;
 extern HQL_API IAtom * aveAtom;
 extern HQL_API IAtom * backupAtom;
+extern HQL_API IAtom * balancedAtom;
 extern HQL_API IAtom * bcdAtom;
 extern HQL_API IAtom * beforeAtom;
 extern HQL_API IAtom * bestAtom;

+ 63 - 1
ecl/hql/hqlopt.cpp

@@ -758,6 +758,54 @@ IHqlExpression * CTreeOptimizer::optimizeDatasetIf(IHqlExpression * transformed)
     return LINK(transformed);
 }
 
+static bool branchesMatch(IHqlExpression * left, IHqlExpression * right)
+{
+    if (left->queryBody() == right->queryBody())
+        return true;
+
+    node_operator leftOp = left->getOperator();
+    if (leftOp != right->getOperator())
+        return false;
+
+    switch (leftOp)
+    {
+    case no_hqlproject:
+    case no_newusertable:
+        break;
+    default:
+        return false;
+    }
+    if (left->numChildren() != right->numChildren())
+        return false;
+
+    //Check for the situation where the only difference between two projects is the selector sequence
+    ForEachChild(i, left)
+    {
+        IHqlExpression * curLeft = left->queryChild(i);
+        if (curLeft->isAttribute() && (curLeft->queryName() == _selectorSequence_Atom))
+            continue;
+        IHqlExpression * curRight = right->queryChild(i);
+        if (curLeft->queryBody() != curRight->queryBody())
+        {
+            //The following code allows LEFT to be referred to within the transform, but I don't think it is worth enabling
+            //because of the potential cost of replacing the selseq within the transform.
+            if (false)
+            {
+                if ((leftOp != no_hqlproject) || !curLeft->isTransform())
+                    return false;
+                if (!recordTypesMatch(curLeft,curRight))
+                    return false;
+                OwnedHqlExpr newTransform = replaceExpression(curLeft, querySelSeq(left), querySelSeq(right));
+                if (newTransform->queryBody() != curRight->queryBody())
+                    return false;
+            }
+
+            return false;
+        }
+    }
+    return true;
+}
+
 IHqlExpression * CTreeOptimizer::optimizeIf(IHqlExpression * expr)
 {
     IHqlExpression * trueExpr = expr->queryChild(1);
@@ -766,7 +814,7 @@ IHqlExpression * CTreeOptimizer::optimizeIf(IHqlExpression * expr)
     if (!falseExpr)
         return NULL;
 
-    if (trueExpr->queryBody() == falseExpr->queryBody())
+    if (branchesMatch(trueExpr, falseExpr))
     {
         noteUnused(trueExpr);       // inherit usage() will increase the usage again
         noteUnused(falseExpr);
@@ -2538,6 +2586,20 @@ IHqlExpression * CTreeOptimizer::doCreateTransformed(IHqlExpression * transforme
             return createDataset(no_hqlproject, args);
         }
         break;
+    case no_split:
+        node_operator childOp = child->getOperator();
+        if (childOp == no_split)
+        {
+            //Don't convert an unbalanced splitter into a balanced splitter
+            //- best would be to set unbalanced on the child, but that would require more complication.
+            if (transformed->hasAttribute(balancedAtom) || !child->hasAttribute(balancedAtom))
+                return removeParentNode(transformed);
+        }
+
+        //This would remove splits only used once, but dangerous if we ever get the usage counting wrong...
+        //if (queryBodyExtra(transformed)->useCount == 1)
+        //    return removeParentNode(transformed);
+        break;
     }
 
     bool shared = childrenAreShared(transformed);

+ 0 - 2
ecl/hqlcpp/hqlcatom.cpp

@@ -32,7 +32,6 @@ IAtom * activeMatchUtf8Atom;
 IAtom * activeProductionMarkerAtom;
 IAtom * activeValidateMarkerAtom;
 IAtom * activityIdMarkerAtom;
-IAtom * balancedAtom;
 IAtom * bitfieldOffsetAtom;
 IAtom * blobHelperAtom;
 IAtom * branchAtom;
@@ -1406,7 +1405,6 @@ MODULE_INIT(INIT_PRIORITY_HQLATOM-1)
     MAKEATOM(activeProductionMarker);
     MAKEATOM(activeValidateMarker);
     MAKEATOM(activityIdMarker);
-    MAKEATOM(balanced);
     MAKEATOM(bitfieldOffset);
     MAKEATOM(blobHelper);
     MAKEATOM(branch);

+ 0 - 1
ecl/hqlcpp/hqlcatom.hpp

@@ -32,7 +32,6 @@ extern IAtom * activeMatchUtf8Atom;
 extern IAtom * activeProductionMarkerAtom;
 extern IAtom * activeValidateMarkerAtom;
 extern IAtom * activityIdMarkerAtom;
-extern IAtom * balancedAtom;
 extern IAtom * bitfieldOffsetAtom;
 extern IAtom * blobHelperAtom;
 extern IAtom * branchAtom;