Coverage Report

Created: 2026-02-14 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cranelift-codegen-0.128.3/src/ir/layout.rs
Line
Count
Source
1
//! Function layout.
2
//!
3
//! The order of basic blocks in a function and the order of instructions in a block is
4
//! determined by the `Layout` data structure defined in this module.
5
6
use crate::entity::SecondaryMap;
7
use crate::ir::progpoint::ProgramPoint;
8
use crate::ir::{Block, Inst};
9
use crate::packed_option::PackedOption;
10
use crate::{timing, trace};
11
use core::cmp;
12
13
/// The `Layout` struct determines the layout of blocks and instructions in a function. It does not
14
/// contain definitions of instructions or blocks, but depends on `Inst` and `Block` entity references
15
/// being defined elsewhere.
16
///
17
/// This data structure determines:
18
///
19
/// - The order of blocks in the function.
20
/// - Which block contains a given instruction.
21
/// - The order of instructions with a block.
22
///
23
/// While data dependencies are not recorded, instruction ordering does affect control
24
/// dependencies, so part of the semantics of the program are determined by the layout.
25
///
26
#[derive(Debug, Clone, PartialEq, Hash)]
27
pub struct Layout {
28
    /// Linked list nodes for the layout order of blocks Forms a doubly linked list, terminated in
29
    /// both ends by `None`.
30
    blocks: SecondaryMap<Block, BlockNode>,
31
32
    /// Linked list nodes for the layout order of instructions. Forms a double linked list per block,
33
    /// terminated in both ends by `None`.
34
    insts: SecondaryMap<Inst, InstNode>,
35
36
    /// First block in the layout order, or `None` when no blocks have been laid out.
37
    first_block: Option<Block>,
38
39
    /// Last block in the layout order, or `None` when no blocks have been laid out.
40
    last_block: Option<Block>,
41
}
42
43
impl Layout {
44
    /// Create a new empty `Layout`.
45
629k
    pub fn new() -> Self {
46
629k
        Self {
47
629k
            blocks: SecondaryMap::new(),
48
629k
            insts: SecondaryMap::new(),
49
629k
            first_block: None,
50
629k
            last_block: None,
51
629k
        }
52
629k
    }
<cranelift_codegen::ir::layout::Layout>::new
Line
Count
Source
45
157k
    pub fn new() -> Self {
46
157k
        Self {
47
157k
            blocks: SecondaryMap::new(),
48
157k
            insts: SecondaryMap::new(),
49
157k
            first_block: None,
50
157k
            last_block: None,
51
157k
        }
52
157k
    }
<cranelift_codegen::ir::layout::Layout>::new
Line
Count
Source
45
472k
    pub fn new() -> Self {
46
472k
        Self {
47
472k
            blocks: SecondaryMap::new(),
48
472k
            insts: SecondaryMap::new(),
49
472k
            first_block: None,
50
472k
            last_block: None,
51
472k
        }
52
472k
    }
53
54
    /// Clear the layout.
55
0
    pub fn clear(&mut self) {
56
0
        self.blocks.clear();
57
0
        self.insts.clear();
58
0
        self.first_block = None;
59
0
        self.last_block = None;
60
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::clear
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::clear
61
62
    /// Returns the capacity of the `BlockData` map.
63
2.58M
    pub fn block_capacity(&self) -> usize {
64
2.58M
        self.blocks.capacity()
65
2.58M
    }
<cranelift_codegen::ir::layout::Layout>::block_capacity
Line
Count
Source
63
579k
    pub fn block_capacity(&self) -> usize {
64
579k
        self.blocks.capacity()
65
579k
    }
<cranelift_codegen::ir::layout::Layout>::block_capacity
Line
Count
Source
63
2.00M
    pub fn block_capacity(&self) -> usize {
64
2.00M
        self.blocks.capacity()
65
2.00M
    }
66
}
67
68
/// Sequence numbers.
69
///
70
/// All instructions are given a sequence number that can be used to quickly determine
71
/// their relative position in a block. The sequence numbers are not contiguous, but are assigned
72
/// like line numbers in BASIC: 10, 20, 30, ...
73
///
74
/// Sequence numbers are strictly increasing within a block, but are reset between blocks.
75
///
76
/// The result is that sequence numbers work like BASIC line numbers for the textual form of the IR.
77
type SequenceNumber = u32;
78
79
/// Initial stride assigned to new sequence numbers.
80
const MAJOR_STRIDE: SequenceNumber = 10;
81
82
/// Secondary stride used when renumbering locally.
83
const MINOR_STRIDE: SequenceNumber = 2;
84
85
/// Limit on the sequence number range we'll renumber locally. If this limit is exceeded, we'll
86
/// switch to a full block renumbering.
87
const LOCAL_LIMIT: SequenceNumber = 100 * MINOR_STRIDE;
88
89
/// Compute the midpoint between `a` and `b`.
90
/// Return `None` if the midpoint would be equal to either.
91
9.34M
fn midpoint(a: SequenceNumber, b: SequenceNumber) -> Option<SequenceNumber> {
92
9.34M
    debug_assert!(a < b);
93
    // Avoid integer overflow.
94
9.34M
    let m = a + (b - a) / 2;
95
9.34M
    if m > a { Some(m) } else { None }
96
9.34M
}
cranelift_codegen::ir::layout::midpoint
Line
Count
Source
91
1.12M
fn midpoint(a: SequenceNumber, b: SequenceNumber) -> Option<SequenceNumber> {
92
1.12M
    debug_assert!(a < b);
93
    // Avoid integer overflow.
94
1.12M
    let m = a + (b - a) / 2;
95
1.12M
    if m > a { Some(m) } else { None }
96
1.12M
}
cranelift_codegen::ir::layout::midpoint
Line
Count
Source
91
8.22M
fn midpoint(a: SequenceNumber, b: SequenceNumber) -> Option<SequenceNumber> {
92
8.22M
    debug_assert!(a < b);
93
    // Avoid integer overflow.
94
8.22M
    let m = a + (b - a) / 2;
95
8.22M
    if m > a { Some(m) } else { None }
96
8.22M
}
97
98
impl Layout {
99
    /// Compare the program points `a` and `b` in the same block relative to this program order.
100
    ///
101
    /// Return `Less` if `a` appears in the program before `b`.
102
    ///
103
    /// This is declared as a generic such that it can be called with `Inst` and `Block` arguments
104
    /// directly. Depending on the implementation, there is a good chance performance will be
105
    /// improved for those cases where the type of either argument is known statically.
106
91.8M
    pub fn pp_cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
107
91.8M
    where
108
91.8M
        A: Into<ProgramPoint>,
109
91.8M
        B: Into<ProgramPoint>,
110
    {
111
91.8M
        let a = a.into();
112
91.8M
        let b = b.into();
113
91.8M
        debug_assert_eq!(self.pp_block(a), self.pp_block(b));
114
91.8M
        let a_seq = match a {
115
0
            ProgramPoint::Block(_block) => 0,
116
91.8M
            ProgramPoint::Inst(inst) => self.insts[inst].seq,
117
        };
118
91.8M
        let b_seq = match b {
119
0
            ProgramPoint::Block(_block) => 0,
120
91.8M
            ProgramPoint::Inst(inst) => self.insts[inst].seq,
121
        };
122
91.8M
        a_seq.cmp(&b_seq)
123
91.8M
    }
<cranelift_codegen::ir::layout::Layout>::pp_cmp::<cranelift_codegen::ir::progpoint::ProgramPoint, cranelift_codegen::ir::progpoint::ProgramPoint>
Line
Count
Source
106
13.6M
    pub fn pp_cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
107
13.6M
    where
108
13.6M
        A: Into<ProgramPoint>,
109
13.6M
        B: Into<ProgramPoint>,
110
    {
111
13.6M
        let a = a.into();
112
13.6M
        let b = b.into();
113
13.6M
        debug_assert_eq!(self.pp_block(a), self.pp_block(b));
114
13.6M
        let a_seq = match a {
115
0
            ProgramPoint::Block(_block) => 0,
116
13.6M
            ProgramPoint::Inst(inst) => self.insts[inst].seq,
117
        };
118
13.6M
        let b_seq = match b {
119
0
            ProgramPoint::Block(_block) => 0,
120
13.6M
            ProgramPoint::Inst(inst) => self.insts[inst].seq,
121
        };
122
13.6M
        a_seq.cmp(&b_seq)
123
13.6M
    }
<cranelift_codegen::ir::layout::Layout>::pp_cmp::<cranelift_codegen::ir::progpoint::ProgramPoint, cranelift_codegen::ir::progpoint::ProgramPoint>
Line
Count
Source
106
78.1M
    pub fn pp_cmp<A, B>(&self, a: A, b: B) -> cmp::Ordering
107
78.1M
    where
108
78.1M
        A: Into<ProgramPoint>,
109
78.1M
        B: Into<ProgramPoint>,
110
    {
111
78.1M
        let a = a.into();
112
78.1M
        let b = b.into();
113
78.1M
        debug_assert_eq!(self.pp_block(a), self.pp_block(b));
114
78.1M
        let a_seq = match a {
115
0
            ProgramPoint::Block(_block) => 0,
116
78.1M
            ProgramPoint::Inst(inst) => self.insts[inst].seq,
117
        };
118
78.1M
        let b_seq = match b {
119
0
            ProgramPoint::Block(_block) => 0,
120
78.1M
            ProgramPoint::Inst(inst) => self.insts[inst].seq,
121
        };
122
78.1M
        a_seq.cmp(&b_seq)
123
78.1M
    }
124
}
125
126
// Private methods for dealing with sequence numbers.
127
impl Layout {
128
    /// Assign a valid sequence number to `inst` such that the numbers are still monotonic. This may
129
    /// require renumbering.
130
28.6M
    fn assign_inst_seq(&mut self, inst: Inst) {
131
        // Get the sequence number immediately before `inst`.
132
28.6M
        let prev_seq = match self.insts[inst].prev.expand() {
133
25.6M
            Some(prev_inst) => self.insts[prev_inst].seq,
134
3.02M
            None => 0,
135
        };
136
137
        // Get the sequence number immediately following `inst`.
138
28.6M
        let next_seq = if let Some(next_inst) = self.insts[inst].next.expand() {
139
9.34M
            self.insts[next_inst].seq
140
        } else {
141
            // There is nothing after `inst`. We can just use a major stride.
142
19.2M
            self.insts[inst].seq = prev_seq + MAJOR_STRIDE;
143
19.2M
            return;
144
        };
145
146
        // Check if there is room between these sequence numbers.
147
9.34M
        if let Some(seq) = midpoint(prev_seq, next_seq) {
148
7.39M
            self.insts[inst].seq = seq;
149
7.39M
        } else {
150
1.95M
            // No available integers between `prev_seq` and `next_seq`. We have to renumber.
151
1.95M
            self.renumber_insts(inst, prev_seq + MINOR_STRIDE, prev_seq + LOCAL_LIMIT);
152
1.95M
        }
153
28.6M
    }
<cranelift_codegen::ir::layout::Layout>::assign_inst_seq
Line
Count
Source
130
3.59M
    fn assign_inst_seq(&mut self, inst: Inst) {
131
        // Get the sequence number immediately before `inst`.
132
3.59M
        let prev_seq = match self.insts[inst].prev.expand() {
133
3.31M
            Some(prev_inst) => self.insts[prev_inst].seq,
134
277k
            None => 0,
135
        };
136
137
        // Get the sequence number immediately following `inst`.
138
3.59M
        let next_seq = if let Some(next_inst) = self.insts[inst].next.expand() {
139
1.12M
            self.insts[next_inst].seq
140
        } else {
141
            // There is nothing after `inst`. We can just use a major stride.
142
2.47M
            self.insts[inst].seq = prev_seq + MAJOR_STRIDE;
143
2.47M
            return;
144
        };
145
146
        // Check if there is room between these sequence numbers.
147
1.12M
        if let Some(seq) = midpoint(prev_seq, next_seq) {
148
812k
            self.insts[inst].seq = seq;
149
812k
        } else {
150
311k
            // No available integers between `prev_seq` and `next_seq`. We have to renumber.
151
311k
            self.renumber_insts(inst, prev_seq + MINOR_STRIDE, prev_seq + LOCAL_LIMIT);
152
311k
        }
153
3.59M
    }
<cranelift_codegen::ir::layout::Layout>::assign_inst_seq
Line
Count
Source
130
25.0M
    fn assign_inst_seq(&mut self, inst: Inst) {
131
        // Get the sequence number immediately before `inst`.
132
25.0M
        let prev_seq = match self.insts[inst].prev.expand() {
133
22.2M
            Some(prev_inst) => self.insts[prev_inst].seq,
134
2.75M
            None => 0,
135
        };
136
137
        // Get the sequence number immediately following `inst`.
138
25.0M
        let next_seq = if let Some(next_inst) = self.insts[inst].next.expand() {
139
8.22M
            self.insts[next_inst].seq
140
        } else {
141
            // There is nothing after `inst`. We can just use a major stride.
142
16.8M
            self.insts[inst].seq = prev_seq + MAJOR_STRIDE;
143
16.8M
            return;
144
        };
145
146
        // Check if there is room between these sequence numbers.
147
8.22M
        if let Some(seq) = midpoint(prev_seq, next_seq) {
148
6.58M
            self.insts[inst].seq = seq;
149
6.58M
        } else {
150
1.63M
            // No available integers between `prev_seq` and `next_seq`. We have to renumber.
151
1.63M
            self.renumber_insts(inst, prev_seq + MINOR_STRIDE, prev_seq + LOCAL_LIMIT);
152
1.63M
        }
153
25.0M
    }
154
155
    /// Renumber instructions starting from `inst` until the end of the block or until numbers catch
156
    /// up.
157
    ///
158
    /// If sequence numbers exceed `limit`, switch to a full block renumbering.
159
1.95M
    fn renumber_insts(&mut self, inst: Inst, seq: SequenceNumber, limit: SequenceNumber) {
160
1.95M
        let mut inst = inst;
161
1.95M
        let mut seq = seq;
162
163
        loop {
164
13.9M
            self.insts[inst].seq = seq;
165
166
            // Next instruction.
167
13.9M
            inst = match self.insts[inst].next.expand() {
168
754k
                None => return,
169
13.2M
                Some(next) => next,
170
            };
171
172
13.2M
            if seq < self.insts[inst].seq {
173
                // Sequence caught up.
174
1.19M
                return;
175
12.0M
            }
176
177
12.0M
            if seq > limit {
178
                // We're pushing too many instructions in front of us.
179
                // Switch to a full block renumbering to make some space.
180
22
                self.full_block_renumber(
181
22
                    self.inst_block(inst)
182
22
                        .expect("inst must be inserted before assigning an seq"),
183
                );
184
22
                return;
185
12.0M
            }
186
187
12.0M
            seq += MINOR_STRIDE;
188
        }
189
1.95M
    }
<cranelift_codegen::ir::layout::Layout>::renumber_insts
Line
Count
Source
159
311k
    fn renumber_insts(&mut self, inst: Inst, seq: SequenceNumber, limit: SequenceNumber) {
160
311k
        let mut inst = inst;
161
311k
        let mut seq = seq;
162
163
        loop {
164
2.84M
            self.insts[inst].seq = seq;
165
166
            // Next instruction.
167
2.84M
            inst = match self.insts[inst].next.expand() {
168
143k
                None => return,
169
2.69M
                Some(next) => next,
170
            };
171
172
2.69M
            if seq < self.insts[inst].seq {
173
                // Sequence caught up.
174
168k
                return;
175
2.53M
            }
176
177
2.53M
            if seq > limit {
178
                // We're pushing too many instructions in front of us.
179
                // Switch to a full block renumbering to make some space.
180
4
                self.full_block_renumber(
181
4
                    self.inst_block(inst)
182
4
                        .expect("inst must be inserted before assigning an seq"),
183
                );
184
4
                return;
185
2.53M
            }
186
187
2.53M
            seq += MINOR_STRIDE;
188
        }
189
311k
    }
<cranelift_codegen::ir::layout::Layout>::renumber_insts
Line
Count
Source
159
1.63M
    fn renumber_insts(&mut self, inst: Inst, seq: SequenceNumber, limit: SequenceNumber) {
160
1.63M
        let mut inst = inst;
161
1.63M
        let mut seq = seq;
162
163
        loop {
164
11.1M
            self.insts[inst].seq = seq;
165
166
            // Next instruction.
167
11.1M
            inst = match self.insts[inst].next.expand() {
168
610k
                None => return,
169
10.5M
                Some(next) => next,
170
            };
171
172
10.5M
            if seq < self.insts[inst].seq {
173
                // Sequence caught up.
174
1.02M
                return;
175
9.49M
            }
176
177
9.49M
            if seq > limit {
178
                // We're pushing too many instructions in front of us.
179
                // Switch to a full block renumbering to make some space.
180
18
                self.full_block_renumber(
181
18
                    self.inst_block(inst)
182
18
                        .expect("inst must be inserted before assigning an seq"),
183
                );
184
18
                return;
185
9.49M
            }
186
187
9.49M
            seq += MINOR_STRIDE;
188
        }
189
1.63M
    }
190
191
    /// Renumber all instructions in a block.
192
    ///
193
    /// This doesn't affect the position of anything, but it gives more room in the internal
194
    /// sequence numbers for inserting instructions later.
195
22
    fn full_block_renumber(&mut self, block: Block) {
196
22
        let _tt = timing::layout_renumber();
197
        // Avoid 0 as this is reserved for the program point indicating the block itself
198
22
        let mut seq = MAJOR_STRIDE;
199
22
        let mut next_inst = self.blocks[block].first_inst.expand();
200
67.8k
        while let Some(inst) = next_inst {
201
67.8k
            self.insts[inst].seq = seq;
202
67.8k
            seq += MAJOR_STRIDE;
203
67.8k
            next_inst = self.insts[inst].next.expand();
204
67.8k
        }
205
206
22
        trace!("Renumbered {} program points", seq / MAJOR_STRIDE);
207
22
    }
<cranelift_codegen::ir::layout::Layout>::full_block_renumber
Line
Count
Source
195
4
    fn full_block_renumber(&mut self, block: Block) {
196
4
        let _tt = timing::layout_renumber();
197
        // Avoid 0 as this is reserved for the program point indicating the block itself
198
4
        let mut seq = MAJOR_STRIDE;
199
4
        let mut next_inst = self.blocks[block].first_inst.expand();
200
14.3k
        while let Some(inst) = next_inst {
201
14.3k
            self.insts[inst].seq = seq;
202
14.3k
            seq += MAJOR_STRIDE;
203
14.3k
            next_inst = self.insts[inst].next.expand();
204
14.3k
        }
205
206
4
        trace!("Renumbered {} program points", seq / MAJOR_STRIDE);
207
4
    }
<cranelift_codegen::ir::layout::Layout>::full_block_renumber
Line
Count
Source
195
18
    fn full_block_renumber(&mut self, block: Block) {
196
18
        let _tt = timing::layout_renumber();
197
        // Avoid 0 as this is reserved for the program point indicating the block itself
198
18
        let mut seq = MAJOR_STRIDE;
199
18
        let mut next_inst = self.blocks[block].first_inst.expand();
200
53.4k
        while let Some(inst) = next_inst {
201
53.4k
            self.insts[inst].seq = seq;
202
53.4k
            seq += MAJOR_STRIDE;
203
53.4k
            next_inst = self.insts[inst].next.expand();
204
53.4k
        }
205
206
18
        trace!("Renumbered {} program points", seq / MAJOR_STRIDE);
207
18
    }
208
}
209
210
/// Methods for laying out blocks.
211
///
212
/// An unknown block starts out as *not inserted* in the block layout. The layout is a linear order of
213
/// inserted blocks. Once a block has been inserted in the layout, instructions can be added. A block
214
/// can only be removed from the layout when it is empty.
215
///
216
/// Since every block must end with a terminator instruction which cannot fall through, the layout of
217
/// blocks do not affect the semantics of the program.
218
///
219
impl Layout {
220
    /// Is `block` currently part of the layout?
221
52.9M
    pub fn is_block_inserted(&self, block: Block) -> bool {
222
52.9M
        Some(block) == self.first_block || self.blocks[block].prev.is_some()
223
52.9M
    }
<cranelift_codegen::ir::layout::Layout>::is_block_inserted
Line
Count
Source
221
8.27M
    pub fn is_block_inserted(&self, block: Block) -> bool {
222
8.27M
        Some(block) == self.first_block || self.blocks[block].prev.is_some()
223
8.27M
    }
<cranelift_codegen::ir::layout::Layout>::is_block_inserted
Line
Count
Source
221
44.7M
    pub fn is_block_inserted(&self, block: Block) -> bool {
222
44.7M
        Some(block) == self.first_block || self.blocks[block].prev.is_some()
223
44.7M
    }
224
225
    /// Insert `block` as the last block in the layout.
226
2.31M
    pub fn append_block(&mut self, block: Block) {
227
2.31M
        debug_assert!(
228
0
            !self.is_block_inserted(block),
229
            "Cannot append block that is already in the layout"
230
        );
231
        {
232
2.31M
            let node = &mut self.blocks[block];
233
2.31M
            debug_assert!(node.first_inst.is_none() && node.last_inst.is_none());
234
2.31M
            node.prev = self.last_block.into();
235
2.31M
            node.next = None.into();
236
        }
237
2.31M
        if let Some(last) = self.last_block {
238
1.88M
            self.blocks[last].next = block.into();
239
1.88M
        } else {
240
430k
            self.first_block = Some(block);
241
430k
        }
242
2.31M
        self.last_block = Some(block);
243
2.31M
    }
<cranelift_codegen::ir::layout::Layout>::append_block
Line
Count
Source
226
221k
    pub fn append_block(&mut self, block: Block) {
227
221k
        debug_assert!(
228
0
            !self.is_block_inserted(block),
229
            "Cannot append block that is already in the layout"
230
        );
231
        {
232
221k
            let node = &mut self.blocks[block];
233
221k
            debug_assert!(node.first_inst.is_none() && node.last_inst.is_none());
234
221k
            node.prev = self.last_block.into();
235
221k
            node.next = None.into();
236
        }
237
221k
        if let Some(last) = self.last_block {
238
125k
            self.blocks[last].next = block.into();
239
125k
        } else {
240
96.6k
            self.first_block = Some(block);
241
96.6k
        }
242
221k
        self.last_block = Some(block);
243
221k
    }
<cranelift_codegen::ir::layout::Layout>::append_block
Line
Count
Source
226
2.09M
    pub fn append_block(&mut self, block: Block) {
227
2.09M
        debug_assert!(
228
0
            !self.is_block_inserted(block),
229
            "Cannot append block that is already in the layout"
230
        );
231
        {
232
2.09M
            let node = &mut self.blocks[block];
233
2.09M
            debug_assert!(node.first_inst.is_none() && node.last_inst.is_none());
234
2.09M
            node.prev = self.last_block.into();
235
2.09M
            node.next = None.into();
236
        }
237
2.09M
        if let Some(last) = self.last_block {
238
1.75M
            self.blocks[last].next = block.into();
239
1.75M
        } else {
240
333k
            self.first_block = Some(block);
241
333k
        }
242
2.09M
        self.last_block = Some(block);
243
2.09M
    }
244
245
    /// Insert `block` in the layout before the existing block `before`.
246
0
    pub fn insert_block(&mut self, block: Block, before: Block) {
247
0
        debug_assert!(
248
0
            !self.is_block_inserted(block),
249
            "Cannot insert block that is already in the layout"
250
        );
251
0
        debug_assert!(
252
0
            self.is_block_inserted(before),
253
            "block Insertion point not in the layout"
254
        );
255
0
        let after = self.blocks[before].prev;
256
0
        {
257
0
            let node = &mut self.blocks[block];
258
0
            node.next = before.into();
259
0
            node.prev = after;
260
0
        }
261
0
        self.blocks[before].prev = block.into();
262
0
        match after.expand() {
263
0
            None => self.first_block = Some(block),
264
0
            Some(a) => self.blocks[a].next = block.into(),
265
        }
266
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::insert_block
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::insert_block
267
268
    /// Insert `block` in the layout *after* the existing block `after`.
269
60
    pub fn insert_block_after(&mut self, block: Block, after: Block) {
270
60
        debug_assert!(
271
0
            !self.is_block_inserted(block),
272
            "Cannot insert block that is already in the layout"
273
        );
274
60
        debug_assert!(
275
0
            self.is_block_inserted(after),
276
            "block Insertion point not in the layout"
277
        );
278
60
        let before = self.blocks[after].next;
279
60
        {
280
60
            let node = &mut self.blocks[block];
281
60
            node.next = before;
282
60
            node.prev = after.into();
283
60
        }
284
60
        self.blocks[after].next = block.into();
285
60
        match before.expand() {
286
60
            None => self.last_block = Some(block),
287
0
            Some(b) => self.blocks[b].prev = block.into(),
288
        }
289
60
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::insert_block_after
<cranelift_codegen::ir::layout::Layout>::insert_block_after
Line
Count
Source
269
60
    pub fn insert_block_after(&mut self, block: Block, after: Block) {
270
60
        debug_assert!(
271
0
            !self.is_block_inserted(block),
272
            "Cannot insert block that is already in the layout"
273
        );
274
60
        debug_assert!(
275
0
            self.is_block_inserted(after),
276
            "block Insertion point not in the layout"
277
        );
278
60
        let before = self.blocks[after].next;
279
60
        {
280
60
            let node = &mut self.blocks[block];
281
60
            node.next = before;
282
60
            node.prev = after.into();
283
60
        }
284
60
        self.blocks[after].next = block.into();
285
60
        match before.expand() {
286
60
            None => self.last_block = Some(block),
287
0
            Some(b) => self.blocks[b].prev = block.into(),
288
        }
289
60
    }
290
291
    /// Remove `block` from the layout.
292
279k
    pub fn remove_block(&mut self, block: Block) {
293
279k
        debug_assert!(self.is_block_inserted(block), "block not in the layout");
294
279k
        debug_assert!(self.first_inst(block).is_none(), "block must be empty.");
295
296
        // Clear the `block` node and extract links.
297
        let prev;
298
        let next;
299
279k
        {
300
279k
            let n = &mut self.blocks[block];
301
279k
            prev = n.prev;
302
279k
            next = n.next;
303
279k
            n.prev = None.into();
304
279k
            n.next = None.into();
305
279k
        }
306
        // Fix up links to `block`.
307
279k
        match prev.expand() {
308
0
            None => self.first_block = next.expand(),
309
279k
            Some(p) => self.blocks[p].next = next,
310
        }
311
279k
        match next.expand() {
312
408
            None => self.last_block = prev.expand(),
313
278k
            Some(n) => self.blocks[n].prev = prev,
314
        }
315
279k
    }
<cranelift_codegen::ir::layout::Layout>::remove_block
Line
Count
Source
292
74
    pub fn remove_block(&mut self, block: Block) {
293
74
        debug_assert!(self.is_block_inserted(block), "block not in the layout");
294
74
        debug_assert!(self.first_inst(block).is_none(), "block must be empty.");
295
296
        // Clear the `block` node and extract links.
297
        let prev;
298
        let next;
299
74
        {
300
74
            let n = &mut self.blocks[block];
301
74
            prev = n.prev;
302
74
            next = n.next;
303
74
            n.prev = None.into();
304
74
            n.next = None.into();
305
74
        }
306
        // Fix up links to `block`.
307
74
        match prev.expand() {
308
0
            None => self.first_block = next.expand(),
309
74
            Some(p) => self.blocks[p].next = next,
310
        }
311
74
        match next.expand() {
312
20
            None => self.last_block = prev.expand(),
313
54
            Some(n) => self.blocks[n].prev = prev,
314
        }
315
74
    }
<cranelift_codegen::ir::layout::Layout>::remove_block
Line
Count
Source
292
279k
    pub fn remove_block(&mut self, block: Block) {
293
279k
        debug_assert!(self.is_block_inserted(block), "block not in the layout");
294
279k
        debug_assert!(self.first_inst(block).is_none(), "block must be empty.");
295
296
        // Clear the `block` node and extract links.
297
        let prev;
298
        let next;
299
279k
        {
300
279k
            let n = &mut self.blocks[block];
301
279k
            prev = n.prev;
302
279k
            next = n.next;
303
279k
            n.prev = None.into();
304
279k
            n.next = None.into();
305
279k
        }
306
        // Fix up links to `block`.
307
279k
        match prev.expand() {
308
0
            None => self.first_block = next.expand(),
309
279k
            Some(p) => self.blocks[p].next = next,
310
        }
311
279k
        match next.expand() {
312
388
            None => self.last_block = prev.expand(),
313
278k
            Some(n) => self.blocks[n].prev = prev,
314
        }
315
279k
    }
316
317
    /// Return an iterator over all blocks in layout order.
318
9.89M
    pub fn blocks(&self) -> Blocks<'_> {
319
9.89M
        Blocks {
320
9.89M
            layout: self,
321
9.89M
            next: self.first_block,
322
9.89M
        }
323
9.89M
    }
<cranelift_codegen::ir::layout::Layout>::blocks
Line
Count
Source
318
2.22M
    pub fn blocks(&self) -> Blocks<'_> {
319
2.22M
        Blocks {
320
2.22M
            layout: self,
321
2.22M
            next: self.first_block,
322
2.22M
        }
323
2.22M
    }
<cranelift_codegen::ir::layout::Layout>::blocks
Line
Count
Source
318
7.67M
    pub fn blocks(&self) -> Blocks<'_> {
319
7.67M
        Blocks {
320
7.67M
            layout: self,
321
7.67M
            next: self.first_block,
322
7.67M
        }
323
7.67M
    }
324
325
    /// Get the function's entry block.
326
    /// This is simply the first block in the layout order.
327
33.7M
    pub fn entry_block(&self) -> Option<Block> {
328
33.7M
        self.first_block
329
33.7M
    }
<cranelift_codegen::ir::layout::Layout>::entry_block
Line
Count
Source
327
4.62M
    pub fn entry_block(&self) -> Option<Block> {
328
4.62M
        self.first_block
329
4.62M
    }
<cranelift_codegen::ir::layout::Layout>::entry_block
Line
Count
Source
327
29.1M
    pub fn entry_block(&self) -> Option<Block> {
328
29.1M
        self.first_block
329
29.1M
    }
330
331
    /// Get the last block in the layout.
332
430k
    pub fn last_block(&self) -> Option<Block> {
333
430k
        self.last_block
334
430k
    }
<cranelift_codegen::ir::layout::Layout>::last_block
Line
Count
Source
332
96.6k
    pub fn last_block(&self) -> Option<Block> {
333
96.6k
        self.last_block
334
96.6k
    }
<cranelift_codegen::ir::layout::Layout>::last_block
Line
Count
Source
332
333k
    pub fn last_block(&self) -> Option<Block> {
333
333k
        self.last_block
334
333k
    }
335
336
    /// Get the block preceding `block` in the layout order.
337
2.59M
    pub fn prev_block(&self, block: Block) -> Option<Block> {
338
2.59M
        self.blocks[block].prev.expand()
339
2.59M
    }
<cranelift_codegen::ir::layout::Layout>::prev_block
Line
Count
Source
337
221k
    pub fn prev_block(&self, block: Block) -> Option<Block> {
338
221k
        self.blocks[block].prev.expand()
339
221k
    }
<cranelift_codegen::ir::layout::Layout>::prev_block
Line
Count
Source
337
2.37M
    pub fn prev_block(&self, block: Block) -> Option<Block> {
338
2.37M
        self.blocks[block].prev.expand()
339
2.37M
    }
340
341
    /// Get the block following `block` in the layout order.
342
53.3M
    pub fn next_block(&self, block: Block) -> Option<Block> {
343
53.3M
        self.blocks[block].next.expand()
344
53.3M
    }
<cranelift_codegen::ir::layout::Layout>::next_block
Line
Count
Source
342
5.54M
    pub fn next_block(&self, block: Block) -> Option<Block> {
343
5.54M
        self.blocks[block].next.expand()
344
5.54M
    }
<cranelift_codegen::ir::layout::Layout>::next_block
Line
Count
Source
342
47.8M
    pub fn next_block(&self, block: Block) -> Option<Block> {
343
47.8M
        self.blocks[block].next.expand()
344
47.8M
    }
345
346
    /// Mark a block as "cold".
347
    ///
348
    /// This will try to move it out of the ordinary path of execution
349
    /// when lowered to machine code.
350
0
    pub fn set_cold(&mut self, block: Block) {
351
0
        self.blocks[block].cold = true;
352
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::set_cold
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::set_cold
353
354
    /// Is the given block cold?
355
4.85M
    pub fn is_cold(&self, block: Block) -> bool {
356
4.85M
        self.blocks[block].cold
357
4.85M
    }
<cranelift_codegen::ir::layout::Layout>::is_cold
Line
Count
Source
355
830k
    pub fn is_cold(&self, block: Block) -> bool {
356
830k
        self.blocks[block].cold
357
830k
    }
<cranelift_codegen::ir::layout::Layout>::is_cold
Line
Count
Source
355
4.02M
    pub fn is_cold(&self, block: Block) -> bool {
356
4.02M
        self.blocks[block].cold
357
4.02M
    }
358
}
359
360
/// A single node in the linked-list of blocks.
361
// **Note:** Whenever you add new fields here, don't forget to update the custom serializer for `Layout` too.
362
#[derive(Clone, Debug, Default, PartialEq, Hash)]
363
struct BlockNode {
364
    prev: PackedOption<Block>,
365
    next: PackedOption<Block>,
366
    first_inst: PackedOption<Inst>,
367
    last_inst: PackedOption<Inst>,
368
    cold: bool,
369
}
370
371
/// Iterate over blocks in layout order. See [crate::ir::layout::Layout::blocks].
372
pub struct Blocks<'f> {
373
    layout: &'f Layout,
374
    next: Option<Block>,
375
}
376
377
impl<'f> Iterator for Blocks<'f> {
378
    type Item = Block;
379
380
58.6M
    fn next(&mut self) -> Option<Block> {
381
58.6M
        match self.next {
382
48.7M
            Some(block) => {
383
48.7M
                self.next = self.layout.next_block(block);
384
48.7M
                Some(block)
385
            }
386
9.89M
            None => None,
387
        }
388
58.6M
    }
<cranelift_codegen::ir::layout::Blocks as core::iter::traits::iterator::Iterator>::next
Line
Count
Source
380
7.32M
    fn next(&mut self) -> Option<Block> {
381
7.32M
        match self.next {
382
5.10M
            Some(block) => {
383
5.10M
                self.next = self.layout.next_block(block);
384
5.10M
                Some(block)
385
            }
386
2.22M
            None => None,
387
        }
388
7.32M
    }
<cranelift_codegen::ir::layout::Blocks as core::iter::traits::iterator::Iterator>::next
Line
Count
Source
380
51.3M
    fn next(&mut self) -> Option<Block> {
381
51.3M
        match self.next {
382
43.6M
            Some(block) => {
383
43.6M
                self.next = self.layout.next_block(block);
384
43.6M
                Some(block)
385
            }
386
7.67M
            None => None,
387
        }
388
51.3M
    }
389
}
390
391
/// Use a layout reference in a for loop.
392
impl<'f> IntoIterator for &'f Layout {
393
    type Item = Block;
394
    type IntoIter = Blocks<'f>;
395
396
3.01M
    fn into_iter(self) -> Blocks<'f> {
397
3.01M
        self.blocks()
398
3.01M
    }
<&cranelift_codegen::ir::layout::Layout as core::iter::traits::collect::IntoIterator>::into_iter
Line
Count
Source
396
676k
    fn into_iter(self) -> Blocks<'f> {
397
676k
        self.blocks()
398
676k
    }
<&cranelift_codegen::ir::layout::Layout as core::iter::traits::collect::IntoIterator>::into_iter
Line
Count
Source
396
2.33M
    fn into_iter(self) -> Blocks<'f> {
397
2.33M
        self.blocks()
398
2.33M
    }
399
}
400
401
/// Methods for arranging instructions.
402
///
403
/// An instruction starts out as *not inserted* in the layout. An instruction can be inserted into
404
/// a block at a given position.
405
impl Layout {
406
    /// Get the block containing `inst`, or `None` if `inst` is not inserted in the layout.
407
644M
    pub fn inst_block(&self, inst: Inst) -> Option<Block> {
408
644M
        self.insts[inst].block.into()
409
644M
    }
<cranelift_codegen::ir::layout::Layout>::inst_block
Line
Count
Source
407
92.7M
    pub fn inst_block(&self, inst: Inst) -> Option<Block> {
408
92.7M
        self.insts[inst].block.into()
409
92.7M
    }
<cranelift_codegen::ir::layout::Layout>::inst_block
Line
Count
Source
407
551M
    pub fn inst_block(&self, inst: Inst) -> Option<Block> {
408
551M
        self.insts[inst].block.into()
409
551M
    }
410
411
    /// Get the block containing the program point `pp`. Panic if `pp` is not in the layout.
412
0
    pub fn pp_block(&self, pp: ProgramPoint) -> Block {
413
0
        match pp {
414
0
            ProgramPoint::Block(block) => block,
415
0
            ProgramPoint::Inst(inst) => self.inst_block(inst).expect("Program point not in layout"),
416
        }
417
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::pp_block
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::pp_block
418
419
    /// Append `inst` to the end of `block`.
420
19.2M
    pub fn append_inst(&mut self, inst: Inst, block: Block) {
421
19.2M
        debug_assert_eq!(self.inst_block(inst), None);
422
19.2M
        debug_assert!(
423
0
            self.is_block_inserted(block),
424
            "Cannot append instructions to block not in layout"
425
        );
426
        {
427
19.2M
            let block_node = &mut self.blocks[block];
428
            {
429
19.2M
                let inst_node = &mut self.insts[inst];
430
19.2M
                inst_node.block = block.into();
431
19.2M
                inst_node.prev = block_node.last_inst;
432
19.2M
                debug_assert!(inst_node.next.is_none());
433
            }
434
19.2M
            if block_node.first_inst.is_none() {
435
2.31M
                block_node.first_inst = inst.into();
436
16.9M
            } else {
437
16.9M
                self.insts[block_node.last_inst.unwrap()].next = inst.into();
438
16.9M
            }
439
19.2M
            block_node.last_inst = inst.into();
440
        }
441
19.2M
        self.assign_inst_seq(inst);
442
19.2M
    }
<cranelift_codegen::ir::layout::Layout>::append_inst
Line
Count
Source
420
2.47M
    pub fn append_inst(&mut self, inst: Inst, block: Block) {
421
2.47M
        debug_assert_eq!(self.inst_block(inst), None);
422
2.47M
        debug_assert!(
423
0
            self.is_block_inserted(block),
424
            "Cannot append instructions to block not in layout"
425
        );
426
        {
427
2.47M
            let block_node = &mut self.blocks[block];
428
            {
429
2.47M
                let inst_node = &mut self.insts[inst];
430
2.47M
                inst_node.block = block.into();
431
2.47M
                inst_node.prev = block_node.last_inst;
432
2.47M
                debug_assert!(inst_node.next.is_none());
433
            }
434
2.47M
            if block_node.first_inst.is_none() {
435
221k
                block_node.first_inst = inst.into();
436
2.25M
            } else {
437
2.25M
                self.insts[block_node.last_inst.unwrap()].next = inst.into();
438
2.25M
            }
439
2.47M
            block_node.last_inst = inst.into();
440
        }
441
2.47M
        self.assign_inst_seq(inst);
442
2.47M
    }
<cranelift_codegen::ir::layout::Layout>::append_inst
Line
Count
Source
420
16.8M
    pub fn append_inst(&mut self, inst: Inst, block: Block) {
421
16.8M
        debug_assert_eq!(self.inst_block(inst), None);
422
16.8M
        debug_assert!(
423
0
            self.is_block_inserted(block),
424
            "Cannot append instructions to block not in layout"
425
        );
426
        {
427
16.8M
            let block_node = &mut self.blocks[block];
428
            {
429
16.8M
                let inst_node = &mut self.insts[inst];
430
16.8M
                inst_node.block = block.into();
431
16.8M
                inst_node.prev = block_node.last_inst;
432
16.8M
                debug_assert!(inst_node.next.is_none());
433
            }
434
16.8M
            if block_node.first_inst.is_none() {
435
2.09M
                block_node.first_inst = inst.into();
436
14.7M
            } else {
437
14.7M
                self.insts[block_node.last_inst.unwrap()].next = inst.into();
438
14.7M
            }
439
16.8M
            block_node.last_inst = inst.into();
440
        }
441
16.8M
        self.assign_inst_seq(inst);
442
16.8M
    }
443
444
    /// Fetch a block's first instruction.
445
26.8M
    pub fn first_inst(&self, block: Block) -> Option<Inst> {
446
26.8M
        self.blocks[block].first_inst.into()
447
26.8M
    }
<cranelift_codegen::ir::layout::Layout>::first_inst
Line
Count
Source
445
2.70M
    pub fn first_inst(&self, block: Block) -> Option<Inst> {
446
2.70M
        self.blocks[block].first_inst.into()
447
2.70M
    }
<cranelift_codegen::ir::layout::Layout>::first_inst
Line
Count
Source
445
24.0M
    pub fn first_inst(&self, block: Block) -> Option<Inst> {
446
24.0M
        self.blocks[block].first_inst.into()
447
24.0M
    }
448
449
    /// Fetch a block's last instruction.
450
162M
    pub fn last_inst(&self, block: Block) -> Option<Inst> {
451
162M
        self.blocks[block].last_inst.into()
452
162M
    }
<cranelift_codegen::ir::layout::Layout>::last_inst
Line
Count
Source
450
20.5M
    pub fn last_inst(&self, block: Block) -> Option<Inst> {
451
20.5M
        self.blocks[block].last_inst.into()
452
20.5M
    }
<cranelift_codegen::ir::layout::Layout>::last_inst
Line
Count
Source
450
141M
    pub fn last_inst(&self, block: Block) -> Option<Inst> {
451
141M
        self.blocks[block].last_inst.into()
452
141M
    }
453
454
    /// Fetch the instruction following `inst`.
455
41.2M
    pub fn next_inst(&self, inst: Inst) -> Option<Inst> {
456
41.2M
        self.insts[inst].next.expand()
457
41.2M
    }
<cranelift_codegen::ir::layout::Layout>::next_inst
Line
Count
Source
455
5.96M
    pub fn next_inst(&self, inst: Inst) -> Option<Inst> {
456
5.96M
        self.insts[inst].next.expand()
457
5.96M
    }
<cranelift_codegen::ir::layout::Layout>::next_inst
Line
Count
Source
455
35.2M
    pub fn next_inst(&self, inst: Inst) -> Option<Inst> {
456
35.2M
        self.insts[inst].next.expand()
457
35.2M
    }
458
459
    /// Fetch the instruction preceding `inst`.
460
37.6M
    pub fn prev_inst(&self, inst: Inst) -> Option<Inst> {
461
37.6M
        self.insts[inst].prev.expand()
462
37.6M
    }
<cranelift_codegen::ir::layout::Layout>::prev_inst
Line
Count
Source
460
4.55M
    pub fn prev_inst(&self, inst: Inst) -> Option<Inst> {
461
4.55M
        self.insts[inst].prev.expand()
462
4.55M
    }
<cranelift_codegen::ir::layout::Layout>::prev_inst
Line
Count
Source
460
33.1M
    pub fn prev_inst(&self, inst: Inst) -> Option<Inst> {
461
33.1M
        self.insts[inst].prev.expand()
462
33.1M
    }
463
464
    /// Insert `inst` before the instruction `before` in the same block.
465
9.34M
    pub fn insert_inst(&mut self, inst: Inst, before: Inst) {
466
9.34M
        debug_assert_eq!(self.inst_block(inst), None);
467
9.34M
        let block = self
468
9.34M
            .inst_block(before)
469
9.34M
            .expect("Instruction before insertion point not in the layout");
470
9.34M
        let after = self.insts[before].prev;
471
9.34M
        {
472
9.34M
            let inst_node = &mut self.insts[inst];
473
9.34M
            inst_node.block = block.into();
474
9.34M
            inst_node.next = before.into();
475
9.34M
            inst_node.prev = after;
476
9.34M
        }
477
9.34M
        self.insts[before].prev = inst.into();
478
9.34M
        match after.expand() {
479
713k
            None => self.blocks[block].first_inst = inst.into(),
480
8.63M
            Some(a) => self.insts[a].next = inst.into(),
481
        }
482
9.34M
        self.assign_inst_seq(inst);
483
9.34M
    }
<cranelift_codegen::ir::layout::Layout>::insert_inst
Line
Count
Source
465
1.12M
    pub fn insert_inst(&mut self, inst: Inst, before: Inst) {
466
1.12M
        debug_assert_eq!(self.inst_block(inst), None);
467
1.12M
        let block = self
468
1.12M
            .inst_block(before)
469
1.12M
            .expect("Instruction before insertion point not in the layout");
470
1.12M
        let after = self.insts[before].prev;
471
1.12M
        {
472
1.12M
            let inst_node = &mut self.insts[inst];
473
1.12M
            inst_node.block = block.into();
474
1.12M
            inst_node.next = before.into();
475
1.12M
            inst_node.prev = after;
476
1.12M
        }
477
1.12M
        self.insts[before].prev = inst.into();
478
1.12M
        match after.expand() {
479
56.0k
            None => self.blocks[block].first_inst = inst.into(),
480
1.06M
            Some(a) => self.insts[a].next = inst.into(),
481
        }
482
1.12M
        self.assign_inst_seq(inst);
483
1.12M
    }
<cranelift_codegen::ir::layout::Layout>::insert_inst
Line
Count
Source
465
8.22M
    pub fn insert_inst(&mut self, inst: Inst, before: Inst) {
466
8.22M
        debug_assert_eq!(self.inst_block(inst), None);
467
8.22M
        let block = self
468
8.22M
            .inst_block(before)
469
8.22M
            .expect("Instruction before insertion point not in the layout");
470
8.22M
        let after = self.insts[before].prev;
471
8.22M
        {
472
8.22M
            let inst_node = &mut self.insts[inst];
473
8.22M
            inst_node.block = block.into();
474
8.22M
            inst_node.next = before.into();
475
8.22M
            inst_node.prev = after;
476
8.22M
        }
477
8.22M
        self.insts[before].prev = inst.into();
478
8.22M
        match after.expand() {
479
657k
            None => self.blocks[block].first_inst = inst.into(),
480
7.56M
            Some(a) => self.insts[a].next = inst.into(),
481
        }
482
8.22M
        self.assign_inst_seq(inst);
483
8.22M
    }
484
485
    /// Remove `inst` from the layout.
486
15.6M
    pub fn remove_inst(&mut self, inst: Inst) {
487
15.6M
        let block = self.inst_block(inst).expect("Instruction already removed.");
488
        // Clear the `inst` node and extract links.
489
        let prev;
490
        let next;
491
15.6M
        {
492
15.6M
            let n = &mut self.insts[inst];
493
15.6M
            prev = n.prev;
494
15.6M
            next = n.next;
495
15.6M
            n.block = None.into();
496
15.6M
            n.prev = None.into();
497
15.6M
            n.next = None.into();
498
15.6M
        }
499
        // Fix up links to `inst`.
500
15.6M
        match prev.expand() {
501
7.37M
            None => self.blocks[block].first_inst = next,
502
8.22M
            Some(p) => self.insts[p].next = next,
503
        }
504
15.6M
        match next.expand() {
505
279k
            None => self.blocks[block].last_inst = prev,
506
15.3M
            Some(n) => self.insts[n].prev = prev,
507
        }
508
15.6M
    }
<cranelift_codegen::ir::layout::Layout>::remove_inst
Line
Count
Source
486
1.60M
    pub fn remove_inst(&mut self, inst: Inst) {
487
1.60M
        let block = self.inst_block(inst).expect("Instruction already removed.");
488
        // Clear the `inst` node and extract links.
489
        let prev;
490
        let next;
491
1.60M
        {
492
1.60M
            let n = &mut self.insts[inst];
493
1.60M
            prev = n.prev;
494
1.60M
            next = n.next;
495
1.60M
            n.block = None.into();
496
1.60M
            n.prev = None.into();
497
1.60M
            n.next = None.into();
498
1.60M
        }
499
        // Fix up links to `inst`.
500
1.60M
        match prev.expand() {
501
710k
            None => self.blocks[block].first_inst = next,
502
895k
            Some(p) => self.insts[p].next = next,
503
        }
504
1.60M
        match next.expand() {
505
74
            None => self.blocks[block].last_inst = prev,
506
1.60M
            Some(n) => self.insts[n].prev = prev,
507
        }
508
1.60M
    }
<cranelift_codegen::ir::layout::Layout>::remove_inst
Line
Count
Source
486
13.9M
    pub fn remove_inst(&mut self, inst: Inst) {
487
13.9M
        let block = self.inst_block(inst).expect("Instruction already removed.");
488
        // Clear the `inst` node and extract links.
489
        let prev;
490
        let next;
491
13.9M
        {
492
13.9M
            let n = &mut self.insts[inst];
493
13.9M
            prev = n.prev;
494
13.9M
            next = n.next;
495
13.9M
            n.block = None.into();
496
13.9M
            n.prev = None.into();
497
13.9M
            n.next = None.into();
498
13.9M
        }
499
        // Fix up links to `inst`.
500
13.9M
        match prev.expand() {
501
6.66M
            None => self.blocks[block].first_inst = next,
502
7.33M
            Some(p) => self.insts[p].next = next,
503
        }
504
13.9M
        match next.expand() {
505
279k
            None => self.blocks[block].last_inst = prev,
506
13.7M
            Some(n) => self.insts[n].prev = prev,
507
        }
508
13.9M
    }
509
510
    /// Iterate over the instructions in `block` in layout order.
511
42.3M
    pub fn block_insts(&self, block: Block) -> Insts<'_> {
512
42.3M
        Insts {
513
42.3M
            layout: self,
514
42.3M
            head: self.blocks[block].first_inst.into(),
515
42.3M
            tail: self.blocks[block].last_inst.into(),
516
42.3M
        }
517
42.3M
    }
<cranelift_codegen::ir::layout::Layout>::block_insts
Line
Count
Source
511
4.39M
    pub fn block_insts(&self, block: Block) -> Insts<'_> {
512
4.39M
        Insts {
513
4.39M
            layout: self,
514
4.39M
            head: self.blocks[block].first_inst.into(),
515
4.39M
            tail: self.blocks[block].last_inst.into(),
516
4.39M
        }
517
4.39M
    }
<cranelift_codegen::ir::layout::Layout>::block_insts
Line
Count
Source
511
37.9M
    pub fn block_insts(&self, block: Block) -> Insts<'_> {
512
37.9M
        Insts {
513
37.9M
            layout: self,
514
37.9M
            head: self.blocks[block].first_inst.into(),
515
37.9M
            tail: self.blocks[block].last_inst.into(),
516
37.9M
        }
517
37.9M
    }
518
519
    /// Does the given block contain exactly one instruction?
520
191k
    pub fn block_contains_exactly_one_inst(&self, block: Block) -> bool {
521
191k
        let block = &self.blocks[block];
522
191k
        block.first_inst.is_some() && block.first_inst == block.last_inst
523
191k
    }
<cranelift_codegen::ir::layout::Layout>::block_contains_exactly_one_inst
Line
Count
Source
520
6.79k
    pub fn block_contains_exactly_one_inst(&self, block: Block) -> bool {
521
6.79k
        let block = &self.blocks[block];
522
6.79k
        block.first_inst.is_some() && block.first_inst == block.last_inst
523
6.79k
    }
<cranelift_codegen::ir::layout::Layout>::block_contains_exactly_one_inst
Line
Count
Source
520
184k
    pub fn block_contains_exactly_one_inst(&self, block: Block) -> bool {
521
184k
        let block = &self.blocks[block];
522
184k
        block.first_inst.is_some() && block.first_inst == block.last_inst
523
184k
    }
524
525
    /// Split the block containing `before` in two.
526
    ///
527
    /// Insert `new_block` after the old block and move `before` and the following instructions to
528
    /// `new_block`:
529
    ///
530
    /// ```text
531
    /// old_block:
532
    ///     i1
533
    ///     i2
534
    ///     i3 << before
535
    ///     i4
536
    /// ```
537
    /// becomes:
538
    ///
539
    /// ```text
540
    /// old_block:
541
    ///     i1
542
    ///     i2
543
    /// new_block:
544
    ///     i3 << before
545
    ///     i4
546
    /// ```
547
0
    pub fn split_block(&mut self, new_block: Block, before: Inst) {
548
0
        let old_block = self
549
0
            .inst_block(before)
550
0
            .expect("The `before` instruction must be in the layout");
551
0
        debug_assert!(!self.is_block_inserted(new_block));
552
553
        // Insert new_block after old_block.
554
0
        let next_block = self.blocks[old_block].next;
555
0
        let last_inst = self.blocks[old_block].last_inst;
556
0
        {
557
0
            let node = &mut self.blocks[new_block];
558
0
            node.prev = old_block.into();
559
0
            node.next = next_block;
560
0
            node.first_inst = before.into();
561
0
            node.last_inst = last_inst;
562
0
        }
563
0
        self.blocks[old_block].next = new_block.into();
564
565
        // Fix backwards link.
566
0
        if Some(old_block) == self.last_block {
567
0
            self.last_block = Some(new_block);
568
0
        } else {
569
0
            self.blocks[next_block.unwrap()].prev = new_block.into();
570
0
        }
571
572
        // Disconnect the instruction links.
573
0
        let prev_inst = self.insts[before].prev;
574
0
        self.insts[before].prev = None.into();
575
0
        self.blocks[old_block].last_inst = prev_inst;
576
0
        match prev_inst.expand() {
577
0
            None => self.blocks[old_block].first_inst = None.into(),
578
0
            Some(pi) => self.insts[pi].next = None.into(),
579
        }
580
581
        // Fix the instruction -> block pointers.
582
0
        let mut opt_i = Some(before);
583
0
        while let Some(i) = opt_i {
584
0
            debug_assert_eq!(self.insts[i].block.expand(), Some(old_block));
585
0
            self.insts[i].block = new_block.into();
586
0
            opt_i = self.insts[i].next.into();
587
        }
588
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::split_block
Unexecuted instantiation: <cranelift_codegen::ir::layout::Layout>::split_block
589
}
590
591
#[derive(Clone, Debug, Default)]
592
struct InstNode {
593
    /// The Block containing this instruction, or `None` if the instruction is not yet inserted.
594
    block: PackedOption<Block>,
595
    prev: PackedOption<Inst>,
596
    next: PackedOption<Inst>,
597
    seq: SequenceNumber,
598
}
599
600
impl PartialEq for InstNode {
601
0
    fn eq(&self, other: &Self) -> bool {
602
        // Ignore the sequence number as it is an optimization used by pp_cmp and may be different
603
        // even for equivalent layouts.
604
0
        self.block == other.block && self.prev == other.prev && self.next == other.next
605
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::InstNode as core::cmp::PartialEq>::eq
Unexecuted instantiation: <cranelift_codegen::ir::layout::InstNode as core::cmp::PartialEq>::eq
606
}
607
608
impl core::hash::Hash for InstNode {
609
0
    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
610
        // Ignore the sequence number as it is an optimization used by pp_cmp and may be different
611
        // even for equivalent layouts.
612
0
        self.block.hash(state);
613
0
        self.prev.hash(state);
614
0
        self.next.hash(state);
615
0
    }
Unexecuted instantiation: <cranelift_codegen::ir::layout::InstNode as core::hash::Hash>::hash::<_>
Unexecuted instantiation: <cranelift_codegen::ir::layout::InstNode as core::hash::Hash>::hash::<_>
616
}
617
618
/// Iterate over instructions in a block in layout order. See `Layout::block_insts()`.
619
pub struct Insts<'f> {
620
    layout: &'f Layout,
621
    head: Option<Inst>,
622
    tail: Option<Inst>,
623
}
624
625
impl<'f> Iterator for Insts<'f> {
626
    type Item = Inst;
627
628
360M
    fn next(&mut self) -> Option<Inst> {
629
360M
        let rval = self.head;
630
360M
        if let Some(inst) = rval {
631
321M
            if self.head == self.tail {
632
39.2M
                self.head = None;
633
39.2M
                self.tail = None;
634
282M
            } else {
635
282M
                self.head = self.layout.insts[inst].next.into();
636
282M
            }
637
38.3M
        }
638
360M
        rval
639
360M
    }
<cranelift_codegen::ir::layout::Insts as core::iter::traits::iterator::Iterator>::next
Line
Count
Source
628
48.6M
    fn next(&mut self) -> Option<Inst> {
629
48.6M
        let rval = self.head;
630
48.6M
        if let Some(inst) = rval {
631
44.6M
            if self.head == self.tail {
632
4.07M
                self.head = None;
633
4.07M
                self.tail = None;
634
40.5M
            } else {
635
40.5M
                self.head = self.layout.insts[inst].next.into();
636
40.5M
            }
637
4.00M
        }
638
48.6M
        rval
639
48.6M
    }
<cranelift_codegen::ir::layout::Insts as core::iter::traits::iterator::Iterator>::next
Line
Count
Source
628
311M
    fn next(&mut self) -> Option<Inst> {
629
311M
        let rval = self.head;
630
311M
        if let Some(inst) = rval {
631
277M
            if self.head == self.tail {
632
35.1M
                self.head = None;
633
35.1M
                self.tail = None;
634
241M
            } else {
635
241M
                self.head = self.layout.insts[inst].next.into();
636
241M
            }
637
34.3M
        }
638
311M
        rval
639
311M
    }
640
}
641
642
impl<'f> DoubleEndedIterator for Insts<'f> {
643
15.0M
    fn next_back(&mut self) -> Option<Inst> {
644
15.0M
        let rval = self.tail;
645
15.0M
        if let Some(inst) = rval {
646
13.0M
            if self.head == self.tail {
647
2.03M
                self.head = None;
648
2.03M
                self.tail = None;
649
10.9M
            } else {
650
10.9M
                self.tail = self.layout.insts[inst].prev.into();
651
10.9M
            }
652
2.03M
        }
653
15.0M
        rval
654
15.0M
    }
<cranelift_codegen::ir::layout::Insts as core::iter::traits::double_ended::DoubleEndedIterator>::next_back
Line
Count
Source
643
2.21M
    fn next_back(&mut self) -> Option<Inst> {
644
2.21M
        let rval = self.tail;
645
2.21M
        if let Some(inst) = rval {
646
1.98M
            if self.head == self.tail {
647
221k
                self.head = None;
648
221k
                self.tail = None;
649
1.76M
            } else {
650
1.76M
                self.tail = self.layout.insts[inst].prev.into();
651
1.76M
            }
652
221k
        }
653
2.21M
        rval
654
2.21M
    }
<cranelift_codegen::ir::layout::Insts as core::iter::traits::double_ended::DoubleEndedIterator>::next_back
Line
Count
Source
643
12.8M
    fn next_back(&mut self) -> Option<Inst> {
644
12.8M
        let rval = self.tail;
645
12.8M
        if let Some(inst) = rval {
646
11.0M
            if self.head == self.tail {
647
1.81M
                self.head = None;
648
1.81M
                self.tail = None;
649
9.22M
            } else {
650
9.22M
                self.tail = self.layout.insts[inst].prev.into();
651
9.22M
            }
652
1.81M
        }
653
12.8M
        rval
654
12.8M
    }
655
}
656
657
/// A custom serialize and deserialize implementation for [`Layout`].
658
///
659
/// This doesn't use a derived implementation as [`Layout`] is a manual implementation of a linked
660
/// list. Storing it directly as a regular list saves a lot of space.
661
///
662
/// The following format is used. (notated in EBNF form)
663
///
664
/// ```plain
665
/// data = block_data * ;
666
/// block_data = "block_id" , "cold" , "inst_count" , ( "inst_id" * ) ;
667
/// ```
668
#[cfg(feature = "enable-serde")]
669
mod serde {
670
    use ::serde::de::{Deserializer, Error, SeqAccess, Visitor};
671
    use ::serde::ser::{SerializeSeq, Serializer};
672
    use ::serde::{Deserialize, Serialize};
673
    use core::fmt;
674
    use core::marker::PhantomData;
675
676
    use super::*;
677
678
    impl Serialize for Layout {
679
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
680
        where
681
            S: Serializer,
682
        {
683
            let size = self.blocks().count() * 3
684
                + self
685
                    .blocks()
686
                    .map(|block| self.block_insts(block).count())
687
                    .sum::<usize>();
688
            let mut seq = serializer.serialize_seq(Some(size))?;
689
            for block in self.blocks() {
690
                seq.serialize_element(&block)?;
691
                seq.serialize_element(&self.blocks[block].cold)?;
692
                seq.serialize_element(&u32::try_from(self.block_insts(block).count()).unwrap())?;
693
                for inst in self.block_insts(block) {
694
                    seq.serialize_element(&inst)?;
695
                }
696
            }
697
            seq.end()
698
        }
699
    }
700
701
    impl<'de> Deserialize<'de> for Layout {
702
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
703
        where
704
            D: Deserializer<'de>,
705
        {
706
            deserializer.deserialize_seq(LayoutVisitor {
707
                marker: PhantomData,
708
            })
709
        }
710
    }
711
712
    struct LayoutVisitor {
713
        marker: PhantomData<fn() -> Layout>,
714
    }
715
716
    impl<'de> Visitor<'de> for LayoutVisitor {
717
        type Value = Layout;
718
719
        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
720
            write!(formatter, "a `cranelift_codegen::ir::Layout`")
721
        }
722
723
        fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
724
        where
725
            M: SeqAccess<'de>,
726
        {
727
            let mut layout = Layout::new();
728
729
            while let Some(block) = access.next_element::<Block>()? {
730
                layout.append_block(block);
731
732
                let cold = access
733
                    .next_element::<bool>()?
734
                    .ok_or_else(|| Error::missing_field("cold"))?;
735
                layout.blocks[block].cold = cold;
736
737
                let count = access
738
                    .next_element::<u32>()?
739
                    .ok_or_else(|| Error::missing_field("count"))?;
740
741
                for _ in 0..count {
742
                    let inst = access
743
                        .next_element::<Inst>()?
744
                        .ok_or_else(|| Error::missing_field("inst"))?;
745
                    layout.append_inst(inst, block);
746
                }
747
            }
748
749
            Ok(layout)
750
        }
751
    }
752
}
753
754
#[cfg(test)]
755
mod tests {
756
    use super::*;
757
    use crate::cursor::{Cursor, CursorPosition};
758
    use crate::entity::EntityRef;
759
    use crate::ir::{Block, Inst, SourceLoc};
760
    use alloc::vec::Vec;
761
    use core::cmp::Ordering;
762
763
    #[test]
764
    fn test_midpoint() {
765
        assert_eq!(midpoint(0, 1), None);
766
        assert_eq!(midpoint(0, 2), Some(1));
767
        assert_eq!(midpoint(0, 3), Some(1));
768
        assert_eq!(midpoint(0, 4), Some(2));
769
        assert_eq!(midpoint(1, 4), Some(2));
770
        assert_eq!(midpoint(2, 4), Some(3));
771
        assert_eq!(midpoint(3, 4), None);
772
        assert_eq!(midpoint(3, 4), None);
773
    }
774
775
    struct LayoutCursor<'f> {
776
        /// Borrowed function layout. Public so it can be re-borrowed from this cursor.
777
        pub layout: &'f mut Layout,
778
        pos: CursorPosition,
779
    }
780
781
    impl<'f> Cursor for LayoutCursor<'f> {
782
        fn position(&self) -> CursorPosition {
783
            self.pos
784
        }
785
786
        fn set_position(&mut self, pos: CursorPosition) {
787
            self.pos = pos;
788
        }
789
790
        fn srcloc(&self) -> SourceLoc {
791
            unimplemented!()
792
        }
793
794
        fn set_srcloc(&mut self, _srcloc: SourceLoc) {
795
            unimplemented!()
796
        }
797
798
        fn layout(&self) -> &Layout {
799
            self.layout
800
        }
801
802
        fn layout_mut(&mut self) -> &mut Layout {
803
            self.layout
804
        }
805
    }
806
807
    impl<'f> LayoutCursor<'f> {
808
        /// Create a new `LayoutCursor` for `layout`.
809
        /// The cursor holds a mutable reference to `layout` for its entire lifetime.
810
        pub fn new(layout: &'f mut Layout) -> Self {
811
            Self {
812
                layout,
813
                pos: CursorPosition::Nowhere,
814
            }
815
        }
816
    }
817
818
    fn verify(layout: &mut Layout, blocks: &[(Block, &[Inst])]) {
819
        // Check that blocks are inserted and instructions belong the right places.
820
        // Check forward linkage with iterators.
821
        // Check that layout sequence numbers are strictly monotonic.
822
        {
823
            let mut block_iter = layout.blocks();
824
            for &(block, insts) in blocks {
825
                assert!(layout.is_block_inserted(block));
826
                assert_eq!(block_iter.next(), Some(block));
827
828
                let mut seq = 0;
829
                let mut inst_iter = layout.block_insts(block);
830
                for &inst in insts {
831
                    assert_eq!(layout.inst_block(inst), Some(block));
832
                    assert_eq!(inst_iter.next(), Some(inst));
833
                    assert!(layout.insts[inst].seq > seq);
834
                    seq = layout.insts[inst].seq;
835
                }
836
                assert_eq!(inst_iter.next(), None);
837
            }
838
            assert_eq!(block_iter.next(), None);
839
        }
840
841
        // Check backwards linkage with a cursor.
842
        let mut cur = LayoutCursor::new(layout);
843
        for &(block, insts) in blocks.into_iter().rev() {
844
            assert_eq!(cur.prev_block(), Some(block));
845
            for &inst in insts.into_iter().rev() {
846
                assert_eq!(cur.prev_inst(), Some(inst));
847
            }
848
            assert_eq!(cur.prev_inst(), None);
849
        }
850
        assert_eq!(cur.prev_block(), None);
851
    }
852
853
    #[test]
854
    fn append_block() {
855
        let mut layout = Layout::new();
856
        let e0 = Block::new(0);
857
        let e1 = Block::new(1);
858
        let e2 = Block::new(2);
859
860
        {
861
            let imm = &layout;
862
            assert!(!imm.is_block_inserted(e0));
863
            assert!(!imm.is_block_inserted(e1));
864
        }
865
        verify(&mut layout, &[]);
866
867
        layout.append_block(e1);
868
        assert!(!layout.is_block_inserted(e0));
869
        assert!(layout.is_block_inserted(e1));
870
        assert!(!layout.is_block_inserted(e2));
871
        let v: Vec<Block> = layout.blocks().collect();
872
        assert_eq!(v, [e1]);
873
874
        layout.append_block(e2);
875
        assert!(!layout.is_block_inserted(e0));
876
        assert!(layout.is_block_inserted(e1));
877
        assert!(layout.is_block_inserted(e2));
878
        let v: Vec<Block> = layout.blocks().collect();
879
        assert_eq!(v, [e1, e2]);
880
881
        layout.append_block(e0);
882
        assert!(layout.is_block_inserted(e0));
883
        assert!(layout.is_block_inserted(e1));
884
        assert!(layout.is_block_inserted(e2));
885
        let v: Vec<Block> = layout.blocks().collect();
886
        assert_eq!(v, [e1, e2, e0]);
887
888
        {
889
            let imm = &layout;
890
            let mut v = Vec::new();
891
            for e in imm {
892
                v.push(e);
893
            }
894
            assert_eq!(v, [e1, e2, e0]);
895
        }
896
897
        // Test cursor positioning.
898
        let mut cur = LayoutCursor::new(&mut layout);
899
        assert_eq!(cur.position(), CursorPosition::Nowhere);
900
        assert_eq!(cur.next_inst(), None);
901
        assert_eq!(cur.position(), CursorPosition::Nowhere);
902
        assert_eq!(cur.prev_inst(), None);
903
        assert_eq!(cur.position(), CursorPosition::Nowhere);
904
905
        assert_eq!(cur.next_block(), Some(e1));
906
        assert_eq!(cur.position(), CursorPosition::Before(e1));
907
        assert_eq!(cur.next_inst(), None);
908
        assert_eq!(cur.position(), CursorPosition::After(e1));
909
        assert_eq!(cur.next_inst(), None);
910
        assert_eq!(cur.position(), CursorPosition::After(e1));
911
        assert_eq!(cur.next_block(), Some(e2));
912
        assert_eq!(cur.prev_inst(), None);
913
        assert_eq!(cur.position(), CursorPosition::Before(e2));
914
        assert_eq!(cur.next_block(), Some(e0));
915
        assert_eq!(cur.next_block(), None);
916
        assert_eq!(cur.position(), CursorPosition::Nowhere);
917
918
        // Backwards through the blocks.
919
        assert_eq!(cur.prev_block(), Some(e0));
920
        assert_eq!(cur.position(), CursorPosition::After(e0));
921
        assert_eq!(cur.prev_block(), Some(e2));
922
        assert_eq!(cur.prev_block(), Some(e1));
923
        assert_eq!(cur.prev_block(), None);
924
        assert_eq!(cur.position(), CursorPosition::Nowhere);
925
    }
926
927
    #[test]
928
    fn insert_block() {
929
        let mut layout = Layout::new();
930
        let e0 = Block::new(0);
931
        let e1 = Block::new(1);
932
        let e2 = Block::new(2);
933
934
        {
935
            let imm = &layout;
936
            assert!(!imm.is_block_inserted(e0));
937
            assert!(!imm.is_block_inserted(e1));
938
939
            let v: Vec<Block> = layout.blocks().collect();
940
            assert_eq!(v, []);
941
        }
942
943
        layout.append_block(e1);
944
        assert!(!layout.is_block_inserted(e0));
945
        assert!(layout.is_block_inserted(e1));
946
        assert!(!layout.is_block_inserted(e2));
947
        verify(&mut layout, &[(e1, &[])]);
948
949
        layout.insert_block(e2, e1);
950
        assert!(!layout.is_block_inserted(e0));
951
        assert!(layout.is_block_inserted(e1));
952
        assert!(layout.is_block_inserted(e2));
953
        verify(&mut layout, &[(e2, &[]), (e1, &[])]);
954
955
        layout.insert_block(e0, e1);
956
        assert!(layout.is_block_inserted(e0));
957
        assert!(layout.is_block_inserted(e1));
958
        assert!(layout.is_block_inserted(e2));
959
        verify(&mut layout, &[(e2, &[]), (e0, &[]), (e1, &[])]);
960
    }
961
962
    #[test]
963
    fn insert_block_after() {
964
        let mut layout = Layout::new();
965
        let e0 = Block::new(0);
966
        let e1 = Block::new(1);
967
        let e2 = Block::new(2);
968
969
        layout.append_block(e1);
970
        layout.insert_block_after(e2, e1);
971
        verify(&mut layout, &[(e1, &[]), (e2, &[])]);
972
973
        layout.insert_block_after(e0, e1);
974
        verify(&mut layout, &[(e1, &[]), (e0, &[]), (e2, &[])]);
975
    }
976
977
    #[test]
978
    fn append_inst() {
979
        let mut layout = Layout::new();
980
        let e1 = Block::new(1);
981
982
        layout.append_block(e1);
983
        let v: Vec<Inst> = layout.block_insts(e1).collect();
984
        assert_eq!(v, []);
985
986
        let i0 = Inst::new(0);
987
        let i1 = Inst::new(1);
988
        let i2 = Inst::new(2);
989
990
        assert_eq!(layout.inst_block(i0), None);
991
        assert_eq!(layout.inst_block(i1), None);
992
        assert_eq!(layout.inst_block(i2), None);
993
994
        layout.append_inst(i1, e1);
995
        assert_eq!(layout.inst_block(i0), None);
996
        assert_eq!(layout.inst_block(i1), Some(e1));
997
        assert_eq!(layout.inst_block(i2), None);
998
        let v: Vec<Inst> = layout.block_insts(e1).collect();
999
        assert_eq!(v, [i1]);
1000
1001
        layout.append_inst(i2, e1);
1002
        assert_eq!(layout.inst_block(i0), None);
1003
        assert_eq!(layout.inst_block(i1), Some(e1));
1004
        assert_eq!(layout.inst_block(i2), Some(e1));
1005
        let v: Vec<Inst> = layout.block_insts(e1).collect();
1006
        assert_eq!(v, [i1, i2]);
1007
1008
        // Test double-ended instruction iterator.
1009
        let v: Vec<Inst> = layout.block_insts(e1).rev().collect();
1010
        assert_eq!(v, [i2, i1]);
1011
1012
        layout.append_inst(i0, e1);
1013
        verify(&mut layout, &[(e1, &[i1, i2, i0])]);
1014
1015
        // Test cursor positioning.
1016
        let mut cur = LayoutCursor::new(&mut layout).at_top(e1);
1017
        assert_eq!(cur.position(), CursorPosition::Before(e1));
1018
        assert_eq!(cur.prev_inst(), None);
1019
        assert_eq!(cur.position(), CursorPosition::Before(e1));
1020
        assert_eq!(cur.next_inst(), Some(i1));
1021
        assert_eq!(cur.position(), CursorPosition::At(i1));
1022
        assert_eq!(cur.next_inst(), Some(i2));
1023
        assert_eq!(cur.next_inst(), Some(i0));
1024
        assert_eq!(cur.prev_inst(), Some(i2));
1025
        assert_eq!(cur.position(), CursorPosition::At(i2));
1026
        assert_eq!(cur.next_inst(), Some(i0));
1027
        assert_eq!(cur.position(), CursorPosition::At(i0));
1028
        assert_eq!(cur.next_inst(), None);
1029
        assert_eq!(cur.position(), CursorPosition::After(e1));
1030
        assert_eq!(cur.next_inst(), None);
1031
        assert_eq!(cur.position(), CursorPosition::After(e1));
1032
        assert_eq!(cur.prev_inst(), Some(i0));
1033
        assert_eq!(cur.prev_inst(), Some(i2));
1034
        assert_eq!(cur.prev_inst(), Some(i1));
1035
        assert_eq!(cur.prev_inst(), None);
1036
        assert_eq!(cur.position(), CursorPosition::Before(e1));
1037
1038
        // Test remove_inst.
1039
        cur.goto_inst(i2);
1040
        assert_eq!(cur.remove_inst(), i2);
1041
        verify(cur.layout, &[(e1, &[i1, i0])]);
1042
        assert_eq!(cur.layout.inst_block(i2), None);
1043
        assert_eq!(cur.remove_inst(), i0);
1044
        verify(cur.layout, &[(e1, &[i1])]);
1045
        assert_eq!(cur.layout.inst_block(i0), None);
1046
        assert_eq!(cur.position(), CursorPosition::After(e1));
1047
        cur.layout.remove_inst(i1);
1048
        verify(cur.layout, &[(e1, &[])]);
1049
        assert_eq!(cur.layout.inst_block(i1), None);
1050
    }
1051
1052
    #[test]
1053
    fn insert_inst() {
1054
        let mut layout = Layout::new();
1055
        let e1 = Block::new(1);
1056
1057
        layout.append_block(e1);
1058
        let v: Vec<Inst> = layout.block_insts(e1).collect();
1059
        assert_eq!(v, []);
1060
1061
        let i0 = Inst::new(0);
1062
        let i1 = Inst::new(1);
1063
        let i2 = Inst::new(2);
1064
1065
        assert_eq!(layout.inst_block(i0), None);
1066
        assert_eq!(layout.inst_block(i1), None);
1067
        assert_eq!(layout.inst_block(i2), None);
1068
1069
        layout.append_inst(i1, e1);
1070
        assert_eq!(layout.inst_block(i0), None);
1071
        assert_eq!(layout.inst_block(i1), Some(e1));
1072
        assert_eq!(layout.inst_block(i2), None);
1073
        let v: Vec<Inst> = layout.block_insts(e1).collect();
1074
        assert_eq!(v, [i1]);
1075
1076
        layout.insert_inst(i2, i1);
1077
        assert_eq!(layout.inst_block(i0), None);
1078
        assert_eq!(layout.inst_block(i1), Some(e1));
1079
        assert_eq!(layout.inst_block(i2), Some(e1));
1080
        let v: Vec<Inst> = layout.block_insts(e1).collect();
1081
        assert_eq!(v, [i2, i1]);
1082
1083
        layout.insert_inst(i0, i1);
1084
        verify(&mut layout, &[(e1, &[i2, i0, i1])]);
1085
    }
1086
1087
    #[test]
1088
    fn multiple_blocks() {
1089
        let mut layout = Layout::new();
1090
1091
        let e0 = Block::new(0);
1092
        let e1 = Block::new(1);
1093
1094
        assert_eq!(layout.entry_block(), None);
1095
        layout.append_block(e0);
1096
        assert_eq!(layout.entry_block(), Some(e0));
1097
        layout.append_block(e1);
1098
        assert_eq!(layout.entry_block(), Some(e0));
1099
1100
        let i0 = Inst::new(0);
1101
        let i1 = Inst::new(1);
1102
        let i2 = Inst::new(2);
1103
        let i3 = Inst::new(3);
1104
1105
        layout.append_inst(i0, e0);
1106
        layout.append_inst(i1, e0);
1107
        layout.append_inst(i2, e1);
1108
        layout.append_inst(i3, e1);
1109
1110
        let v0: Vec<Inst> = layout.block_insts(e0).collect();
1111
        let v1: Vec<Inst> = layout.block_insts(e1).collect();
1112
        assert_eq!(v0, [i0, i1]);
1113
        assert_eq!(v1, [i2, i3]);
1114
    }
1115
1116
    #[test]
1117
    fn split_block() {
1118
        let mut layout = Layout::new();
1119
1120
        let e0 = Block::new(0);
1121
        let e1 = Block::new(1);
1122
        let e2 = Block::new(2);
1123
1124
        let i0 = Inst::new(0);
1125
        let i1 = Inst::new(1);
1126
        let i2 = Inst::new(2);
1127
        let i3 = Inst::new(3);
1128
1129
        layout.append_block(e0);
1130
        layout.append_inst(i0, e0);
1131
        assert_eq!(layout.inst_block(i0), Some(e0));
1132
        layout.split_block(e1, i0);
1133
        assert_eq!(layout.inst_block(i0), Some(e1));
1134
1135
        {
1136
            let mut cur = LayoutCursor::new(&mut layout);
1137
            assert_eq!(cur.next_block(), Some(e0));
1138
            assert_eq!(cur.next_inst(), None);
1139
            assert_eq!(cur.next_block(), Some(e1));
1140
            assert_eq!(cur.next_inst(), Some(i0));
1141
            assert_eq!(cur.next_inst(), None);
1142
            assert_eq!(cur.next_block(), None);
1143
1144
            // Check backwards links.
1145
            assert_eq!(cur.prev_block(), Some(e1));
1146
            assert_eq!(cur.prev_inst(), Some(i0));
1147
            assert_eq!(cur.prev_inst(), None);
1148
            assert_eq!(cur.prev_block(), Some(e0));
1149
            assert_eq!(cur.prev_inst(), None);
1150
            assert_eq!(cur.prev_block(), None);
1151
        }
1152
1153
        layout.append_inst(i1, e0);
1154
        layout.append_inst(i2, e0);
1155
        layout.append_inst(i3, e0);
1156
        layout.split_block(e2, i2);
1157
1158
        assert_eq!(layout.inst_block(i0), Some(e1));
1159
        assert_eq!(layout.inst_block(i1), Some(e0));
1160
        assert_eq!(layout.inst_block(i2), Some(e2));
1161
        assert_eq!(layout.inst_block(i3), Some(e2));
1162
1163
        {
1164
            let mut cur = LayoutCursor::new(&mut layout);
1165
            assert_eq!(cur.next_block(), Some(e0));
1166
            assert_eq!(cur.next_inst(), Some(i1));
1167
            assert_eq!(cur.next_inst(), None);
1168
            assert_eq!(cur.next_block(), Some(e2));
1169
            assert_eq!(cur.next_inst(), Some(i2));
1170
            assert_eq!(cur.next_inst(), Some(i3));
1171
            assert_eq!(cur.next_inst(), None);
1172
            assert_eq!(cur.next_block(), Some(e1));
1173
            assert_eq!(cur.next_inst(), Some(i0));
1174
            assert_eq!(cur.next_inst(), None);
1175
            assert_eq!(cur.next_block(), None);
1176
1177
            assert_eq!(cur.prev_block(), Some(e1));
1178
            assert_eq!(cur.prev_inst(), Some(i0));
1179
            assert_eq!(cur.prev_inst(), None);
1180
            assert_eq!(cur.prev_block(), Some(e2));
1181
            assert_eq!(cur.prev_inst(), Some(i3));
1182
            assert_eq!(cur.prev_inst(), Some(i2));
1183
            assert_eq!(cur.prev_inst(), None);
1184
            assert_eq!(cur.prev_block(), Some(e0));
1185
            assert_eq!(cur.prev_inst(), Some(i1));
1186
            assert_eq!(cur.prev_inst(), None);
1187
            assert_eq!(cur.prev_block(), None);
1188
        }
1189
1190
        // Check `ProgramOrder`.
1191
        assert_eq!(layout.pp_cmp(e2, e2), Ordering::Equal);
1192
        assert_eq!(layout.pp_cmp(e2, i2), Ordering::Less);
1193
        assert_eq!(layout.pp_cmp(i3, i2), Ordering::Greater)
1194
    }
1195
}