xref: /llvm-project/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-invalid.mlir (revision ced2fc7819d5ddea616ec330f18e08ff284c1868)
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