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