...
Source file src/pkg/cmd/compile/internal/ssa/phiopt.go
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 phiopt(f *Func) {
27 sdom := f.sdom()
28 for _, b := range f.Blocks {
29 if len(b.Preds) != 2 || len(b.Values) == 0 {
30
31 continue
32 }
33
34 pb0, b0 := b, b.Preds[0].b
35 for len(b0.Succs) == 1 && len(b0.Preds) == 1 {
36 pb0, b0 = b0, b0.Preds[0].b
37 }
38 if b0.Kind != BlockIf {
39 continue
40 }
41 pb1, b1 := b, b.Preds[1].b
42 for len(b1.Succs) == 1 && len(b1.Preds) == 1 {
43 pb1, b1 = b1, b1.Preds[0].b
44 }
45 if b1 != b0 {
46 continue
47 }
48
49
50
51 var reverse int
52 if b0.Succs[0].b == pb0 && b0.Succs[1].b == pb1 {
53 reverse = 0
54 } else if b0.Succs[0].b == pb1 && b0.Succs[1].b == pb0 {
55 reverse = 1
56 } else {
57 b.Fatalf("invalid predecessors\n")
58 }
59
60 for _, v := range b.Values {
61 if v.Op != OpPhi {
62 continue
63 }
64
65
66 if v.Type.IsInteger() {
67 phioptint(v, b0, reverse)
68 }
69
70 if !v.Type.IsBoolean() {
71 continue
72 }
73
74
75
76
77
78 if v.Args[0].Op == OpConstBool && v.Args[1].Op == OpConstBool {
79 if v.Args[reverse].AuxInt != v.Args[1-reverse].AuxInt {
80 ops := [2]Op{OpNot, OpCopy}
81 v.reset(ops[v.Args[reverse].AuxInt])
82 v.AddArg(b0.Control)
83 if f.pass.debug > 0 {
84 f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
85 }
86 continue
87 }
88 }
89
90
91
92
93
94
95 if v.Args[reverse].Op == OpConstBool && v.Args[reverse].AuxInt == 1 {
96 if tmp := v.Args[1-reverse]; sdom.isAncestorEq(tmp.Block, b) {
97 v.reset(OpOrB)
98 v.SetArgs2(b0.Control, tmp)
99 if f.pass.debug > 0 {
100 f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
101 }
102 continue
103 }
104 }
105
106
107
108
109
110
111 if v.Args[1-reverse].Op == OpConstBool && v.Args[1-reverse].AuxInt == 0 {
112 if tmp := v.Args[reverse]; sdom.isAncestorEq(tmp.Block, b) {
113 v.reset(OpAndB)
114 v.SetArgs2(b0.Control, tmp)
115 if f.pass.debug > 0 {
116 f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
117 }
118 continue
119 }
120 }
121 }
122 }
123 }
124
125 func phioptint(v *Value, b0 *Block, reverse int) {
126 a0 := v.Args[0]
127 a1 := v.Args[1]
128 if a0.Op != a1.Op {
129 return
130 }
131
132 switch a0.Op {
133 case OpConst8, OpConst16, OpConst32, OpConst64:
134 default:
135 return
136 }
137
138 negate := false
139 switch {
140 case a0.AuxInt == 0 && a1.AuxInt == 1:
141 negate = true
142 case a0.AuxInt == 1 && a1.AuxInt == 0:
143 default:
144 return
145 }
146
147 if reverse == 1 {
148 negate = !negate
149 }
150
151 switch v.Type.Size() {
152 case 1:
153 v.reset(OpCopy)
154 case 2:
155 v.reset(OpZeroExt8to16)
156 case 4:
157 v.reset(OpZeroExt8to32)
158 case 8:
159 v.reset(OpZeroExt8to64)
160 default:
161 v.Fatalf("bad int size %d", v.Type.Size())
162 }
163
164 a := b0.Control
165 if negate {
166 a = v.Block.NewValue1(v.Pos, OpNot, a.Type, a)
167 }
168 v.AddArg(a)
169
170 f := b0.Func
171 if f.pass.debug > 0 {
172 f.Warnl(v.Block.Pos, "converted OpPhi bool -> int%d", v.Type.Size()*8)
173 }
174 }
175
View as plain text