1
2
3
4
5 package ssa
6
7 import "cmd/internal/src"
8
9
10
11 func trim(f *Func) {
12 n := 0
13 for _, b := range f.Blocks {
14 if !trimmableBlock(b) {
15 f.Blocks[n] = b
16 n++
17 continue
18 }
19
20 bPos := b.Pos
21 bIsStmt := bPos.IsStmt() == src.PosIsStmt
22
23
24
25 p, i := b.Preds[0].b, b.Preds[0].i
26 s, j := b.Succs[0].b, b.Succs[0].i
27 ns := len(s.Preds)
28 p.Succs[i] = Edge{s, j}
29 s.Preds[j] = Edge{p, i}
30
31 for _, e := range b.Preds[1:] {
32 p, i := e.b, e.i
33 p.Succs[i] = Edge{s, len(s.Preds)}
34 s.Preds = append(s.Preds, Edge{p, i})
35 }
36
37
38 if bIsStmt {
39 sawStmt := false
40 for _, v := range s.Values {
41 if isPoorStatementOp(v.Op) {
42 continue
43 }
44 if v.Pos.SameFileAndLine(bPos) {
45 v.Pos = v.Pos.WithIsStmt()
46 }
47 sawStmt = true
48 break
49 }
50 if !sawStmt && s.Pos.SameFileAndLine(bPos) {
51 s.Pos = s.Pos.WithIsStmt()
52 }
53 }
54
55
56 if ns > 1 {
57 for _, v := range s.Values {
58 if v.Op == OpPhi {
59 mergePhi(v, j, b)
60 }
61
62 }
63
64
65 k := 0
66 for _, v := range b.Values {
67 if v.Op == OpPhi {
68 if v.Uses == 0 {
69 v.resetArgs()
70 continue
71 }
72
73
74
75
76
77
78 args := make([]*Value, len(v.Args))
79 copy(args, v.Args)
80 v.resetArgs()
81 for x := 0; x < j; x++ {
82 v.AddArg(v)
83 }
84 v.AddArg(args[0])
85 for x := j + 1; x < ns; x++ {
86 v.AddArg(v)
87 }
88 for _, a := range args[1:] {
89 v.AddArg(a)
90 }
91 }
92 b.Values[k] = v
93 k++
94 }
95 b.Values = b.Values[:k]
96 }
97
98
99 for _, v := range b.Values {
100 v.Block = s
101 }
102 k := len(b.Values)
103 m := len(s.Values)
104 for i := 0; i < k; i++ {
105 s.Values = append(s.Values, nil)
106 }
107 copy(s.Values[k:], s.Values[:m])
108 copy(s.Values, b.Values)
109 }
110 if n < len(f.Blocks) {
111 f.invalidateCFG()
112 tail := f.Blocks[n:]
113 for i := range tail {
114 tail[i] = nil
115 }
116 f.Blocks = f.Blocks[:n]
117 }
118 }
119
120
121
122 func emptyBlock(b *Block) bool {
123 for _, v := range b.Values {
124 if v.Op != OpPhi {
125 return false
126 }
127 }
128 return true
129 }
130
131
132
133
134
135
136
137
138 func trimmableBlock(b *Block) bool {
139 if b.Kind != BlockPlain || b == b.Func.Entry {
140 return false
141 }
142 s := b.Succs[0].b
143 return s != b && (len(s.Preds) == 1 || emptyBlock(b))
144 }
145
146
147
148 func mergePhi(v *Value, i int, b *Block) {
149 u := v.Args[i]
150 if u.Block == b {
151 if u.Op != OpPhi {
152 b.Func.Fatalf("value %s is not a phi operation", u.LongString())
153 }
154
155
156
157
158
159 v.SetArg(i, u.Args[0])
160 v.AddArgs(u.Args[1:]...)
161 } else {
162
163
164
165
166
167
168 for j := 1; j < len(b.Preds); j++ {
169 v.AddArg(v.Args[i])
170 }
171 }
172 }
173
View as plain text