LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_for.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 127 190 66.8 %
Date: 2024-10-04 20:04:04 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "opt_for.h"
      15             : 
      16             : #if 0
      17             : static InstrPtr
      18             : ReplaceWithNil(MalBlkPtr mb, InstrPtr p, int pos)
      19             : {
      20             :         p = pushNilBat(mb, p);  /* push at end */
      21             :         getArg(p, pos) = getArg(p, p->argc - 1);
      22             :         p->argc--;
      23             :         return p;
      24             : }
      25             : #endif
      26             : 
      27             : static bool
      28           1 : allConstExcept(MalBlkPtr mb, InstrPtr p, int except)
      29             : {
      30           2 :         for (int j = p->retc; j < p->argc; j++) {
      31           2 :                 if (j != except && getArgType(mb, p, j) >= TYPE_any)
      32             :                         return false;
      33             :         }
      34             :         return true;
      35             : }
      36             : 
      37             : str
      38      566241 : OPTforImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      39             : {
      40      566241 :         int i, j, k, limit, slimit;
      41      566241 :         InstrPtr p = 0, *old = NULL;
      42      566241 :         int actions = 0;
      43      566241 :         int *varisfor = NULL, *varforvalue = NULL;
      44      566241 :         str msg = MAL_SUCCEED;
      45             : 
      46      566241 :         (void) cntxt;
      47      566241 :         (void) stk;                                     /* to fool compilers */
      48             : 
      49      566241 :         if (mb->inlineProp)
      50           0 :                 goto wrapup;
      51             : 
      52      566241 :         limit = mb->stop;
      53             : 
      54    22436117 :         for (i = 0; i < limit; i++) {
      55    21869883 :                 p = mb->stmt[i];
      56    21869883 :                 if (p && p->retc == 1 && getModuleId(p) == forRef
      57          12 :                         && getFunctionId(p) == decompressRef) {
      58             :                         break;
      59             :                 }
      60             :         }
      61      566241 :         if (i == limit)
      62      566234 :                 goto wrapup;                    /* nothing to do */
      63             : 
      64           7 :         varisfor = GDKzalloc(2 * mb->vtop * sizeof(int));
      65           7 :         varforvalue = GDKzalloc(2 * mb->vtop * sizeof(int));
      66           7 :         if (varisfor == NULL || varforvalue == NULL)
      67           0 :                 goto wrapup;
      68             : 
      69           7 :         slimit = mb->ssize;
      70           7 :         old = mb->stmt;
      71           7 :         if (newMalBlkStmt(mb, mb->ssize) < 0) {
      72           0 :                 GDKfree(varisfor);
      73           0 :                 GDKfree(varforvalue);
      74           0 :                 throw(MAL, "optimizer.for", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      75             :         }
      76             :         // Consolidate the actual need for variables
      77         503 :         for (i = 0; i < limit; i++) {
      78         496 :                 p = old[i];
      79         496 :                 if (p == 0)
      80           0 :                         continue;                       //left behind by others?
      81         496 :                 if (p->retc == 1 && getModuleId(p) == forRef
      82           8 :                         && getFunctionId(p) == decompressRef) {
      83             :                         // remember we have encountered a for decompress function
      84           8 :                         k = getArg(p, 0);
      85           8 :                         varisfor[k] = getArg(p, 1);
      86           8 :                         varforvalue[k] = getArg(p, 2);
      87           8 :                         freeInstruction(p);
      88           8 :                         continue;
      89             :                 }
      90        1489 :                 int done = 0;
      91        1489 :                 for (j = p->retc; j < p->argc; j++) {
      92        1017 :                         k = getArg(p, j);
      93        1017 :                         if (varisfor[k]) {      // maybe we could delay this usage
      94          27 :                                 if (getModuleId(p) == algebraRef
      95          19 :                                         && getFunctionId(p) == projectionRef) {
      96             :                                         /* projection(cand, col) with col = for.decompress(o,min_val)
      97             :                                          * v1 = projection(cand, o)
      98             :                                          * for.decompress(v1, min_val) */
      99          14 :                                         InstrPtr r = copyInstruction(p);
     100          14 :                                         if (r == NULL) {
     101           0 :                                                 msg = createException(MAL, "optimizer.for",
     102             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     103           0 :                                                 break;
     104             :                                         }
     105          14 :                                         int tpe = getVarType(mb, varisfor[k]);
     106          14 :                                         int l = getArg(r, 0);
     107          14 :                                         getArg(r, 0) = newTmpVariable(mb, tpe);
     108          14 :                                         getArg(r, j) = varisfor[k];
     109          14 :                                         varisfor[l] = getArg(r, 0);
     110          14 :                                         varforvalue[l] = varforvalue[k];
     111          14 :                                         pushInstruction(mb, r);
     112          14 :                                         freeInstruction(p);
     113          14 :                                         done = 1;
     114          14 :                                         break;
     115          13 :                                 } else if (p->argc == 2 && p->retc == 1
     116           1 :                                                    && p->barrier == ASSIGNsymbol) {
     117             :                                         /* a = b */
     118           0 :                                         int l = getArg(p, 0);
     119           0 :                                         varisfor[l] = varisfor[k];
     120           0 :                                         varforvalue[l] = varforvalue[k];
     121           0 :                                         freeInstruction(p);
     122           0 :                                         done = 1;
     123           0 :                                         break;
     124          13 :                                 } else if (getModuleId(p) == algebraRef
     125           5 :                                                    && getFunctionId(p) == subsliceRef) {
     126             :                                         /* pos = subslice(col, l, h) with col = for.decompress(o,min_val)
     127             :                                          * pos = subslice(o, l, h) */
     128           0 :                                         InstrPtr r = copyInstruction(p);
     129           0 :                                         if (r == NULL) {
     130           0 :                                                 msg = createException(MAL, "optimizer.for",
     131             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     132           0 :                                                 break;
     133             :                                         }
     134           0 :                                         getArg(r, j) = varisfor[k];
     135           0 :                                         pushInstruction(mb, r);
     136           0 :                                         freeInstruction(p);
     137           0 :                                         done = 1;
     138           0 :                                         break;
     139          13 :                                 } else if ((getModuleId(p) == batRef
     140           0 :                                                         && getFunctionId(p) == mirrorRef)
     141          13 :                                                    || (getModuleId(p) == batcalcRef
     142           2 :                                                            && getFunctionId(p) == identityRef)) {
     143             :                                         /* id = mirror/identity(col) with col = for.decompress(o,min_val)
     144             :                                          * id = mirror/identity(o) */
     145           0 :                                         InstrPtr r = copyInstruction(p);
     146           0 :                                         if (r == NULL) {
     147           0 :                                                 msg = createException(MAL, "optimizer.for",
     148             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     149           0 :                                                 break;
     150             :                                         }
     151           0 :                                         getArg(r, j) = varisfor[k];
     152           0 :                                         pushInstruction(mb, r);
     153           0 :                                         freeInstruction(p);
     154           0 :                                         done = 1;
     155           0 :                                         break;
     156          13 :                                 } else if (getFunctionId(p) == thetaselectRef) {
     157             :                                         /* pos = thetaselect(col, cand, l, ...) with col = for.decompress(o, minval)
     158             :                                          * l = calc.-(l, minval);
     159             :                                          * nl = calc.bte(l);
     160             :                                          * or
     161             :                                          * nl = calc.sht(l);
     162             :                                          * pos = select(o, cand, nl,  ...) */
     163             : 
     164           1 :                                         InstrPtr q = newInstructionArgs(mb, calcRef, minusRef, 3);
     165           1 :                                         if (q == NULL) {
     166           0 :                                                 msg = createException(MAL, "optimizer.for",
     167             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     168           0 :                                                 break;
     169             :                                         }
     170           1 :                                         int tpe = getVarType(mb, getArg(p, 3));
     171           1 :                                         getArg(q, 0) = newTmpVariable(mb, tpe);
     172           1 :                                         q = pushArgument(mb, q, getArg(p, 3));
     173           1 :                                         q = pushArgument(mb, q, varforvalue[k]);
     174           1 :                                         pushInstruction(mb, q);
     175             : 
     176           1 :                                         InstrPtr r;
     177           1 :                                         tpe = getBatType(getVarType(mb, varisfor[k]));
     178           1 :                                         if (tpe == TYPE_bte)
     179           1 :                                                 r = newInstructionArgs(mb, calcRef, putName("bte"), 2);
     180             :                                         else
     181           0 :                                                 r = newInstructionArgs(mb, calcRef, putName("sht"), 2);
     182           1 :                                         if (r == NULL) {
     183           0 :                                                 msg = createException(MAL, "optimizer.for",
     184             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     185           0 :                                                 break;
     186             :                                         }
     187           1 :                                         getArg(r, 0) = newTmpVariable(mb, tpe);
     188           1 :                                         r = pushArgument(mb, r, getArg(q, 0));
     189           1 :                                         pushInstruction(mb, r);
     190             : 
     191           1 :                                         q = copyInstruction(p);
     192           1 :                                         if (q == NULL) {
     193           0 :                                                 msg = createException(MAL, "optimizer.for",
     194             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     195           0 :                                                 break;
     196             :                                         }
     197           1 :                                         getArg(q, j) = varisfor[k];
     198           1 :                                         getArg(q, 3) = getArg(r, 0);
     199           1 :                                         pushInstruction(mb, q);
     200           1 :                                         freeInstruction(p);
     201           1 :                                         done = 1;
     202           1 :                                         break;
     203             : #if 0
     204             :                                 } else if (getFunctionId(p) == selectRef && p->argc == 9) {
     205             :                                         /* select (c, s, l, h, li, hi, anti, unknown ) */
     206             :                                         InstrPtr r = newInstructionArgs(mb, dictRef, selectRef, 10);
     207             :                                         if (r == NULL) {
     208             :                                                 msg = createException(MAL, "optimizer.for",
     209             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     210             :                                                 break;
     211             :                                         }
     212             : 
     213             :                                         getArg(r, 0) = getArg(p, 0);
     214             :                                         r = pushArgument(mb, r, varisdict[k]);
     215             :                                         r = pushArgument(mb, r, getArg(p, 2));  /* cand */
     216             :                                         r = pushArgument(mb, r, vardictvalue[k]);
     217             :                                         r = pushArgument(mb, r, getArg(p, 3));  /* l */
     218             :                                         r = pushArgument(mb, r, getArg(p, 4));  /* h */
     219             :                                         r = pushArgument(mb, r, getArg(p, 5));  /* li */
     220             :                                         r = pushArgument(mb, r, getArg(p, 6));  /* hi */
     221             :                                         r = pushArgument(mb, r, getArg(p, 7));  /* anti */
     222             :                                         r = pushArgument(mb, r, getArg(p, 8));  /* unknown */
     223             :                                         pushInstruction(mb, r);
     224             :                                         freeInstruction(p);
     225             :                                         done = 1;
     226             :                                         break;
     227             :                                 } else if (isSelect(p)) {
     228             :                                         /* pos = select(col, cand, l, h, ...) with col = dict.decompress(o,u)
     229             :                                          * tp = select(u, nil, l, h, ...)
     230             :                                          * tp2 = batcalc.bte/sht/int(tp)
     231             :                                          * pos = intersect(o, tp2, cand, nil) */
     232             : 
     233             :                                         int cand = getArg(p, j + 1);
     234             :                                         InstrPtr r = copyInstruction(p);
     235             :                                         if (r == NULL) {
     236             :                                                 msg = createException(MAL, "optimizer.for",
     237             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     238             :                                                 break;
     239             :                                         }
     240             :                                         getArg(r, j) = vardictvalue[k];
     241             :                                         if (cand)
     242             :                                                 r = ReplaceWithNil(mb, r, j + 1);       /* no candidate list */
     243             :                                         pushInstruction(mb, r);
     244             : 
     245             :                                         int tpe = getVarType(mb, varisdict[k]);
     246             :                                         InstrPtr s = newInstructionArgs(mb, dictRef, putName("convert"), 3);
     247             :                                         if (s == NULL) {
     248             :                                                 msg = createException(MAL, "optimizer.for",
     249             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     250             :                                                 break;
     251             :                                         }
     252             :                                         getArg(s, 0) = newTmpVariable(mb, tpe);
     253             :                                         s = pushArgument(mb, s, getArg(r, 0));
     254             :                                         pushInstruction(mb, s);
     255             : 
     256             :                                         InstrPtr t = newInstructionArgs(mb, algebraRef, intersectRef, 9);
     257             :                                         if (t == NULL) {
     258             :                                                 msg = createException(MAL, "optimizer.for",
     259             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     260             :                                                 break;
     261             :                                         }
     262             :                                         getArg(t, 0) = getArg(p, 0);
     263             :                                         t = pushArgument(mb, t, varisdict[k]);
     264             :                                         t = pushArgument(mb, t, getArg(s, 0));
     265             :                                         t = pushArgument(mb, t, cand);
     266             :                                         t = pushNilBat(mb, t);
     267             :                                         t = pushBit(mb, t, TRUE);       /* nil matches */
     268             :                                         t = pushBit(mb, t, TRUE);       /* max_one */
     269             :                                         t = pushNil(mb, t, TYPE_lng);   /* estimate */
     270             :                                         pushInstruction(mb, t);
     271             :                                         freeInstruction(p);
     272             :                                         done = 1;
     273             :                                         break;
     274             : #endif
     275          12 :                                 } else if ((isMapOp(p) || isMap2Op(p))
     276           2 :                                                    && (getFunctionId(p) == plusRef
     277           2 :                                                            || getFunctionId(p) == minusRef) && p->argc > 2
     278           1 :                                                    && getBatType(getArgType(mb, p, 2)) != TYPE_oid
     279           1 :                                                    && allConstExcept(mb, p, j)) {
     280             :                                         /* filter out unary batcalc.- with and without a candidate list */
     281             :                                         /* batcalc.-(1, col) with col = for.decompress(o,min_val)
     282             :                                          * v1 = calc.-(1, min_val)
     283             :                                          * for.decompress(o, v1) */
     284             :                                         /* we assume binary operators only ! */
     285           0 :                                         InstrPtr r = newInstructionArgs(mb, calcRef, getFunctionId(p), 3);
     286           0 :                                         if (r == NULL) {
     287           0 :                                                 msg = createException(MAL, "optimizer.for",
     288             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     289           0 :                                                 break;
     290             :                                         }
     291           0 :                                         int tpe = getBatType(getVarType(mb, getArg(p, 0)));
     292           0 :                                         getArg(r, 0) = newTmpVariable(mb, tpe);
     293           0 :                                         int l = getArg(r, 0), m = getArg(p, 0);
     294           0 :                                         r = pushArgument(mb, r, getArg(p, 1));
     295           0 :                                         r = pushArgument(mb, r, getArg(p, 2));
     296           0 :                                         getArg(r, j) = varforvalue[k];
     297             : 
     298             :                                         /* new and old result are now min-values */
     299           0 :                                         varisfor[l] = varisfor[m] = varisfor[k];
     300           0 :                                         varforvalue[l] = varforvalue[m] = getArg(r, 0);
     301           0 :                                         pushInstruction(mb, r);
     302           0 :                                         freeInstruction(p);
     303           0 :                                         done = 1;
     304           0 :                                         break;
     305          12 :                                 } else if (getModuleId(p) == groupRef
     306           1 :                                                    && (getFunctionId(p) == subgroupRef
     307           1 :                                                            || getFunctionId(p) == subgroupdoneRef
     308           1 :                                                            || getFunctionId(p) == groupRef
     309           1 :                                                            || getFunctionId(p) == groupdoneRef)) {
     310             :                                         /* group.group[done](col) | group.subgroup[done](col, grp) with col = for.decompress(o,min_val)
     311             :                                          * v1 = group.group[done](o) | group.subgroup[done](o, grp) */
     312           1 :                                         int input = varisfor[k];
     313           1 :                                         InstrPtr r = copyInstruction(p);
     314           1 :                                         if (r == NULL) {
     315           0 :                                                 msg = createException(MAL, "optimizer.for",
     316             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     317           0 :                                                 break;
     318             :                                         }
     319           1 :                                         getArg(r, j) = input;
     320           1 :                                         pushInstruction(mb, r);
     321           1 :                                         freeInstruction(p);
     322           1 :                                         done = 1;
     323           1 :                                         break;
     324             :                                 } else {
     325             :                                         /* need to decompress */
     326          11 :                                         int tpe = getArgType(mb, p, j);
     327          11 :                                         InstrPtr r = newInstructionArgs(mb, forRef, decompressRef, 3);
     328          11 :                                         if (r == NULL) {
     329           0 :                                                 msg = createException(MAL, "optimizer.for",
     330             :                                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     331           0 :                                                 break;
     332             :                                         }
     333          11 :                                         getArg(r, 0) = newTmpVariable(mb, tpe);
     334          11 :                                         r = pushArgument(mb, r, varisfor[k]);
     335          11 :                                         r = pushArgument(mb, r, varforvalue[k]);
     336          11 :                                         pushInstruction(mb, r);
     337             : 
     338          11 :                                         getArg(p, j) = getArg(r, 0);
     339          11 :                                         actions++;
     340             :                                 }
     341             :                         }
     342             :                 }
     343           0 :                 if (msg)
     344             :                         break;
     345         488 :                 if (done)
     346          16 :                         actions++;
     347             :                 else
     348         472 :                         pushInstruction(mb, p);
     349             :         }
     350             : 
     351        1303 :         for (; i < slimit; i++)
     352        1296 :                 if (old[i])
     353           0 :                         freeInstruction(old[i]);
     354             :         /* Defense line against incorrect plans */
     355           7 :         if (msg == MAL_SUCCEED && actions > 0) {
     356           7 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     357           7 :                 if (!msg)
     358           7 :                         msg = chkFlow(mb);
     359           7 :                 if (!msg)
     360           7 :                         msg = chkDeclarations(mb);
     361             :         }
     362             :         /* keep all actions taken as a post block comment */
     363           0 :   wrapup:
     364             :         /* keep actions taken as a fake argument */
     365      566241 :         (void) pushInt(mb, pci, actions);
     366             : 
     367      566236 :         GDKfree(old);
     368      566236 :         GDKfree(varisfor);
     369      566234 :         GDKfree(varforvalue);
     370      566234 :         return msg;
     371             : }

Generated by: LCOV version 1.14