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 : /* 14 : * Constant Duplicate Removal 15 : * The compilers may generate an abundance of constants on 16 : * the stack. This simple optimizer merges them into a single reference. 17 : * This makes it easier to search for statement duplicates 18 : * and alias their variables. 19 : */ 20 : /* We should not look at constants in simple, side-effect functions, because 21 : * they can not be removed later on. 22 : */ 23 : /* 24 : * We have to keep an alias table to reorganize the program 25 : * after the variable stack has changed. 26 : * The plan may contain many constants and to check them all would be quadratic 27 : * in the size of the constant list. 28 : * The heuristic is to look back into the list only partially. 29 : * A hash structure could help out with further reduction. 30 : */ 31 : #include "monetdb_config.h" 32 : #include "mal_instruction.h" 33 : #include "opt_constants.h" 34 : 35 : str 36 477404 : OPTconstantsImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 37 : InstrPtr pci) 38 : { 39 477404 : int i, j, k = 1, n = 0, fnd = 0, actions = 0, limit = 0; 40 477404 : int *alias = NULL, *index = NULL, *cand = NULL; 41 477404 : VarPtr x, y, *cst = NULL; 42 477404 : str msg = MAL_SUCCEED; 43 477404 : InstrPtr p, q; 44 : 45 477404 : if (isSimpleSQL(mb)) { 46 272871 : goto wrapup; 47 : } 48 204532 : alias = (int *) GDKzalloc(sizeof(int) * mb->vtop); 49 204592 : cand = (int *) GDKzalloc(sizeof(int) * mb->vtop); 50 204585 : cst = (VarPtr *) GDKzalloc(sizeof(VarPtr) * mb->vtop); 51 204593 : index = (int *) GDKzalloc(sizeof(int) * mb->vtop); 52 : 53 204587 : if (alias == NULL || cst == NULL || index == NULL || cand == NULL) { 54 0 : msg = createException(MAL, "optimizer.constants", 55 : SQLSTATE(HY013) MAL_MALLOC_FAIL); 56 0 : goto wrapup; 57 : } 58 : 59 : (void) stk; 60 : (void) cntxt; 61 : 62 20093664 : for (i = 0; i < mb->stop; i++) { 63 19888812 : q = getInstrPtr(mb, i); 64 19888812 : if (!q) { 65 0 : continue; 66 : } 67 19888812 : if (getModuleId(q) == sqlRef && getFunctionId(q) != tidRef) { 68 3947981 : continue; 69 : } 70 15940831 : if (hasSideEffects(mb, q, 1)) 71 5919155 : continue; 72 36408691 : for (k = q->retc; k < q->argc; k++) { 73 26386750 : j = getArg(q, k); 74 26386750 : if (cand[j] == 0) { 75 21507750 : cand[j] = isVarConstant(mb, j) && isVarFixed(mb, j) 76 21507750 : && getVarType(mb, j) != TYPE_ptr; 77 : } 78 : } 79 : } 80 : 81 36678104 : for (i = 0; i < mb->vtop; i++) 82 36473252 : alias[i] = i; 83 36679402 : for (i = 0; i < mb->vtop; i++) 84 36474845 : if (cand[i]) { 85 2416935 : x = getVar(mb, i); 86 2416935 : fnd = 0; 87 2416935 : limit = n - 128; // don't look to far back 88 2416935 : if (x->type && x->value.vtype) 89 54289019 : for (k = n - 1; k >= 0 && k > limit; k--) { 90 52784353 : y = cst[k]; 91 52784353 : if (x->type == y->type && x->rowcnt == y->rowcnt 92 22438672 : && x->value.vtype == y->value.vtype 93 22438167 : && (x->value.vtype == TYPE_any 94 22438082 : || ATOMcmp(x->value.vtype, VALptr(&x->value), 95 : VALptr(&y->value)) == 0)) { 96 : 97 : /* re-use a constant */ 98 541079 : alias[i] = index[k]; 99 541079 : fnd = 1; 100 541079 : actions++; 101 541079 : break; 102 : } 103 : } 104 541079 : if (fnd == 0) { 105 1875561 : cst[n] = x; 106 1875561 : index[n] = i; 107 1875561 : n++; 108 : } 109 : } 110 : 111 204557 : if (actions) 112 14216230 : for (i = 0; i < mb->stop; i++) { 113 14162062 : p = getInstrPtr(mb, i); 114 74391590 : for (k = 0; k < p->argc; k++) 115 60229528 : getArg(p, k) = alias[getArg(p, k)]; 116 : } 117 : 118 : /* Defense line against incorrect plans */ 119 : /* Plan remains unaffected */ 120 : // msg = chkTypes(cntxt->usermodule, mb, FALSE); 121 : // if (!msg) 122 : // msg = chkFlow(mb); 123 : // if(!msg) 124 : // msg = chkDeclarations(mb); 125 : /* keep all actions taken as a post block comment */ 126 204557 : wrapup: 127 : /* keep actions taken as a fake argument */ 128 477428 : (void) pushInt(mb, pci, actions); 129 : 130 477433 : if (cand) 131 204562 : GDKfree(cand); 132 477456 : if (alias) 133 204585 : GDKfree(alias); 134 477463 : if (cst) 135 204592 : GDKfree(cst); 136 477452 : if (index) 137 204581 : GDKfree(index); 138 477463 : return msg; 139 : }