diff --git a/src/codegen/Function.go b/src/codegen/Function.go index 5800efc..b911b27 100644 --- a/src/codegen/Function.go +++ b/src/codegen/Function.go @@ -14,6 +14,7 @@ type Function struct { Assembler asm.Assembler Steps []*Step ValueToStep map[ssa.Value]*Step + BlockToRegion map[*ssa.Block]region CPU *cpu.CPU Preserved set.Ordered[cpu.Register] Count count diff --git a/src/codegen/createLiveRanges.go b/src/codegen/createLiveRanges.go index 57b384d..6ff486e 100644 --- a/src/codegen/createLiveRanges.go +++ b/src/codegen/createLiveRanges.go @@ -1,18 +1,9 @@ package codegen -import "git.urbach.dev/cli/q/src/ssa" - // createLiveRanges adds the `value` to the list of live values in its live range. -func (f *Function) createLiveRanges(step *Step) { - for _, user := range step.Value.Users() { - userStep := f.ValueToStep[user] - index := 0 - _, isPhi := user.(*ssa.Phi) - - if !isPhi { - index = userStep.Block.Index(user) - } - - f.markAlive(step, userStep.Block.Instructions[:index], userStep.Block, userStep) +func (f *Function) createLiveRanges(live *Step) { + for _, user := range live.Value.Users() { + use := f.ValueToStep[user] + f.markAlive(live, use.Block, use) } } \ No newline at end of file diff --git a/src/codegen/createSteps.go b/src/codegen/createSteps.go index a328d4e..cda57d4 100644 --- a/src/codegen/createSteps.go +++ b/src/codegen/createSteps.go @@ -12,6 +12,7 @@ func (f *Function) createSteps(ir ssa.IR) { storage := make([]Step, count) f.Steps = make([]*Step, count) f.ValueToStep = make(map[ssa.Value]*Step, count) + f.BlockToRegion = make(map[*ssa.Block]region, len(ir.Blocks)) i := 0 for _, block := range ir.Blocks { @@ -25,6 +26,11 @@ func (f *Function) createSteps(ir ssa.IR) { i++ } + f.BlockToRegion[block] = region{ + Start: uint32(i), + End: uint32(i + len(block.Instructions)), + } + for _, instr := range block.Instructions { step := &storage[i] step.Index = i diff --git a/src/codegen/markAlive.go b/src/codegen/markAlive.go index e223990..625afa4 100644 --- a/src/codegen/markAlive.go +++ b/src/codegen/markAlive.go @@ -6,21 +6,38 @@ import ( "git.urbach.dev/cli/q/src/ssa" ) -// markAlive marks the `live` value in the `instructions` as alive and recursively +// markAlive marks the `live` value in the `block` as alive and recursively // proceeds in the predecessors of `block` if they can reach the definition. -func (f *Function) markAlive(live *Step, instructions []ssa.Value, block *ssa.Block, use *Step) { - for _, current := range slices.Backward(instructions) { - currentStep := f.ValueToStep[current] +func (f *Function) markAlive(live *Step, block *ssa.Block, use *Step) { + if use.Block == block { + phi, isPhi := use.Value.(*ssa.Phi) - if slices.Contains(currentStep.Live, live) { + if isPhi { + index := phi.Arguments.Index(live.Value) + pre := block.Predecessors[index] + f.markAlive(live, pre, use) return } + } - currentStep.Live = append(currentStep.Live, live) + region := f.BlockToRegion[block] - if live.Value == current { - _, isParam := current.(*ssa.Parameter) - _, isPhi := current.(*ssa.Phi) + if use.Block == block { + region.End = uint32(use.Index) + } + + steps := f.Steps[region.Start:region.End] + + for _, current := range slices.Backward(steps) { + if slices.Contains(current.Live, live) { + return + } + + current.Live = append(current.Live, live) + + if live.Value == current.Value { + _, isParam := current.Value.(*ssa.Parameter) + _, isPhi := current.Value.(*ssa.Phi) if !isParam && !isPhi { return @@ -28,19 +45,9 @@ func (f *Function) markAlive(live *Step, instructions []ssa.Value, block *ssa.Bl } } - if use.Block == block { - switch instr := use.Value.(type) { - case *ssa.Phi: - index := instr.Arguments.Index(live.Value) - pre := block.Predecessors[index] - f.markAlive(live, pre.Instructions, pre, use) - return - } - } - for _, pre := range block.Predecessors { if pre.CanReachPredecessor(live.Block) { - f.markAlive(live, pre.Instructions, pre, use) + f.markAlive(live, pre, use) } } } \ No newline at end of file diff --git a/src/codegen/region.go b/src/codegen/region.go new file mode 100644 index 0000000..af6d1cc --- /dev/null +++ b/src/codegen/region.go @@ -0,0 +1,7 @@ +package codegen + +// region is used to mark the start and end indices of a block. +type region struct { + Start uint32 + End uint32 +} \ No newline at end of file