Add syntax for cold blocks to CLIF.

This commit adds support for denoting cold blocks in the CLIF text
format as follows:

```plain

function %f() {
block0(...):
  ...

block1 cold:
  ...

block2(...) cold:
  ...

block3:
  ...
```

With this syntax, we are able to see the cold-block flag in CLIF, we can
write tests using it, and it is preserved when round-tripping.

Fixes #3701.
This commit is contained in:
Chris Fallin
2022-01-20 15:37:07 -08:00
parent 90e7cef56c
commit 51649d56b7
3 changed files with 65 additions and 6 deletions

View File

@@ -447,6 +447,11 @@ impl Context {
self.function.layout.append_block(block);
Ok(block)
}
/// Set a block as cold.
fn set_cold_block(&mut self, block: Block) {
self.function.layout.set_cold(block);
}
}
impl<'a> Parser<'a> {
@@ -1856,7 +1861,8 @@ impl<'a> Parser<'a> {
// Parse a basic block, add contents to `ctx`.
//
// extended-basic-block ::= * block-header { instruction }
// block-header ::= Block(block) [block-params] ":"
// block-header ::= Block(block) [block-params] [block-flags] ":"
// block-flags ::= [Cold]
//
fn parse_basic_block(&mut self, ctx: &mut Context) -> ParseResult<()> {
// Collect comments for the next block.
@@ -1869,12 +1875,16 @@ impl<'a> Parser<'a> {
return Err(self.error("too many blocks"));
}
if !self.optional(Token::Colon) {
// block-header ::= Block(block) [ * block-params ] ":"
if self.token() == Some(Token::LPar) {
self.parse_block_params(ctx, block)?;
self.match_token(Token::Colon, "expected ':' after block parameters")?;
}
if self.optional(Token::Cold) {
ctx.set_cold_block(block);
}
self.match_token(Token::Colon, "expected ':' after block parameters")?;
// Collect any trailing comments.
self.token();
self.claim_gathered_comments(block);
@@ -3728,4 +3738,23 @@ mod tests {
"0x00000003000000020000000100000000"
);
}
#[test]
fn parse_cold_blocks() {
let code = "function %test() {
block0 cold:
return
block1(v0: i32) cold:
return
block2(v1: i32):
return
}";
let mut parser = Parser::new(code);
let func = parser.parse_function().unwrap().0;
assert_eq!(func.layout.blocks().count(), 3);
assert!(func.layout.is_cold(Block::from_u32(0)));
assert!(func.layout.is_cold(Block::from_u32(1)));
assert!(!func.layout.is_cold(Block::from_u32(2)));
}
}