]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: remove OFORUNTIL
authorKeith Randall <khr@golang.org>
Tue, 19 Jul 2022 20:15:05 +0000 (13:15 -0700)
committerKeith Randall <khr@google.com>
Thu, 18 Aug 2022 18:07:23 +0000 (18:07 +0000)
Not used any more.

Fixes #53860

Change-Id: Id0b1c3ed30b576d6c5f08f064d1262de337262b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/418374
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

12 files changed:
src/cmd/compile/internal/escape/stmt.go
src/cmd/compile/internal/ir/fmt.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/node_gen.go
src/cmd/compile/internal/ir/op_string.go
src/cmd/compile/internal/ir/stmt.go
src/cmd/compile/internal/ssa/prove.go
src/cmd/compile/internal/ssagen/ssa.go
src/cmd/compile/internal/typecheck/stmt.go
src/cmd/compile/internal/typecheck/typecheck.go
src/cmd/compile/internal/walk/range.go
src/cmd/compile/internal/walk/stmt.go

index 8b361bcbd0dfddf4e642659d4918b46ee26b6230..90d4f2dedcde8709bcc99a32ce1bf0b4c8616f84 100644 (file)
@@ -78,7 +78,7 @@ func (e *escape) stmt(n ir.Node) {
                n := n.(*ir.UnaryExpr)
                e.discard(n.X)
 
-       case ir.OFOR, ir.OFORUNTIL:
+       case ir.OFOR:
                n := n.(*ir.ForStmt)
                e.loopDepth++
                e.discard(n.Cond)
index 5912438d095a8632dae65872d590d658221cf252..f12054e657b117d797057729a24258870ca43682 100644 (file)
@@ -50,7 +50,6 @@ var OpNames = []string{
        OEQ:          "==",
        OFALL:        "fallthrough",
        OFOR:         "for",
-       OFORUNTIL:    "foruntil", // not actual syntax; used to avoid off-end pointer live on backedge.892
        OGE:          ">=",
        OGOTO:        "goto",
        OGT:          ">",
@@ -274,7 +273,6 @@ var OpPrec = []int{
        ODEFER:      -1,
        OFALL:       -1,
        OFOR:        -1,
-       OFORUNTIL:   -1,
        OGOTO:       -1,
        OIF:         -1,
        OLABEL:      -1,
@@ -290,7 +288,7 @@ var OpPrec = []int{
 // StmtWithInit reports whether op is a statement with an explicit init list.
 func StmtWithInit(op Op) bool {
        switch op {
-       case OIF, OFOR, OFORUNTIL, OSWITCH:
+       case OIF, OFOR, OSWITCH:
                return true
        }
        return false
@@ -401,18 +399,14 @@ func stmtFmt(n Node, s fmt.State) {
                        fmt.Fprintf(s, " else { %v }", n.Else)
                }
 
-       case OFOR, OFORUNTIL:
+       case OFOR:
                n := n.(*ForStmt)
-               opname := "for"
-               if n.Op() == OFORUNTIL {
-                       opname = "foruntil"
-               }
                if !exportFormat { // TODO maybe only if FmtShort, same below
-                       fmt.Fprintf(s, "%s loop", opname)
+                       fmt.Fprintf(s, "for loop")
                        break
                }
 
-               fmt.Fprint(s, opname)
+               fmt.Fprint(s, "for")
                if simpleinit {
                        fmt.Fprintf(s, " %v;", n.Init()[0])
                } else if n.Post != nil {
@@ -429,10 +423,6 @@ func stmtFmt(n Node, s fmt.State) {
                        fmt.Fprint(s, ";")
                }
 
-               if n.Op() == OFORUNTIL && len(n.Late) != 0 {
-                       fmt.Fprintf(s, "; %v", n.Late)
-               }
-
                fmt.Fprintf(s, " { %v }", n.Body)
 
        case ORANGE:
index 3b69f984265bbb44467d20eebc5dbf6f207aa1c2..0ce5339c12d01499103b59ecb6d7100019cd56ae 100644 (file)
@@ -263,24 +263,14 @@ const (
        ODEFER    // defer Call
        OFALL     // fallthrough
        OFOR      // for Init; Cond; Post { Body }
-       // OFORUNTIL is like OFOR, but the test (Cond) is applied after the body:
-       //      Init
-       //      top: { Body }   // Execute the body at least once
-       //      cont: Post
-       //      if Cond {        // And then test the loop condition
-       //              List     // Before looping to top, execute List
-       //              goto top
-       //      }
-       // OFORUNTIL is created by walk. There's no way to write this in Go code.
-       OFORUNTIL
-       OGOTO   // goto Label
-       OIF     // if Init; Cond { Then } else { Else }
-       OLABEL  // Label:
-       OGO     // go Call
-       ORANGE  // for Key, Value = range X { Body }
-       ORETURN // return Results
-       OSELECT // select { Cases }
-       OSWITCH // switch Init; Expr { Cases }
+       OGOTO     // goto Label
+       OIF       // if Init; Cond { Then } else { Else }
+       OLABEL    // Label:
+       OGO       // go Call
+       ORANGE    // for Key, Value = range X { Body }
+       ORETURN   // return Results
+       OSELECT   // select { Cases }
+       OSWITCH   // switch Init; Expr { Cases }
        // OTYPESW:  X := Y.(type) (appears as .Tag of OSWITCH)
        //   X is nil if there is no type-switch variable
        OTYPESW
index 6e14bea16918ba9b884c8c38c810b2100e231aed..108e3c494c96d9edfeed1d27dce6734333e2862a 100644 (file)
@@ -483,7 +483,6 @@ func (n *ForStmt) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
 func (n *ForStmt) copy() Node {
        c := *n
        c.init = copyNodes(c.init)
-       c.Late = copyNodes(c.Late)
        c.Body = copyNodes(c.Body)
        return &c
 }
@@ -494,9 +493,6 @@ func (n *ForStmt) doChildren(do func(Node) bool) bool {
        if n.Cond != nil && do(n.Cond) {
                return true
        }
-       if doNodes(n.Late, do) {
-               return true
-       }
        if n.Post != nil && do(n.Post) {
                return true
        }
@@ -510,7 +506,6 @@ func (n *ForStmt) editChildren(edit func(Node) Node) {
        if n.Cond != nil {
                n.Cond = edit(n.Cond).(Node)
        }
-       editNodes(n.Late, edit)
        if n.Post != nil {
                n.Post = edit(n.Post).(Node)
        }
index 5d475a799571ae2167519315743bbc5bf5a8e0d5..d2a933f9ec4cb977477ed82abed7d2afac1e1ab8 100644 (file)
@@ -129,44 +129,43 @@ func _() {
        _ = x[ODEFER-118]
        _ = x[OFALL-119]
        _ = x[OFOR-120]
-       _ = x[OFORUNTIL-121]
-       _ = x[OGOTO-122]
-       _ = x[OIF-123]
-       _ = x[OLABEL-124]
-       _ = x[OGO-125]
-       _ = x[ORANGE-126]
-       _ = x[ORETURN-127]
-       _ = x[OSELECT-128]
-       _ = x[OSWITCH-129]
-       _ = x[OTYPESW-130]
-       _ = x[OFUNCINST-131]
-       _ = x[OINLCALL-132]
-       _ = x[OEFACE-133]
-       _ = x[OITAB-134]
-       _ = x[OIDATA-135]
-       _ = x[OSPTR-136]
-       _ = x[OCFUNC-137]
-       _ = x[OCHECKNIL-138]
-       _ = x[OVARDEF-139]
-       _ = x[OVARKILL-140]
-       _ = x[OVARLIVE-141]
-       _ = x[ORESULT-142]
-       _ = x[OINLMARK-143]
-       _ = x[OLINKSYMOFFSET-144]
-       _ = x[OJUMPTABLE-145]
-       _ = x[ODYNAMICDOTTYPE-146]
-       _ = x[ODYNAMICDOTTYPE2-147]
-       _ = x[ODYNAMICTYPE-148]
-       _ = x[OTAILCALL-149]
-       _ = x[OGETG-150]
-       _ = x[OGETCALLERPC-151]
-       _ = x[OGETCALLERSP-152]
-       _ = x[OEND-153]
+       _ = x[OGOTO-121]
+       _ = x[OIF-122]
+       _ = x[OLABEL-123]
+       _ = x[OGO-124]
+       _ = x[ORANGE-125]
+       _ = x[ORETURN-126]
+       _ = x[OSELECT-127]
+       _ = x[OSWITCH-128]
+       _ = x[OTYPESW-129]
+       _ = x[OFUNCINST-130]
+       _ = x[OINLCALL-131]
+       _ = x[OEFACE-132]
+       _ = x[OITAB-133]
+       _ = x[OIDATA-134]
+       _ = x[OSPTR-135]
+       _ = x[OCFUNC-136]
+       _ = x[OCHECKNIL-137]
+       _ = x[OVARDEF-138]
+       _ = x[OVARKILL-139]
+       _ = x[OVARLIVE-140]
+       _ = x[ORESULT-141]
+       _ = x[OINLMARK-142]
+       _ = x[OLINKSYMOFFSET-143]
+       _ = x[OJUMPTABLE-144]
+       _ = x[ODYNAMICDOTTYPE-145]
+       _ = x[ODYNAMICDOTTYPE2-146]
+       _ = x[ODYNAMICTYPE-147]
+       _ = x[OTAILCALL-148]
+       _ = x[OGETG-149]
+       _ = x[OGETCALLERPC-150]
+       _ = x[OGETCALLERSP-151]
+       _ = x[OEND-152]
 }
 
-const _Op_name = "XXXNAMENONAMETYPELITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2REALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORFORUNTILGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETJUMPTABLEDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND"
+const _Op_name = "XXXNAMENONAMETYPELITERALNILADDSUBORXORADDSTRADDRANDANDAPPENDBYTES2STRBYTES2STRTMPRUNES2STRSTR2BYTESSTR2BYTESTMPSTR2RUNESSLICE2ARRPTRASAS2AS2DOTTYPEAS2FUNCAS2MAPRAS2RECVASOPCALLCALLFUNCCALLMETHCALLINTERCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVIDATACONVNOPCOPYDCLDCLFUNCDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTDEREFINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMAKESLICECOPYMULDIVMODLSHRSHANDANDNOTNEWNOTBITNOTPLUSNEGORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRSLICEHEADERRECOVERRECOVERFPRECVRUNESTRSELRECV2REALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFUNSAFEADDUNSAFESLICEMETHEXPRMETHVALUEBLOCKBREAKCASECONTINUEDEFERFALLFORGOTOIFLABELGORANGERETURNSELECTSWITCHTYPESWFUNCINSTINLCALLEFACEITABIDATASPTRCFUNCCHECKNILVARDEFVARKILLVARLIVERESULTINLMARKLINKSYMOFFSETJUMPTABLEDYNAMICDOTTYPEDYNAMICDOTTYPE2DYNAMICTYPETAILCALLGETGGETCALLERPCGETCALLERSPEND"
 
-var _Op_index = [...]uint16{0, 3, 7, 13, 17, 24, 27, 30, 33, 35, 38, 44, 48, 54, 60, 69, 81, 90, 99, 111, 120, 132, 134, 137, 147, 154, 161, 168, 172, 176, 184, 192, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 282, 289, 293, 296, 303, 311, 318, 324, 327, 333, 340, 348, 352, 359, 367, 369, 371, 373, 375, 377, 379, 384, 389, 397, 400, 409, 412, 416, 424, 431, 440, 453, 456, 459, 462, 465, 468, 471, 477, 480, 483, 489, 493, 496, 500, 505, 510, 516, 521, 525, 530, 538, 546, 552, 561, 572, 579, 588, 592, 599, 607, 611, 615, 622, 629, 637, 643, 652, 663, 671, 680, 685, 690, 694, 702, 707, 711, 714, 722, 726, 728, 733, 735, 740, 746, 752, 758, 764, 772, 779, 784, 788, 793, 797, 802, 810, 816, 823, 830, 836, 843, 856, 865, 879, 894, 905, 913, 917, 928, 939, 942}
+var _Op_index = [...]uint16{0, 3, 7, 13, 17, 24, 27, 30, 33, 35, 38, 44, 48, 54, 60, 69, 81, 90, 99, 111, 120, 132, 134, 137, 147, 154, 161, 168, 172, 176, 184, 192, 201, 204, 209, 216, 223, 229, 238, 246, 254, 260, 264, 273, 282, 289, 293, 296, 303, 311, 318, 324, 327, 333, 340, 348, 352, 359, 367, 369, 371, 373, 375, 377, 379, 384, 389, 397, 400, 409, 412, 416, 424, 431, 440, 453, 456, 459, 462, 465, 468, 471, 477, 480, 483, 489, 493, 496, 500, 505, 510, 516, 521, 525, 530, 538, 546, 552, 561, 572, 579, 588, 592, 599, 607, 611, 615, 622, 629, 637, 643, 652, 663, 671, 680, 685, 690, 694, 702, 707, 711, 714, 718, 720, 725, 727, 732, 738, 744, 750, 756, 764, 771, 776, 780, 785, 789, 794, 802, 808, 815, 822, 828, 835, 848, 857, 871, 886, 897, 905, 909, 920, 931, 934}
 
 func (i Op) String() string {
        if i >= Op(len(_Op_index)-1) {
index cae773b722716bb2679d2fb7002cfb208f867273..9f2d04f450554c8fb9d6e1b9de01697461fa65d4 100644 (file)
@@ -205,12 +205,10 @@ func NewCommStmt(pos src.XPos, comm Node, body []Node) *CommClause {
 }
 
 // A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
-// Op can be OFOR or OFORUNTIL (!Cond).
 type ForStmt struct {
        miniStmt
        Label    *types.Sym
        Cond     Node
-       Late     Nodes
        Post     Node
        Body     Nodes
        HasBreak bool
@@ -227,13 +225,6 @@ func NewForStmt(pos src.XPos, init Node, cond, post Node, body []Node) *ForStmt
        return n
 }
 
-func (n *ForStmt) SetOp(op Op) {
-       if op != OFOR && op != OFORUNTIL {
-               panic(n.no("SetOp " + op.String()))
-       }
-       n.op = op
-}
-
 // A GoDeferStmt is a go or defer statement: go Call / defer Call.
 //
 // The two opcodes use a single syntax because the implementations
index a6cd687999d7a24e45dd5b06c13dfe7b5a0f0ee0..fec79a413b4dd2dd0851d742e2665e8e1be316be 100644 (file)
@@ -1099,8 +1099,7 @@ func addRestrictions(parent *Block, ft *factsTable, t domain, v, w *Value, r rel
 // addLocalInductiveFacts adds inductive facts when visiting b, where
 // b is a join point in a loop. In contrast with findIndVar, this
 // depends on facts established for b, which is why it happens when
-// visiting b. addLocalInductiveFacts specifically targets the pattern
-// created by OFORUNTIL, which isn't detected by findIndVar.
+// visiting b.
 //
 // TODO: It would be nice to combine this with findIndVar.
 func addLocalInductiveFacts(ft *factsTable, b *Block) {
index e5fe646eaf746b5140957c7c0a2b79b45757eb5e..0c30cfecab8a030fb38b05fb9b97fd9de3a535bb 100644 (file)
@@ -1738,12 +1738,9 @@ func (s *state) stmt(n ir.Node) {
                b.Pos = s.lastPos.WithIsStmt() // Do this even if b is an empty block.
                b.AddEdgeTo(to)
 
-       case ir.OFOR, ir.OFORUNTIL:
+       case ir.OFOR:
                // OFOR: for Ninit; Left; Right { Nbody }
                // cond (Left); body (Nbody); incr (Right)
-               //
-               // OFORUNTIL: for Ninit; Left; Right; List { Nbody }
-               // => body: { Nbody }; incr: Right; if Left { lateincr: List; goto body }; end:
                n := n.(*ir.ForStmt)
                bCond := s.f.NewBlock(ssa.BlockPlain)
                bBody := s.f.NewBlock(ssa.BlockPlain)
@@ -1753,21 +1750,17 @@ func (s *state) stmt(n ir.Node) {
                // ensure empty for loops have correct position; issue #30167
                bBody.Pos = n.Pos()
 
-               // first, jump to condition test (OFOR) or body (OFORUNTIL)
+               // first, jump to condition test
                b := s.endBlock()
-               if n.Op() == ir.OFOR {
-                       b.AddEdgeTo(bCond)
-                       // generate code to test condition
-                       s.startBlock(bCond)
-                       if n.Cond != nil {
-                               s.condBranch(n.Cond, bBody, bEnd, 1)
-                       } else {
-                               b := s.endBlock()
-                               b.Kind = ssa.BlockPlain
-                               b.AddEdgeTo(bBody)
-                       }
+               b.AddEdgeTo(bCond)
 
+               // generate code to test condition
+               s.startBlock(bCond)
+               if n.Cond != nil {
+                       s.condBranch(n.Cond, bBody, bEnd, 1)
                } else {
+                       b := s.endBlock()
+                       b.Kind = ssa.BlockPlain
                        b.AddEdgeTo(bBody)
                }
 
@@ -1801,29 +1794,18 @@ func (s *state) stmt(n ir.Node) {
                        b.AddEdgeTo(bIncr)
                }
 
-               // generate incr (and, for OFORUNTIL, condition)
+               // generate incr
                s.startBlock(bIncr)
                if n.Post != nil {
                        s.stmt(n.Post)
                }
-               if n.Op() == ir.OFOR {
-                       if b := s.endBlock(); b != nil {
-                               b.AddEdgeTo(bCond)
-                               // It can happen that bIncr ends in a block containing only VARKILL,
-                               // and that muddles the debugging experience.
-                               if b.Pos == src.NoXPos {
-                                       b.Pos = bCond.Pos
-                               }
+               if b := s.endBlock(); b != nil {
+                       b.AddEdgeTo(bCond)
+                       // It can happen that bIncr ends in a block containing only VARKILL,
+                       // and that muddles the debugging experience.
+                       if b.Pos == src.NoXPos {
+                               b.Pos = bCond.Pos
                        }
-               } else {
-                       // bCond is unused in OFORUNTIL, so repurpose it.
-                       bLateIncr := bCond
-                       // test condition
-                       s.condBranch(n.Cond, bLateIncr, bEnd, 1)
-                       // generate late increment
-                       s.startBlock(bLateIncr)
-                       s.stmtList(n.Late)
-                       s.endBlock().AddEdgeTo(bBody)
                }
 
                s.startBlock(bEnd)
index 370e3248742654e10be68a9a4f2cd8e67061f820..5eeab4115e3a61c97ae6e12183fba650ab0c2f06 100644 (file)
@@ -258,9 +258,6 @@ func tcFor(n *ir.ForStmt) ir.Node {
                }
        }
        n.Post = Stmt(n.Post)
-       if n.Op() == ir.OFORUNTIL {
-               Stmts(n.Late)
-       }
        Stmts(n.Body)
        return n
 }
index 3b0c1f734ede45fd5717102505d32cc4401f7feb..44e1b3ef78e6e7bd40f8963aa3de904fdd55af59 100644 (file)
@@ -774,7 +774,7 @@ func typecheck1(n ir.Node, top int) ir.Node {
                tcGoDefer(n)
                return n
 
-       case ir.OFOR, ir.OFORUNTIL:
+       case ir.OFOR:
                n := n.(*ir.ForStmt)
                return tcFor(n)
 
@@ -1697,7 +1697,7 @@ func markBreak(fn *ir.Func) {
                                setHasBreak(labels[n.Label])
                        }
 
-               case ir.OFOR, ir.OFORUNTIL, ir.OSWITCH, ir.OSELECT, ir.ORANGE:
+               case ir.OFOR, ir.OSWITCH, ir.OSELECT, ir.ORANGE:
                        old := implicit
                        implicit = n
                        var sym *types.Sym
@@ -1773,7 +1773,7 @@ func isTermNode(n ir.Node) bool {
        case ir.OGOTO, ir.ORETURN, ir.OTAILCALL, ir.OPANIC, ir.OFALL:
                return true
 
-       case ir.OFOR, ir.OFORUNTIL:
+       case ir.OFOR:
                n := n.(*ir.ForStmt)
                if n.Cond != nil {
                        return false
index 4a2b55c71a37008310c6508d158d9576e01a4868..f2591c362af910779bd7d0c86743a4b9ad858689 100644 (file)
@@ -123,19 +123,6 @@ func walkRange(nrange *ir.RangeStmt) ir.Node {
                        break
                }
 
-               // TODO(austin): OFORUNTIL is a strange beast, but is
-               // necessary for expressing the control flow we need
-               // while also making "break" and "continue" work. It
-               // would be nice to just lower ORANGE during SSA, but
-               // racewalk needs to see many of the operations
-               // involved in ORANGE's implementation. If racewalk
-               // moves into SSA, consider moving ORANGE into SSA and
-               // eliminating OFORUNTIL.
-
-               // TODO(austin): OFORUNTIL inhibits bounds-check
-               // elimination on the index variable (see #20711).
-               // Enhance the prove pass to understand this.
-
                // Slice to iterate over
                var hs ir.Node
                if t.IsSlice() {
index 8a42dbf777cd4798be2a4752d9d56256937b09c6..9ddc82336cd59fbee18fc095dd420f1200daa4ac 100644 (file)
@@ -124,7 +124,7 @@ func walkStmt(n ir.Node) ir.Node {
                n := n.(*ir.GoDeferStmt)
                return walkGoDefer(n)
 
-       case ir.OFOR, ir.OFORUNTIL:
+       case ir.OFOR:
                n := n.(*ir.ForStmt)
                return walkFor(n)
 
@@ -178,7 +178,7 @@ func walkStmtList(s []ir.Node) {
        }
 }
 
-// walkFor walks an OFOR or OFORUNTIL node.
+// walkFor walks an OFOR node.
 func walkFor(n *ir.ForStmt) ir.Node {
        if n.Cond != nil {
                init := ir.TakeInit(n.Cond)
@@ -188,9 +188,6 @@ func walkFor(n *ir.ForStmt) ir.Node {
        }
 
        n.Post = walkStmt(n.Post)
-       if n.Op() == ir.OFORUNTIL {
-               walkStmtList(n.Late)
-       }
        walkStmtList(n.Body)
        return n
 }