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