Backport r69961 to trunk, replacing JUMP_IF_{TRUE,FALSE} with
POP_JUMP_IF_{TRUE,FALSE} and JUMP_IF_{TRUE,FALSE}_OR_POP. This avoids executing
a POP_TOP on each conditional and sometimes allows the peephole optimizer to
skip a JUMP_ABSOLUTE entirely. It speeds up list comprehensions significantly.
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py
index 5098f2c..be0255d 100644
--- a/Lib/compiler/pyassem.py
+++ b/Lib/compiler/pyassem.py
@@ -122,6 +122,9 @@
     for b in remaining:
         if __debug__ and b.next:
             assert b is b.next[0].prev[0], (b, b.next)
+        # Make sure every block appears in dominators, even if no
+        # other block must precede it.
+        dominators.setdefault(b, set())
         # preceeding blocks dominate following blocks
         for c in b.get_followers():
             while 1:
diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py
index 6d5a41c..81234d1 100644
--- a/Lib/compiler/pycodegen.py
+++ b/Lib/compiler/pycodegen.py
@@ -421,13 +421,11 @@
             self.set_lineno(test)
             self.visit(test)
             nextTest = self.newBlock()
-            self.emit('JUMP_IF_FALSE', nextTest)
+            self.emit('POP_JUMP_IF_FALSE', nextTest)
             self.nextBlock()
-            self.emit('POP_TOP')
             self.visit(suite)
             self.emit('JUMP_FORWARD', end)
             self.startBlock(nextTest)
-            self.emit('POP_TOP')
         if node.else_:
             self.visit(node.else_)
         self.nextBlock(end)
@@ -446,15 +444,13 @@
 
         self.set_lineno(node, force=True)
         self.visit(node.test)
-        self.emit('JUMP_IF_FALSE', else_ or after)
+        self.emit('POP_JUMP_IF_FALSE', else_ or after)
 
         self.nextBlock()
-        self.emit('POP_TOP')
         self.visit(node.body)
         self.emit('JUMP_ABSOLUTE', loop)
 
         self.startBlock(else_) # or just the POPs if not else clause
-        self.emit('POP_TOP')
         self.emit('POP_BLOCK')
         self.setups.pop()
         if node.else_:
@@ -525,26 +521,23 @@
             self.visit(child)
             self.emit(jump, end)
             self.nextBlock()
-            self.emit('POP_TOP')
         self.visit(node.nodes[-1])
         self.nextBlock(end)
 
     def visitAnd(self, node):
-        self.visitTest(node, 'JUMP_IF_FALSE')
+        self.visitTest(node, 'JUMP_IF_FALSE_OR_POP')
 
     def visitOr(self, node):
-        self.visitTest(node, 'JUMP_IF_TRUE')
+        self.visitTest(node, 'JUMP_IF_TRUE_OR_POP')
 
     def visitIfExp(self, node):
         endblock = self.newBlock()
         elseblock = self.newBlock()
         self.visit(node.test)
-        self.emit('JUMP_IF_FALSE', elseblock)
-        self.emit('POP_TOP')
+        self.emit('POP_JUMP_IF_FALSE', elseblock)
         self.visit(node.then)
         self.emit('JUMP_FORWARD', endblock)
         self.nextBlock(elseblock)
-        self.emit('POP_TOP')
         self.visit(node.else_)
         self.nextBlock(endblock)
 
@@ -556,9 +549,8 @@
             self.emit('DUP_TOP')
             self.emit('ROT_THREE')
             self.emit('COMPARE_OP', op)
-            self.emit('JUMP_IF_FALSE', cleanup)
+            self.emit('JUMP_IF_FALSE_OR_POP', cleanup)
             self.nextBlock()
-            self.emit('POP_TOP')
         # now do the last comparison
         if node.ops:
             op, code = node.ops[-1]
@@ -593,11 +585,7 @@
 
         for start, cont, anchor in stack:
             if cont:
-                skip_one = self.newBlock()
-                self.emit('JUMP_FORWARD', skip_one)
-                self.startBlock(cont)
-                self.emit('POP_TOP')
-                self.nextBlock(skip_one)
+                self.nextBlock(cont)
             self.emit('JUMP_ABSOLUTE', start)
             self.startBlock(anchor)
 
@@ -617,9 +605,8 @@
     def visitListCompIf(self, node, branch):
         self.set_lineno(node, force=True)
         self.visit(node.test)
-        self.emit('JUMP_IF_FALSE', branch)
+        self.emit('POP_JUMP_IF_FALSE', branch)
         self.newBlock()
-        self.emit('POP_TOP')
 
     def _makeClosure(self, gen, args):
         frees = gen.scope.get_free_vars()
@@ -665,11 +652,7 @@
 
         for start, cont, anchor, end in stack:
             if cont:
-                skip_one = self.newBlock()
-                self.emit('JUMP_FORWARD', skip_one)
-                self.startBlock(cont)
-                self.emit('POP_TOP')
-                self.nextBlock(skip_one)
+                self.nextBlock(cont)
             self.emit('JUMP_ABSOLUTE', start)
             self.startBlock(anchor)
             self.emit('POP_BLOCK')
@@ -702,9 +685,8 @@
     def visitGenExprIf(self, node, branch):
         self.set_lineno(node, force=True)
         self.visit(node.test)
-        self.emit('JUMP_IF_FALSE', branch)
+        self.emit('POP_JUMP_IF_FALSE', branch)
         self.newBlock()
-        self.emit('POP_TOP')
 
     # exception related
 
@@ -719,9 +701,8 @@
             # is a sort of renaming op.
             self.nextBlock()
             self.visit(node.test)
-            self.emit('JUMP_IF_TRUE', end)
+            self.emit('POP_JUMP_IF_TRUE', end)
             self.nextBlock()
-            self.emit('POP_TOP')
             self.emit('LOAD_GLOBAL', 'AssertionError')
             if node.fail:
                 self.visit(node.fail)
@@ -729,7 +710,6 @@
             else:
                 self.emit('RAISE_VARARGS', 1)
             self.nextBlock(end)
-            self.emit('POP_TOP')
 
     def visitRaise(self, node):
         self.set_lineno(node)
@@ -772,9 +752,8 @@
                 self.visit(expr)
                 self.emit('COMPARE_OP', 'exception match')
                 next = self.newBlock()
-                self.emit('JUMP_IF_FALSE', next)
+                self.emit('POP_JUMP_IF_FALSE', next)
                 self.nextBlock()
-                self.emit('POP_TOP')
             self.emit('POP_TOP')
             if target:
                 self.visit(target)
@@ -787,8 +766,6 @@
                 self.nextBlock(next)
             else:
                 self.nextBlock()
-            if expr: # XXX
-                self.emit('POP_TOP')
         self.emit('END_FINALLY')
         if node.else_:
             self.nextBlock(lElse)
diff --git a/Lib/opcode.py b/Lib/opcode.py
index d41383b..24d5dcc 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -146,9 +146,11 @@
 name_op('IMPORT_FROM', 108)     # Index in name list
 
 jrel_op('JUMP_FORWARD', 110)    # Number of bytes to skip
-jrel_op('JUMP_IF_FALSE', 111)   # ""
-jrel_op('JUMP_IF_TRUE', 112)    # ""
-jabs_op('JUMP_ABSOLUTE', 113)   # Target byte offset from beginning of code
+jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
+jabs_op('JUMP_IF_TRUE_OR_POP', 112)  # ""
+jabs_op('JUMP_ABSOLUTE', 113)        # ""
+jabs_op('POP_JUMP_IF_FALSE', 114)    # ""
+jabs_op('POP_JUMP_IF_TRUE', 115)     # ""
 
 name_op('LOAD_GLOBAL', 116)     # Index in name list
 
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 6fa437b..613d30a 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -54,25 +54,23 @@
 
 dis_bug1333982 = """\
  %-4d         0 LOAD_CONST               1 (0)
-              3 JUMP_IF_TRUE            33 (to 39)
-              6 POP_TOP
-              7 LOAD_GLOBAL              0 (AssertionError)
-             10 BUILD_LIST               0
-             13 LOAD_FAST                0 (x)
-             16 GET_ITER
-        >>   17 FOR_ITER                12 (to 32)
-             20 STORE_FAST               1 (s)
-             23 LOAD_FAST                1 (s)
-             26 LIST_APPEND              2
-             29 JUMP_ABSOLUTE           17
+              3 POP_JUMP_IF_TRUE        38
+              6 LOAD_GLOBAL              0 (AssertionError)
+              9 BUILD_LIST               0
+             12 LOAD_FAST                0 (x)
+             15 GET_ITER
+        >>   16 FOR_ITER                12 (to 31)
+             19 STORE_FAST               1 (s)
+             22 LOAD_FAST                1 (s)
+             25 LIST_APPEND              2
+             28 JUMP_ABSOLUTE           16
 
- %-4d   >>   32 LOAD_CONST               2 (1)
-             35 BINARY_ADD
-             36 RAISE_VARARGS            2
-        >>   39 POP_TOP
+ %-4d   >>   31 LOAD_CONST               2 (1)
+             34 BINARY_ADD
+             35 RAISE_VARARGS            2
 
- %-4d        40 LOAD_CONST               0 (None)
-             43 RETURN_VALUE
+ %-4d   >>   38 LOAD_CONST               0 (None)
+             41 RETURN_VALUE
 """%(bug1333982.func_code.co_firstlineno + 1,
      bug1333982.func_code.co_firstlineno + 2,
      bug1333982.func_code.co_firstlineno + 3)
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py
index c547984..6638a5a 100644
--- a/Lib/test/test_peepholer.py
+++ b/Lib/test/test_peepholer.py
@@ -19,15 +19,14 @@
 class TestTranforms(unittest.TestCase):
 
     def test_unot(self):
-        # UNARY_NOT JUMP_IF_FALSE POP_TOP  -->  JUMP_IF_TRUE POP_TOP'
+        # UNARY_NOT POP_JUMP_IF_FALSE  -->  POP_JUMP_IF_TRUE
         def unot(x):
             if not x == 2:
                 del x
         asm = disassemble(unot)
-        for elem in ('UNARY_NOT', 'JUMP_IF_FALSE'):
+        for elem in ('UNARY_NOT', 'POP_JUMP_IF_FALSE'):
             self.assert_(elem not in asm)
-        for elem in ('JUMP_IF_TRUE', 'POP_TOP'):
-            self.assert_(elem in asm)
+        self.assert_('POP_JUMP_IF_TRUE' in asm)
 
     def test_elim_inversion_of_is_or_in(self):
         for line, elem in (
@@ -56,13 +55,13 @@
         self.assert_('LOAD_GLOBAL' not in disassemble(f))
 
     def test_while_one(self):
-        # Skip over:  LOAD_CONST trueconst  JUMP_IF_FALSE xx  POP_TOP
+        # Skip over:  LOAD_CONST trueconst  POP_JUMP_IF_FALSE xx
         def f():
             while 1:
                 pass
             return list
         asm = disassemble(f)
-        for elem in ('LOAD_CONST', 'JUMP_IF_FALSE'):
+        for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'):
             self.assert_(elem not in asm)
         for elem in ('JUMP_ABSOLUTE',):
             self.assert_(elem in asm)