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 | /* |
10 | * Constant Duplicate Removal |
11 | * The compilers may generate an abundance of constants on |
12 | * the stack. This simple optimizer merges them into a single reference. |
13 | * This makes it easier to search for statement duplicates |
14 | * and alias their variables. |
15 | */ |
16 | |
17 | /* |
18 | * We have to keep an alias table to reorganize the program |
19 | * after the variable stack has changed. |
20 | * The plan may contain many constants and to check them all would be quadratic |
21 | * in the size of the constant list. |
22 | * The heuristic is to look back into the list only partially. |
23 | * A hash structure could help out with further reduction. |
24 | */ |
25 | #include "monetdb_config.h" |
26 | #include "mal_instruction.h" |
27 | #include "opt_constants.h" |
28 | |
29 | str |
30 | OPTconstantsImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) |
31 | { |
32 | int i, k = 1, n = 0, fnd = 0, actions = 0, limit = 0; |
33 | int *alias, *index; |
34 | VarPtr x,y, *cst; |
35 | char buf[256]; |
36 | lng usec = GDKusec(); |
37 | str msg = MAL_SUCCEED; |
38 | |
39 | if( OPTdebug & OPTconstants){ |
40 | fprintf(stderr, "#CONSTANTS optimizer exit\n" ); |
41 | fprintFunction(stderr, mb, 0, LIST_MAL_ALL); |
42 | } |
43 | alias= (int*) GDKzalloc(sizeof(int) * mb->vtop); |
44 | cst= (VarPtr*) GDKzalloc(sizeof(VarPtr) * mb->vtop); |
45 | index= (int*) GDKzalloc(sizeof(int) * mb->vtop); |
46 | |
47 | if ( alias == NULL || cst == NULL || index == NULL){ |
48 | msg = createException(MAL,"optimizer.constants" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
49 | goto wrapup; |
50 | } |
51 | |
52 | (void) stk; |
53 | (void) cntxt; |
54 | |
55 | for (i=0; i< mb->vtop; i++) |
56 | alias[ i]= i; |
57 | for (i=0; i< mb->vtop; i++) |
58 | if ( isVarConstant(mb,i) && isVarFixed(mb,i) && getVarType(mb,i) != TYPE_ptr){ |
59 | x= getVar(mb,i); |
60 | fnd = 0; |
61 | limit = n - 128; // don't look to far back |
62 | if ( x->type && x->value.vtype) |
63 | for( k = n-1; k >= 0 && k > limit; k--){ |
64 | y= cst[k]; |
65 | if ( x->type == y->type && |
66 | x->rowcnt == y->rowcnt && |
67 | x->value.vtype == y->value.vtype && |
68 | ATOMcmp(x->value.vtype, VALptr(&x->value), VALptr(&y->value)) == 0){ |
69 | if( OPTdebug & OPTconstants){ |
70 | fprintf(stderr,"#opt_constants: matching elements %s %d %d\n" , getVarName(mb,i), i,k); |
71 | } |
72 | /* re-use a constant */ |
73 | alias[i]= index[k]; |
74 | fnd=1; |
75 | actions++; |
76 | break; |
77 | } |
78 | } |
79 | if ( fnd == 0){ |
80 | if( OPTdebug & OPTconstants){ |
81 | fprintf(stderr,"swith elements %d %d\n" , i,n); |
82 | } |
83 | cst[n]= x; |
84 | index[n]= i; |
85 | n++; |
86 | } |
87 | } |
88 | |
89 | if (actions) |
90 | for (i = 0; i < mb->stop; i++){ |
91 | p= getInstrPtr(mb,i); |
92 | for (k=0; k < p->argc; k++) |
93 | getArg(p,k) = alias[getArg(p,k)]; |
94 | } |
95 | |
96 | /* Defense line against incorrect plans */ |
97 | /* Plan remains unaffected */ |
98 | //chkTypes(cntxt->usermodule, mb, FALSE); |
99 | //chkFlow(mb); |
100 | //chkDeclarations(mb); |
101 | |
102 | /* keep all actions taken as a post block comment */ |
103 | usec = GDKusec()- usec; |
104 | snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec" ,"constants" ,actions,usec); |
105 | newComment(mb,buf); |
106 | if (actions >= 0) |
107 | addtoMalBlkHistory(mb); |
108 | |
109 | wrapup: |
110 | if( alias) GDKfree(alias); |
111 | if( cst) GDKfree(cst); |
112 | if( index) GDKfree(index); |
113 | if( OPTdebug & OPTconstants){ |
114 | fprintf(stderr, "#CONSTANTS optimizer exit\n" ); |
115 | fprintFunction(stderr, mb, 0, LIST_MAL_ALL); |
116 | } |
117 | return msg; |
118 | } |
119 | |