Skip to content

Comments on switch cases prevent us from merging patterns #1536

@randomPoison

Description

@randomPoison

Comments on switch cases are resulting in excessive nodes in the CFG that prevent one of the relooper optimizations from applying. This results in overly complex control flow. This affects both the master branch and the relooper2 work on legare/relooper-experiment.

Input:

switch (x) {
    case 0: // comment
    case 1: // comment
    case 2:
        x++;
}

Expected output:

match x {
    0 | 1 | 2 => {
        x += 1;
    }
    _ => {}
}

Actual output (on master):

let mut current_block: u64;
match x {
    1 => {
        current_block = 773005375064117377;
    }
    0 | 2 => {
        current_block = 773005375064117377;
    }
    _ => {
        current_block = 14155750587950065367;
    }
}
match current_block {
    773005375064117377 => {
        x += 1;
    }
    _ => {}
}

Details

As part of the relooper algorithm, when a switch has multiple cases that go to the same place we merge those cases into a single | pattern. This is important for our ability to nest the code for the combined switch case into the corresponding match arm, since translating each case into its own match arm would mean we need to place the shared logic after the match in some way (either with current_block or with labeled blocks/breaks).

The issue here is likely happening when we build the CFG that we feed to relooper. The way the pattern merging logic works is that it merges switch cases that go to the same CFG node. Writing out the CFG as C pseudocode:

entry:
  switch (x) {
    case 0: goto A;
    case 1: goto A;
    case 2: goto A;
    default: goto B;
  }

A:
  x++;
  goto B;

B:
  return;

When we add comments to each of the cases we end up seeing a CFG more like this:

entry:
  switch (x) {
    case 0: goto A;
    case 1: goto B;
    case 2: goto C;
    default: goto D;
  }

A:
  goto B;

B:
  goto C;

C:
  x++;
  goto D;

D:
  return;

The two CFGs represent the same behavior, but the extra nodes in the latter case prevent the case merging optimization from working.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions