[PATCH] D142006: [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops
springerm updated this revision to Diff 492765. springerm added a comment. Herald added a subscriber: thopre. rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D142006/new/ https://reviews.llvm.org/D142006 Files: mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir @@ -136,7 +136,7 @@ // CHECK-LABEL: func @select_different_tensors( // CHECK-SAME: %[[t:.*]]: tensor -func.func @select_different_tensors(%t: tensor, %sz: index, %c: i1) -> tensor { +func.func @select_different_tensors(%t: tensor, %sz: index, %pos: index, %c: i1) -> f32 { // CHECK-DAG: %[[m:.*]] = bufferization.to_memref %[[t]] : memref // CHECK-DAG: %[[alloc:.*]] = memref.alloc(%{{.*}}) {{.*}} : memref %0 = bufferization.alloc_tensor(%sz) : tensor @@ -145,7 +145,8 @@ // CHECK: %[[casted:.*]] = memref.cast %[[alloc]] : memref to memref // CHECK: arith.select %{{.*}}, %[[casted]], %[[m]] %1 = arith.select %c, %0, %t : tensor - return %1 : tensor + %2 = tensor.extract %1[%pos] : tensor + return %2 : f32 } // - Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir @@ -5,7 +5,7 @@ // CHECK: (S) 1 num-buffer-alloc // CHECK: (S) 1 num-buffer-dealloc // CHECK: (S) 1 num-tensor-in-place -// CHECK: (S) 1 num-tensor-out-of-place +// CHECK: (S) 2 num-tensor-out-of-place func.func @read_after_write_conflict(%cst : f32, %idx : index, %idx2 : index) -> (f32, f32) { %t = "test.dummy_op"() : () -> (tensor<10xf32>) Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir @@ -100,11 +100,14 @@ %t1: tensor, %o: index, %s: index) -> (tensor, tensor) { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] // CHECK: %[[subview:.*]] = memref.subview %[[m1]] + // The op must alloc because "test.dummy" may bufferize to a memory write. + // CHECK: %[[alloc:.*]] = memref.alloc + // CHECK: memref.copy %[[subview]], %[[alloc]] %0 = tensor.extract_slice %t1[%o][%s][1] : tensor to tensor - // CHECK: %[[subview_tensor:.*]] = bufferization.to_tensor %[[subview]] - // CHECK: %[[dummy:.*]] = "test.dummy_op"(%[[subview_tensor]]) + // CHECK: %[[alloc_tensor:.*]] = bufferization.to_tensor %[[alloc]] + // CHECK: %[[dummy:.*]] = "test.dummy_op"(%[[alloc_tensor]]) %1 = "test.dummy_op"(%0) : (tensor) -> tensor - // CHECK: return %[[subview_tensor]], %[[dummy]] + // CHECK: return %[[alloc_tensor]], %[[dummy]] return %0, %1 : tensor, tensor } Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir === --- /dev/null +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir @@ -0,0 +1,34 @@ +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only" -allow-unregistered-dialect -split-input-file | FileCheck %s + +// CHECK-LABEL: func @unknown_op_aliasing( +func.func @unknown_op_aliasing(%f: f32, %f2: f32, %pos: index) -> f32 { + %0 = tensor.empty() : tensor<10xf32> + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %1 = linalg.fill ins(%f : f32) outs(%0 : tensor<10xf32>) -> tensor<10xf32> + + // Something must bufferize out-of-place because the op may return an alias + // of %1. + // CHECK: "dummy.dummy_op"(%{{.*}}) {__inplace_operands_attr__ = ["false"]} + %alias = "dummy.dummy_op"(%1) : (tensor<10xf32>) -> (tensor<10xf32>) + + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %2 = linalg.fill ins(%f2 : f32) outs(%1 : tensor<10xf32>) -> tensor<10xf32> + %3 = tensor.extract %alias[%pos] : tensor<10xf32> + return %3 : f32 +} + +// - + +// CHECK-LABEL: func @un
[PATCH] D142006: [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops
This revision was automatically updated to reflect the committed changes. Closed by commit rGf3483c23ce2c: [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops (authored by springerm). Changed prior to commit: https://reviews.llvm.org/D142006?vs=492765&id=493228#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D142006/new/ https://reviews.llvm.org/D142006 Files: mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir @@ -136,7 +136,7 @@ // CHECK-LABEL: func @select_different_tensors( // CHECK-SAME: %[[t:.*]]: tensor -func.func @select_different_tensors(%t: tensor, %sz: index, %c: i1) -> tensor { +func.func @select_different_tensors(%t: tensor, %sz: index, %pos: index, %c: i1) -> f32 { // CHECK-DAG: %[[m:.*]] = bufferization.to_memref %[[t]] : memref // CHECK-DAG: %[[alloc:.*]] = memref.alloc(%{{.*}}) {{.*}} : memref %0 = bufferization.alloc_tensor(%sz) : tensor @@ -145,7 +145,8 @@ // CHECK: %[[casted:.*]] = memref.cast %[[alloc]] : memref to memref // CHECK: arith.select %{{.*}}, %[[casted]], %[[m]] %1 = arith.select %c, %0, %t : tensor - return %1 : tensor + %2 = tensor.extract %1[%pos] : tensor + return %2 : f32 } // - Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir @@ -5,7 +5,7 @@ // CHECK: (S) 1 num-buffer-alloc // CHECK: (S) 1 num-buffer-dealloc // CHECK: (S) 1 num-tensor-in-place -// CHECK: (S) 1 num-tensor-out-of-place +// CHECK: (S) 2 num-tensor-out-of-place func.func @read_after_write_conflict(%cst : f32, %idx : index, %idx2 : index) -> (f32, f32) { %t = "test.dummy_op"() : () -> (tensor<10xf32>) Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir @@ -100,11 +100,14 @@ %t1: tensor, %o: index, %s: index) -> (tensor, tensor) { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] // CHECK: %[[subview:.*]] = memref.subview %[[m1]] + // The op must alloc because "test.dummy" may bufferize to a memory write. + // CHECK: %[[alloc:.*]] = memref.alloc + // CHECK: memref.copy %[[subview]], %[[alloc]] %0 = tensor.extract_slice %t1[%o][%s][1] : tensor to tensor - // CHECK: %[[subview_tensor:.*]] = bufferization.to_tensor %[[subview]] - // CHECK: %[[dummy:.*]] = "test.dummy_op"(%[[subview_tensor]]) + // CHECK: %[[alloc_tensor:.*]] = bufferization.to_tensor %[[alloc]] + // CHECK: %[[dummy:.*]] = "test.dummy_op"(%[[alloc_tensor]]) %1 = "test.dummy_op"(%0) : (tensor) -> tensor - // CHECK: return %[[subview_tensor]], %[[dummy]] + // CHECK: return %[[alloc_tensor]], %[[dummy]] return %0, %1 : tensor, tensor } Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir === --- /dev/null +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir @@ -0,0 +1,34 @@ +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only" -allow-unregistered-dialect -split-input-file | FileCheck %s + +// CHECK-LABEL: func @unknown_op_aliasing( +func.func @unknown_op_aliasing(%f: f32, %f2: f32, %pos: index) -> f32 { + %0 = tensor.empty() : tensor<10xf32> + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %1 = linalg.fill ins(%f : f32) outs(%0 : tensor<10xf32>) -> tensor<10xf32> + + // Something must bufferize out-of-place because the op may return an alias + // of %1. + // CHECK: "dummy.dummy_op"(%{{.*}}) {__inplace_operands_attr__ = ["false"]} + %alias = "dummy.dummy_op"(%1) : (tensor<10xf32>) -> (tensor<10xf32>) + + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %2 = linal
[PATCH] D142006: [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops
springerm updated this revision to Diff 490397. springerm added a comment. Herald added a project: clang. Herald added a subscriber: cfe-commits. update Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D142006/new/ https://reviews.llvm.org/D142006 Files: clang/lib/AST/Interp/Descriptor.cpp clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/InterpFrame.cpp clang/test/AST/Interp/cxx20.cpp clang/test/AST/Interp/records.cpp Index: clang/test/AST/Interp/records.cpp === --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -295,13 +295,14 @@ // ref-note 2{{non-constexpr constructor 'Base' cannot be used in a constant expression}} }; - // FIXME: This is currently not being diagnosed with the new constant interpreter. constexpr Derived D(12); // ref-error {{must be initialized by a constant expression}} \ // ref-note {{in call to 'Derived(12)'}} \ // ref-note {{declared here}} \ // expected-error {{must be initialized by a constant expression}} static_assert(D.Val == 0, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{initializer of 'D' is not a constant expression}} + // ref-note {{initializer of 'D' is not a constant expression}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{read of object outside its lifetime}} struct AnotherBase { int Val; Index: clang/test/AST/Interp/cxx20.cpp === --- clang/test/AST/Interp/cxx20.cpp +++ clang/test/AST/Interp/cxx20.cpp @@ -85,11 +85,10 @@ // ref-note {{in call to}} -struct Int { int a; }; +struct Int { int a; }; // expected-note {{subobject declared here}} constexpr int initializedLocal3() { - Int i; - return i.a; // expected-note {{read of object outside its lifetime}} \ - // ref-note {{read of uninitialized object is not allowed in a constant expression}} + Int i; // expected-note {{subobject of type 'int' is not initialized}} + return i.a; // ref-note {{read of uninitialized object is not allowed in a constant expression}} } static_assert(initializedLocal3() == 20); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to}} \ @@ -134,3 +133,35 @@ // ref-note {{declared here}} static_assert(!b4); // ref-error {{not an integral constant expression}} \ // ref-note {{not a constant expression}} + +namespace UninitializedFields { + class A { + public: +int a; // expected-note {{subobject declared here}} \ + // ref-note {{subobject declared here}} +constexpr A() {} + }; + constexpr A a; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{subobject of type 'int' is not initialized}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject of type 'int' is not initialized}} + + + class Base { + public: +bool b; +int a; // expected-note {{subobject declared here}} \ + // ref-note {{subobject declared here}} +constexpr Base() : b(true) {} + }; + + class Derived : public Base { + public: +constexpr Derived() : Base() {} // expected-note {{subobject of type 'int' is not initialized}} + }; + +constexpr Derived D; // expected-error {{must be initialized by a constant expression}} \\ + // expected-note {{in call to 'Derived()'}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject of type 'int' is not initialized}} +}; Index: clang/lib/AST/Interp/InterpFrame.cpp === --- clang/lib/AST/Interp/InterpFrame.cpp +++ clang/lib/AST/Interp/InterpFrame.cpp @@ -64,8 +64,6 @@ } InterpFrame::~InterpFrame() { - if (Func && Func->isConstructor() && This.isBaseClass()) -This.initialize(); for (auto &Param : Params) S.deallocate(reinterpret_cast(Param.second.get())); } Index: clang/lib/AST/Interp/Interp.h === --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -91,6 +91,9 @@ /// Checks if a method is pure virtual. bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD); +/// Checks that all fields are initialized after a constructor call. +bool CheckCtorCall(InterpState
[PATCH] D142006: [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops
springerm updated this revision to Diff 490398. springerm added a comment. update Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D142006/new/ https://reviews.llvm.org/D142006 Files: mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir @@ -136,7 +136,7 @@ // CHECK-LABEL: func @select_different_tensors( // CHECK-SAME: %[[t:.*]]: tensor -func.func @select_different_tensors(%t: tensor, %sz: index, %c: i1) -> tensor { +func.func @select_different_tensors(%t: tensor, %sz: index, %pos: index, %c: i1) -> f32 { // CHECK-DAG: %[[m:.*]] = bufferization.to_memref %[[t]] : memref // CHECK-DAG: %[[alloc:.*]] = memref.alloc(%{{.*}}) {{.*}} : memref %0 = bufferization.alloc_tensor(%sz) : tensor @@ -145,7 +145,8 @@ // CHECK: %[[casted:.*]] = memref.cast %[[alloc]] : memref to memref // CHECK: arith.select %{{.*}}, %[[casted]], %[[m]] %1 = arith.select %c, %0, %t : tensor - return %1 : tensor + %2 = tensor.extract %1[%pos] : tensor + return %2 : f32 } // - Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-pass-statistics.mlir @@ -5,7 +5,7 @@ // CHECK: (S) 1 num-buffer-alloc // CHECK: (S) 1 num-buffer-dealloc // CHECK: (S) 1 num-tensor-in-place -// CHECK: (S) 1 num-tensor-out-of-place +// CHECK: (S) 2 num-tensor-out-of-place func.func @read_after_write_conflict(%cst : f32, %idx : index, %idx2 : index) -> (f32, f32) { %t = "test.dummy_op"() : () -> (tensor<10xf32>) Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir === --- mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir @@ -100,11 +100,14 @@ %t1: tensor, %o: index, %s: index) -> (tensor, tensor) { // CHECK: %[[m1:.*]] = bufferization.to_memref %[[t1]] // CHECK: %[[subview:.*]] = memref.subview %[[m1]] + // The op must alloc because "test.dummy" may bufferize to a memory write. + // CHECK: %[[alloc:.*]] = memref.alloc + // CHECK: memref.copy %[[subview]], %[[alloc]] %0 = tensor.extract_slice %t1[%o][%s][1] : tensor to tensor - // CHECK: %[[subview_tensor:.*]] = bufferization.to_tensor %[[subview]] - // CHECK: %[[dummy:.*]] = "test.dummy_op"(%[[subview_tensor]]) + // CHECK: %[[alloc_tensor:.*]] = bufferization.to_tensor %[[alloc]] + // CHECK: %[[dummy:.*]] = "test.dummy_op"(%[[alloc_tensor]]) %1 = "test.dummy_op"(%0) : (tensor) -> tensor - // CHECK: return %[[subview_tensor]], %[[dummy]] + // CHECK: return %[[alloc_tensor]], %[[dummy]] return %0, %1 : tensor, tensor } Index: mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir === --- /dev/null +++ mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir @@ -0,0 +1,34 @@ +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only" -allow-unregistered-dialect -split-input-file | FileCheck %s + +// CHECK-LABEL: func @unknown_op_aliasing( +func.func @unknown_op_aliasing(%f: f32, %f2: f32, %pos: index) -> f32 { + %0 = tensor.empty() : tensor<10xf32> + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %1 = linalg.fill ins(%f : f32) outs(%0 : tensor<10xf32>) -> tensor<10xf32> + + // Something must bufferize out-of-place because the op may return an alias + // of %1. + // CHECK: "dummy.dummy_op"(%{{.*}}) {__inplace_operands_attr__ = ["false"]} + %alias = "dummy.dummy_op"(%1) : (tensor<10xf32>) -> (tensor<10xf32>) + + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %2 = linalg.fill ins(%f2 : f32) outs(%1 : tensor<10xf32>) -> tensor<10xf32> + %3 = tensor.extract %alias[%pos] : tensor<10xf32> + return %3 : f32 +} + +// - + +// CHECK-LABEL: func @unknown_op_writing( +func.func @unkno