Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | When one or more arguments to a function are constants, try to factor out just those arguments into initialization code. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
50d350abbc9176cd6fc606bc45b8fc30 |
User & Date: | drh 2013-11-21 16:08:52.350 |
Context
2013-11-21
| ||
17:24 | Make sure the OP_Next and OP_NextIfOpen opcodes are numbered close together for efficiency in switch() statements. OP_Prev and OP_PrevIfOpen too. (check-in: d4ccf0f5c6 user: drh tags: trunk) | |
16:08 | When one or more arguments to a function are constants, try to factor out just those arguments into initialization code. (check-in: 50d350abbc user: drh tags: trunk) | |
14:44 | Remove the obsolete TK_CONST_FUNC token type. (check-in: 9b4217f055 user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
2677 2678 2679 2680 2681 2682 2683 2684 | */ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); break; } if( pFarg ){ | > > > > > > > > > > > > | > | 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 | */ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ assert( nFarg>=1 ); sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); break; } for(i=0; i<nFarg; i++){ if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){ constMask |= (1<<i); } if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr); } } if( pFarg ){ 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 ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data ** loading. */ if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ |
︙ | ︙ | |||
2700 2701 2702 2703 2704 2705 2706 | testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); pFarg->a[0].pExpr->op2 = pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); } } sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ | | > | 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 | testcase( pDef->funcFlags & OPFLAG_LENGTHARG ); pFarg->a[0].pExpr->op2 = pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG); } } sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ sqlite3ExprCodeExprList(pParse, pFarg, r1, SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */ }else{ r1 = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* Possibly overload the function if the first argument is ** a virtual table column. |
︙ | ︙ | |||
2724 2725 2726 2727 2728 2729 2730 | */ if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); }else if( nFarg>0 ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); } #endif | < < < < < < < < | | 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 | */ if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); }else if( nFarg>0 ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); } #endif if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nFarg); if( nFarg && constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); } break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { |
︙ | ︙ | |||
2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 | } #endif } sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); return inReg; } /* ** Generate code to evaluate an expression and store the results ** into a register. Return the register number where the results ** are stored. ** ** If the register is a temporary register that can be deallocated, | > > > > > > > > > > > > > | 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 | } #endif } sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); 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 ** are stored. ** ** If the register is a temporary register that can be deallocated, |
︙ | ︙ | |||
3006 3007 3008 3009 3010 3011 3012 | if( p ){ for(i=0; i<p->nExpr; i++){ if( sqlite3ExprCompare(p->a[i].pExpr, pExpr, -1)==0 ){ return p->a[i].u.iConstExprReg; } } } | < < < > | 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 | if( p ){ for(i=0; i<p->nExpr; i++){ if( sqlite3ExprCompare(p->a[i].pExpr, pExpr, -1)==0 ){ return p->a[i].u.iConstExprReg; } } } r2 = ++pParse->nMem; sqlite3ExprCodeAtInit(pParse, pExpr, r2); }else{ int r1 = sqlite3GetTempReg(pParse); r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( r2==r1 ){ *pReg = r1; }else{ sqlite3ReleaseTempReg(pParse, r1); |
︙ | ︙ | |||
3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 | #endif /* SQLITE_DEBUG */ /* ** Generate code that pushes the value of every element of the given ** expression list into a sequence of registers beginning at target. ** ** Return the number of elements evaluated. */ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ ExprList *pList, /* The expression list to be coded */ int target, /* Where to write results */ | > > > > > > | > > > > > | | | < > | 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 | #endif /* SQLITE_DEBUG */ /* ** Generate code that pushes the value of every element of the given ** 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 */ 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; i<n; i++, pItem++){ Expr *pExpr = pItem->pExpr; 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; } /* ** Generate code for a BETWEEN operator. |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
595 596 597 598 599 600 601 | sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ sqlite3ExprCacheClear(pParse); | | > | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i); } }else if( eDest!=SRT_Exists ){ /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pEList, regResult, (eDest==SRT_Output)?SQLITE_ECEL_DUP:0); } nColumn = nResultCol; /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ |
︙ | ︙ | |||
3881 3882 3883 3884 3885 3886 3887 | int addrNext = 0; int regAgg; ExprList *pList = pF->pExpr->x.pList; assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); | | | 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 | int addrNext = 0; int regAgg; ExprList *pList = pF->pExpr->x.pList; assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) ); if( pList ){ nArg = pList->nExpr; regAgg = sqlite3GetTempRange(pParse, nArg); sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP); }else{ nArg = 0; regAgg = 0; } if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); assert( nArg==1 ); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 | void sqlite3ExprCacheStore(Parse*, int, int, int); void sqlite3ExprCachePush(Parse*); void sqlite3ExprCachePop(Parse*, int); void sqlite3ExprCacheRemove(Parse*, int, int); void sqlite3ExprCacheClear(Parse*); void sqlite3ExprCacheAffinityChange(Parse*, int, int); int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); int sqlite3ExprCodeAndCache(Parse*, Expr*, int); | > | > > | 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 | void sqlite3ExprCacheStore(Parse*, int, int, int); void sqlite3ExprCachePush(Parse*); void sqlite3ExprCachePop(Parse*, int); 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, 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*); Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*); Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *); Index *sqlite3FindIndex(sqlite3*,const char*, const char*); void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); |
︙ | ︙ |