// Input domain for loom-raise-opt --loom-lift-cf-to-scf. // // A linked LLVM module enters the raising pipeline with its LLVM callable // envelopes intact, so every callable is an llvm.func that owns its own body. // Mechanical CFG recovery runs on that callable region in `cf` form, so the // bodies below spell exact `cf` branch structure inside llvm.func. // // Sampled callable shapes: // * wholly admissible callables (diamond, sequential diamonds, counted // cycle with a latch-owned loop annotation); // * callables holding one profile-bearing (weighted) branch, which is a // local obstacle to the whole-callable projection but leaves independent // regions before/after/inside it recoverable. start: {new COUNT = random.randint(2, 4); new I = 0} preamble funcs; preamble: '#loop_ann = #llvm.loop_annotation\n\n'; funcs: (I < COUNT) func {I += 1} funcs | (I == COUNT) ''; func: plain_diamond | sequential_diamonds | counted_cycle | weighted_then_plain | plain_then_weighted | nested_weighted_arm | weighted_then_cycle; // ---------------------------------------------------------------- no obstacle plain_diamond: {new NAME = 'plain_diamond_' + str(I)} 'llvm.func @' [NAME] '(%c: i1, %a: i32, %b: i32) -> i32 {\n' ' cf.cond_br %c, ^yes, ^no\n' '^yes:\n' ' cf.br ^exit(%a : i32)\n' '^no:\n' ' cf.br ^exit(%b : i32)\n' '^exit(%r: i32):\n' ' llvm.return %r : i32\n' '}\n\n'; sequential_diamonds: {new NAME = 'sequential_diamonds_' + str(I); new K = random.randint(1, 6)} 'llvm.func @' [NAME] '(%first: i1, %second: i1, %a: i32, %b: i32) -> i32 {\n' ' %k = arith.constant ' [str(K)] ' : i32\n' ' cf.cond_br %first, ^one_yes, ^one_no\n' '^one_yes:\n' ' cf.br ^middle(%a : i32)\n' '^one_no:\n' ' cf.br ^middle(%b : i32)\n' '^middle(%seed: i32):\n' ' cf.cond_br %second, ^two_yes, ^two_no\n' '^two_yes:\n' ' %sum = arith.addi %seed, %k : i32\n' ' cf.br ^exit(%sum : i32)\n' '^two_no:\n' ' cf.br ^exit(%seed : i32)\n' '^exit(%r: i32):\n' ' llvm.return %r : i32\n' '}\n\n'; counted_cycle: {new NAME = 'counted_cycle_' + str(I); new STEP = random.randint(1, 4)} 'llvm.func @' [NAME] '(%limit: i32) -> i32 {\n' ' %zero = arith.constant 0 : i32\n' ' %step = arith.constant ' [str(STEP)] ' : i32\n' ' cf.br ^header(%zero : i32)\n' '^header(%iv: i32):\n' ' %done = arith.cmpi eq, %iv, %limit : i32\n' ' cf.cond_br %done, ^exit, ^latch\n' '^latch:\n' ' %next = arith.addi %iv, %step : i32\n' ' cf.br ^header(%next : i32)' loop_hint '\n' '^exit:\n' ' llvm.return %iv : i32\n' '}\n\n'; // A hint on a latch that closes a backedge to one dominating header has an // exact loop owner; the alternative omits the hint entirely. loop_hint: ' {llvm.loop_annotation = #loop_ann}' | ''; // ------------------------------------------------- one profile-bearing branch weighted_then_plain: {new NAME = 'weighted_then_plain_' + str(I); new WA = random.randint(1, 9)} 'llvm.func @' [NAME] '(%weighted: i1, %plain: i1, %a: i32, %b: i32) -> i32 {\n' ' cf.cond_br %weighted weights([' [str(WA)] ', ' [str(10 - WA)] ']), ^weighted_true, ^weighted_false\n' '^weighted_true:\n' ' cf.br ^plain_entry(%a : i32)\n' '^weighted_false:\n' ' cf.br ^plain_entry(%b : i32)\n' '^plain_entry(%seed: i32):\n' ' cf.cond_br %plain, ^plain_true, ^plain_false\n' '^plain_true:\n' ' cf.br ^exit(%seed : i32)\n' '^plain_false:\n' ' cf.br ^exit(%seed : i32)\n' '^exit(%r: i32):\n' ' llvm.return %r : i32\n' '}\n\n'; plain_then_weighted: {new NAME = 'plain_then_weighted_' + str(I); new WB = random.randint(1, 9)} 'llvm.func @' [NAME] '(%plain: i1, %weighted: i1, %a: i32, %b: i32) -> i32 {\n' ' cf.cond_br %plain, ^plain_true, ^plain_false\n' '^plain_true:\n' ' cf.br ^weighted_entry(%a : i32)\n' '^plain_false:\n' ' cf.br ^weighted_entry(%b : i32)\n' '^weighted_entry(%seed: i32):\n' ' cf.cond_br %weighted weights([' [str(WB)] ', ' [str(10 - WB)] ']), ^weighted_true, ^weighted_false\n' '^weighted_true:\n' ' cf.br ^exit(%seed : i32)\n' '^weighted_false:\n' ' cf.br ^exit(%seed : i32)\n' '^exit(%r: i32):\n' ' llvm.return %r : i32\n' '}\n\n'; nested_weighted_arm: {new NAME = 'nested_weighted_arm_' + str(I); new WC = random.randint(1, 9)} 'llvm.func @' [NAME] '(%weighted: i1, %plain: i1, %a: i32, %b: i32) -> i32 {\n' ' cf.cond_br %weighted weights([' [str(WC)] ', ' [str(10 - WC)] ']), ^left, ^right\n' '^left:\n' ' cf.cond_br %plain, ^left_true, ^left_false\n' '^left_true:\n' ' cf.br ^exit(%a : i32)\n' '^left_false:\n' ' cf.br ^exit(%b : i32)\n' '^right:\n' ' cf.br ^exit(%b : i32)\n' '^exit(%r: i32):\n' ' llvm.return %r : i32\n' '}\n\n'; weighted_then_cycle: {new NAME = 'weighted_then_cycle_' + str(I); new WD = random.randint(1, 9)} 'llvm.func @' [NAME] '(%weighted: i1, %limit: i32) -> i32 {\n' ' %zero = arith.constant 0 : i32\n' ' %one = arith.constant 1 : i32\n' ' cf.cond_br %weighted weights([' [str(WD)] ', ' [str(10 - WD)] ']), ^left, ^right\n' '^left:\n' ' cf.br ^header(%zero : i32)\n' '^right:\n' ' cf.br ^header(%one : i32)\n' '^header(%iv: i32):\n' ' %done = arith.cmpi eq, %iv, %limit : i32\n' ' cf.cond_br %done, ^exit, ^latch\n' '^latch:\n' ' %next = arith.addi %iv, %one : i32\n' ' cf.br ^header(%next : i32)' loop_hint '\n' '^exit:\n' ' llvm.return %iv : i32\n' '}\n\n';