Skip to content

Commit d71c945

Browse files
authored
Make DataFlowGraph::blocks public (#5740)
Similar to when we exposed the DataFlowGraph::insts field through a restrictive newtype, expose DataFlowGraph::blocks through an interface that allows a restrictive set of operations. This field being public now allows us to avoid a rematch in ssa construction, and simplifies the implementation of adding a block argument to a block referenced by a br_table instruction.
1 parent f3b408d commit d71c945

File tree

3 files changed

+73
-48
lines changed

3 files changed

+73
-48
lines changed

cranelift/codegen/src/ir/dfg.rs

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,45 @@ impl IndexMut<Inst> for Insts {
4545
}
4646
}
4747

48+
/// Storage for basic blocks within the DFG.
49+
#[derive(Clone, PartialEq, Hash)]
50+
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
51+
pub struct Blocks(PrimaryMap<Block, BlockData>);
52+
53+
impl Blocks {
54+
/// Create a new basic block.
55+
pub fn add(&mut self) -> Block {
56+
self.0.push(BlockData::new())
57+
}
58+
59+
/// Get the total number of basic blocks created in this function, whether they are
60+
/// currently inserted in the layout or not.
61+
///
62+
/// This is intended for use with `SecondaryMap::with_capacity`.
63+
pub fn len(&self) -> usize {
64+
self.0.len()
65+
}
66+
67+
/// Returns `true` if the given block reference is valid.
68+
pub fn is_valid(&self, block: Block) -> bool {
69+
self.0.is_valid(block)
70+
}
71+
}
72+
73+
impl Index<Block> for Blocks {
74+
type Output = BlockData;
75+
76+
fn index(&self, block: Block) -> &BlockData {
77+
&self.0[block]
78+
}
79+
}
80+
81+
impl IndexMut<Block> for Blocks {
82+
fn index_mut(&mut self, block: Block) -> &mut BlockData {
83+
&mut self.0[block]
84+
}
85+
}
86+
4887
/// A data flow graph defines all instructions and basic blocks in a function as well as
4988
/// the data flow dependencies between them. The DFG also tracks values which can be either
5089
/// instruction results or block parameters.
@@ -70,7 +109,7 @@ pub struct DataFlowGraph {
70109
///
71110
/// This map is not in program order. That is handled by `Layout`, and so is the sequence of
72111
/// instructions contained in each block.
73-
blocks: PrimaryMap<Block, BlockData>,
112+
pub blocks: Blocks,
74113

75114
/// Dynamic types created.
76115
pub dynamic_types: DynamicTypes,
@@ -113,7 +152,7 @@ impl DataFlowGraph {
113152
Self {
114153
insts: Insts(PrimaryMap::new()),
115154
results: SecondaryMap::new(),
116-
blocks: PrimaryMap::new(),
155+
blocks: Blocks(PrimaryMap::new()),
117156
dynamic_types: DynamicTypes::new(),
118157
value_lists: ValueListPool::new(),
119158
values: PrimaryMap::new(),
@@ -130,7 +169,7 @@ impl DataFlowGraph {
130169
pub fn clear(&mut self) {
131170
self.insts.0.clear();
132171
self.results.clear();
133-
self.blocks.clear();
172+
self.blocks.0.clear();
134173
self.dynamic_types.clear();
135174
self.value_lists.clear();
136175
self.values.clear();
@@ -1084,17 +1123,17 @@ impl DataFlowGraph {
10841123
impl DataFlowGraph {
10851124
/// Create a new basic block.
10861125
pub fn make_block(&mut self) -> Block {
1087-
self.blocks.push(BlockData::new())
1126+
self.blocks.add()
10881127
}
10891128

10901129
/// Get the number of parameters on `block`.
10911130
pub fn num_block_params(&self, block: Block) -> usize {
1092-
self.blocks[block].params.len(&self.value_lists)
1131+
self.blocks[block].params(&self.value_lists).len()
10931132
}
10941133

10951134
/// Get the parameters on `block`.
10961135
pub fn block_params(&self, block: Block) -> &[Value] {
1097-
self.blocks[block].params.as_slice(&self.value_lists)
1136+
self.blocks[block].params(&self.value_lists)
10981137
}
10991138

11001139
/// Get the types of the parameters on `block`.
@@ -1250,7 +1289,7 @@ impl DataFlowGraph {
12501289
/// match the function arguments.
12511290
#[derive(Clone, PartialEq, Hash)]
12521291
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1253-
struct BlockData {
1292+
pub struct BlockData {
12541293
/// List of parameters to this block.
12551294
params: ValueList,
12561295
}
@@ -1261,6 +1300,11 @@ impl BlockData {
12611300
params: ValueList::new(),
12621301
}
12631302
}
1303+
1304+
/// Get the parameters on `block`.
1305+
pub fn params<'a>(&self, pool: &'a ValueListPool) -> &'a [Value] {
1306+
self.params.as_slice(pool)
1307+
}
12641308
}
12651309

12661310
/// Object that can display an instruction.

cranelift/codegen/src/ir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub use crate::ir::builder::{
3333
InsertBuilder, InstBuilder, InstBuilderBase, InstInserterBase, ReplaceBuilder,
3434
};
3535
pub use crate::ir::constant::{ConstantData, ConstantPool};
36-
pub use crate::ir::dfg::{DataFlowGraph, ValueDef};
36+
pub use crate::ir::dfg::{BlockData, DataFlowGraph, ValueDef};
3737
pub use crate::ir::dynamic_type::{dynamic_to_fixed, DynamicTypeData, DynamicTypes};
3838
pub use crate::ir::entities::{
3939
Block, Constant, DynamicStackSlot, DynamicType, FuncRef, GlobalValue, Immediate, Inst,

cranelift/frontend/src/ssa.rs

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ use cranelift_codegen::cursor::{Cursor, FuncCursor};
1515
use cranelift_codegen::entity::{EntityList, EntitySet, ListPool, SecondaryMap};
1616
use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
1717
use cranelift_codegen::ir::types::{F32, F64, I128, I64};
18-
use cranelift_codegen::ir::{
19-
Block, Function, Inst, InstBuilder, InstructionData, JumpTableData, Type, Value,
20-
};
18+
use cranelift_codegen::ir::{Block, Function, Inst, InstBuilder, InstructionData, Type, Value};
2119
use cranelift_codegen::packed_option::PackedOption;
2220

2321
/// Structure containing the data relevant the construction of SSA for a given function.
@@ -577,58 +575,41 @@ impl SSABuilder {
577575
dest_block: Block,
578576
val: Value,
579577
) -> Option<(Block, Inst)> {
580-
match &func.dfg.insts[branch] {
578+
let dfg = &mut func.stencil.dfg;
579+
match &mut dfg.insts[branch] {
581580
// For a single destination appending a jump argument to the instruction
582581
// is sufficient.
583-
InstructionData::Jump { .. } => {
584-
let dfg = &mut func.dfg;
585-
for dest in dfg.insts[branch].branch_destination_mut() {
586-
dest.append_argument(val, &mut dfg.value_lists);
587-
}
582+
InstructionData::Jump { destination, .. } => {
583+
destination.append_argument(val, &mut dfg.value_lists);
588584
None
589585
}
590-
InstructionData::Brif { .. } => {
591-
let dfg = &mut func.dfg;
592-
for block in dfg.insts[branch].branch_destination_mut() {
586+
InstructionData::Brif { blocks, .. } => {
587+
for block in blocks {
593588
if block.block(&dfg.value_lists) == dest_block {
594589
block.append_argument(val, &mut dfg.value_lists);
595590
}
596591
}
597592
None
598593
}
599-
InstructionData::BranchTable { table: mut jt, .. } => {
594+
InstructionData::BranchTable {
595+
table: jt,
596+
destination,
597+
..
598+
} => {
600599
// In the case of a jump table, the situation is tricky because br_table doesn't
601600
// support arguments. We have to split the critical edge.
602-
let middle_block = func.dfg.make_block();
603-
func.layout.append_block(middle_block);
604-
605-
let table = &func.jump_tables[jt];
606-
let mut copied = JumpTableData::with_capacity(table.len());
607-
let mut changed = false;
608-
for &destination in table.iter() {
609-
if destination == dest_block {
610-
copied.push_entry(middle_block);
611-
changed = true;
612-
} else {
613-
copied.push_entry(destination);
614-
}
615-
}
601+
let middle_block = dfg.blocks.add();
602+
func.stencil.layout.append_block(middle_block);
616603

617-
if changed {
618-
jt = func.create_jump_table(copied);
604+
let table = &mut func.stencil.jump_tables[*jt];
605+
for block in table.iter_mut() {
606+
if *block == dest_block {
607+
*block = middle_block;
608+
}
619609
}
620610

621-
// Redo the match from above, but this time capture mutable references
622-
match &mut func.dfg.insts[branch] {
623-
InstructionData::BranchTable {
624-
destination, table, ..
625-
} => {
626-
if *destination == dest_block {
627-
*destination = middle_block;
628-
}
629-
*table = jt;
630-
}
631-
_ => unreachable!(),
611+
if *destination == dest_block {
612+
*destination = middle_block;
632613
}
633614

634615
let mut cur = FuncCursor::new(func).at_bottom(middle_block);

0 commit comments

Comments
 (0)