@@ -61,11 +61,64 @@ type worklist struct {
61
61
uses []* Value // uses for re-visiting because lattice of def is changed
62
62
visited map [edge ]bool // visited edges
63
63
latticeCells map [* Value ]lattice // constant lattices
64
- defUse map [* Value ][]* Value // def-use chains
64
+ defUse map [* Value ][]* Value // def-use chains for some values
65
65
defBlock map [* Value ][]* Block // use blocks of def
66
66
}
67
67
68
+ func possibleConst (val * Value ) bool {
69
+ switch val .Op {
70
+ case OpConst64 , OpConst32 , OpConst16 , OpConst8 ,
71
+ OpConstBool , OpConst32F , OpConst64F :
72
+ fallthrough
73
+ case OpCopy :
74
+ fallthrough
75
+ case OpPhi :
76
+ fallthrough
77
+ case
78
+ OpNeg8 , OpNeg16 , OpNeg32 , OpNeg64 , OpNeg32F , OpNeg64F ,
79
+ OpCom8 , OpCom16 , OpCom32 , OpCom64 ,
80
+ OpFloor , OpCeil , OpTrunc , OpRoundToEven ,
81
+ OpNot :
82
+ fallthrough
83
+ case
84
+ OpAdd64 , OpAdd32 , OpAdd16 , OpAdd8 ,
85
+ OpAdd32F , OpAdd64F ,
86
+ OpSub64 , OpSub32 , OpSub16 , OpSub8 ,
87
+ OpSub32F , OpSub64F ,
88
+ OpMul64 , OpMul32 , OpMul16 , OpMul8 ,
89
+ OpMul32F , OpMul64F ,
90
+ OpDiv32F , OpDiv64F ,
91
+ OpDiv8 , OpDiv16 , OpDiv32 , OpDiv64 ,
92
+ OpDiv8u , OpDiv16u , OpDiv32u , OpDiv64u ,
93
+ OpMod8 , OpMod16 , OpMod32 , OpMod64 ,
94
+ OpMod8u , OpMod16u , OpMod32u , OpMod64u ,
95
+ OpEq64 , OpEq32 , OpEq16 , OpEq8 ,
96
+ OpEq32F , OpEq64F ,
97
+ OpLess64 , OpLess32 , OpLess16 , OpLess8 ,
98
+ OpLess64U , OpLess32U , OpLess16U , OpLess8U ,
99
+ OpLess32F , OpLess64F ,
100
+ OpLeq64 , OpLeq32 , OpLeq16 , OpLeq8 ,
101
+ OpLeq64U , OpLeq32U , OpLeq16U , OpLeq8U ,
102
+ OpLeq32F , OpLeq64F ,
103
+ OpEqB , OpNeqB ,
104
+ OpLsh64x64 , OpRsh64x64 , OpRsh64Ux64 , OpLsh32x64 ,
105
+ OpRsh32x64 , OpRsh32Ux64 , OpLsh16x64 , OpRsh16x64 ,
106
+ OpRsh16Ux64 , OpLsh8x64 , OpRsh8x64 , OpRsh8Ux64 ,
107
+ OpIsInBounds , OpIsSliceInBounds ,
108
+ OpAnd8 , OpAnd16 , OpAnd32 , OpAnd64 ,
109
+ OpOr8 , OpOr16 , OpOr32 , OpOr64 ,
110
+ OpXor8 , OpXor16 , OpXor32 , OpXor64 :
111
+ return true
112
+ default :
113
+ return false
114
+ }
115
+ }
116
+
68
117
func (t * worklist ) getLatticeCell (val * Value ) lattice {
118
+ if ! possibleConst (val ) {
119
+ // they are always worst
120
+ return lattice {bottom , nil }
121
+ }
69
122
lt , exist := t .latticeCells [val ]
70
123
if ! exist {
71
124
return lattice {top , nil } // optimistically for un-visited value
@@ -97,18 +150,20 @@ func isDivByZero(op Op, divisor *Value) bool {
97
150
return false
98
151
}
99
152
100
- // buildDefUses builds def-use chain for all values early, because once lattice of value
153
+ // buildDefUses builds def-use chain for some values early, because once lattice of value
101
154
// is changed, all uses would be added into re-visit uses worklist, we rely heavily on
102
155
// the def-use chain in subsequent propagation.
103
156
func (t * worklist ) buildDefUses () {
104
157
for _ , block := range t .f .Blocks {
105
158
for _ , val := range block .Values {
106
159
for _ , arg := range val .Args {
107
- // for every value, find their uses
108
- if _ , exist := t .defUse [arg ]; ! exist {
109
- t .defUse [arg ] = make ([]* Value , 0 )
160
+ if possibleConst (arg ) {
161
+ // for every value, find their uses
162
+ if _ , exist := t .defUse [arg ]; ! exist {
163
+ t .defUse [arg ] = make ([]* Value , 0 )
164
+ }
165
+ t .defUse [arg ] = append (t .defUse [arg ], val )
110
166
}
111
- t .defUse [arg ] = append (t .defUse [arg ], val )
112
167
}
113
168
}
114
169
for _ , ctl := range block .ControlValues () {
@@ -221,7 +276,7 @@ func (t *worklist) visitValue(val *Value) {
221
276
defer func () {
222
277
// re-visit all uses of value if its lattice is changed
223
278
var newLt = t .getLatticeCell (val )
224
- if newLt . tag != oldLt . tag || newLt . val != oldLt . val {
279
+ if newLt != oldLt {
225
280
t .addUses (val )
226
281
}
227
282
}()
@@ -313,12 +368,12 @@ func (t *worklist) visitValue(val *Value) {
313
368
t .latticeCells [val ] = worstLt
314
369
}
315
370
default :
316
- t . latticeCells [ val ] = worstLt
371
+ // Any other type of value cannot be a constant, they are always worst(Bottom)
317
372
}
318
373
}
319
374
320
375
// propagate propagates constants facts through CFG. If the block has single successor,
321
- // add the successor anyway. If the block has multiply successors, only add the branch
376
+ // add the successor anyway. If the block has multiple successors, only add the branch
322
377
// destination corresponding to lattice value of condition value.
323
378
func (t * worklist ) propagate (block * Block ) {
324
379
switch block .Kind {
0 commit comments