Add the new OP_Once opcode.  Use it to clean up and simplify various
one-time initialization sections in the code, including the fix for
ticket [002caede898ae].

FossilOrigin-Name: 7f00552b739fad79517b042a6ed61abe743a917b
diff --git a/src/expr.c b/src/expr.c
index 7bfcf57..6fd08b2 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1462,8 +1462,7 @@
       int iMem = ++pParse->nMem;
       int iAddr;
 
-      iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
-      sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+      iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
 
       sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
       eType = IN_INDEX_ROWID;
@@ -1494,8 +1493,7 @@
           char *pKey;
   
           pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
-          iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
-          sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
+          iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
   
           sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                                pKey,P4_KEYINFO_HANDOFF);
@@ -1580,6 +1578,7 @@
   int rReg = 0;                           /* Register storing resulting */
   Vdbe *v = sqlite3GetVdbe(pParse);
   if( NEVER(v==0) ) return 0;
+  assert( sqlite3VdbeCurrentAddr(v)>0 );
   sqlite3ExprCachePush(pParse);
 
   /* This code must be run in its entirety every time it is encountered
@@ -1594,8 +1593,7 @@
   */
   if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
     int mem = ++pParse->nMem;
-    sqlite3VdbeAddOp1(v, OP_If, mem);
-    testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
+    testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
     assert( testAddr>0 || pParse->db->mallocFailed );
   }
 
@@ -1695,7 +1693,7 @@
           ** expression we need to rerun this code each time.
           */
           if( testAddr && !sqlite3ExprIsConstant(pE2) ){
-            sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
+            sqlite3VdbeChangeToNoop(v, testAddr);
             testAddr = 0;
           }
 
@@ -1766,7 +1764,7 @@
   }
 
   if( testAddr ){
-    sqlite3VdbeJumpHere(v, testAddr-1);
+    sqlite3VdbeJumpHere(v, testAddr);
   }
   sqlite3ExprCachePop(pParse, 1);
 
diff --git a/src/select.c b/src/select.c
index 2ddc751..277f5c0 100644
--- a/src/select.c
+++ b/src/select.c
@@ -3831,7 +3831,7 @@
       ** is a register allocated to hold the subroutine return address
       */
       int topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
-      int regOnce = 0;
+      int onceAddr = 0;
       assert( pItem->addrFillSub==0 );
       pItem->addrFillSub = topAddr+1;
       pItem->regReturn = ++pParse->nMem;
@@ -3839,15 +3839,14 @@
         /* If the subquery is no correlated and if we are not inside of
         ** a trigger, then we only need to compute the value of the subquery
         ** once. */
-        regOnce = ++pParse->nMem;
-        sqlite3VdbeAddOp1(v, OP_If, regOnce);
-        sqlite3VdbeAddOp2(v, OP_Integer, 1, regOnce);
+        int regOnce = ++pParse->nMem;
+        onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
       }
       sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
       explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
       sqlite3Select(pParse, pSub, &dest);
       pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
-      if( regOnce ) sqlite3VdbeJumpHere(v, topAddr+1);
+      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
       sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
       sqlite3VdbeJumpHere(v, topAddr);
       sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1);
@@ -3991,7 +3990,7 @@
     ** into an OP_Noop.
     */
     if( addrSortIndex>=0 && pOrderBy==0 ){
-      sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
+      sqlite3VdbeChangeToNoop(v, addrSortIndex);
       p->addrOpenEphm[2] = -1;
     }
 
@@ -4274,7 +4273,7 @@
         sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
       }else{
         sqlite3WhereEnd(pWInfo);
-        sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
+        sqlite3VdbeChangeToNoop(v, addrSortingIdx);
       }
 
       /* Output the final row of result
diff --git a/src/vdbe.c b/src/vdbe.c
index 906058c..4f7fd6b 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -2021,6 +2021,16 @@
   break;
 }
 
+/* Opcode: Once P1 P2 * * *
+**
+** Jump to P2 if the value in register P1 is a not null or zero.  If
+** the value is NULL or zero, fall through and change the P1 register
+** to an integer 1.
+**
+** When P1 is not used otherwise in a program, this opcode falls through
+** once and jumps on all subsequent invocations.  It is the equivalent
+** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
+*/
 /* Opcode: If P1 P2 P3 * *
 **
 ** Jump to P2 if the value in register P1 is true.  The value
@@ -2033,6 +2043,7 @@
 ** is considered true if it has a numeric value of zero.  If the value
 ** in P1 is NULL then take the jump if P3 is true.
 */
+case OP_Once:               /* jump, in1 */
 case OP_If:                 /* jump, in1 */
 case OP_IfNot: {            /* jump, in1 */
   int c;
@@ -2049,6 +2060,12 @@
   }
   if( c ){
     pc = pOp->p2-1;
+  }else if( pOp->opcode==OP_Once ){
+    assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
+    memAboutToChange(p, pIn1);
+    pIn1->flags = MEM_Int;
+    pIn1->u.i = 1;
+    REGISTER_TRACE(pOp->p1, pIn1);
   }
   break;
 }
diff --git a/src/vdbe.h b/src/vdbe.h
index f4691c0..948c73b 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -180,7 +180,7 @@
 void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
 void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
 void sqlite3VdbeJumpHere(Vdbe*, int addr);
-void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
+void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
 void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
 void sqlite3VdbeUsesBtree(Vdbe*, int);
 VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index b007684..1d5f713 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -670,18 +670,15 @@
 }
 
 /*
-** Change N opcodes starting at addr to No-ops.
+** Change the opcode at addr into OP_Noop
 */
-void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
+void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
   if( p->aOp ){
     VdbeOp *pOp = &p->aOp[addr];
     sqlite3 *db = p->db;
-    while( N-- ){
-      freeP4(db, pOp->p4type, pOp->p4.p);
-      memset(pOp, 0, sizeof(pOp[0]));
-      pOp->opcode = OP_Noop;
-      pOp++;
-    }
+    freeP4(db, pOp->p4type, pOp->p4.p);
+    memset(pOp, 0, sizeof(pOp[0]));
+    pOp->opcode = OP_Noop;
   }
 }
 
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index a8728e6..ae77a47 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -273,7 +273,7 @@
 
       /* Configure the OP_TableLock instruction */
 #ifdef SQLITE_OMIT_SHARED_CACHE
-      sqlite3VdbeChangeToNoop(v, 2, 1);
+      sqlite3VdbeChangeToNoop(v, 2);
 #else
       sqlite3VdbeChangeP1(v, 2, iDb);
       sqlite3VdbeChangeP2(v, 2, pTab->tnum);
@@ -283,7 +283,7 @@
 
       /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
       ** parameter of the other to pTab->tnum.  */
-      sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
+      sqlite3VdbeChangeToNoop(v, 4 - flags);
       sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
       sqlite3VdbeChangeP3(v, 3 + flags, iDb);
 
diff --git a/src/where.c b/src/where.c
index 21fb7f4..17490b0 100644
--- a/src/where.c
+++ b/src/where.c
@@ -1994,8 +1994,7 @@
   v = pParse->pVdbe;
   assert( v!=0 );
   regIsInit = ++pParse->nMem;
-  addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
-  sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
+  addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
 
   /* Count the number of columns that will be added to the index
   ** and used to match WHERE clause constraints */