ssa: removes redundantParameterIndexToValue map (#2250)

Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
Takeshi Yoneda
2024-06-14 08:52:40 -07:00
committed by GitHub
parent bf42c25657
commit ec36887ad2
2 changed files with 49 additions and 39 deletions

View File

@@ -134,15 +134,14 @@ type Builder interface {
// NewBuilder returns a new Builder implementation.
func NewBuilder() Builder {
return &builder{
instructionsPool: wazevoapi.NewPool[Instruction](resetInstruction),
basicBlocksPool: wazevoapi.NewPool[basicBlock](resetBasicBlock),
varLengthBasicBlockPool: wazevoapi.NewVarLengthPool[BasicBlock](),
varLengthPool: wazevoapi.NewVarLengthPool[Value](),
valueAnnotations: make(map[ValueID]string),
signatures: make(map[SignatureID]*Signature),
valueIDAliases: make(map[ValueID]Value),
redundantParameterIndexToValue: make(map[int]Value),
returnBlk: &basicBlock{id: basicBlockIDReturnBlock},
instructionsPool: wazevoapi.NewPool[Instruction](resetInstruction),
basicBlocksPool: wazevoapi.NewPool[basicBlock](resetBasicBlock),
varLengthBasicBlockPool: wazevoapi.NewVarLengthPool[BasicBlock](),
varLengthPool: wazevoapi.NewVarLengthPool[Value](),
valueAnnotations: make(map[ValueID]string),
signatures: make(map[SignatureID]*Signature),
valueIDAliases: make(map[ValueID]Value),
returnBlk: &basicBlock{id: basicBlockIDReturnBlock},
}
}
@@ -184,12 +183,11 @@ type builder struct {
loopNestingForestRoots []BasicBlock
// The followings are used for optimization passes/deterministic compilation.
instStack []*Instruction
valueIDToInstruction []*Instruction
blkStack []*basicBlock
blkStack2 []*basicBlock
ints []int
redundantParameterIndexToValue map[int]Value
instStack []*Instruction
valueIDToInstruction []*Instruction
blkStack []*basicBlock
blkStack2 []*basicBlock
redundantParams []redundantParam
// blockIterCur is used to implement blockIteratorBegin and blockIteratorNext.
blockIterCur int
@@ -207,6 +205,15 @@ type builder struct {
zeros [typeEnd]Value
}
// redundantParam is a pair of the index of the redundant parameter and the Value.
// This is used to eliminate the redundant parameters in the optimization pass.
type redundantParam struct {
// index is the index of the redundant parameter in the basicBlock.
index int
// uniqueValue is the Value which is passed to the redundant parameter.
uniqueValue Value
}
// InsertZeroValue implements Builder.InsertZeroValue.
func (b *builder) InsertZeroValue(t Type) {
if b.zeros[t].Valid() {
@@ -256,7 +263,7 @@ func (b *builder) Init(s *Signature) {
sig.used = false
}
b.ints = b.ints[:0]
b.redundantParams = b.redundantParams[:0]
b.blkStack = b.blkStack[:0]
b.blkStack2 = b.blkStack2[:0]
b.dominators = b.dominators[:0]

View File

@@ -112,7 +112,7 @@ func passDeadBlockEliminationOpt(b *builder) {
// This requires the reverse post-order traversal to be calculated before calling this function,
// hence passCalculateImmediateDominators must be called before this.
func passRedundantPhiEliminationOpt(b *builder) {
redundantParameterIndexes := b.ints[:0] // reuse the slice from previous iterations.
redundantParams := b.redundantParams[:0] // reuse the slice from previous iterations.
// TODO: this might be costly for large programs, but at least, as far as I did the experiment, it's almost the
// same as the single iteration version in terms of the overall compilation time. That *might be* mostly thanks to the fact
@@ -163,55 +163,58 @@ func passRedundantPhiEliminationOpt(b *builder) {
}
if redundant {
b.redundantParameterIndexToValue[paramIndex] = nonSelfReferencingValue
redundantParameterIndexes = append(redundantParameterIndexes, paramIndex)
redundantParams = append(redundantParams, redundantParam{
index: paramIndex, uniqueValue: nonSelfReferencingValue,
})
}
}
if len(b.redundantParameterIndexToValue) == 0 {
if len(redundantParams) == 0 {
continue
}
changed = true
// Remove the redundant PHIs from the argument list of branching instructions.
for predIndex := range blk.preds {
var cur int
redundantParamsCur, predParamCur := 0, 0
predBlk := blk.preds[predIndex]
branchInst := predBlk.branch
view := branchInst.vs.View()
for argIndex, value := range view {
if _, ok := b.redundantParameterIndexToValue[argIndex]; !ok {
view[cur] = value
cur++
if len(redundantParams) == redundantParamsCur ||
redundantParams[redundantParamsCur].index != argIndex {
view[predParamCur] = value
predParamCur++
} else {
redundantParamsCur++
}
}
branchInst.vs.Cut(cur)
branchInst.vs.Cut(predParamCur)
}
// Still need to have the definition of the value of the PHI (previously as the parameter).
for _, redundantParamIndex := range redundantParameterIndexes {
phiValue := params[redundantParamIndex]
onlyValue := b.redundantParameterIndexToValue[redundantParamIndex]
for i := range redundantParams {
redundantValue := &redundantParams[i]
phiValue := params[redundantValue.index]
// Create an alias in this block from the only phi argument to the phi value.
b.alias(phiValue, onlyValue)
b.alias(phiValue, redundantValue.uniqueValue)
}
// Finally, Remove the param from the blk.
var cur int
paramsCur, redundantParamsCur := 0, 0
for paramIndex := 0; paramIndex < paramNum; paramIndex++ {
param := params[paramIndex]
if _, ok := b.redundantParameterIndexToValue[paramIndex]; !ok {
params[cur] = param
cur++
if len(redundantParams) == redundantParamsCur || redundantParams[redundantParamsCur].index != paramIndex {
params[paramsCur] = param
paramsCur++
} else {
redundantParamsCur++
}
}
blk.params.Cut(cur)
blk.params.Cut(paramsCur)
// Clears the map for the next iteration.
for _, paramIndex := range redundantParameterIndexes {
delete(b.redundantParameterIndexToValue, paramIndex)
}
redundantParameterIndexes = redundantParameterIndexes[:0]
redundantParams = redundantParams[:0]
}
if !changed {
@@ -220,7 +223,7 @@ func passRedundantPhiEliminationOpt(b *builder) {
}
// Reuse the slice for the future passes.
b.ints = redundantParameterIndexes
b.redundantParams = redundantParams
}
// passDeadCodeEliminationOpt traverses all the instructions, and calculates the reference count of each Value, and