1
2
3
4
5 package deadcode
6
7 import (
8 "go/constant"
9
10 "cmd/compile/internal/base"
11 "cmd/compile/internal/ir"
12 )
13
14 func Func(fn *ir.Func) {
15 stmts(&fn.Body)
16
17 if len(fn.Body) == 0 {
18 return
19 }
20
21 for _, n := range fn.Body {
22 if len(n.Init()) > 0 {
23 return
24 }
25 switch n.Op() {
26 case ir.OIF:
27 n := n.(*ir.IfStmt)
28 if !ir.IsConst(n.Cond, constant.Bool) || len(n.Body) > 0 || len(n.Else) > 0 {
29 return
30 }
31 case ir.OFOR:
32 n := n.(*ir.ForStmt)
33 if !ir.IsConst(n.Cond, constant.Bool) || ir.BoolVal(n.Cond) {
34 return
35 }
36 default:
37 return
38 }
39 }
40
41 ir.VisitList(fn.Body, markHiddenClosureDead)
42 fn.Body = []ir.Node{ir.NewBlockStmt(base.Pos, nil)}
43 }
44
45 func stmts(nn *ir.Nodes) {
46 var lastLabel = -1
47 for i, n := range *nn {
48 if n != nil && n.Op() == ir.OLABEL {
49 lastLabel = i
50 }
51 }
52 for i, n := range *nn {
53
54
55
56 cut := false
57 if n == nil {
58 continue
59 }
60 if n.Op() == ir.OIF {
61 n := n.(*ir.IfStmt)
62 n.Cond = expr(n.Cond)
63 if ir.IsConst(n.Cond, constant.Bool) {
64 var body ir.Nodes
65 if ir.BoolVal(n.Cond) {
66 ir.VisitList(n.Else, markHiddenClosureDead)
67 n.Else = ir.Nodes{}
68 body = n.Body
69 } else {
70 ir.VisitList(n.Body, markHiddenClosureDead)
71 n.Body = ir.Nodes{}
72 body = n.Else
73 }
74
75
76
77
78
79 if body := body; len(body) != 0 {
80 switch body[(len(body) - 1)].Op() {
81 case ir.ORETURN, ir.OTAILCALL, ir.OPANIC:
82 if i > lastLabel {
83 cut = true
84 }
85 }
86 }
87 }
88 }
89
90 if len(n.Init()) != 0 {
91 stmts(n.(ir.InitNode).PtrInit())
92 }
93 switch n.Op() {
94 case ir.OBLOCK:
95 n := n.(*ir.BlockStmt)
96 stmts(&n.List)
97 case ir.OFOR:
98 n := n.(*ir.ForStmt)
99 stmts(&n.Body)
100 case ir.OIF:
101 n := n.(*ir.IfStmt)
102 stmts(&n.Body)
103 stmts(&n.Else)
104 case ir.ORANGE:
105 n := n.(*ir.RangeStmt)
106 stmts(&n.Body)
107 case ir.OSELECT:
108 n := n.(*ir.SelectStmt)
109 for _, cas := range n.Cases {
110 stmts(&cas.Body)
111 }
112 case ir.OSWITCH:
113 n := n.(*ir.SwitchStmt)
114 for _, cas := range n.Cases {
115 stmts(&cas.Body)
116 }
117 }
118
119 if cut {
120 ir.VisitList((*nn)[i+1:len(*nn)], markHiddenClosureDead)
121 *nn = (*nn)[:i+1]
122 break
123 }
124 }
125 }
126
127 func expr(n ir.Node) ir.Node {
128
129
130
131 switch n.Op() {
132 case ir.OANDAND:
133 n := n.(*ir.LogicalExpr)
134 n.X = expr(n.X)
135 n.Y = expr(n.Y)
136 if ir.IsConst(n.X, constant.Bool) {
137 if ir.BoolVal(n.X) {
138 return n.Y
139 } else {
140 return n.X
141 }
142 }
143 case ir.OOROR:
144 n := n.(*ir.LogicalExpr)
145 n.X = expr(n.X)
146 n.Y = expr(n.Y)
147 if ir.IsConst(n.X, constant.Bool) {
148 if ir.BoolVal(n.X) {
149 return n.X
150 } else {
151 return n.Y
152 }
153 }
154 }
155 return n
156 }
157
158 func markHiddenClosureDead(n ir.Node) {
159 if n.Op() != ir.OCLOSURE {
160 return
161 }
162 clo := n.(*ir.ClosureExpr)
163 if clo.Func.IsHiddenClosure() {
164 clo.Func.SetIsDeadcodeClosure(true)
165 }
166 ir.VisitList(clo.Func.Body, markHiddenClosureDead)
167 }
168
View as plain text