Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 58 additions & 79 deletions test/neura/interpreter/loop_convert_controlflow_to_dataflow.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -7,95 +7,74 @@
// RUN: --fold-constant \
// RUN: %s -o %t_dataflow.mlir

// RUN: neura-interpreter %t_dataflow.mlir --verbose --dataflow > %t_output.txt 2>&1
// RUN: neura-interpreter %t_dataflow.mlir --verbose --dataflow > %t_output.txt

// RUN: FileCheck %s --check-prefix=DATAFLOW_IR --input-file=%t_dataflow.mlir

// RUN: FileCheck %s --check-prefix=INTERPRETER_OUTPUT --input-file=%t_output.txt

func.func @loop_sum() -> f32 {
%init_i = arith.constant 0.0 : f32
%init_sum = arith.constant 0.0 : f32
%step = arith.constant 1.0 : f32
%add_val = arith.constant 3.0 : f32
%limit = arith.constant 5.0 : f32
%c0 = "neura.constant"() <{predicate = true, value = 0.000000e+00 : f32}> : () -> f32 // init_i / init_sum
%c1 = "neura.constant"() <{predicate = true, value = 1.000000e+00 : f32}> : () -> f32 // step
%c2 = "neura.constant"() <{predicate = true, value = 3.000000e+00 : f32}> : () -> f32 // add_val
%c3 = "neura.constant"() <{predicate = true, value = 5.000000e+00 : f32}> : () -> f32 // limit

%v_i = "neura.reserve"() : () -> (f32)
%v_sum = "neura.reserve"() : () -> (f32)
// Entry: jump to loop head with initial i and sum
neura.br %c0, %c0 : f32, f32 to ^loop_head

"neura.ctrl_mov"(%init_i, %v_i) : (f32, f32) -> ()
"neura.ctrl_mov"(%init_sum, %v_sum) : (f32, f32) -> ()
^loop_head(%i: f32, %sum: f32): // predecessors: entry, ^loop_body
%cond = "neura.fcmp"(%i, %c3) <{cmpType = "lt"}> : (f32, f32) -> i1
// If cond true, go to body carrying i and sum; else go to exit with sum
neura.cond_br %cond : i1 then %i, %sum : f32, f32 to ^loop_body else %sum : f32 to ^loop_exit

"neura.br"() [^loop_head] {operandSegmentSizes = array<i32: 0>} : () -> ()
^loop_body(%i_in: f32, %sum_in: f32): // pred: ^loop_head
%new_sum = "neura.fadd"(%sum_in, %c2) : (f32, f32) -> f32
%new_i = "neura.fadd"(%i_in, %c1) : (f32, f32) -> f32
// loop back with updated i and sum
neura.br %new_i, %new_sum : f32, f32 to ^loop_head

^loop_head:
%i = "neura.phi"(%v_i, %init_i) : (f32, f32) -> f32
%sum = "neura.phi"(%v_sum, %init_sum) : (f32, f32) -> f32

%cond = "neura.fcmp"(%i, %limit) {cmpType = "lt"} : (f32, f32) -> i1

"neura.cond_br"(%cond) [^loop_body, ^loop_exit] {operandSegmentSizes = array<i32: 1, 0, 0, 0>} : (i1) -> ()

^loop_body:
%new_sum = "neura.fadd"(%sum, %add_val) : (f32, f32) -> f32

%new_i = "neura.fadd"(%i, %step) : (f32, f32) -> f32

"neura.ctrl_mov"(%new_i, %v_i) : (f32, f32) -> ()
"neura.ctrl_mov"(%new_sum, %v_sum) : (f32, f32) -> ()

"neura.br"() [^loop_head] {operandSegmentSizes = array<i32: 0>} : () -> ()

^loop_exit:
return %sum : f32
^loop_exit(%ret_sum: f32): // pred: ^loop_head
"neura.return"(%ret_sum) : (f32) -> ()
}

// DATAFLOW_IR: module {
// DATAFLOW_IR: func.func @loop_sum() -> f32 attributes {accelerator = "neura"} {
// DATAFLOW_IR: %cst = arith.constant 0.000000e+00 : f32
// DATAFLOW_IR: %cst_0 = arith.constant 1.000000e+00 : f32
// DATAFLOW_IR: %cst_1 = arith.constant 3.000000e+00 : f32
// DATAFLOW_IR: %cst_2 = arith.constant 5.000000e+00 : f32
// DATAFLOW_IR: %0 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR: %1 = "neura.grant_once"(%0) : (!neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR: %2 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR: %3 = "neura.grant_once"(%2) : (!neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %cst -> %0 : f32 !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %cst -> %2 : f32 !neura.data<f32, i1>
// DATAFLOW_IR: %4 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR: %5 = "neura.phi"(%4, %cst_2) : (!neura.data<f32, i1>, f32) -> !neura.data<f32, i1>
// DATAFLOW_IR: %6 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR: %7 = "neura.phi"(%6, %3) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR: %8 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR: %9 = "neura.phi"(%8, %cst) : (!neura.data<f32, i1>, f32) -> !neura.data<f32, i1>
// DATAFLOW_IR: %10 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR: %11 = "neura.phi"(%10, %1) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR: %12 = "neura.phi"(%11, %9) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR: %13 = "neura.phi"(%7, %9) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR: %14 = "neura.fcmp"(%12, %5) <{cmpType = "lt"}> : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<i1, i1>
// DATAFLOW_IR: %15 = neura.grant_predicate %13, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR: %16 = neura.grant_predicate %cst_1, %14 : f32, !neura.data<i1, i1> -> f32
// DATAFLOW_IR: %17 = neura.grant_predicate %12, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR: %18 = neura.grant_predicate %cst_0, %14 : f32, !neura.data<i1, i1> -> f32
// DATAFLOW_IR: %19 = neura.grant_predicate %1, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR: %20 = neura.grant_predicate %3, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR: %21 = neura.grant_predicate %cst, %14 : f32, !neura.data<i1, i1> -> f32
// DATAFLOW_IR: %22 = neura.grant_predicate %cst_2, %14 : f32, !neura.data<i1, i1> -> f32
// DATAFLOW_IR: %23 = "neura.not"(%14) : (!neura.data<i1, i1>) -> !neura.data<i1, i1>
// DATAFLOW_IR: %24 = neura.grant_predicate %13, %23 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR: %25 = "neura.fadd"(%15, %16) : (!neura.data<f32, i1>, f32) -> !neura.data<f32, i1>
// DATAFLOW_IR: %26 = "neura.fadd"(%17, %18) : (!neura.data<f32, i1>, f32) -> !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %26 -> %19 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %25 -> %20 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %19 -> %10 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %21 -> %8 : f32 !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %20 -> %6 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR: neura.ctrl_mov %22 -> %4 : f32 !neura.data<f32, i1>
// DATAFLOW_IR: "neura.return"(%24) : (!neura.data<f32, i1>) -> ()
// DATAFLOW_IR: }
// DATAFLOW_IR: }
// DATAFLOW_IR: func.func @loop_sum() -> f32 attributes {accelerator = "neura"} {
// DATAFLOW_IR-NEXT: %0 = "neura.grant_once"() <{constant_value = 0.000000e+00 : f32}> : () -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %1 = "neura.grant_once"() <{constant_value = 1.000000e+00 : f32}> : () -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %2 = "neura.grant_once"() <{constant_value = 3.000000e+00 : f32}> : () -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %3 = "neura.grant_once"() <{constant_value = 5.000000e+00 : f32}> : () -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %4 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %5 = "neura.phi"(%4, %1) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %6 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %7 = "neura.phi"(%6, %2) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %8 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %9 = "neura.phi"(%8, %3) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %10 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %11 = "neura.phi"(%10, %0) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %12 = neura.reserve : !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %13 = "neura.phi"(%12, %0) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %14 = "neura.fcmp"(%13, %9) <{cmpType = "lt"}> : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<i1, i1>
// DATAFLOW_IR-NEXT: %15 = neura.grant_predicate %13, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %16 = neura.grant_predicate %11, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %17 = neura.grant_predicate %7, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %18 = neura.grant_predicate %5, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %19 = neura.grant_predicate %9, %14 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %20 = "neura.not"(%14) : (!neura.data<i1, i1>) -> !neura.data<i1, i1>
// DATAFLOW_IR-NEXT: %21 = neura.grant_predicate %11, %20 : !neura.data<f32, i1>, !neura.data<i1, i1> -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %22 = "neura.fadd"(%16, %17) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: %23 = "neura.fadd"(%15, %18) : (!neura.data<f32, i1>, !neura.data<f32, i1>) -> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: neura.ctrl_mov %23 -> %12 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: neura.ctrl_mov %22 -> %10 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: neura.ctrl_mov %19 -> %8 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: neura.ctrl_mov %17 -> %6 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: neura.ctrl_mov %18 -> %4 : !neura.data<f32, i1> !neura.data<f32, i1>
// DATAFLOW_IR-NEXT: "neura.return"(%21) : (!neura.data<f32, i1>) -> ()
// DATAFLOW_IR-NEXT: }

// INTERPRETER_OUTPUT: [neura-interpreter] Executing neura.return:
// INTERPRETER_OUTPUT: [neura-interpreter] ├─ Return values:
// INTERPRETER_OUTPUT: [neura-interpreter] │ └─15.000000, [pred = 1]
// INTERPRETER_OUTPUT: [neura-interpreter] └─ Execution terminated successfully
// INTERPRETER_OUTPUT: [neura-interpreter] DFG Iteration 5 | Topological Level 6 | ready_to_execute_ops 3
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] ========================================
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] Executing operation: "neura.return"(%21) : (!neura.data<f32, i1>) -> ()
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] Executing neura.return:
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] ├─ Return values:
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] │ └─15.000000, [pred = 1]
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] └─ Execution terminated successfully
// INTERPRETER_OUTPUT-NEXT: [neura-interpreter] Termination signal received
Loading