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 const (
14 blDEFAULT = 0
15 blMin = blDEFAULT
16 blCALL = 1
17 blRET = 2
18 blEXIT = 3
19 )
20
21 var bllikelies = [4]string{"default", "call", "ret", "exit"}
22
23 func describePredictionAgrees(b *ssa.Block, prediction ssa.BranchPrediction) string {
24 s := ""
25 if prediction == b.Likely {
26 s = " (agrees with previous)"
27 } else if b.Likely != ssa.BranchUnknown {
28 s = " (disagrees with previous, ignored)"
29 }
30 return s
31 }
32
33 func describeBranchPrediction(f *ssa.Func, b *ssa.Block, likely, not int8, prediction ssa.BranchPrediction) {
34 f.Warnl(b.Pos, "Branch prediction rule %s < %s%s",
35 bllikelies[likely-blMin], bllikelies[not-blMin], describePredictionAgrees(b, prediction))
36 }
37
38 func likelyadjust(f *ssa.Func) {
39
40
41
42
43 certain := f.Cache.AllocInt8Slice(f.NumBlocks())
44 defer f.Cache.FreeInt8Slice(certain)
45 local := f.Cache.AllocInt8Slice(f.NumBlocks())
46 defer f.Cache.FreeInt8Slice(local)
47
48 po := f.Postorder()
49 nest := f.Loopnest()
50 b2l := nest.B2L
51
52 for _, b := range po {
53 switch b.Kind {
54 case block.BlockExit:
55
56 local[b.ID] = blEXIT
57 certain[b.ID] = blEXIT
58
59
60 case block.BlockRet, block.BlockRetJmp:
61 local[b.ID] = blRET
62 certain[b.ID] = blRET
63
64
65
66
67 case block.BlockDefer:
68 local[b.ID] = blCALL
69 certain[b.ID] = max(blCALL, certain[b.Succs[0].B.ID])
70
71 default:
72 if len(b.Succs) == 1 {
73 certain[b.ID] = certain[b.Succs[0].B.ID]
74 } else if len(b.Succs) == 2 {
75
76
77
78
79
80
81 b0 := b.Succs[0].B.ID
82 b1 := b.Succs[1].B.ID
83 certain[b.ID] = min(certain[b0], certain[b1])
84
85 l := b2l[b.ID]
86 l0 := b2l[b0]
87 l1 := b2l[b1]
88
89 prediction := b.Likely
90
91
92
93 if l != nil && l0 != l1 {
94 noprediction := false
95 switch {
96
97 case l1 == nil:
98 prediction = ssa.BranchLikely
99 case l0 == nil:
100 prediction = ssa.BranchUnlikely
101
102
103 case l == l0:
104 prediction = ssa.BranchLikely
105 case l == l1:
106 prediction = ssa.BranchUnlikely
107 default:
108 noprediction = true
109 }
110 if f.Pass.Debug > 0 && !noprediction {
111 f.Warnl(b.Pos, "Branch prediction rule stay in loop%s",
112 describePredictionAgrees(b, prediction))
113 }
114
115 } else {
116
117 if certain[b1] > certain[b0] {
118 prediction = ssa.BranchLikely
119 if f.Pass.Debug > 0 {
120 describeBranchPrediction(f, b, certain[b0], certain[b1], prediction)
121 }
122 } else if certain[b0] > certain[b1] {
123 prediction = ssa.BranchUnlikely
124 if f.Pass.Debug > 0 {
125 describeBranchPrediction(f, b, certain[b1], certain[b0], prediction)
126 }
127 } else if local[b1] > local[b0] {
128 prediction = ssa.BranchLikely
129 if f.Pass.Debug > 0 {
130 describeBranchPrediction(f, b, local[b0], local[b1], prediction)
131 }
132 } else if local[b0] > local[b1] {
133 prediction = ssa.BranchUnlikely
134 if f.Pass.Debug > 0 {
135 describeBranchPrediction(f, b, local[b1], local[b0], prediction)
136 }
137 }
138 }
139 if b.Likely != prediction {
140 if b.Likely == ssa.BranchUnknown {
141 b.Likely = prediction
142 }
143 }
144 }
145
146 for _, v := range b.Values {
147 if ssaop.OpcodeTable[v.Op].Call {
148 local[b.ID] = blCALL
149 certain[b.ID] = max(blCALL, certain[b.Succs[0].B.ID])
150 break
151 }
152 }
153 }
154 if f.Pass.Debug > 2 {
155 f.Warnl(b.Pos, "BP: Block %s, local=%s, certain=%s", b, bllikelies[local[b.ID]-blMin], bllikelies[certain[b.ID]-blMin])
156 }
157
158 }
159 }
160
View as plain text