1// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="bufferize-function-boundaries=1" -split-input-file -verify-diagnostics 2 3func.func @scf_for(%A : tensor<?xf32>, 4 %B : tensor<?xf32> {bufferization.writable = true}, 5 %C : tensor<4xf32>, 6 %lb : index, %ub : index, %step : index) 7 -> (f32, f32) 8{ 9 %r0:2 = scf.for %i = %lb to %ub step %step iter_args(%tA = %A, %tB = %B) 10 -> (tensor<?xf32>, tensor<?xf32>) 11 { 12 %ttA = tensor.insert_slice %C into %tA[0][4][1] : tensor<4xf32> into tensor<?xf32> 13 %ttB = tensor.insert_slice %C into %tB[0][4][1] : tensor<4xf32> into tensor<?xf32> 14 15 // Throw a wrench in the system by swapping yielded values: this result in a 16 // ping-pong of values at each iteration on which we currently want to fail. 17 18 // expected-error @+1 {{Yield operand #0 is not equivalent to the corresponding iter bbArg}} 19 scf.yield %ttB, %ttA : tensor<?xf32>, tensor<?xf32> 20 } 21 22 %f0 = tensor.extract %r0#0[%step] : tensor<?xf32> 23 %f1 = tensor.extract %r0#1[%step] : tensor<?xf32> 24 return %f0, %f1: f32, f32 25} 26 27// ----- 28 29func.func @scf_while_non_equiv_condition(%arg0: tensor<5xi1>, 30 %arg1: tensor<5xi1>, 31 %idx: index) -> (i1, i1) 32{ 33 %r0, %r1 = scf.while (%w0 = %arg0, %w1 = %arg1) 34 : (tensor<5xi1>, tensor<5xi1>) -> (tensor<5xi1>, tensor<5xi1>) { 35 %condition = tensor.extract %w0[%idx] : tensor<5xi1> 36 // expected-error @+1 {{Condition arg #0 is not equivalent to the corresponding iter bbArg}} 37 scf.condition(%condition) %w1, %w0 : tensor<5xi1>, tensor<5xi1> 38 } do { 39 ^bb0(%b0: tensor<5xi1>, %b1: tensor<5xi1>): 40 %pos = "dummy.some_op"() : () -> (index) 41 %val = "dummy.another_op"() : () -> (i1) 42 %1 = tensor.insert %val into %b0[%pos] : tensor<5xi1> 43 scf.yield %1, %b1 : tensor<5xi1>, tensor<5xi1> 44 } 45 46 %v0 = tensor.extract %r0[%idx] : tensor<5xi1> 47 %v1 = tensor.extract %r1[%idx] : tensor<5xi1> 48 return %v0, %v1 : i1, i1 49} 50 51// ----- 52 53func.func @scf_while_non_equiv_yield(%arg0: tensor<5xi1>, 54 %arg1: tensor<5xi1>, 55 %idx: index) -> (i1, i1) 56{ 57 %r0, %r1 = scf.while (%w0 = %arg0, %w1 = %arg1) 58 : (tensor<5xi1>, tensor<5xi1>) -> (tensor<5xi1>, tensor<5xi1>) { 59 %condition = tensor.extract %w0[%idx] : tensor<5xi1> 60 scf.condition(%condition) %w0, %w1 : tensor<5xi1>, tensor<5xi1> 61 } do { 62 ^bb0(%b0: tensor<5xi1>, %b1: tensor<5xi1>): 63 %pos = "dummy.some_op"() : () -> (index) 64 %val = "dummy.another_op"() : () -> (i1) 65 %1 = tensor.insert %val into %b0[%pos] : tensor<5xi1> 66 // expected-error @+1 {{Yield operand #0 is not equivalent to the corresponding iter bbArg}} 67 scf.yield %b1, %1 : tensor<5xi1>, tensor<5xi1> 68 } 69 70 %v0 = tensor.extract %r0[%idx] : tensor<5xi1> 71 %v1 = tensor.extract %r1[%idx] : tensor<5xi1> 72 return %v0, %v1 : i1, i1 73} 74 75// ----- 76 77func.func @to_tensor_op_unsupported(%m: memref<?xf32>, %idx: index) -> (f32) { 78 // expected-error @+1 {{to_tensor ops without `restrict` are not supported by One-Shot Analysis}} 79 %0 = bufferization.to_tensor %m : memref<?xf32> to tensor<?xf32> 80 81 %1 = tensor.extract %0[%idx] : tensor<?xf32> 82 return %1 : f32 83} 84 85// ----- 86 87func.func @yield_alloc_dominance_test_2(%cst : f32, %idx : index, 88 %idx2 : index) -> f32 { 89 %1 = bufferization.alloc_tensor(%idx) : tensor<?xf32> 90 91 %0 = scf.execute_region -> tensor<?xf32> { 92 // This YieldOp returns a value that is defined in a parent block, thus 93 // no error. 94 scf.yield %1 : tensor<?xf32> 95 } 96 %2 = tensor.insert %cst into %0[%idx] : tensor<?xf32> 97 %r = tensor.extract %2[%idx2] : tensor<?xf32> 98 return %r : f32 99} 100 101// ----- 102 103func.func @copy_of_unranked_tensor(%t: tensor<*xf32>) -> tensor<*xf32> { 104 // Unranked tensor OpOperands always bufferize in-place. With this limitation, 105 // there is no way to bufferize this IR correctly. 106 // expected-error @+1 {{not bufferizable under the given constraints: cannot avoid RaW conflict}} 107 func.call @maybe_writing_func(%t) : (tensor<*xf32>) -> () 108 return %t : tensor<*xf32> 109} 110 111// This function may write to buffer(%ptr). 112func.func private @maybe_writing_func(%ptr : tensor<*xf32>) 113 114// ----- 115 116func.func @regression_scf_while() { 117 %false = arith.constant false 118 %8 = bufferization.alloc_tensor() : tensor<10x10xf32> 119 scf.while (%arg0 = %8) : (tensor<10x10xf32>) -> () { 120 scf.condition(%false) 121 } do { 122 // expected-error @+1 {{Yield operand #0 is not equivalent to the corresponding iter bbArg}} 123 scf.yield %8 : tensor<10x10xf32> 124 } 125 return 126} 127 128// ----- 129 130// expected-error @below{{could not infer buffer type of block argument}} 131// expected-error @below{{failed to bufferize op}} 132func.func @func_multiple_yields(%t: tensor<5xf32>) -> tensor<5xf32> { 133 func.return %t : tensor<5xf32> 134^bb1(%arg1 : tensor<5xf32>): 135 func.return %arg1 : tensor<5xf32> 136} 137