/ Check-in [50d350ab]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:50d350abbc9176cd6fc606bc45b8fc3020719500
User & Date: drh 2013-11-21 16:08:52
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: d4ccf0f5 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: 50d350ab user: drh tags: trunk
14:44
Remove the obsolete TK_CONST_FUNC token type. check-in: 9b4217f0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  2677   2677         */
  2678   2678         if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
  2679   2679           assert( nFarg>=1 );
  2680   2680           sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
  2681   2681           break;
  2682   2682         }
  2683   2683   
         2684  +      for(i=0; i<nFarg; i++){
         2685  +        if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
         2686  +          constMask |= (1<<i);
         2687  +        }
         2688  +        if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
         2689  +          pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
         2690  +        }
         2691  +      }
  2684   2692         if( pFarg ){
  2685         -        r1 = sqlite3GetTempRange(pParse, nFarg);
         2693  +        if( constMask ){
         2694  +          r1 = pParse->nMem+1;
         2695  +          pParse->nMem += nFarg;
         2696  +        }else{
         2697  +          r1 = sqlite3GetTempRange(pParse, nFarg);
         2698  +        }
  2686   2699   
  2687   2700           /* For length() and typeof() functions with a column argument,
  2688   2701           ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
  2689   2702           ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
  2690   2703           ** loading.
  2691   2704           */
  2692   2705           if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
................................................................................
  2700   2713               testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
  2701   2714               pFarg->a[0].pExpr->op2 = 
  2702   2715                     pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
  2703   2716             }
  2704   2717           }
  2705   2718   
  2706   2719           sqlite3ExprCachePush(pParse);     /* Ticket 2ea2425d34be */
  2707         -        sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
         2720  +        sqlite3ExprCodeExprList(pParse, pFarg, r1, 
         2721  +                                SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
  2708   2722           sqlite3ExprCachePop(pParse, 1);   /* Ticket 2ea2425d34be */
  2709   2723         }else{
  2710   2724           r1 = 0;
  2711   2725         }
  2712   2726   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2713   2727         /* Possibly overload the function if the first argument is
  2714   2728         ** a virtual table column.
................................................................................
  2724   2738         */
  2725   2739         if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
  2726   2740           pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
  2727   2741         }else if( nFarg>0 ){
  2728   2742           pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
  2729   2743         }
  2730   2744   #endif
  2731         -      for(i=0; i<nFarg; i++){
  2732         -        if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
  2733         -          constMask |= (1<<i);
  2734         -        }
  2735         -        if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
  2736         -          pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
  2737         -        }
  2738         -      }
  2739   2745         if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
  2740   2746           if( !pColl ) pColl = db->pDfltColl; 
  2741   2747           sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
  2742   2748         }
  2743   2749         sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
  2744   2750                           (char*)pDef, P4_FUNCDEF);
  2745   2751         sqlite3VdbeChangeP5(v, (u8)nFarg);
  2746         -      if( nFarg ){
         2752  +      if( nFarg && constMask==0 ){
  2747   2753           sqlite3ReleaseTempRange(pParse, r1, nFarg);
  2748   2754         }
  2749   2755         break;
  2750   2756       }
  2751   2757   #ifndef SQLITE_OMIT_SUBQUERY
  2752   2758       case TK_EXISTS:
  2753   2759       case TK_SELECT: {
................................................................................
  2975   2981       }
  2976   2982   #endif
  2977   2983     }
  2978   2984     sqlite3ReleaseTempReg(pParse, regFree1);
  2979   2985     sqlite3ReleaseTempReg(pParse, regFree2);
  2980   2986     return inReg;
  2981   2987   }
         2988  +
         2989  +/*
         2990  +** Factor out the code of the given expression to initialization time.
         2991  +*/
         2992  +void sqlite3ExprCodeAtInit(Parse *pParse, Expr *pExpr, int regDest){
         2993  +  ExprList *p;
         2994  +  assert( pParse->cookieGoto>0 ); /* Only possible if cookie will be coded */
         2995  +  p = pParse->pConstExpr;
         2996  +  pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
         2997  +  p = sqlite3ExprListAppend(pParse, p, pExpr);
         2998  +  if( p ) p->a[p->nExpr-1].u.iConstExprReg = regDest;
         2999  +  pParse->pConstExpr = p;
         3000  +}
  2982   3001   
  2983   3002   /*
  2984   3003   ** Generate code to evaluate an expression and store the results
  2985   3004   ** into a register.  Return the register number where the results
  2986   3005   ** are stored.
  2987   3006   **
  2988   3007   ** If the register is a temporary register that can be deallocated,
................................................................................
  3006   3025       if( p ){
  3007   3026         for(i=0; i<p->nExpr; i++){
  3008   3027           if( sqlite3ExprCompare(p->a[i].pExpr, pExpr, -1)==0 ){
  3009   3028             return p->a[i].u.iConstExprReg;
  3010   3029           }
  3011   3030         }
  3012   3031       }
  3013         -    p = sqlite3ExprListAppend(pParse, p, sqlite3ExprDup(pParse->db, pExpr, 0));
  3014         -    pParse->pConstExpr = p;
  3015   3032       r2 = ++pParse->nMem;
  3016         -    if( p ) p->a[p->nExpr-1].u.iConstExprReg = r2;
         3033  +    sqlite3ExprCodeAtInit(pParse, pExpr, r2);
  3017   3034     }else{
  3018   3035       int r1 = sqlite3GetTempReg(pParse);
  3019   3036       r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
  3020   3037       if( r2==r1 ){
  3021   3038         *pReg = r1;
  3022   3039       }else{
  3023   3040         sqlite3ReleaseTempReg(pParse, r1);
................................................................................
  3354   3371   #endif /* SQLITE_DEBUG */
  3355   3372   
  3356   3373   /*
  3357   3374   ** Generate code that pushes the value of every element of the given
  3358   3375   ** expression list into a sequence of registers beginning at target.
  3359   3376   **
  3360   3377   ** Return the number of elements evaluated.
         3378  +**
         3379  +** The SQLITE_ECEL_DUP flag prevents the arguments from being
         3380  +** filled using OP_SCopy.  OP_Copy must be used instead.
         3381  +**
         3382  +** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
         3383  +** factored out into initialization code.
  3361   3384   */
  3362   3385   int sqlite3ExprCodeExprList(
  3363   3386     Parse *pParse,     /* Parsing context */
  3364   3387     ExprList *pList,   /* The expression list to be coded */
  3365   3388     int target,        /* Where to write results */
  3366         -  int doHardCopy     /* Make a hard copy of every element */
         3389  +  u8 flags           /* SQLITE_ECEL_* flags */
  3367   3390   ){
  3368   3391     struct ExprList_item *pItem;
  3369   3392     int i, n;
         3393  +  u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
  3370   3394     assert( pList!=0 );
  3371   3395     assert( target>0 );
  3372   3396     assert( pParse->pVdbe!=0 );  /* Never gets this far otherwise */
  3373   3397     n = pList->nExpr;
         3398  +  if( pParse->cookieGoto<=0 ) flags &= ~SQLITE_ECEL_FACTOR;
  3374   3399     for(pItem=pList->a, i=0; i<n; i++, pItem++){
  3375   3400       Expr *pExpr = pItem->pExpr;
  3376         -    int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
  3377         -    if( inReg!=target+i ){
  3378         -      sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy,
  3379         -                        inReg, target+i);
         3401  +    if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
         3402  +      sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
         3403  +    }else{
         3404  +      int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
         3405  +      if( inReg!=target+i ){
         3406  +        sqlite3VdbeAddOp2(pParse->pVdbe, copyOp, inReg, target+i);
         3407  +      }
  3380   3408       }
  3381   3409     }
  3382   3410     return n;
  3383   3411   }
  3384   3412   
  3385   3413   /*
  3386   3414   ** Generate code for a BETWEEN operator.

Changes to src/select.c.

   595    595         sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
   596    596       }
   597    597     }else if( eDest!=SRT_Exists ){
   598    598       /* If the destination is an EXISTS(...) expression, the actual
   599    599       ** values returned by the SELECT are not required.
   600    600       */
   601    601       sqlite3ExprCacheClear(pParse);
   602         -    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
          602  +    sqlite3ExprCodeExprList(pParse, pEList, regResult,
          603  +                            (eDest==SRT_Output)?SQLITE_ECEL_DUP:0);
   603    604     }
   604    605     nColumn = nResultCol;
   605    606   
   606    607     /* If the DISTINCT keyword was present on the SELECT statement
   607    608     ** and this row has been seen before, then do not make this row
   608    609     ** part of the result.
   609    610     */
................................................................................
  3881   3882       int addrNext = 0;
  3882   3883       int regAgg;
  3883   3884       ExprList *pList = pF->pExpr->x.pList;
  3884   3885       assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
  3885   3886       if( pList ){
  3886   3887         nArg = pList->nExpr;
  3887   3888         regAgg = sqlite3GetTempRange(pParse, nArg);
  3888         -      sqlite3ExprCodeExprList(pParse, pList, regAgg, 1);
         3889  +      sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP);
  3889   3890       }else{
  3890   3891         nArg = 0;
  3891   3892         regAgg = 0;
  3892   3893       }
  3893   3894       if( pF->iDistinct>=0 ){
  3894   3895         addrNext = sqlite3VdbeMakeLabel(v);
  3895   3896         assert( nArg==1 );

Changes to src/sqliteInt.h.

  2899   2899   void sqlite3ExprCacheStore(Parse*, int, int, int);
  2900   2900   void sqlite3ExprCachePush(Parse*);
  2901   2901   void sqlite3ExprCachePop(Parse*, int);
  2902   2902   void sqlite3ExprCacheRemove(Parse*, int, int);
  2903   2903   void sqlite3ExprCacheClear(Parse*);
  2904   2904   void sqlite3ExprCacheAffinityChange(Parse*, int, int);
  2905   2905   int sqlite3ExprCode(Parse*, Expr*, int);
         2906  +void sqlite3ExprCodeAtInit(Parse*, Expr*, int);
  2906   2907   int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
  2907   2908   int sqlite3ExprCodeTarget(Parse*, Expr*, int);
  2908   2909   int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
  2909         -int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int);
         2910  +int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
         2911  +#define SQLITE_ECEL_DUP      0x01  /* Deep, not shallow copies */
         2912  +#define SQLITE_ECEL_FACTOR   0x02  /* Factor out constant terms */
  2910   2913   void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
  2911   2914   void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
  2912   2915   Table *sqlite3FindTable(sqlite3*,const char*, const char*);
  2913   2916   Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
  2914   2917   Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
  2915   2918   Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
  2916   2919   void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);