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
29str
30OPTconstantsImplementation(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
109wrapup:
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