...
Source file src/pkg/cmd/compile/internal/ssa/shortcircuit.go
1
2
3
4
5 package ssa
6
7
8
9
10
11 func shortcircuit(f *Func) {
12
13
14
15
16
17
18
19
20 var ct, cf *Value
21 for _, b := range f.Blocks {
22 for _, v := range b.Values {
23 if v.Op != OpPhi {
24 continue
25 }
26 if !v.Type.IsBoolean() {
27 continue
28 }
29 for i, a := range v.Args {
30 e := b.Preds[i]
31 p := e.b
32 if p.Kind != BlockIf {
33 continue
34 }
35 if p.Control != a {
36 continue
37 }
38 if e.i == 0 {
39 if ct == nil {
40 ct = f.ConstBool(f.Config.Types.Bool, true)
41 }
42 v.SetArg(i, ct)
43 } else {
44 if cf == nil {
45 cf = f.ConstBool(f.Config.Types.Bool, false)
46 }
47 v.SetArg(i, cf)
48 }
49 }
50 }
51 }
52
53
54 live := make([]bool, f.NumValues())
55 for _, b := range f.Blocks {
56 for _, v := range b.Values {
57 for _, a := range v.Args {
58 if a.Block != v.Block {
59 live[a.ID] = true
60 }
61 }
62 }
63 if b.Control != nil && b.Control.Block != b {
64 live[b.Control.ID] = true
65 }
66 }
67
68
69
70
71
72
73
74
75
76 for _, b := range f.Blocks {
77 if b.Kind != BlockIf {
78 continue
79 }
80 if len(b.Values) != 1 {
81 continue
82 }
83 v := b.Values[0]
84 if v.Op != OpPhi {
85 continue
86 }
87 if b.Control != v {
88 continue
89 }
90 if live[v.ID] {
91 continue
92 }
93 for i := 0; i < len(v.Args); i++ {
94 a := v.Args[i]
95 if a.Op != OpConstBool {
96 continue
97 }
98
99
100 e1 := b.Preds[i]
101 p := e1.b
102 pi := e1.i
103
104
105
106 e2 := b.Succs[1-a.AuxInt]
107 t := e2.b
108 ti := e2.i
109
110
111 b.removePred(i)
112 n := len(b.Preds)
113 v.Args[i].Uses--
114 v.Args[i] = v.Args[n]
115 v.Args[n] = nil
116 v.Args = v.Args[:n]
117
118
119 p.Succs[pi] = Edge{t, len(t.Preds)}
120
121
122 t.Preds = append(t.Preds, Edge{p, pi})
123 for _, w := range t.Values {
124 if w.Op != OpPhi {
125 continue
126 }
127 w.AddArg(w.Args[ti])
128 }
129
130 if len(b.Preds) == 1 {
131 v.Op = OpCopy
132
133 break
134 }
135 i--
136 }
137 }
138 }
139
View as plain text