LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_inline.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 89 108 82.4 %
Date: 2024-10-03 20:03:20 Functions: 3 4 75.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_inline.h"
      15             : 
      16             : #define MAXEXPANSION 256
      17             : 
      18             : int
      19         521 : inlineMALblock(MalBlkPtr mb, int pc, MalBlkPtr mc)
      20             : {
      21         521 :         int i, k, l, n;
      22         521 :         InstrPtr *ns, p, q;
      23         521 :         int *nv;
      24             : 
      25         521 :         p = getInstrPtr(mb, pc);
      26         521 :         q = getInstrPtr(mc, 0);
      27         521 :         ns = GDKzalloc((l = (mb->ssize + mc->ssize + p->retc - 3)) * sizeof(InstrPtr));
      28         521 :         if (ns == NULL)
      29             :                 return -1;
      30         521 :         nv = (int *) GDKmalloc(mc->vtop * sizeof(int));
      31         521 :         if (nv == 0) {
      32           0 :                 GDKfree(ns);
      33           0 :                 return -1;
      34             :         }
      35             : 
      36             :         /* add all variables of the new block to the target environment */
      37       27874 :         for (n = 0; n < mc->vtop; n++) {
      38       27353 :                 char *nme = mc->var[n].name;
      39       27353 :                 if (nme && isExceptionVariable(nme)) {
      40           1 :                         nv[n] = newVariable(mb, nme, strlen(nme), TYPE_str);
      41       27352 :                 } else if (isVarTypedef(mc, n)) {
      42           1 :                         nv[n] = newTypeVariable(mb, getVarType(mc, n));
      43       27351 :                 } else if (isVarConstant(mc, n)) {
      44        3318 :                         nv[n] = cpyConstant(mb, getVar(mc, n));
      45             :                 } else {
      46       24033 :                         nv[n] = newTmpVariable(mb, getVarType(mc, n));
      47             :                 }
      48       27353 :                 if (nv[n] < 0) {
      49           0 :                         GDKfree(nv);
      50           0 :                         GDKfree(ns);
      51           0 :                         return -1;
      52             :                 }
      53             :         }
      54             : 
      55             :         /* use an alias mapping to keep track of the actual arguments */
      56        1217 :         for (n = p->retc; n < p->argc; n++)
      57         696 :                 nv[getArg(q, n)] = getArg(p, n);
      58             : 
      59       23729 :         k = 0;
      60             :         /* find the return statement of the inline function */
      61       23729 :         for (i = 1; i < mc->stop - 1; i++) {
      62       23208 :                 q = mc->stmt[i];
      63       23208 :                 if (q->barrier == RETURNsymbol) {
      64             :                         /* add the mapping of the return variables */
      65        1038 :                         for (n = 0; n < p->retc; n++)
      66         519 :                                 nv[getArg(q, n)] = getArg(p, n);
      67             :                 }
      68             :         }
      69             : 
      70             :         /* copy the stable part */
      71      391186 :         for (i = 0; i < pc; i++)
      72      390665 :                 ns[k++] = mb->stmt[i];
      73             : 
      74        8499 :         for (i = 1; i < mc->stop - 1; i++) {
      75        8486 :                 q = mc->stmt[i];
      76        8486 :                 if (q->token == ENDsymbol)
      77             :                         break;
      78             : 
      79             :                 /* copy the instruction and fix variable references */
      80        7978 :                 ns[k] = copyInstruction(q);
      81        7978 :                 if (ns[k] == NULL) {
      82           0 :                         GDKfree(nv);
      83           0 :                         GDKfree(ns);
      84           0 :                         return -1;
      85             :                 }
      86             : 
      87       29995 :                 for (n = 0; n < q->argc; n++)
      88       22017 :                         getArg(ns[k], n) = nv[getArg(q, n)];
      89             : 
      90        7978 :                 if (q->barrier == RETURNsymbol) {
      91        1038 :                         for (n = 0; n < q->retc; n++)
      92         519 :                                 clrVarFixed(mb, getArg(ns[k], n));      /* for typing */
      93         519 :                         setModuleId(ns[k], getModuleId(q));
      94         519 :                         setFunctionId(ns[k], getFunctionId(q));
      95         519 :                         ns[k]->typeresolved = false;
      96         519 :                         ns[k]->barrier = 0;
      97         519 :                         ns[k]->token = ASSIGNsymbol;
      98             :                 }
      99        7978 :                 k++;
     100             :         }
     101             : 
     102             :         /* copy the remainder of the stable part */
     103         521 :         freeInstruction(p);
     104       19932 :         for (i = pc + 1; i < mb->stop; i++) {
     105       19411 :                 ns[k++] = mb->stmt[i];
     106             :         }
     107             :         /* remove any free instruction */
     108     1284890 :         for (; i < mb->ssize; i++)
     109     1284369 :                 if (mb->stmt[i]) {
     110           0 :                         freeInstruction(mb->stmt[i]);
     111           0 :                         mb->stmt[i] = 0;
     112             :                 }
     113         521 :         GDKfree(mb->stmt);
     114         521 :         mb->stmt = ns;
     115             : 
     116         521 :         mb->ssize = l;
     117         521 :         mb->stop = k;
     118         521 :         GDKfree(nv);
     119         521 :         return pc;
     120             : }
     121             : 
     122             : static bool
     123         313 : isCorrectInline(MalBlkPtr mb)
     124             : {
     125             :         /* make sure we have a simple inline function with a single return */
     126         313 :         InstrPtr p;
     127         313 :         int i, retseen = 0;
     128             : 
     129       15023 :         for (i = 1; i < mb->stop; i++) {
     130       14710 :                 p = getInstrPtr(mb, i);
     131       14710 :                 if (p->token == RETURNsymbol || p->barrier == RETURNsymbol)
     132         311 :                         retseen++;
     133             :         }
     134         313 :         return retseen <= 1;
     135             : }
     136             : 
     137             : 
     138             : static bool
     139           0 : OPTinlineMultiplex(MalBlkPtr mb, InstrPtr p)
     140             : {
     141           0 :         Symbol s;
     142           0 :         str mod, fcn;
     143             : 
     144           0 :         int plus_one = getArgType(mb, p, p->retc) == TYPE_lng ? 1 : 0;
     145           0 :         mod = VALget(&getVar(mb, getArg(p, p->retc + 0 + plus_one))->value);
     146           0 :         fcn = VALget(&getVar(mb, getArg(p, p->retc + 1 + plus_one))->value);
     147           0 :         if ((s = findSymbolInModule(getModule(putName(mod)), putName(fcn))) == 0)
     148             :                 return false;
     149           0 :         return s->def->inlineProp;
     150             : }
     151             : 
     152             : 
     153             : str
     154      554175 : OPTinlineImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     155             : {
     156      554175 :         int i;
     157      554175 :         InstrPtr q, sig;
     158      554175 :         int actions = 0;
     159      554175 :         str msg = MAL_SUCCEED;
     160             : 
     161      554175 :         (void) stk;
     162             : 
     163    27032459 :         for (i = 1; i < mb->stop; i++) {
     164    26478292 :                 q = getInstrPtr(mb, i);
     165    26478292 :                 if (q->blk) {
     166         667 :                         sig = getInstrPtr(q->blk, 0);
     167             :                         /*
     168             :                          * Time for inlining functions that are used in multiplex operations.
     169             :                          * They are produced by SQL compiler.
     170             :                          */
     171         667 :                         if (isMultiplex(q)) {
     172           0 :                                 OPTinlineMultiplex(mb, q);
     173             :                         } else
     174             :                                 /*
     175             :                                  * Check if the function definition is tagged as being inlined.
     176             :                                  */
     177         659 :                         if (sig->token == FUNCTIONsymbol && q->blk->inlineProp
     178         313 :                                         && isCorrectInline(q->blk)) {
     179         313 :                                 (void) inlineMALblock(mb, i, q->blk);
     180         313 :                                 i--;
     181         313 :                                 actions++;
     182             :                         }
     183             :                 }
     184             :         }
     185             : 
     186             :         //mnstr_printf(cntxt->fdout,"inline limit %d ssize %d vtop %d vsize %d\n", mb->stop, (int)(mb->ssize), mb->vtop, (int)(mb->vsize));
     187             :         /* Defense line against incorrect plans */
     188      554167 :         if (actions > 0) {
     189         244 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     190         244 :                 if (!msg)
     191         244 :                         msg = chkFlow(mb);
     192         244 :                 if (!msg)
     193         244 :                         msg = chkDeclarations(mb);
     194             :         }
     195             :         /* keep actions taken as a fake argument */
     196      554167 :         (void) pushInt(mb, pci, actions);
     197      554168 :         return msg;
     198             : }

Generated by: LCOV version 1.14