1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9#include "monetdb_config.h"
10#include "opt_inline.h"
11
12static bool
13isCorrectInline(MalBlkPtr mb){
14 /* make sure we have a simple inline function with a singe return */
15 InstrPtr p;
16 int i, retseen=0;
17
18 for( i= 1; i < mb->stop; i++){
19 p= getInstrPtr(mb,i);
20 if ( p->token == RETURNsymbol || p->token == YIELDsymbol ||
21 p->barrier == RETURNsymbol || p->barrier == YIELDsymbol)
22 retseen++;
23 }
24 return retseen <= 1;
25}
26
27
28static bool OPTinlineMultiplex(Client cntxt, MalBlkPtr mb, InstrPtr p){
29 Symbol s;
30 str mod,fcn;
31
32 mod = VALget(&getVar(mb, getArg(p, 1))->value);
33 fcn = VALget(&getVar(mb, getArg(p, 2))->value);
34 if( (s= findSymbol(cntxt->usermodule, mod,fcn)) ==0 )
35 return false;
36 if (s->def == mb) /* avoid infinite recursion */
37 return false;
38 /*
39 * Before we decide to propagate the inline request
40 * to the multiplex operation, we check some basic properties
41 * of the target function. Moreover, we apply the inline optimizer
42 * to the target function as well.
43 * This code should be protected against overflow due to recursive calls.
44 * In general, this is a hard problem. For now, we just expand.
45 */
46 (void) OPTinlineImplementation(cntxt, s->def, NULL, p);
47 return s->def->inlineProp;
48}
49
50
51str
52OPTinlineImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
53{
54 int i;
55 InstrPtr q,sig;
56 int actions = 0;
57 char buf[256];
58 lng usec = GDKusec();
59 str msg = MAL_SUCCEED;
60
61 (void) p;
62 (void)stk;
63
64 for (i = 1; i < mb->stop; i++) {
65 q = getInstrPtr(mb, i);
66 if( q->blk ){
67 sig = getInstrPtr(q->blk,0);
68 /*
69 * Time for inlining functions that are used in multiplex operations.
70 * They are produced by SQL compiler.
71 */
72 if (isMultiplex(q)) {
73 if (OPTinlineMultiplex(cntxt,mb,q)) {
74
75 if( OPTdebug & OPTinline){
76 fprintf(stderr,"#multiplex inline function\n");
77 fprintInstruction(stderr,mb,0,q,LIST_MAL_ALL);
78 }
79 }
80 } else
81 /*
82 * Check if the function definition is tagged as being inlined.
83 */
84 if (sig->token == FUNCTIONsymbol && q->blk->inlineProp &&
85 isCorrectInline(q->blk) ) {
86 (void) inlineMALblock(mb,i,q->blk);
87 i--;
88 actions++;
89
90 if( OPTdebug & OPTinline){
91 fprintf(stderr,"#inline function at %d\n",i);
92 fprintFunction(stderr, mb, 0, LIST_MAL_ALL);
93 fprintInstruction(stderr,q->blk,0,sig,LIST_MAL_ALL);
94 }
95
96 }
97 }
98 }
99
100 /* Defense line against incorrect plans */
101 if( actions > 0){
102 chkTypes(cntxt->usermodule, mb, FALSE);
103 chkFlow(mb);
104 chkDeclarations(mb);
105 }
106 /* keep all actions taken as a post block comment */
107 usec = GDKusec()- usec;
108 snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","inline",actions, usec);
109 newComment(mb,buf);
110 if( actions >= 0)
111 addtoMalBlkHistory(mb);
112
113 if( OPTdebug & OPTinline){
114 fprintf(stderr, "#INLINE optimizer exit\n");
115 fprintFunction(stderr, mb, 0, LIST_MAL_ALL);
116 }
117 return msg;
118}
119