From: drh Date: Thu, 21 Nov 2013 16:08:52 +0000 (+0000) Subject: When one or more arguments to a function are constants, try to factor X-Git-Tag: version-3.8.2~63 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d1a01edac9ff763ef8d2909bf6deff4ad68345bf;p=thirdparty%2Fsqlite.git When one or more arguments to a function are constants, try to factor out just those arguments into initialization code. FossilOrigin-Name: 50d350abbc9176cd6fc606bc45b8fc3020719500 --- diff --git a/manifest b/manifest index 5d827ec820..6704560739 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sobsolete\sTK_CONST_FUNC\stoken\stype. -D 2013-11-21T14:44:38.999 +C When\sone\sor\smore\sarguments\sto\sa\sfunction\sare\sconstants,\stry\sto\sfactor\nout\sjust\sthose\sarguments\sinto\sinitialization\scode. +D 2013-11-21T16:08:52.350 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -175,7 +175,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 F src/delete.c 909936019ccb8d0f4a10d0d10ad607c38ee62cbe -F src/expr.c 98800f5a545bc93ab90acf4c89e904069c8b4bcf +F src/expr.c 3c629b4b208933c115f5652d2c6fcc877188c4fb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5 F src/func.c ef30d26ae4d79bbc7300c74e77fd117a0ba30235 @@ -219,12 +219,12 @@ F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c a70e32ae6ccb7b780f2b6d3e9e21837affc25ee5 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 253cb683e4a05b0b56b0f9c816f3c4a4e5575ebb +F src/select.c d41381d80a22d3a83352aeca274cccf264ac277a F src/shell.c 849ee96c952d20e504d417e42a06acc5ca94ef17 F src/sqlite.h.in a5dc058a909d9f14470bad9329d9e9303020ea4e F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 300dbe249ea28b094bdf304d6d96d414fef0bb26 +F src/sqliteInt.h 8cd0bb5b2cd8430482460c2a302edd2619d17293 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1140,7 +1140,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1b0f779e19a5c0d51eddd2d88db50034d77d132c -R 4765b9c971cb7bd4e939f413b1d14806 +P 9b4217f055e9bced186b4c56a5753bd6da7115b5 +R cd046aaa4606fb86e4dbb88d28c9046d U drh -Z 408c8bf331ed8f56b61161d6e80b7e89 +Z f1aad5e966fd81185b357b5fc8c7f131 diff --git a/manifest.uuid b/manifest.uuid index 1c14211a72..65377c8b4c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9b4217f055e9bced186b4c56a5753bd6da7115b5 \ No newline at end of file +50d350abbc9176cd6fc606bc45b8fc3020719500 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 62055d246b..9d405343e9 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2681,8 +2681,21 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ break; } + for(i=0; ia[i].pExpr) ){ + constMask |= (1<funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); + } + } if( pFarg ){ - r1 = sqlite3GetTempRange(pParse, nFarg); + if( constMask ){ + r1 = pParse->nMem+1; + pParse->nMem += nFarg; + }else{ + r1 = sqlite3GetTempRange(pParse, nFarg); + } /* For length() and typeof() functions with a column argument, ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG @@ -2704,7 +2717,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ } sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ - sqlite3ExprCodeExprList(pParse, pFarg, r1, 1); + sqlite3ExprCodeExprList(pParse, pFarg, r1, + SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */ }else{ r1 = 0; @@ -2728,14 +2742,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); } #endif - for(i=0; ia[i].pExpr) ){ - constMask |= (1<funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ - pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); - } - } if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); @@ -2743,7 +2749,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nFarg); - if( nFarg ){ + if( nFarg && constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); } break; @@ -2980,6 +2986,19 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ return inReg; } +/* +** Factor out the code of the given expression to initialization time. +*/ +void sqlite3ExprCodeAtInit(Parse *pParse, Expr *pExpr, int regDest){ + ExprList *p; + assert( pParse->cookieGoto>0 ); /* Only possible if cookie will be coded */ + p = pParse->pConstExpr; + pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); + p = sqlite3ExprListAppend(pParse, p, pExpr); + if( p ) p->a[p->nExpr-1].u.iConstExprReg = regDest; + pParse->pConstExpr = p; +} + /* ** Generate code to evaluate an expression and store the results ** into a register. Return the register number where the results @@ -3010,10 +3029,8 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ } } } - p = sqlite3ExprListAppend(pParse, p, sqlite3ExprDup(pParse->db, pExpr, 0)); - pParse->pConstExpr = p; r2 = ++pParse->nMem; - if( p ) p->a[p->nExpr-1].u.iConstExprReg = r2; + sqlite3ExprCodeAtInit(pParse, pExpr, r2); }else{ int r1 = sqlite3GetTempReg(pParse); r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); @@ -3358,25 +3375,36 @@ void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){ ** expression list into a sequence of registers beginning at target. ** ** Return the number of elements evaluated. +** +** The SQLITE_ECEL_DUP flag prevents the arguments from being +** filled using OP_SCopy. OP_Copy must be used instead. +** +** The SQLITE_ECEL_FACTOR argument allows constant arguments to be +** factored out into initialization code. */ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ int target, /* Where to write results */ - int doHardCopy /* Make a hard copy of every element */ + u8 flags /* SQLITE_ECEL_* flags */ ){ struct ExprList_item *pItem; int i, n; + u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy; assert( pList!=0 ); assert( target>0 ); assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ n = pList->nExpr; + if( pParse->cookieGoto<=0 ) flags &= ~SQLITE_ECEL_FACTOR; for(pItem=pList->a, i=0; ipExpr; - int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); - if( inReg!=target+i ){ - sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy, - inReg, target+i); + if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ + sqlite3ExprCodeAtInit(pParse, pExpr, target+i); + }else{ + int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); + if( inReg!=target+i ){ + sqlite3VdbeAddOp2(pParse->pVdbe, copyOp, inReg, target+i); + } } } return n; diff --git a/src/select.c b/src/select.c index 04a523434b..aa8e54b02f 100644 --- a/src/select.c +++ b/src/select.c @@ -599,7 +599,8 @@ static void selectInnerLoop( ** values returned by the SELECT are not required. */ sqlite3ExprCacheClear(pParse); - sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output); + sqlite3ExprCodeExprList(pParse, pEList, regResult, + (eDest==SRT_Output)?SQLITE_ECEL_DUP:0); } nColumn = nResultCol; @@ -3885,7 +3886,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); - sqlite3ExprCodeExprList(pParse, pList, regAgg, 1); + sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP); }else{ nArg = 0; regAgg = 0; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 84c69972a1..7c4c04337b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2903,10 +2903,13 @@ void sqlite3ExprCacheRemove(Parse*, int, int); void sqlite3ExprCacheClear(Parse*); void sqlite3ExprCacheAffinityChange(Parse*, int, int); int sqlite3ExprCode(Parse*, Expr*, int); +void sqlite3ExprCodeAtInit(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); int sqlite3ExprCodeAndCache(Parse*, Expr*, int); -int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int); +int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8); +#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */ +#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */ void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite3*,const char*, const char*);