Skip to content

Commit

Permalink
cmd/compile: remove OFORUNTIL
Browse files Browse the repository at this point in the history
Not used any more.

Fixes #53860

Change-Id: Id0b1c3ed30b576d6c5f08f064d1262de337262b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/418374
Reviewed-by: Cuong Manh Le <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
Reviewed-by: David Chase <[email protected]>
Run-TryBot: Keith Randall <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
  • Loading branch information
randall77 committed Aug 18, 2022
1 parent 6dc7b06 commit a5370d0
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 142 deletions.
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/escape/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 4 additions & 14 deletions src/cmd/compile/internal/ir/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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: ">",
Expand Down Expand Up @@ -274,7 +273,6 @@ var OpPrec = []int{
ODEFER: -1,
OFALL: -1,
OFOR: -1,
OFORUNTIL: -1,
OGOTO: -1,
OIF: -1,
OLABEL: -1,
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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:
Expand Down
26 changes: 8 additions & 18 deletions src/cmd/compile/internal/ir/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions src/cmd/compile/internal/ir/node_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 34 additions & 35 deletions src/cmd/compile/internal/ir/op_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 0 additions & 9 deletions src/cmd/compile/internal/ir/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/cmd/compile/internal/ssa/prove.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
50 changes: 16 additions & 34 deletions src/cmd/compile/internal/ssagen/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
}

Expand Down Expand Up @@ -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)
Expand Down
3 changes: 0 additions & 3 deletions src/cmd/compile/internal/typecheck/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions src/cmd/compile/internal/typecheck/typecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
13 changes: 0 additions & 13 deletions src/cmd/compile/internal/walk/range.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Loading

0 comments on commit a5370d0

Please sign in to comment.