Back to PBT run
test.mlir
// RUN: loom-raise-opt --loom-lower-scf-to-dfg %s | FileCheck %s
func.func @native_helper(%arg0: index) -> index {
return %arg0 : index
}
dataflow.thread private @t0 domain(#dataflow.thread_domain<dense>)(
%scratch: memref<8xindex>, %memory: memref<8xindex>, %grid: memref<4x4xindex>,
%n: index) ctrl (%ctrl: none) {
"loom.spatial_region"(%n, %memory, %grid)
<{operandSegmentSizes = array<i32: 1, 0, 2, 0>,
resultSegmentSizes = array<i32: 0, 0>}> ({
^bb0(%limit: index, %target: memref<8xindex>, %tile: memref<4x4xindex>):
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%cw = arith.constant 2 : index
%kv = arith.constant 7 : index
%ocond = arith.cmpi slt, %c0, %limit : index
scf.if %ocond {
scf.parallel (%pi) = (%c0) to (%cw) step (%c1) {
scf.parallel (%pj) = (%c0) to (%cw) step (%c1) {
memref.store %kv, %tile[%pi, %pj] : memref<4x4xindex>
scf.reduce
}
scf.reduce
}
}
"loom.spatial_yield"()
<{operandSegmentSizes = array<i32: 0, 0>}> : () -> ()
}) {graph_name = "g_t0_0", source_maps = []} :
(index, memref<8xindex>, memref<4x4xindex>) -> ()
dataflow.thread.yield
}
dataflow.thread private @t1 domain(#dataflow.thread_domain<dense>)(
%scratch: memref<8xindex>, %memory: memref<8xindex>, %grid: memref<4x4xindex>,
%n: index) ctrl (%ctrl: none) {
"loom.spatial_region"(%n, %memory, %grid)
<{operandSegmentSizes = array<i32: 1, 0, 2, 0>,
resultSegmentSizes = array<i32: 0, 0>}> ({
^bb0(%limit: index, %target: memref<8xindex>, %tile: memref<4x4xindex>):
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
%cw = arith.constant 4 : index
scf.for %oi = %c0 to %limit step %c1 {
scf.parallel (%lane) = (%c0) to (%cw) step (%c1) {
%wres = scf.while (%wi = %c0) : (index) -> index {
%wc = arith.cmpi slt, %wi, %limit : index
scf.condition(%wc) %wi : index
} do {
^bb0(%wb: index):
%wn = arith.addi %wb, %c1 : index
scf.yield %wn : index
}
memref.store %wres, %target[%lane] : memref<8xindex>
scf.reduce
}
}
"loom.spatial_yield"()
<{operandSegmentSizes = array<i32: 0, 0>}> : () -> ()
}) {graph_name = "g_t1_0", source_maps = []} :
(index, memref<8xindex>, memref<4x4xindex>) -> ()
dataflow.thread.yield
}
// CHECK: module {
// CHECK-NEXT: func.func @native_helper(%arg0: index) -> index {
// CHECK-NEXT: return %arg0 : index
// CHECK-NEXT: }
// CHECK-NEXT: dataflow.thread private @t0 domain(#dataflow.thread_domain<dense>)(%arg0: memref<8xindex>, %arg1: memref<8xindex>, %arg2: memref<4x4xindex>, %arg3: index) ctrl (%arg4: none) {
// CHECK-NEXT: %done = dataflow.graph.launch @g_t0_0 deps(%arg4) values(%arg3) stream_inputs() memories(%arg1, %arg2) stream_outputs() : (none, index, memref<8xindex>, memref<4x4xindex>) -> none
// CHECK-NEXT: dataflow.thread.yield %done : none
// CHECK-NEXT: }
// CHECK-NEXT: dataflow.thread private @t1 domain(#dataflow.thread_domain<dense>)(%arg0: memref<8xindex>, %arg1: memref<8xindex>, %arg2: memref<4x4xindex>, %arg3: index) ctrl (%arg4: none) {
// CHECK-NEXT: %done = dataflow.graph.launch @g_t1_0 deps(%arg4) values(%arg3) stream_inputs() memories(%arg1, %arg2) stream_outputs() : (none, index, memref<8xindex>, memref<4x4xindex>) -> none
// CHECK-NEXT: dataflow.thread.yield %done : none
// CHECK-NEXT: }
// CHECK-NEXT: dataflow.graph private @g_t0_0(%arg0: none, %arg1: index, %arg2: memref<8xindex>, %arg3: memref<4x4xindex>) -> () attributes {input_segments = array<i32: 1, 0, 2>, result_segments = array<i32: 0, 0, 0>} {
// CHECK-NEXT: %0 = dataflow.constant %arg0 {const_value = 0 : index} : index
// CHECK-NEXT: %1 = dataflow.constant %arg0 {const_value = 7 : index} : index
// CHECK-NEXT: %2 = arith.cmpi sgt, %arg1, %0 : index
// CHECK-NEXT: %3:2 = dataflow.demux %2, %arg0 : (i1, none) -> (none, none)
// CHECK-NEXT: %4:2 = dataflow.demux %2, %arg0 : (i1, none) -> (none, none)
// CHECK-NEXT: %5:2 = dataflow.demux %2, %1 : (i1, index) -> (index, index)
// CHECK-NEXT: %6 = dataflow.constant %3#1 {const_value = 0 : index} : index
// CHECK-NEXT: %7 = dataflow.constant %3#1 {const_value = 0 : index} : index
// CHECK-NEXT: %8:2 = dataflow.sync %3#1, %4#1 : (none, none) -> (none, none)
// CHECK-NEXT: %9 = dataflow.constant %3#1 {const_value = 4 : index} : index
// CHECK-NEXT: %10 = arith.muli %6, %9 : index
// CHECK-NEXT: %11 = arith.addi %10, %7 : index
// CHECK-NEXT: %12 = dataflow.store %arg3[%11] %5#1 %8#0 : memref<4x4xindex>
// CHECK-NEXT: %13 = dataflow.constant %3#1 {const_value = 0 : index} : index
// CHECK-NEXT: %14 = dataflow.constant %3#1 {const_value = 1 : index} : index
// CHECK-NEXT: %15:2 = dataflow.sync %3#1, %4#1 : (none, none) -> (none, none)
// CHECK-NEXT: %16 = dataflow.constant %3#1 {const_value = 4 : index} : index
// CHECK-NEXT: %17 = arith.muli %13, %16 : index
// CHECK-NEXT: %18 = arith.addi %17, %14 : index
// CHECK-NEXT: %19 = dataflow.store %arg3[%18] %5#1 %15#0 : memref<4x4xindex>
// CHECK-NEXT: %20 = dataflow.constant %3#1 {const_value = 1 : index} : index
// CHECK-NEXT: %21 = dataflow.constant %3#1 {const_value = 0 : index} : index
// CHECK-NEXT: %22:2 = dataflow.sync %3#1, %4#1 : (none, none) -> (none, none)
// CHECK-NEXT: %23 = dataflow.constant %3#1 {const_value = 4 : index} : index
// CHECK-NEXT: %24 = arith.muli %20, %23 : index
// CHECK-NEXT: %25 = arith.addi %24, %21 : index
// CHECK-NEXT: %26 = dataflow.store %arg3[%25] %5#1 %22#0 : memref<4x4xindex>
// CHECK-NEXT: %27 = dataflow.constant %3#1 {const_value = 1 : index} : index
// CHECK-NEXT: %28 = dataflow.constant %3#1 {const_value = 1 : index} : index
// CHECK-NEXT: %29:2 = dataflow.sync %3#1, %4#1 : (none, none) -> (none, none)
// CHECK-NEXT: %30 = dataflow.constant %3#1 {const_value = 4 : index} : index
// CHECK-NEXT: %31 = arith.muli %27, %30 : index
// CHECK-NEXT: %32 = arith.addi %31, %28 : index
// CHECK-NEXT: %33 = dataflow.store %arg3[%32] %5#1 %29#0 : memref<4x4xindex>
// CHECK-NEXT: %34:4 = dataflow.sync %12, %19, %26, %33 : (none, none, none, none) -> (none, none, none, none)
// CHECK-NEXT: %35 = dataflow.mux %2, %4#0, %34#0 : (i1, none, none) -> none
// CHECK-NEXT: %36 = dataflow.mux %2, %3#0, %3#1 : (i1, none, none) -> none
// CHECK-NEXT: dataflow.graph.return values() streams() memories() complete(%36, %35 : none, none)
// CHECK-NEXT: }
// CHECK-NEXT: dataflow.graph private @g_t1_0(%arg0: none, %arg1: index, %arg2: memref<8xindex>, %arg3: memref<4x4xindex>) -> () attributes {input_segments = array<i32: 1, 0, 2>, result_segments = array<i32: 0, 0, 0>} {
// CHECK-NEXT: %0 = dataflow.constant %arg0 {const_value = 0 : index} : index
// CHECK-NEXT: %1 = dataflow.constant %arg0 {const_value = 1 : index} : index
// CHECK-NEXT: %2 = dataflow.constant %arg0 {const_value = 4 : index} : index
// CHECK-NEXT: %3 = arith.index_cast %0 : index to i32
// CHECK-NEXT: %4 = arith.index_cast %arg1 : index to i32
// CHECK-NEXT: %5 = arith.index_cast %1 : index to i32
// CHECK-NEXT: %iv, %phase = dataflow.stream %3, %4, %5 step add while slt : i32
// CHECK-NEXT: %6 = dataflow.carry %phase, %arg0, %94#0 : none
// CHECK-NEXT: %7:2 = dataflow.demux %phase, %6 : (i1, none) -> (none, none)
// CHECK-NEXT: %8 = dataflow.invariant %phase, %arg1 : index
// CHECK-NEXT: %after_cond, %after_value = dataflow.gate %phase, %8 : index
// CHECK-NEXT: %9:2 = dataflow.demux %after_cond, %after_value : (i1, index) -> (index, index)
// CHECK-NEXT: %10 = dataflow.invariant %phase, %1 : index
// CHECK-NEXT: %after_cond_0, %after_value_1 = dataflow.gate %phase, %10 : index
// CHECK-NEXT: %11:2 = dataflow.demux %after_cond_0, %after_value_1 : (i1, index) -> (index, index)
// CHECK-NEXT: %12 = dataflow.invariant %phase, %0 : index
// CHECK-NEXT: %after_cond_2, %after_value_3 = dataflow.gate %phase, %12 : index
// CHECK-NEXT: %13:2 = dataflow.demux %after_cond_2, %after_value_3 : (i1, index) -> (index, index)
// CHECK-NEXT: %14 = dataflow.invariant %phase, %2 : index
// CHECK-NEXT: %after_cond_4, %after_value_5 = dataflow.gate %phase, %14 : index
// CHECK-NEXT: %15:2 = dataflow.demux %after_cond_4, %after_value_5 : (i1, index) -> (index, index)
// CHECK-NEXT: %16 = dataflow.carry %phase, %arg0, %95#0 : none
// CHECK-NEXT: %17:2 = dataflow.demux %phase, %16 : (i1, none) -> (none, none)
// CHECK-NEXT: %18 = dataflow.constant %7#1 {const_value = 0 : index} : index
// CHECK-NEXT: %19 = dataflow.carry %22, %7#1, %after_value_7 : none
// CHECK-NEXT: %20 = dataflow.carry %22, %after_value_3, %28 : index
// CHECK-NEXT: %21 = dataflow.invariant %22, %after_value : index
// CHECK-NEXT: %22 = arith.cmpi slt, %20, %21 : index
// CHECK-NEXT: %23:2 = dataflow.demux %22, %19 : (i1, none) -> (none, none)
// CHECK-NEXT: %after_cond_6, %after_value_7 = dataflow.gate %22, %19 : none
// CHECK-NEXT: %24:2 = dataflow.demux %after_cond_6, %after_value_7 : (i1, none) -> (none, none)
// CHECK-NEXT: %25:2 = dataflow.demux %22, %20 : (i1, index) -> (index, index)
// CHECK-NEXT: %26 = dataflow.invariant %22, %after_value_1 : index
// CHECK-NEXT: %after_cond_8, %after_value_9 = dataflow.gate %22, %26 : index
// CHECK-NEXT: %27:2 = dataflow.demux %after_cond_8, %after_value_9 : (i1, index) -> (index, index)
// CHECK-NEXT: %28 = arith.addi %25#1, %after_value_9 : index
// CHECK-NEXT: %29:2 = dataflow.demux %after_cond_6, %after_value_7 : (i1, none) -> (none, none)
// CHECK-NEXT: %30:3 = dataflow.sync %29#0, %24#0, %27#0 : (none, none, index) -> (none, none, index)
// CHECK-NEXT: %31 = dataflow.mux %after_cond_6, %30#0, %29#1 : (i1, none, none) -> none
// CHECK-NEXT: %32 = dataflow.carry %22, %7#1, %31 : none
// CHECK-NEXT: %33:2 = dataflow.demux %22, %32 : (i1, none) -> (none, none)
// CHECK-NEXT: %34:2 = dataflow.sync %23#0, %33#0 : (none, none) -> (none, none)
// CHECK-NEXT: %35:2 = dataflow.sync %34#0, %17#1 : (none, none) -> (none, none)
// CHECK-NEXT: %36 = dataflow.store %arg2[%18] %25#0 %35#0 : memref<8xindex>
// CHECK-NEXT: %37 = dataflow.constant %7#1 {const_value = 1 : index} : index
// CHECK-NEXT: %38 = dataflow.carry %41, %7#1, %after_value_11 : none
// CHECK-NEXT: %39 = dataflow.carry %41, %after_value_3, %47 : index
// CHECK-NEXT: %40 = dataflow.invariant %41, %after_value : index
// CHECK-NEXT: %41 = arith.cmpi slt, %39, %40 : index
// CHECK-NEXT: %42:2 = dataflow.demux %41, %38 : (i1, none) -> (none, none)
// CHECK-NEXT: %after_cond_10, %after_value_11 = dataflow.gate %41, %38 : none
// CHECK-NEXT: %43:2 = dataflow.demux %after_cond_10, %after_value_11 : (i1, none) -> (none, none)
// CHECK-NEXT: %44:2 = dataflow.demux %41, %39 : (i1, index) -> (index, index)
// CHECK-NEXT: %45 = dataflow.invariant %41, %after_value_1 : index
// CHECK-NEXT: %after_cond_12, %after_value_13 = dataflow.gate %41, %45 : index
// CHECK-NEXT: %46:2 = dataflow.demux %after_cond_12, %after_value_13 : (i1, index) -> (index, index)
// CHECK-NEXT: %47 = arith.addi %44#1, %after_value_13 : index
// CHECK-NEXT: %48:2 = dataflow.demux %after_cond_10, %after_value_11 : (i1, none) -> (none, none)
// CHECK-NEXT: %49:3 = dataflow.sync %48#0, %43#0, %46#0 : (none, none, index) -> (none, none, index)
// CHECK-NEXT: %50 = dataflow.mux %after_cond_10, %49#0, %48#1 : (i1, none, none) -> none
// CHECK-NEXT: %51 = dataflow.carry %41, %7#1, %50 : none
// CHECK-NEXT: %52:2 = dataflow.demux %41, %51 : (i1, none) -> (none, none)
// CHECK-NEXT: %53:2 = dataflow.sync %42#0, %52#0 : (none, none) -> (none, none)
// CHECK-NEXT: %54:2 = dataflow.sync %53#0, %17#1 : (none, none) -> (none, none)
// CHECK-NEXT: %55 = dataflow.store %arg2[%37] %44#0 %54#0 : memref<8xindex>
// CHECK-NEXT: %56 = dataflow.constant %7#1 {const_value = 2 : index} : index
// CHECK-NEXT: %57 = dataflow.carry %60, %7#1, %after_value_15 : none
// CHECK-NEXT: %58 = dataflow.carry %60, %after_value_3, %66 : index
// CHECK-NEXT: %59 = dataflow.invariant %60, %after_value : index
// CHECK-NEXT: %60 = arith.cmpi slt, %58, %59 : index
// CHECK-NEXT: %61:2 = dataflow.demux %60, %57 : (i1, none) -> (none, none)
// CHECK-NEXT: %after_cond_14, %after_value_15 = dataflow.gate %60, %57 : none
// CHECK-NEXT: %62:2 = dataflow.demux %after_cond_14, %after_value_15 : (i1, none) -> (none, none)
// CHECK-NEXT: %63:2 = dataflow.demux %60, %58 : (i1, index) -> (index, index)
// CHECK-NEXT: %64 = dataflow.invariant %60, %after_value_1 : index
// CHECK-NEXT: %after_cond_16, %after_value_17 = dataflow.gate %60, %64 : index
// CHECK-NEXT: %65:2 = dataflow.demux %after_cond_16, %after_value_17 : (i1, index) -> (index, index)
// CHECK-NEXT: %66 = arith.addi %63#1, %after_value_17 : index
// CHECK-NEXT: %67:2 = dataflow.demux %after_cond_14, %after_value_15 : (i1, none) -> (none, none)
// CHECK-NEXT: %68:3 = dataflow.sync %67#0, %62#0, %65#0 : (none, none, index) -> (none, none, index)
// CHECK-NEXT: %69 = dataflow.mux %after_cond_14, %68#0, %67#1 : (i1, none, none) -> none
// CHECK-NEXT: %70 = dataflow.carry %60, %7#1, %69 : none
// CHECK-NEXT: %71:2 = dataflow.demux %60, %70 : (i1, none) -> (none, none)
// CHECK-NEXT: %72:2 = dataflow.sync %61#0, %71#0 : (none, none) -> (none, none)
// CHECK-NEXT: %73:2 = dataflow.sync %72#0, %17#1 : (none, none) -> (none, none)
// CHECK-NEXT: %74 = dataflow.store %arg2[%56] %63#0 %73#0 : memref<8xindex>
// CHECK-NEXT: %75 = dataflow.constant %7#1 {const_value = 3 : index} : index
// CHECK-NEXT: %76 = dataflow.carry %79, %7#1, %after_value_19 : none
// CHECK-NEXT: %77 = dataflow.carry %79, %after_value_3, %85 : index
// CHECK-NEXT: %78 = dataflow.invariant %79, %after_value : index
// CHECK-NEXT: %79 = arith.cmpi slt, %77, %78 : index
// CHECK-NEXT: %80:2 = dataflow.demux %79, %76 : (i1, none) -> (none, none)
// CHECK-NEXT: %after_cond_18, %after_value_19 = dataflow.gate %79, %76 : none
// CHECK-NEXT: %81:2 = dataflow.demux %after_cond_18, %after_value_19 : (i1, none) -> (none, none)
// CHECK-NEXT: %82:2 = dataflow.demux %79, %77 : (i1, index) -> (index, index)
// CHECK-NEXT: %83 = dataflow.invariant %79, %after_value_1 : index
// CHECK-NEXT: %after_cond_20, %after_value_21 = dataflow.gate %79, %83 : index
// CHECK-NEXT: %84:2 = dataflow.demux %after_cond_20, %after_value_21 : (i1, index) -> (index, index)
// CHECK-NEXT: %85 = arith.addi %82#1, %after_value_21 : index
// CHECK-NEXT: %86:2 = dataflow.demux %after_cond_18, %after_value_19 : (i1, none) -> (none, none)
// CHECK-NEXT: %87:3 = dataflow.sync %86#0, %81#0, %84#0 : (none, none, index) -> (none, none, index)
// CHECK-NEXT: %88 = dataflow.mux %after_cond_18, %87#0, %86#1 : (i1, none, none) -> none
// CHECK-NEXT: %89 = dataflow.carry %79, %7#1, %88 : none
// CHECK-NEXT: %90:2 = dataflow.demux %79, %89 : (i1, none) -> (none, none)
// CHECK-NEXT: %91:2 = dataflow.sync %80#0, %90#0 : (none, none) -> (none, none)
// CHECK-NEXT: %92:2 = dataflow.sync %91#0, %17#1 : (none, none) -> (none, none)
// CHECK-NEXT: %93 = dataflow.store %arg2[%75] %82#0 %92#0 : memref<8xindex>
// CHECK-NEXT: %94:4 = dataflow.sync %34#0, %53#0, %72#0, %91#0 : (none, none, none, none) -> (none, none, none, none)
// CHECK-NEXT: %95:4 = dataflow.sync %36, %55, %74, %93 : (none, none, none, none) -> (none, none, none, none)
// CHECK-NEXT: %96 = arith.cmpi slt, %3, %4 : i32
// CHECK-NEXT: %97:2 = dataflow.demux %96, %7#0 : (i1, none) -> (none, none)
// CHECK-NEXT: %98:2 = dataflow.sync %97#1, %9#0 : (none, index) -> (none, index)
// CHECK-NEXT: %99:2 = dataflow.sync %98#0, %11#0 : (none, index) -> (none, index)
// CHECK-NEXT: %100:2 = dataflow.sync %13#0, %15#0 : (index, index) -> (index, index)
// CHECK-NEXT: %101:2 = dataflow.sync %99#0, %100#0 : (none, index) -> (none, index)
// CHECK-NEXT: %102 = dataflow.mux %96, %97#0, %101#0 : (i1, none, none) -> none
// CHECK-NEXT: dataflow.graph.return values() streams() memories() complete(%102, %17#0 : none, none)
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-EMPTY: