]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: distinguish exit and return blocks
authorKeith Randall <khr@golang.org>
Thu, 3 Sep 2015 16:09:59 +0000 (09:09 -0700)
committerKeith Randall <khr@golang.org>
Thu, 3 Sep 2015 17:42:38 +0000 (17:42 +0000)
It is confusing to have exceptional edges jump back into
real code.  Distinguish return blocks, which execute acutal
code, and the exit block, which is a merge point for the regular
and exceptional return flow.

Prevent critical edge insertion from adding blocks on edges
into the exit block.  These added blocks serve no purpose and
add a bunch of dead jumps to the assembly output.  Furthermore,
live variable analysis is confused by these jumps.

Change-Id: Ifd69e6c00e90338ed147e7cb351b5100dc0364df
Reviewed-on: https://go-review.googlesource.com/14254
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/check.go
src/cmd/compile/internal/ssa/critical.go
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/opGen.go

index 77c822787d82971f011ebe90d441b1f5227e70fd..f0cad90d40d8ffd90b7ef55c300ea1ef96a4cc23 100644 (file)
@@ -562,6 +562,7 @@ func (s *state) stmt(n *Node) {
        case ORETURN:
                s.stmtList(n.List)
                b := s.endBlock()
+               b.Kind = ssa.BlockRet
                b.AddEdgeTo(s.exit)
 
        case OCONTINUE, OBREAK:
@@ -3358,6 +3359,7 @@ func genBlock(b, next *ssa.Block, branches []branch) []branch {
                        branches = append(branches, branch{p, b.Succs[0]})
                }
        case ssa.BlockExit:
+       case ssa.BlockRet:
                Prog(obj.ARET)
        case ssa.BlockCall:
                if b.Succs[0] != next {
index 0c2bc4c7f1396e1ec01cb9f2958116eca0f745aa..68ba25a272574b2ef0ca210a6ce8a0675fb56707 100644 (file)
@@ -59,6 +59,16 @@ func checkFunc(f *Func) {
                        if !b.Control.Type.IsMemory() {
                                f.Fatalf("exit block %s has non-memory control value %s", b, b.Control.LongString())
                        }
+               case BlockRet:
+                       if len(b.Succs) != 1 {
+                               f.Fatalf("ret block %s len(Succs)==%d, want 1", b, len(b.Succs))
+                       }
+                       if b.Control != nil {
+                               f.Fatalf("ret block %s has non-nil control %s", b, b.Control.LongString())
+                       }
+                       if b.Succs[0].Kind != BlockExit {
+                               f.Fatalf("ret block %s has successor %s, not Exit", b, b.Succs[0].Kind)
+                       }
                case BlockDead:
                        if len(b.Succs) != 0 {
                                f.Fatalf("dead block %s has successors", b)
index ba754508759a5df6512ad22d76eb2c53cf3d32c5..439d4823e5b8163e7cd75b6f54ac7dbc433ade19 100644 (file)
@@ -9,7 +9,7 @@ package ssa
 // Regalloc wants a critical-edge-free CFG so it can implement phi values.
 func critical(f *Func) {
        for _, b := range f.Blocks {
-               if len(b.Preds) <= 1 {
+               if len(b.Preds) <= 1 || b.Kind == BlockExit {
                        continue
                }
 
index d17f207a80833700f9512e1ae6deef1e7581211f..59b90adfe5c9524ceec47b94dcb10399f89e9192 100644 (file)
@@ -375,6 +375,7 @@ var genericBlocks = []blockData{
        {name: "If"},    // 2 successors, if control goto Succs[0] else goto Succs[1]
        {name: "Call"},  // 2 successors, normal return and panic
        {name: "First"}, // 2 successors, always takes the first one (second is dead)
+       {name: "Ret"},   // 1 successor, branches to exit
 }
 
 func init() {
index f4c74fe34084c7d9b8985c25d009a7dcb4313431..a61c31ad5a0e7a86481b7755b394cc81f20a9120 100644 (file)
@@ -28,6 +28,7 @@ const (
        BlockIf
        BlockCall
        BlockFirst
+       BlockRet
 )
 
 var blockString = [...]string{
@@ -54,6 +55,7 @@ var blockString = [...]string{
        BlockIf:    "If",
        BlockCall:  "Call",
        BlockFirst: "First",
+       BlockRet:   "Ret",
 }
 
 func (k BlockKind) String() string { return blockString[k] }