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, 2025 MonetDB Foundation; 9 : * Copyright August 2008 - 2023 MonetDB B.V.; 10 : * Copyright 1997 - July 2008 CWI. 11 : */ 12 : 13 : /* (c) Martin Kersten 14 : */ 15 : #include "monetdb_config.h" 16 : #include "opt_deadcode.h" 17 : 18 : str 19 1686426 : OPTdeadcodeImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 20 : InstrPtr pci) 21 : { 22 1686426 : int i, k, se, limit, slimit; 23 1686426 : InstrPtr p = 0, *old = NULL; 24 1686426 : int actions = 0; 25 1686426 : int *varused = 0; 26 1686426 : str msg = MAL_SUCCEED; 27 : 28 1686426 : (void) cntxt; 29 1686426 : (void) stk; /* to fool compilers */ 30 : 31 1686426 : if (mb->inlineProp) 32 0 : goto wrapup; 33 : 34 1686426 : varused = GDKzalloc(mb->vtop * sizeof(int)); 35 1687599 : if (varused == NULL) 36 0 : goto wrapup; 37 : 38 1687599 : old = mb->stmt; 39 1687599 : limit = mb->stop; 40 1687599 : slimit = mb->ssize; 41 1687599 : if (newMalBlkStmt(mb, mb->ssize) < 0) { 42 0 : GDKfree(varused); 43 0 : throw(MAL, "optimizer.deadcode", SQLSTATE(HY013) MAL_MALLOC_FAIL); 44 : } 45 : //mnstr_printf(cntxt->fdout,"deadcode limit %d ssize %d vtop %d vsize %d\n", limit, (int)(mb->ssize), mb->vtop, (int)(mb->vsize)); 46 : 47 : // Calculate the instructions in which a variable is used. 48 : // Variables can be used multiple times in an instruction. 49 91251963 : for (i = 1; i < limit; i++) { 50 89564318 : p = old[i]; 51 355926557 : for (k = p->retc; k < p->argc; k++) 52 266362239 : varused[getArg(p, k)]++; 53 89564318 : if (blockCntrl(p)) 54 25198 : for (k = 0; k < p->retc; k++) 55 18428 : varused[getArg(p, k)]++; 56 : } 57 : 58 : // Consolidate the actual need for variables 59 94692841 : for (i = limit; i >= 0; i--) { 60 93005431 : p = old[i]; 61 93005431 : if (p == 0) 62 1686672 : continue; //left behind by others? 63 : 64 91318759 : if (getModuleId(p) == batRef && isUpdateInstruction(p) && !p->barrier) { 65 : /* bat.append and friends are intermediates that need not be retained 66 : * unless they are not used outside of an update */ 67 852809 : if (varused[getArg(p, 1)] > 1) 68 4616 : varused[getArg(p, 0)]++; // force keeping it 69 90466058 : } else if (hasSideEffects(mb, p, FALSE) || !isLinearFlow(p) 70 34994564 : || (p->retc == 1 && mb->unsafeProp) 71 34937835 : || p->barrier /* ==side-effect */ ) { 72 55527588 : varused[getArg(p, 0)]++; // force keeping it 73 55527588 : continue; 74 : } 75 : // The results should be used somewhere 76 35790936 : se = 0; 77 73305186 : for (k = 0; k < p->retc; k++) 78 37514250 : se += varused[getArg(p, k)] > 0; 79 : 80 : // Reduce input variable count when garbage is detected 81 35790936 : if (se == 0) 82 92354458 : for (k = p->retc; k < p->argc; k++) 83 82536199 : varused[getArg(p, k)]--; 84 : } 85 : 86 : // Now we can simply copy the instructions and discard useless ones. 87 1687410 : pushInstruction(mb, old[0]); 88 45551546 : for (i = 1; i < limit; i++) { 89 43864309 : if ((p = old[i]) != NULL) { 90 43862515 : if (p->token == ENDsymbol) { 91 1687411 : pushInstruction(mb, p); 92 : // Also copy the optimizer trace information 93 47468775 : for (i++; i < limit; i++) 94 45781381 : if (old[i]) 95 45781381 : pushInstruction(mb, old[i]); 96 : break; 97 : } 98 : // Is the instruction still relevant? 99 : se = 0; 100 88087689 : for (k = 0; k < p->retc; k++) 101 45912585 : se += varused[getArg(p, k)] > 0; 102 : 103 42175104 : if (se) 104 34044241 : pushInstruction(mb, p); 105 : else { 106 8130863 : freeInstruction(p); 107 8131072 : actions++; 108 : } 109 : } 110 : } 111 : /* save the free instructions records for later */ 112 379979490 : for (; i < slimit; i++) 113 378291911 : if (old[i]) { 114 0 : pushInstruction(mb, old[i]); 115 : } 116 : /* Defense line against incorrect plans */ 117 : /* we don't create or change existing structures */ 118 : // no type change msg = chkTypes(cntxt->usermodule, mb, FALSE); 119 1687579 : if (actions > 0) { 120 567360 : msg = chkFlow(mb); 121 567344 : if (!msg) 122 567344 : msg = chkDeclarations(mb); 123 : } 124 1120219 : wrapup: 125 : /* keep actions taken as a fake argument */ 126 1687548 : (void) pushInt(mb, pci, actions); 127 : 128 1687173 : if (old) 129 1687173 : GDKfree(old); 130 1687647 : if (varused) 131 1687647 : GDKfree(varused); 132 : return msg; 133 : }