package codegen import ( "slices" "git.urbach.dev/cli/q/src/ssa" ) // 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, block *ssa.Block, use *Step, first bool) { if use.Block == block { phi, isPhi := use.Value.(*ssa.Phi) if isPhi { for index, value := range phi.Arguments { if value == live.Value { f.markAlive(live, block.Predecessors[index], use, false) } } return } } region := f.BlockToRegion[block] if first && use.Block == block && (block.Loop == nil || live.Block.Loop != nil) { region.End = uint32(use.Index) } var ( steps = f.Steps[region.Start:region.End] field *ssa.Field isField bool ) for _, current := range slices.Backward(steps) { if slices.Contains(current.Live, live) { return } if isField && field.Tuple == current.Value { return } current.Live = append(current.Live, live) if live.Value == current.Value { field, isField = current.Value.(*ssa.Field) _, isParam := current.Value.(*ssa.Parameter) _, isPhi := current.Value.(*ssa.Phi) if !isParam && !isPhi && !isField { return } } } for _, pre := range block.Predecessors { if pre == block { continue } if !pre.CanReachPredecessor(live.Block) { continue } if f.isDeadAtEnd(live, pre) { continue } f.markAlive(live, pre, use, false) } }