Skip to content

Commit 2227f13

Browse files
committed
sccp on some types of value
1 parent 3383b28 commit 2227f13

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

src/cmd/compile/internal/ssa/_gen/genericOps.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ var genericOps = []opData{
644644
// If [boolean Value] [then, else]
645645
// First [] [always, never]
646646
// Defer [mem] [nopanic, panic] (control opcode should be OpStaticCall to runtime.deferproc)
647-
//JumpTable [boolean Value] [succ1,succ2,..]
647+
//JumpTable [integer Value] [succ1,succ2,..]
648648

649649
var genericBlocks = []blockData{
650650
{name: "Plain"}, // a single successor

src/cmd/compile/internal/ssa/sccp.go

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,64 @@ type worklist struct {
6161
uses []*Value // uses for re-visiting because lattice of def is changed
6262
visited map[edge]bool // visited edges
6363
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
6565
defBlock map[*Value][]*Block // use blocks of def
6666
}
6767

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+
68117
func (t *worklist) getLatticeCell(val *Value) lattice {
118+
if !possibleConst(val) {
119+
// they are always worst
120+
return lattice{bottom, nil}
121+
}
69122
lt, exist := t.latticeCells[val]
70123
if !exist {
71124
return lattice{top, nil} // optimistically for un-visited value
@@ -97,18 +150,20 @@ func isDivByZero(op Op, divisor *Value) bool {
97150
return false
98151
}
99152

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
101154
// is changed, all uses would be added into re-visit uses worklist, we rely heavily on
102155
// the def-use chain in subsequent propagation.
103156
func (t *worklist) buildDefUses() {
104157
for _, block := range t.f.Blocks {
105158
for _, val := range block.Values {
106159
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)
110166
}
111-
t.defUse[arg] = append(t.defUse[arg], val)
112167
}
113168
}
114169
for _, ctl := range block.ControlValues() {
@@ -221,7 +276,7 @@ func (t *worklist) visitValue(val *Value) {
221276
defer func() {
222277
// re-visit all uses of value if its lattice is changed
223278
var newLt = t.getLatticeCell(val)
224-
if newLt.tag != oldLt.tag || newLt.val != oldLt.val {
279+
if newLt != oldLt {
225280
t.addUses(val)
226281
}
227282
}()
@@ -313,12 +368,12 @@ func (t *worklist) visitValue(val *Value) {
313368
t.latticeCells[val] = worstLt
314369
}
315370
default:
316-
t.latticeCells[val] = worstLt
371+
// Any other type of value cannot be a constant, they are always worst(Bottom)
317372
}
318373
}
319374

320375
// 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
322377
// destination corresponding to lattice value of condition value.
323378
func (t *worklist) propagate(block *Block) {
324379
switch block.Kind {

0 commit comments

Comments
 (0)