Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Initial test cases and bug fixes in the CSE logic. (CVS 4946) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e5aff09ac693946dc7ebb2f245b64349 |
User & Date: | drh 2008-04-01 01:42:41.000 |
Context
2008-04-01
| ||
02:45 | Add a configure option for using gcov (makes things easier for versions of GCC that fail to build otherwise) (CVS 4947) (check-in: 7d1e797162 user: mlcreech tags: trunk) | |
01:42 | Initial test cases and bug fixes in the CSE logic. (CVS 4946) (check-in: e5aff09ac6 user: drh tags: trunk) | |
00:36 | Break up the implementation of OP_Move, OP_Copy, and OP_SCopy to reduce the number of branch instructions. (CVS 4945) (check-in: 53e533d3a7 user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.360 2008/04/01 01:42:41 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_Move, iFrom, iTo); for(i=0; i<pParse->nColCache; i++){ if( pParse->aColCache[i].iReg==iFrom ){ pParse->aColCache[i].iReg = iTo; } } } /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". ** Return the register where results are stored. ** ** With this routine, there is no guaranteed that results will | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 | sqlite3VdbeAddOp2(pParse->pVdbe, OP_Move, iFrom, iTo); for(i=0; i<pParse->nColCache; i++){ if( pParse->aColCache[i].iReg==iFrom ){ pParse->aColCache[i].iReg = iTo; } } } /* ** Return true if any register in the range iFrom..iTo (inclusive) ** is used as part of the column cache. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; for(i=0; i<pParse->nColCache; i++){ int r = pParse->aColCache[i].iReg; if( r>=iFrom && r<=iTo ) return 1; } return 0; } /* ** Theres is a value in register iCurrent. We ultimately want ** the value to be in register iTarget. It might be that ** iCurrent and iTarget are the same register. ** ** We are going to modify the value, so we need to make sure it ** is not a cached register. If iCurrent is a cached register, ** then try to move the value over to iTarget. If iTarget is a ** cached register, then clear the corresponding cache line. ** ** Return the register that the value ends up in. */ int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){ assert( pParse->pVdbe!=0 ); if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){ return iCurrent; } sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget); sqlite3ExprExpireColumnCacheLines(pParse, iTarget, iTarget); return iTarget; } /* ** Generate code into the current Vdbe to evaluate the given ** expression. Attempt to store the results in register "target". ** Return the register where results are stored. ** ** With this routine, there is no guaranteed that results will |
︙ | ︙ | |||
2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 | break; } case TK_BITNOT: case TK_NOT: { assert( TK_BITNOT==OP_BitNot ); assert( TK_NOT==OP_Not ); inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); sqlite3VdbeAddOp1(v, op, inReg); break; } case TK_ISNULL: case TK_NOTNULL: { int addr; assert( TK_ISNULL==OP_IsNull ); | > | 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 | break; } case TK_BITNOT: case TK_NOT: { assert( TK_BITNOT==OP_BitNot ); assert( TK_NOT==OP_Not ); inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); inReg = sqlite3ExprWritableRegister(pParse, inReg, target); sqlite3VdbeAddOp1(v, op, inReg); break; } case TK_ISNULL: case TK_NOTNULL: { int addr; assert( TK_ISNULL==OP_IsNull ); |
︙ | ︙ | |||
2413 2414 2415 2416 2417 2418 2419 | assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); pEList = pExpr->pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); | < > | 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 | assert(pExpr->pList); assert((pExpr->pList->nExpr % 2) == 0); assert(pExpr->pList->nExpr > 0); pEList = pExpr->pList; aListelem = pEList->a; nExpr = pEList->nExpr; endLabel = sqlite3VdbeMakeLabel(v); if( (pX = pExpr->pLeft)!=0 ){ cacheX = *pX; cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); cacheX.op = TK_REGISTER; cacheX.iColumn = 0; opCompare.op = TK_EQ; opCompare.pLeft = &cacheX; pTest = &opCompare; } sqlite3ExprColumnCacheDisable(pParse, 1); for(i=0; i<nExpr; i=i+2){ if( pX ){ opCompare.pRight = aListelem[i].pExpr; }else{ pTest = aListelem[i].pExpr; } nextCase = sqlite3VdbeMakeLabel(v); |
︙ | ︙ | |||
3082 3083 3084 3085 3086 3087 3088 | if( pList ){ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); } } } | < < < < < < < < < < < < < | 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 | if( pList ){ for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){ sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); } } } /* ** Allocate or deallocate temporary use registers during code generation. */ int sqlite3GetTempReg(Parse *pParse){ int i, r; if( pParse->nTempReg==0 ){ return ++pParse->nMem; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.684 2008/04/01 01:42:41 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Include the configuration header output by 'configure' if it was run ** (otherwise we get an empty default). |
︙ | ︙ | |||
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 | WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int); void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprColumnCacheDisable(Parse*, int); void sqlite3ExprExpireColumnCacheLines(Parse*, int, int); int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); int sqlite3ExprCodeAndCache(Parse*, Expr*, int); void sqlite3ExprCodeConstants(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*, int); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); | > | 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 | WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int); void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprColumnCacheDisable(Parse*, int); void sqlite3ExprExpireColumnCacheLines(Parse*, int, int); int sqlite3ExprWritableRegister(Parse*,int,int); int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); int sqlite3ExprCodeAndCache(Parse*, Expr*, int); void sqlite3ExprCodeConstants(Parse*, Expr*); int sqlite3ExprCodeExprList(Parse*, ExprList*, int); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); |
︙ | ︙ |
Added test/cse.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | # 2008 April 1 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Test cases designed to exercise and verify the logic for # factoring constant expressions out of loops and for # common subexpression eliminations. # # $Id: cse.test,v 1.1 2008/04/01 01:42:41 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test cse-1.1 { execsql { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e, f); INSERT INTO t1 VALUES(1,11,12,13,14,15); INSERT INTO t1 VALUES(2,21,22,23,24,25); } execsql { SELECT b, -b, ~b, NOT b, NOT NOT b, b-b, b+b, b*b, b/b, b FROM t1 } } {11 -11 -12 0 1 0 22 121 1 11 21 -21 -22 0 1 0 42 441 1 21} do_test cse-1.2 { execsql { SELECT b, b%b, b==b, b!=b, b<b, b<=b, b IS NULL, b NOT NULL, b FROM t1 } } {11 0 1 0 0 1 0 1 11 21 0 1 0 0 1 0 1 21} do_test cse-1.3 { execsql { SELECT b, abs(b), coalesce(b,-b,NOT b,c,NOT c), c, -c FROM t1; } } {11 11 11 12 -12 21 21 21 22 -22} do_test cse-1.4 { execsql { SELECT CASE WHEN a==1 THEN b ELSE c END, b, c FROM t1 } } {11 11 12 22 21 22} do_test cse-1.5 { execsql { SELECT CASE a WHEN 1 THEN b WHEN 2 THEN c ELSE d END, b, c, d FROM t1 } } {11 11 12 13 22 21 22 23} do_test cse-1.6 { execsql { SELECT CASE b WHEN 11 THEN -b WHEN 21 THEN -c ELSE -d END, b, c, d FROM t1 } } {-11 11 12 13 -22 21 22 23} do_test cse-1.7 { execsql { SELECT a, -a, ~a, NOT a, NOT NOT a, a-a, a+a, a*a, a/a, a FROM t1 } } {1 -1 -2 0 1 0 2 1 1 1 2 -2 -3 0 1 0 4 4 1 2} do_test cse-1.8 { execsql { SELECT a, a%a, a==a, a!=a, a<a, a<=a, a IS NULL, a NOT NULL, a FROM t1 } } {1 0 1 0 0 1 0 1 1 2 0 1 0 0 1 0 1 2} finish_test |