[PATCH] D142006: [mlir][bufferization] Fix getAliasingOpOperand/OpResult for non-bufferizable ops

2023-01-27 Thread Matthias Springer via Phabricator via cfe-commits
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

2023-01-30 Thread Matthias Springer via Phabricator via cfe-commits
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

2023-01-19 Thread Matthias Springer via Phabricator via cfe-commits
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

2023-01-19 Thread Matthias Springer via Phabricator via cfe-commits
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