Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions opt/function_control_flow_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package opt

import (
"alon.kr/x/graph"
"alon.kr/x/usm/gen"
)

// FunctionControlFlowInfo holds the flattened basic-block list, the
// block-to-index mapping, and the control-flow graph for a function. It is
// derived purely from gen.FunctionInfo and can be used by any pass that needs
// CFG traversal (e.g. constant propagation, liveness analysis) or block-index
// lookups (e.g. SSA construction).
type FunctionControlFlowInfo struct {
// A linear representation of all basic blocks in the function.
BasicBlocks []*gen.BasicBlockInfo

// Maps each basic block to its index in BasicBlocks.
BasicBlocksToIndex map[*gen.BasicBlockInfo]uint

ControlFlowGraph *graph.Graph
}

// NewFunctionControlFlowInfo builds a FunctionControlFlowInfo from the given
// function by linearising its basic blocks and constructing the CFG from their
// forward edges.
func NewFunctionControlFlowInfo(function *gen.FunctionInfo) FunctionControlFlowInfo {
basicBlocks := function.CollectBasicBlocks()

blockToIndex := make(map[*gen.BasicBlockInfo]uint, len(basicBlocks))
for i, b := range basicBlocks {
blockToIndex[b] = uint(i)
}

forwardEdges := make([][]uint, len(basicBlocks))
for i, b := range basicBlocks {
edges := make([]uint, 0, len(b.ForwardEdges))
for _, target := range b.ForwardEdges {
edges = append(edges, blockToIndex[target])
}
forwardEdges[i] = edges
}

cfg := graph.NewGraph(forwardEdges)
return FunctionControlFlowInfo{
BasicBlocks: basicBlocks,
BasicBlocksToIndex: blockToIndex,
ControlFlowGraph: &cfg,
}
}
48 changes: 9 additions & 39 deletions opt/ssa/function_ssa_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"alon.kr/x/set"
"alon.kr/x/usm/core"
"alon.kr/x/usm/gen"
"alon.kr/x/usm/opt"
)

type forwardingRegisterDescriptor struct {
Expand Down Expand Up @@ -75,14 +76,11 @@ func (p *phiInstructionDescriptor) CommitForwardingRegisters() core.ResultList {
type FunctionSsaInfo struct {
*gen.FunctionInfo

SsaConstructionScheme SsaConstructionScheme

// A linear representation of all basic blocks in the function.
BasicBlocks []*gen.BasicBlockInfo
// Embeds the basic-block list, block-to-index mapping, and CFG that are
// shared with other passes (e.g. constant propagation).
opt.FunctionControlFlowInfo

// A mapping between all basic blocks in the function and their index in the
// Blocks slice.
BasicBlocksToIndex map[*gen.BasicBlockInfo]uint
SsaConstructionScheme SsaConstructionScheme

// A mapping between all basic blocks and the phi instructions that they
// define in their entry.
Expand All @@ -96,32 +94,26 @@ type FunctionSsaInfo struct {
// A mapping from (base) registers to their index in the registers slice.
RegistersToIndex map[*gen.RegisterInfo]uint

ControlFlowGraph *graph.Graph
DominatorJoinGraph *graph.DominatorJoinGraph
}

func NewFunctionSsaInfo(
function *gen.FunctionInfo,
ssaConstructionScheme SsaConstructionScheme,
) FunctionSsaInfo {
basicBlocks := function.CollectBasicBlocks()
basicBlockToIndex := createMappingToIndex(basicBlocks)
forwardEdges := getBasicBlocksForwardEdges(basicBlocks, basicBlockToIndex)
graph := graph.NewGraph(forwardEdges)
dominatorJoinGraph := graph.DominatorJoinGraph(0)
cfInfo := opt.NewFunctionControlFlowInfo(function)
dominatorJoinGraph := cfInfo.ControlFlowGraph.DominatorJoinGraph(0)

baseRegisters := function.Registers.GetAllRegisters()
registersToIndex := createMappingToIndex(baseRegisters)

return FunctionSsaInfo{
FunctionInfo: function,
FunctionControlFlowInfo: cfInfo,
SsaConstructionScheme: ssaConstructionScheme,
BasicBlocks: basicBlocks,
BasicBlocksToIndex: basicBlockToIndex,
PhiInstructionsPerBlock: make([][]phiInstructionDescriptor, len(basicBlocks)),
PhiInstructionsPerBlock: make([][]phiInstructionDescriptor, len(cfInfo.BasicBlocks)),
BaseRegisters: baseRegisters,
RegistersToIndex: registersToIndex,
ControlFlowGraph: &graph,
DominatorJoinGraph: &dominatorJoinGraph,
}
}
Expand All @@ -136,28 +128,6 @@ func createMappingToIndex[T comparable](
return mapping
}

func getSingleBasicBlockForwardEdges(
block *gen.BasicBlockInfo,
basicBlockToIndex map[*gen.BasicBlockInfo]uint,
) []uint {
indices := make([]uint, 0, len(block.ForwardEdges))
for _, targetBlock := range block.ForwardEdges {
indices = append(indices, basicBlockToIndex[targetBlock])
}
return indices
}

func getBasicBlocksForwardEdges(
blocks []*gen.BasicBlockInfo,
basicBlockToIndex map[*gen.BasicBlockInfo]uint,
) [][]uint {
edges := make([][]uint, len(blocks))
for i, block := range blocks {
edges[i] = getSingleBasicBlockForwardEdges(block, basicBlockToIndex)
}
return edges
}

// Returns all the basic blocks in which the provided register is defined.
func (i *FunctionSsaInfo) getDefinitions(
register *gen.RegisterInfo,
Expand Down
Loading