Registerification of the WHERE clause logic. (CVS 4716)

FossilOrigin-Name: b3a141b2b0c09bf3c7704deeade290d71b7c9b77
diff --git a/src/analyze.c b/src/analyze.c
index a1bc2ee..b7e917f 100644
--- a/src/analyze.c
+++ b/src/analyze.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code associated with the ANALYZE command.
 **
-** @(#) $Id: analyze.c,v 1.38 2008/01/12 12:48:08 drh Exp $
+** @(#) $Id: analyze.c,v 1.39 2008/01/17 02:36:28 drh Exp $
 */
 #ifndef SQLITE_OMIT_ANALYZE
 #include "sqliteInt.h"
@@ -216,7 +216,7 @@
       sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
       sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2);
     }
-    sqlite3VdbeAddOp4(v, OP_RegMakeRec, regFields, 3, regRec, "aaa", 0);
+    sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0);
     sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid);
     sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid);
     sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
diff --git a/src/build.c b/src/build.c
index 26ae87d..91d94f0 100644
--- a/src/build.c
+++ b/src/build.c
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.465 2008/01/12 21:35:57 drh Exp $
+** $Id: build.c,v 1.466 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -2215,7 +2215,7 @@
 ** content of an index in response to a REINDEX command.
 **
 ** if memRootPage is not negative, it means that the index is newly
-** created.  The memory cell specified by memRootPage contains the
+** created.  The register specified by memRootPage contains the
 ** root page number of the index.  If memRootPage is negative, then
 ** the index already exists and must be cleared before being refilled and
 ** the root page number of the index is taken from pIndex->tnum.
@@ -2246,8 +2246,7 @@
   v = sqlite3GetVdbe(pParse);
   if( v==0 ) return;
   if( memRootPage>=0 ){
-    sqlite3VdbeAddOp1(v, OP_SCopy, memRootPage);
-    tnum = 0;
+    tnum = memRootPage;
   }else{
     tnum = pIndex->tnum;
     sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
@@ -2736,12 +2735,17 @@
   Vdbe *v;
   v = sqlite3GetVdbe(pParse);
   if( v ){
-    sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 1);
+    int r1 = sqlite3GetTempReg(pParse);
+    int r2 = sqlite3GetTempReg(pParse);
+    int j1;
+    sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1);
     sqlite3VdbeUsesBtree(v, iDb);
-    sqlite3VdbeAddOp1(v, OP_Integer, minFormat);
-    sqlite3VdbeAddOp2(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3);
-    sqlite3VdbeAddOp1(v, OP_Integer, minFormat);
-    sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 1);
+    sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2);
+    j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1);
+    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2);
+    sqlite3VdbeJumpHere(v, j1);
+    sqlite3ReleaseTempReg(pParse, r1);
+    sqlite3ReleaseTempReg(pParse, r2);
   }
 }
 
diff --git a/src/delete.c b/src/delete.c
index 87436ae..ae2ecf9 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.157 2008/01/12 12:48:08 drh Exp $
+** $Id: delete.c,v 1.158 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -61,24 +61,6 @@
 }
 
 /*
-** Allocate nVal contiguous memory cells and return the index of the
-** first. Also pop nVal elements from the stack and store them in the 
-** registers. The element on the top of the stack is stored in the
-** register with the largest index.
-*/
-int sqlite3StackToReg(Parse *p, int nVal){
-  int i;
-  int iRet = p->nMem+1;
-  Vdbe *v = sqlite3GetVdbe(p);
-  assert(v);
-  p->nMem += nVal;
-  for(i=nVal-1; i>=0; i--){
-    sqlite3VdbeAddOp2(v, OP_Move, 0, iRet+i);
-  }
-  return iRet;
-}
-
-/*
 ** Generate code that will open a table for reading.
 */
 void sqlite3OpenTable(
@@ -519,7 +501,7 @@
       sqlite3ColumnDefault(v, pTab, idx);
     }
   }
-  sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nCol+1, regOut);
+  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
   sqlite3IndexAffinityStr(v, pIdx);
   sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
   return regBase;
diff --git a/src/expr.c b/src/expr.c
index 52a0f29..5599398 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.345 2008/01/13 19:02:11 drh Exp $
+** $Id: expr.c,v 1.346 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1786,7 +1786,7 @@
 
           /* Evaluate the expression and insert it into the temp table */
           sqlite3ExprCode(pParse, pE2, r1);
-          sqlite3VdbeAddOp4(v, OP_RegMakeRec, r1, 1, r2, &affinity, 1);
+          sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
           sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
         }
         sqlite3ReleaseTempReg(pParse, r1);
@@ -2246,7 +2246,7 @@
         sqlite3VdbeJumpHere(v, j4);
       }else{
         r2 = regFree2 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp4(v, OP_RegMakeRec, r1, 1, r2, &affinity, 1);
+        sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
         j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
       }
       sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
diff --git a/src/insert.c b/src/insert.c
index 024a340..158dbae 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.223 2008/01/12 12:48:08 drh Exp $
+** $Id: insert.c,v 1.224 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -174,15 +174,15 @@
     pParse->nMem++;
     sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
     addr = sqlite3VdbeCurrentAddr(v);
+    sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0);
     sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+8);
-    sqlite3VdbeAddOp2(v, OP_Column, iCur, 0);
-    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
-    sqlite3VdbeAddOp2(v, OP_Ne, 0, addr+7);
+    sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, memId);
+    sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId);
     sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
     sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1);
     sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8);
-    sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1);
+    sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+2);
     sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
   }
   return memId;
@@ -224,8 +224,7 @@
     j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1);
     sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1);
     sqlite3VdbeJumpHere(v, j1);
-    sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0);
-    sqlite3VdbeAddOp3(v, OP_RegMakeRec, memId-1, 2, memId-1);
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, memId-1);
     sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1);
     sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
     sqlite3VdbeAddOp1(v, OP_Close, iCur);
@@ -525,7 +524,7 @@
       regRec = sqlite3GetTempReg(pParse);
       regRowid = sqlite3GetTempReg(pParse);
       sqlite3VdbeResolveLabel(v, iInsertBlock);
-      sqlite3VdbeAddOp3(v, OP_RegMakeRec, regFromSelect, nColumn, regRec);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
       sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid);
       sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid);
       sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
@@ -738,7 +737,7 @@
       }
     }
     regRec = sqlite3GetTempReg(pParse);
-    sqlite3VdbeAddOp3(v, OP_RegMakeRec, regCols, pTab->nCol, regRec);
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRec);
 
     /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
     ** do not attempt any conversions before assembling the record.
@@ -777,7 +776,7 @@
         sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
       }else{
         VdbeOp *pOp;
-        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
+        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
         pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
         if( pOp && pOp->opcode==OP_Null ){
           appendFlag = 1;
@@ -785,18 +784,16 @@
           pOp->p1 = baseCur;
           pOp->p2 = regRowid;
           pOp->p3 = regAutoinc;
-        }else{
-          /* TODO: Avoid this use of the stack. */
-          sqlite3VdbeAddOp2(v, OP_Move, 0, regRowid);
         }
       }
       /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
       ** to generate a unique primary key value.
       */
       if( !appendFlag ){
-        sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, sqlite3VdbeCurrentAddr(v)+2);
-        sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
+        int j1;
+        j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);
         sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+        sqlite3VdbeJumpHere(v, j1);
         sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
       }
     }else if( IsVirtual(pTab) ){
@@ -1178,7 +1175,7 @@
       }
     }
     sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
-    sqlite3VdbeAddOp3(v, OP_RegMakeRec, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
     sqlite3IndexAffinityStr(v, pIdx);
     sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
 
@@ -1294,7 +1291,7 @@
   }
   regData = regRowid + 1;
   regRec = sqlite3GetTempReg(pParse);
-  sqlite3VdbeAddOp3(v, OP_RegMakeRec, regData, pTab->nCol, regRec);
+  sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
   sqlite3TableAffinityStr(v, pTab);
 #ifndef SQLITE_OMIT_TRIGGER
   if( newIdx>=0 ){
diff --git a/src/pragma.c b/src/pragma.c
index e362f76..11350ae 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.166 2008/01/12 21:35:57 drh Exp $
+** $Id: pragma.c,v 1.167 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -459,11 +459,11 @@
           */
           static const VdbeOpList setMeta6[] = {
             { OP_Transaction,    0,               1,        0},    /* 0 */
-            { OP_ReadCookie,     0,               0,        3},    /* 1 */
-            { OP_If,             0,               0,        0},    /* 2 */
+            { OP_ReadCookie,     0,               1,        3},    /* 1 */
+            { OP_If,             1,               0,        0},    /* 2 */
             { OP_Halt,           SQLITE_OK,       OE_Abort, 0},    /* 3 */
-            { OP_Integer,        0,               0,        0},    /* 4 */
-            { OP_SetCookie,      0,               6,        0},    /* 5 */
+            { OP_Integer,        0,               1,        0},    /* 4 */
+            { OP_SetCookie,      0,               6,        1},    /* 5 */
           };
           int iAddr;
           iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
diff --git a/src/select.c b/src/select.c
index 7538494..3f181d4 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.402 2008/01/15 02:22:24 drh Exp $
+** $Id: select.c,v 1.403 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -404,7 +404,7 @@
   sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
   sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
   sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1);
-  sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord);
+  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
   sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
   sqlite3ReleaseTempReg(pParse, regRecord);
   sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
@@ -466,7 +466,7 @@
 
   v = pParse->pVdbe;
   r1 = sqlite3GetTempReg(pParse);
-  sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, N, r1);
+  sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
   sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1);
   sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
   sqlite3ReleaseTempReg(pParse, r1);
@@ -583,7 +583,7 @@
     */
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
     case SRT_Union: {
-      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
+      sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn);
       if( aff ){
         sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
       }
@@ -597,7 +597,7 @@
     */
     case SRT_Except: {
       int addr;
-      addr = sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
+      addr = sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn);
       sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
       sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3);
       sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0);
@@ -610,7 +610,7 @@
     case SRT_Table:
     case SRT_EphemTab: {
       int r1 = sqlite3GetTempReg(pParse);
-      sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
       if( pOrderBy ){
         pushOntoSorter(pParse, pOrderBy, p, r1);
       }else{
@@ -643,7 +643,7 @@
         pushOntoSorter(pParse, pOrderBy, p, iMem);
       }else{
         int r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, r1, &p->affinity, 1);
+        sqlite3VdbeAddOp4(v, OP_MakeRecord, iMem, 1, r1, &p->affinity, 1);
         sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
         sqlite3ReleaseTempReg(pParse, r1);
       }
@@ -683,7 +683,7 @@
     case SRT_Callback: {
       if( pOrderBy ){
         int r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
+        sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
         pushOntoSorter(pParse, pOrderBy, p, r1);
         sqlite3ReleaseTempReg(pParse, r1);
       }else if( eDest==SRT_Subroutine ){
@@ -808,7 +808,7 @@
       int j1;
       assert( nColumn==1 );
       j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
-      sqlite3VdbeAddOp4(v, OP_RegMakeRec, regRow, 1, regRow, &p->affinity, 1);
+      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRow, &p->affinity, 1);
       sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRow);
       sqlite3VdbeJumpHere(v, j1);
       break;
@@ -3430,7 +3430,7 @@
           }
         }
         regRecord = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nCol, regRecord);
+        sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
         sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
         sqlite3ReleaseTempReg(pParse, regRecord);
         sqlite3ReleaseTempRange(pParse, regBase, nCol);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 83640d8..12552e4 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.649 2008/01/12 19:03:49 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.650 2008/01/17 02:36:28 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1949,7 +1949,6 @@
 void sqlite3StrAccumAppend(StrAccum*,const char*,int);
 char *sqlite3StrAccumFinish(StrAccum*);
 void sqlite3StrAccumReset(StrAccum*);
-int sqlite3StackToReg(Parse *, int);
 void sqlite3SelectDestInit(SelectDest*,int,int);
 
 /*
diff --git a/src/trigger.c b/src/trigger.c
index 310d60f..09cbc43 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -523,12 +523,12 @@
     int base;
     static const VdbeOpList dropTrigger[] = {
       { OP_Rewind,     0, ADDR(9),  0},
-      { OP_String8,    0, 0,        0}, /* 1 */
-      { OP_Column,     0, 1,        0},
-      { OP_Ne,         0, ADDR(8),  0},
-      { OP_String8,    0, 0,        0}, /* 4: "trigger" */
-      { OP_Column,     0, 0,        0},
-      { OP_Ne,         0, ADDR(8),  0},
+      { OP_String8,    0, 1,        0}, /* 1 */
+      { OP_Column,     0, 1,        2},
+      { OP_Ne,         2, ADDR(8),  1},
+      { OP_String8,    0, 1,        0}, /* 4: "trigger" */
+      { OP_Column,     0, 0,        2},
+      { OP_Ne,         2, ADDR(8),  1},
       { OP_Delete,     0, 0,        0},
       { OP_Next,       0, ADDR(1),  0}, /* 8 */
     };
diff --git a/src/update.c b/src/update.c
index 6d1a21f..8d39dbc 100644
--- a/src/update.c
+++ b/src/update.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.167 2008/01/10 23:50:11 drh Exp $
+** $Id: update.c,v 1.168 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -449,7 +449,7 @@
         sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i);
       }
     }
-    sqlite3VdbeAddOp3(v, OP_RegMakeRec, regCols, pTab->nCol, regRow);
+    sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow);
     if( !isView ){
       sqlite3TableAffinityStr(v, pTab);
     }
diff --git a/src/vdbe.c b/src/vdbe.c
index bd4e3bf..144aafc 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.696 2008/01/16 17:46:38 drh Exp $
+** $Id: vdbe.c,v 1.697 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1984,27 +1984,6 @@
   break;
 }
 
-/* Opcode: StackIsNull P1 P2 *
-**
-** Check the top of the stack and jump to P2 if the top of the stack
-** is NULL.  If P1 is positive, then pop P1 elements from the stack
-** regardless of whether or not the jump is taken.  If P1 is negative,
-** pop -P1 elements from the stack only if the jump is taken and leave
-** the stack unchanged if the jump is not taken.
-*/
-case OP_StackIsNull: {            /* no-push, jump */
-  if( pTos->flags & MEM_Null ){
-    pc = pOp->p2-1;
-    if( pOp->p1<0 ){
-      popStack(&pTos, -pOp->p1);
-    }
-  }
-  if( pOp->p1>0 ){
-    popStack(&pTos, pOp->p1);
-  }
-  break;
-}
-
 /* Opcode: IsNull P1 P2 P3 * *
 **
 ** Jump to P2 if the value in register P1 is NULL.  If P3 is greater
@@ -2319,9 +2298,9 @@
   break;
 }
 
-/* Opcode: MakeRecord P1 P2 P4
+/* Opcode: MakeRecord P1 P2 P3 P4 *
 **
-** Convert the top abs(P1) entries of the stack into a single entry
+** Convert P2 registers beginning with P1 into a single entry
 ** suitable for use as a data record in a database table or as a key
 ** in an index.  The details of the format are irrelavant as long as
 ** the OP_Column opcode can decode the record later and as long as the
@@ -2329,13 +2308,6 @@
 ** records.  Refer to source code comments for the details of the record
 ** format.
 **
-** The original stack entries are popped from the stack if P1>0 but
-** remain on the stack if P1<0.
-**
-** If P2 is not zero and one or more of the entries are NULL, then jump
-** to the address given by P2.  This feature can be used to skip a
-** uniqueness test on indices.
-**
 ** P4 may be a string that is P1 characters long.  The nth character of the
 ** string indicates the column affinity that should be used for the nth
 ** field of the index key (i.e. the first character of P4 corresponds to the
@@ -2346,17 +2318,7 @@
 **
 ** If P4 is NULL then all index fields have the affinity NONE.
 */
-/*
-** Opcode: RegMakeRec P1 P2 P3 P4 *
-**
-** Builds a record like OP_MakeRecord.  But the data is taken from
-** P2 registers beginning with P1:  P1, P1+1, P1+2, ..., P1+P2-1.
-** The result is written into P3 or pushed onto the stack if P3 is zero.
-** There is no jump on NULL - that can be done with a separate
-** OP_AnyNull opcode.
-*/
-case OP_RegMakeRec:
-case OP_MakeRecord: {        /* jump */
+case OP_MakeRecord: {
   /* Assuming the record contains N fields, the record format looks
   ** like this:
   **
@@ -2380,41 +2342,20 @@
   int nZero = 0;         /* Number of zero bytes at the end of the record */
   int nVarint;           /* Number of bytes in a varint */
   u32 serial_type;       /* Type field */
-  int containsNull = 0;  /* True if any of the data fields are NULL */
-  Mem *pData0;           /* Bottom of the stack */
-  Mem *pLast;            /* Top of the stack */
-  int leaveOnStack;      /* If true, leave the entries on the stack */
+  Mem *pData0;           /* First field to be combined into the record */
+  Mem *pLast;            /* Last field of the record */
   int nField;            /* Number of fields in the record */
-  int jumpIfNull;        /* Jump here if non-zero and any entries are NULL. */
   char *zAffinity;       /* The affinity string for the record */
   int file_format;       /* File format to use for encoding */
   int i;                 /* Space used in zNewRecord[] */
   char zTemp[NBFS];      /* Space to hold small records */
 
-  if( pOp->p1<0 ){
-    assert( pOp->opcode==OP_MakeRecord );
-    leaveOnStack = 1;
-    nField = -pOp->p1;
-  }else{
-    leaveOnStack = 0;
-    nField = pOp->p1;
-  }
+  nField = pOp->p1;
   zAffinity = pOp->p4.z;
-
-  if( pOp->opcode==OP_RegMakeRec ){
-    assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
-    pData0 = &p->aMem[nField];
-    nField = pOp->p2;
-    leaveOnStack = 1;
-    jumpIfNull = 0;
-    pLast = &pData0[nField-1];
-  }else{
-    jumpIfNull = pOp->p2;
-    pData0 = &pTos[1-nField];
-    pLast = pTos;
-    assert( pData0>=p->aStack );
-  }
-  containsNull = 0;
+  assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
+  pData0 = &p->aMem[nField];
+  nField = pOp->p2;
+  pLast = &pData0[nField-1];
   file_format = p->minWriteFileFormat;
 
   /* Loop through the elements that will make up the record to figure
@@ -2425,9 +2366,6 @@
     if( zAffinity ){
       applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
     }
-    if( pRec->flags&MEM_Null ){
-      containsNull = 1;
-    }
     if( pRec->flags&MEM_Zero && pRec->n>0 ){
       ExpandBlob(pRec);
     }
@@ -2475,10 +2413,6 @@
   }
   assert( i==nByte );
 
-  /* Pop entries off the stack if required. Push the new record on. */
-  if( !leaveOnStack ){
-    popStack(&pTos, nField);
-  }
   if( pOp->p3==0 ){
     pOut = ++pTos;
   }else{
@@ -2504,11 +2438,6 @@
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
   REGISTER_TRACE(pOp->p3, pOut);
   UPDATE_MAX_BLOBSIZE(pOut);
-
-  /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
-  if( jumpIfNull && containsNull ){
-    pc = jumpIfNull - 1;
-  }
   break;
 }
 
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 9d1592f..95d4818 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -717,11 +717,17 @@
 void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
   char *zP4;
   char zPtr[50];
-  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X\n";
+  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
   if( pOut==0 ) pOut = stdout;
   zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
   fprintf(pOut, zFormat1, pc, 
-      sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5);
+      sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
+#ifdef SQLITE_DEBUG
+      pOp->zComment ? pOp->zComment : ""
+#else
+      ""
+#endif
+  );
   fflush(pOut);
 }
 #endif
diff --git a/src/where.c b/src/where.c
index 90d2b87..e046ba6 100644
--- a/src/where.c
+++ b/src/where.c
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.281 2008/01/12 19:03:49 drh Exp $
+** $Id: where.c,v 1.282 2008/01/17 02:36:28 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1705,9 +1705,13 @@
 static void buildIndexProbe(
   Vdbe *v,        /* Generate code into this VM */
   int nColumn,    /* The number of columns to check for NULL */
-  Index *pIdx     /* Index that we will be searching */
+  Index *pIdx,    /* Index that we will be searching */
+  int regSrc,     /* Take values from this register */
+  int regDest     /* Write the result into this register */
 ){
-  sqlite3VdbeAddOp2(v, OP_MakeRecord, nColumn, 0);
+  assert( regSrc>0 );
+  assert( regDest>0 );
+  sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
   sqlite3IndexAffinityStr(v, pIdx);
 }
 
@@ -1717,7 +1721,7 @@
 ** term can be either X=expr or X IN (...).   pTerm is the term to be 
 ** coded.
 **
-** The current value for the constraint is left on the top of the stack.
+** The current value for the constraint is left in register iReg.
 **
 ** For a constraint of the form X=expr, the expression is evaluated and its
 ** result is left on the stack.  For constraints of the form X IN (...)
@@ -1726,14 +1730,17 @@
 static void codeEqualityTerm(
   Parse *pParse,      /* The parsing context */
   WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
-  WhereLevel *pLevel  /* When level of the FROM clause we are working on */
+  WhereLevel *pLevel, /* When level of the FROM clause we are working on */
+  int iReg            /* Leave results in this register */
 ){
   Expr *pX = pTerm->pExpr;
   Vdbe *v = pParse->pVdbe;
+
+  assert( iReg>0 && iReg<=pParse->nMem );
   if( pX->op==TK_EQ ){
-    sqlite3ExprCode(pParse, pX->pRight, 0);
+    sqlite3ExprCode(pParse, pX->pRight, iReg);
   }else if( pX->op==TK_ISNULL ){
-    sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
+    sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
 #ifndef SQLITE_OMIT_SUBQUERY
   }else{
     int eType;
@@ -1753,11 +1760,14 @@
                                     sizeof(pLevel->aInLoop[0])*pLevel->nIn);
     pIn = pLevel->aInLoop;
     if( pIn ){
-      int op = ((eType==IN_INDEX_ROWID)?OP_Rowid:OP_Column);
       pIn += pLevel->nIn - 1;
       pIn->iCur = iTab;
-      pIn->topAddr = sqlite3VdbeAddOp2(v, op, iTab, 0);
-      sqlite3VdbeAddOp2(v, OP_StackIsNull, -1, 0);
+      if( eType==IN_INDEX_ROWID ){
+        pIn->topAddr = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
+      }else{
+        pIn->topAddr = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
+      }
+      sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
     }else{
       pLevel->nIn = 0;
     }
@@ -1789,30 +1799,29 @@
 ** this routine allocates an additional nEq memory cells for internal
 ** use.
 */
-static void codeAllEqualityTerms(
+static int codeAllEqualityTerms(
   Parse *pParse,        /* Parsing context */
   WhereLevel *pLevel,   /* Which nested loop of the FROM we are coding */
   WhereClause *pWC,     /* The WHERE clause */
-  Bitmask notReady      /* Which parts of FROM have not yet been coded */
+  Bitmask notReady,     /* Which parts of FROM have not yet been coded */
+  int nExtraReg         /* Number of extra registers to allocate */
 ){
   int nEq = pLevel->nEq;        /* The number of == or IN constraints to code */
-  int termsInMem = 0;           /* If true, store value in mem[] cells */
   Vdbe *v = pParse->pVdbe;      /* The virtual machine under construction */
   Index *pIdx = pLevel->pIdx;   /* The index being used for this loop */
   int iCur = pLevel->iTabCur;   /* The cursor of the table */
   WhereTerm *pTerm;             /* A single constraint term */
   int j;                        /* Loop counter */
+  int regBase;                  /* Base register */
 
   /* Figure out how many memory cells we will need then allocate them.
   ** We always need at least one used to store the loop terminator
   ** value.  If there are IN operators we'll need one for each == or
   ** IN constraint.
   */
-  pLevel->iMem = ++pParse->nMem;
-  if( pLevel->flags & WHERE_COLUMN_IN ){
-    pParse->nMem += pLevel->nEq;
-    termsInMem = 1;
-  }
+  pLevel->iMem = pParse->nMem + 1;
+  regBase = pParse->nMem + 2;
+  pParse->nMem += pLevel->nEq + 2 + nExtraReg;
 
   /* Evaluate the equality constraints
   */
@@ -1822,22 +1831,12 @@
     pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
     if( pTerm==0 ) break;
     assert( (pTerm->flags & TERM_CODED)==0 );
-    codeEqualityTerm(pParse, pTerm, pLevel);
+    codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
     if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
-      sqlite3VdbeAddOp2(v, OP_StackIsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
-    }
-    if( termsInMem ){
-      sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1);
+      sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk);
     }
   }
-
-  /* Make sure all the constraint values are on the top of the stack
-  */
-  if( termsInMem ){
-    for(j=0; j<nEq; j++){
-      sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem+j+1, 0);
-    }
-  }
+  return regBase;
 }
 
 #if defined(SQLITE_TEST)
@@ -2285,24 +2284,23 @@
       const struct sqlite3_index_constraint *aConstraint =
                                                   pBestIdx->aConstraint;
 
+      iReg = sqlite3GetTempRange(pParse, nConstraint+2);
       for(j=1; j<=nConstraint; j++){
         int k;
         for(k=0; k<nConstraint; k++){
           if( aUsage[k].argvIndex==j ){
             int iTerm = aConstraint[k].iTermOffset;
-            sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight, 0);
+            sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight, iReg+j+1);
             break;
           }
         }
         if( k==nConstraint ) break;
       }
-      iReg = ++pParse->nMem;
-      pParse->nMem++;
-      sqlite3StackToReg(pParse, j-1);
       sqlite3VdbeAddOp2(v, OP_Integer, pBestIdx->idxNum, iReg);
       sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
       sqlite3VdbeAddOp4(v, OP_VFilter, iCur, brk, iReg, pBestIdx->idxStr,
                         pBestIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
+      sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
       pBestIdx->needToFreeIdxStr = 0;
       for(j=0; j<pBestIdx->nConstraint; j++){
         if( aUsage[j].omit ){
@@ -2322,16 +2320,19 @@
       **          we reference multiple rows using a "rowid IN (...)"
       **          construct.
       */
+      int r1;
       pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
       assert( pTerm!=0 );
       assert( pTerm->pExpr!=0 );
       assert( pTerm->leftCursor==iCur );
       assert( omitTable==0 );
-      codeEqualityTerm(pParse, pTerm, pLevel);
+      r1 = sqlite3GetTempReg(pParse);
+      codeEqualityTerm(pParse, pTerm, pLevel, r1);
       nxt = pLevel->nxt;
-      sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, nxt, 1);
-      sqlite3VdbeAddOp2(v, OP_NotExists, iCur, nxt);
+      sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, nxt, 1);
+      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
       VdbeComment((v, "pk"));
+      sqlite3ReleaseTempReg(pParse, r1);
       pLevel->op = OP_Noop;
     }else if( pLevel->flags & WHERE_ROWID_RANGE ){
       /* Case 2:  We have an inequality comparison against the ROWID field.
@@ -2350,14 +2351,16 @@
       }
       if( pStart ){
         Expr *pX;
+        int r1, regFree1;
         pX = pStart->pExpr;
         assert( pX!=0 );
         assert( pStart->leftCursor==iCur );
-        sqlite3ExprCode(pParse, pX->pRight, 0);
-        sqlite3VdbeAddOp3(v, OP_ForceInt, 0, brk, 
+        r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &regFree1);
+        sqlite3VdbeAddOp3(v, OP_ForceInt, r1, brk, 
                              pX->op==TK_LE || pX->op==TK_GT);
-        sqlite3VdbeAddOp2(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);
+        sqlite3VdbeAddOp3(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk, r1);
         VdbeComment((v, "pk"));
+        sqlite3ReleaseTempReg(pParse, regFree1);
         disableTerm(pLevel, pStart);
       }else{
         sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
@@ -2367,9 +2370,8 @@
         pX = pEnd->pExpr;
         assert( pX!=0 );
         assert( pEnd->leftCursor==iCur );
-        sqlite3ExprCode(pParse, pX->pRight, 0);
         pLevel->iMem = ++pParse->nMem;
-        sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
+        sqlite3ExprCode(pParse, pX->pRight, pLevel->iMem);
         if( pX->op==TK_LT || pX->op==TK_GT ){
           testOp = bRev ? OP_Le : OP_Ge;
         }else{
@@ -2382,10 +2384,12 @@
       pLevel->p1 = iCur;
       pLevel->p2 = start;
       if( testOp!=OP_Noop ){
-        sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
-        sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
-        sqlite3VdbeAddOp2(v, testOp, 0, brk);
+        int r1 = sqlite3GetTempReg(pParse);
+        sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
+        /* sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); */
+        sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1);
         sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
+        sqlite3ReleaseTempReg(pParse, r1);
       }
     }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
       /* Case 3: The WHERE clause term that refers to the right-most
@@ -2408,19 +2412,13 @@
       int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;
       int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;
       int isMinQuery = 0;      /* If this is an optimized SELECT min(x) ... */
+      int regBase;        /* Base register holding constraint values */
+      int r1;             /* Temp register */
 
       /* Generate code to evaluate all constraint terms using == or IN
       ** and level the values of those terms on the stack.
       */
-      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
-
-      /* Duplicate the equality term values because they will all be
-      ** used twice: once to make the termination key and once to make the
-      ** start key.
-      */
-      for(j=0; j<nEq; j++){
-        sqlite3VdbeAddOp1(v, OP_Copy, 1-nEq);
-      }
+      regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 2);
 
       /* Figure out what comparison operators to use for top and bottom 
       ** search bounds. For an ascending index, the bottom bound is a > or >=
@@ -2462,13 +2460,13 @@
       nxt = pLevel->nxt;
       if( topLimit ){
         Expr *pX;
-        int k = pIdx->aiColumn[j];
+        int k = pIdx->aiColumn[nEq];
         pTerm = findTerm(&wc, iCur, k, notReady, topOp, pIdx);
         assert( pTerm!=0 );
         pX = pTerm->pExpr;
         assert( (pTerm->flags & TERM_CODED)==0 );
-        sqlite3ExprCode(pParse, pX->pRight, 0);
-        sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq*2+1), nxt);
+        sqlite3ExprCode(pParse, pX->pRight, regBase+nEq);
+        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
         topEq = pTerm->eOperator & (WO_LE|WO_GE);
         disableTerm(pLevel, pTerm);
         testOp = OP_IdxGE;
@@ -2478,18 +2476,15 @@
       }
       if( testOp!=OP_Noop || (isMinQuery&&bRev) ){
         int nCol = nEq + topLimit;
-        pLevel->iMem = ++pParse->nMem;
         if( isMinQuery && !topLimit ){
+          sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol);
           nCol++;
-          sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
           topEq = 0;
         }
-        buildIndexProbe(v, nCol, pIdx);
+        buildIndexProbe(v, nCol, pIdx, regBase, pLevel->iMem);
         if( bRev ){
           int op = topEq ? OP_MoveLe : OP_MoveLt;
-          sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
-        }else{
-          sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
+          sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, pLevel->iMem);
         }
       }else if( bRev ){
         sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk);
@@ -2506,13 +2501,13 @@
       */
       if( btmLimit ){
         Expr *pX;
-        int k = pIdx->aiColumn[j];
+        int k = pIdx->aiColumn[nEq];
         pTerm = findTerm(&wc, iCur, k, notReady, btmOp, pIdx);
         assert( pTerm!=0 );
         pX = pTerm->pExpr;
         assert( (pTerm->flags & TERM_CODED)==0 );
-        sqlite3ExprCode(pParse, pX->pRight, 0);
-        sqlite3VdbeAddOp2(v, OP_StackIsNull, -(nEq+1), nxt);
+        sqlite3ExprCode(pParse, pX->pRight, regBase+nEq);
+        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
         btmEq = pTerm->eOperator & (WO_LE|WO_GE);
         disableTerm(pLevel, pTerm);
       }else{
@@ -2521,18 +2516,21 @@
       if( nEq>0 || btmLimit || (isMinQuery&&!bRev) ){
         int nCol = nEq + btmLimit;
         if( isMinQuery && !btmLimit ){
+          sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nCol);
           nCol++;
-          sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
           btmEq = 0;
         }
-        buildIndexProbe(v, nCol, pIdx);
         if( bRev ){
-          pLevel->iMem = ++pParse->nMem;
-          sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
+          r1 = pLevel->iMem;
           testOp = OP_IdxLT;
         }else{
+          r1 = sqlite3GetTempReg(pParse);
+        }
+        buildIndexProbe(v, nCol, pIdx, regBase, r1);
+        if( !bRev ){
           int op = btmEq ? OP_MoveGe : OP_MoveGt;
-          sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
+          sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
+          sqlite3ReleaseTempReg(pParse, r1);
         }
       }else if( bRev ){
         testOp = OP_Noop;
@@ -2546,20 +2544,21 @@
       */
       start = sqlite3VdbeCurrentAddr(v);
       if( testOp!=OP_Noop ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
-        sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt);
+        sqlite3VdbeAddOp3(v, testOp, iIdxCur, nxt, pLevel->iMem);
         if( (topEq && !bRev) || (!btmEq && bRev) ){
           sqlite3VdbeChangeP5(v, 1);
         }
       }
+      r1 = sqlite3GetTempReg(pParse);
       if( topLimit | btmLimit ){
-        sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq);
-        sqlite3VdbeAddOp2(v, OP_StackIsNull, 1, cont);
+        sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
+        sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
       }
       if( !omitTable ){
-        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);
-        sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0);
+        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
+        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);
       }
+      sqlite3ReleaseTempReg(pParse, r1);
 
       /* Record the instruction used to terminate the loop.
       */
@@ -2573,11 +2572,13 @@
       int start;
       int nEq = pLevel->nEq;
       int isMinQuery = 0;      /* If this is an optimized SELECT min(x) ... */
+      int regBase;             /* Base register of array holding constraints */
+      int r1;
 
       /* Generate code to evaluate all constraint terms using == or IN
       ** and leave the values of those terms on the stack.
       */
-      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
+      regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1);
       nxt = pLevel->nxt;
 
       if( (obflag==ORDERBY_MIN)
@@ -2585,21 +2586,17 @@
        && (pIdx->nColumn>nEq)
        && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
       ){
-        int h;
         isMinQuery = 1;
-        for(h=0; h<nEq; h++){
-          sqlite3VdbeAddOp1(v, OP_Copy, 1-nEq);
-        }
-        buildIndexProbe(v, nEq, pIdx);
-        sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
-        sqlite3VdbeAddOp2(v, OP_Null, 0, 0);
-        buildIndexProbe(v, nEq+1, pIdx);
+        buildIndexProbe(v, nEq, pIdx, regBase, pLevel->iMem);
+        sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
+        r1 = ++pParse->nMem;
+        buildIndexProbe(v, nEq+1, pIdx, regBase, r1);
       }else{
         /* Generate a single key that will be used to both start and 
         ** terminate the search
         */
-        buildIndexProbe(v, nEq, pIdx);
-        sqlite3VdbeAddOp2(v, OP_Copy, 0, pLevel->iMem);
+        r1 = pLevel->iMem;
+        buildIndexProbe(v, nEq, pIdx, regBase, r1);
       }
 
       /* Generate code (1) to move to the first matching element of the table.
@@ -2609,21 +2606,33 @@
       ** iteration of the scan to see if the scan has finished. */
       if( bRev ){
         /* Scan in reverse order */
-        sqlite3VdbeAddOp2(v, (isMinQuery?OP_MoveLt:OP_MoveLe), iIdxCur, nxt);
-        start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
-        sqlite3VdbeAddOp2(v, OP_IdxLT, iIdxCur, nxt);
+        int op;
+        if( isMinQuery ){
+          op = OP_MoveLt;
+        }else{
+          op = OP_MoveLe;
+        }
+        sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
+        start = sqlite3VdbeAddOp3(v, OP_IdxLT, iIdxCur, nxt, pLevel->iMem);
         pLevel->op = OP_Prev;
       }else{
         /* Scan in the forward order */
-        sqlite3VdbeAddOp2(v, (isMinQuery?OP_MoveGt:OP_MoveGe), iIdxCur, nxt);
-        start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
-        sqlite3VdbeAddOp2(v, OP_IdxGE, iIdxCur, nxt);
+        int op;
+        if( isMinQuery ){
+          op = OP_MoveGt;
+        }else{
+          op = OP_MoveGe;
+        }
+        sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
+        start = sqlite3VdbeAddOp3(v, OP_IdxGE, iIdxCur, nxt, pLevel->iMem);
         sqlite3VdbeChangeP5(v, 1);
         pLevel->op = OP_Next;
       }
       if( !omitTable ){
-        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);
-        sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0);
+        r1 = sqlite3GetTempReg(pParse);
+        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
+        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);
+        sqlite3ReleaseTempReg(pParse, r1);
       }
       pLevel->p1 = iIdxCur;
       pLevel->p2 = start;