1
2
3
4
5 package ssacompile
6
7 import (
8 "cmd/compile/internal/ssa"
9 "cmd/compile/internal/ssa/block"
10 "cmd/compile/internal/ssa/ssaop"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 func fuseBranchRedirect(f *ssa.Func) bool {
36 ft := newFactsTable(f)
37 ft.checkpoint()
38
39 changed := false
40 for i := len(f.Blocks) - 1; i >= 0; i-- {
41 b := f.Blocks[i]
42 if b.Kind != block.BlockIf {
43 continue
44 }
45
46
47
48 bCtl := b.Controls[0]
49 if bCtl.Block != b && len(b.Values) != 0 || (len(b.Values) != 1 || bCtl.Uses != 1) && bCtl.Block == b {
50 continue
51 }
52
53 for k := 0; k < len(b.Preds); k++ {
54 pk := b.Preds[k]
55 p := pk.B
56 if p.Kind != block.BlockIf || p == b {
57 continue
58 }
59 pbranch := positive
60 if pk.I == 1 {
61 pbranch = negative
62 }
63 ft.checkpoint()
64
65 addBranchRestrictions(ft, p, pbranch)
66
67 parent := b
68 for j, bbranch := range [...]branch{positive, negative} {
69 ft.checkpoint()
70
71 addBranchRestrictions(ft, parent, bbranch)
72 unsat := ft.unsat
73 ft.restore()
74 if !unsat {
75 continue
76 }
77
78 out := 1 ^ j
79 child := parent.Succs[out].B
80 if child == b {
81 continue
82 }
83 b.RemovePred(k)
84 p.Succs[pk.I] = ssa.Edge{B: child, I: len(child.Preds)}
85
86 for _, v := range b.Values {
87 if v.Op != ssaop.OpPhi {
88 continue
89 }
90 b.RemovePhiArg(v, k)
91 }
92
93 child.Preds = append(child.Preds, ssa.Edge{B: p, I: pk.I})
94 ai := b.Succs[out].I
95 for _, v := range child.Values {
96 if v.Op != ssaop.OpPhi {
97 continue
98 }
99 v.AddArg(v.Args[ai])
100 }
101 if b.Func.Pass.Debug > 0 {
102 b.Func.Warnl(b.Controls[0].Pos, "Redirect %s based on %s", b.Controls[0].Op, p.Controls[0].Op)
103 }
104 changed = true
105 k--
106 break
107 }
108 ft.restore()
109 }
110 if len(b.Preds) == 0 && b != f.Entry {
111
112 b.Kind = block.BlockInvalid
113 }
114 }
115 ft.restore()
116 ft.cleanup(f)
117 return changed
118 }
119
View as plain text