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 | |
12 | static bool |
13 | isCorrectInline(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 | |
28 | static 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 | |
51 | str |
52 | OPTinlineImplementation(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 | |