Check a basic block.
(&mut self, block: Block)
| 415 | |
| 416 | /// Check a basic block. |
| 417 | fn check_block(&mut self, block: Block) -> Result<()> { |
| 418 | let insts = self.func.block_insts(block); |
| 419 | self.check_inst_range(insts)?; |
| 420 | |
| 421 | // Block frequency must be positive. This also excludes zero and NaN. |
| 422 | ensure!( |
| 423 | self.func.block_frequency(block) > 0.0, |
| 424 | "{block}: Frequency must be positive and non-zero" |
| 425 | ); |
| 426 | |
| 427 | // Instruction indicies must be ordered by block and with no gaps. |
| 428 | if block.index() != 0 { |
| 429 | let prev_block = Block::new(block.index() - 1); |
| 430 | let prev_insts = self.func.block_insts(prev_block); |
| 431 | ensure!( |
| 432 | insts.from == prev_insts.to, |
| 433 | "{block}: Instructions are not ordered by block" |
| 434 | ); |
| 435 | } else { |
| 436 | ensure!( |
| 437 | insts.from.index() == 0, |
| 438 | "{block}: Instructions are not ordered by block" |
| 439 | ); |
| 440 | } |
| 441 | if block.index() != self.func.num_blocks() - 1 { |
| 442 | let next_block = Block::new(block.index() + 1); |
| 443 | let next_insts = self.func.block_insts(next_block); |
| 444 | ensure!( |
| 445 | next_insts.from == insts.to, |
| 446 | "{block}: Instructions are not ordered by block" |
| 447 | ); |
| 448 | } else { |
| 449 | ensure!( |
| 450 | insts.to.index() == self.func.num_insts(), |
| 451 | "{block}: Instructions are not ordered by block" |
| 452 | ); |
| 453 | } |
| 454 | |
| 455 | // Check consistency of successors & predecessors. |
| 456 | for &pred in self.func.block_preds(block) { |
| 457 | self.check_entity(Entity::Block(pred))?; |
| 458 | ensure!( |
| 459 | self.func.block_succs(pred).contains(&block), |
| 460 | "Inconsistent predecessors and successors between {pred} and {block}" |
| 461 | ); |
| 462 | } |
| 463 | for &succ in self.func.block_succs(block) { |
| 464 | self.check_entity(Entity::Block(succ))?; |
| 465 | ensure!( |
| 466 | self.func.block_preds(succ).contains(&block), |
| 467 | "Inconsistent predecessors and successors between {block} and {succ}" |
| 468 | ); |
| 469 | } |
| 470 | |
| 471 | // Check for crtical edges. If we have more than one predecessors, those |
| 472 | // must only have one successor (this block). |
| 473 | if self.func.block_preds(block).len() > 1 { |
| 474 | for &pred in self.func.block_preds(block) { |
no test coverage detected