[mlir][side effect] refactor(*): Include more precise side effects (#94213)

This patch adds more precise side effects to the current ops with memory
effects, allowing us to determine which OpOperand/OpResult/BlockArgument
the
operation reads or writes, rather than just recording the reading and
writing
of values. This allows for convenient use of precise side effects to
achieve
analysis and optimization.

Related discussions:
https://discourse.llvm.org/t/rfc-add-operandindex-to-sideeffect-instance/79243
This commit is contained in:
donald chen
2024-06-19 22:10:34 +08:00
committed by GitHub
parent e5b0c210cc
commit 2c1ae801e1
40 changed files with 688 additions and 398 deletions

View File

@@ -1058,9 +1058,9 @@ void fir::BoxRankOp::getEffects(
llvm::SmallVectorImpl<
mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
&effects) {
mlir::Value inputBox = getBox();
if (fir::isBoxAddress(inputBox.getType()))
effects.emplace_back(mlir::MemoryEffects::Read::get(), inputBox,
mlir::OpOperand &inputBox = getBoxMutable();
if (fir::isBoxAddress(inputBox.get().getType()))
effects.emplace_back(mlir::MemoryEffects::Read::get(), &inputBox,
mlir::SideEffects::DefaultResource::get());
}
@@ -2901,9 +2901,9 @@ void fir::ReboxAssumedRankOp::getEffects(
llvm::SmallVectorImpl<
mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
&effects) {
mlir::Value inputBox = getBox();
if (fir::isBoxAddress(inputBox.getType()))
effects.emplace_back(mlir::MemoryEffects::Read::get(), inputBox,
mlir::OpOperand &inputBox = getBoxMutable();
if (fir::isBoxAddress(inputBox.get().getType()))
effects.emplace_back(mlir::MemoryEffects::Read::get(), &inputBox,
mlir::SideEffects::DefaultResource::get());
}

View File

@@ -45,7 +45,7 @@ getIntrinsicEffects(mlir::Operation *self,
"hlfir intrinsic ops only produce 1 result");
if (mlir::isa<hlfir::ExprType>(self->getResult(0).getType()))
effects.emplace_back(mlir::MemoryEffects::Allocate::get(),
self->getResult(0),
self->getOpResult(0),
mlir::SideEffects::DefaultResource::get());
// read effect if we read from a pointer or refference type
@@ -59,10 +59,10 @@ getIntrinsicEffects(mlir::Operation *self,
// } to {
// hlfir.yield %0#0 : !fir.box<!fir.array<?x?xf32>>
// }
for (mlir::Value operand : self->getOperands()) {
mlir::Type opTy = operand.getType();
for (mlir::OpOperand &operand : self->getOpOperands()) {
mlir::Type opTy = operand.get().getType();
if (fir::isa_ref_type(opTy) || fir::isa_box_type(opTy))
effects.emplace_back(mlir::MemoryEffects::Read::get(), operand,
effects.emplace_back(mlir::MemoryEffects::Read::get(), &operand,
mlir::SideEffects::DefaultResource::get());
}
}

View File

@@ -225,14 +225,14 @@ static void gatherMemoryEffects(
/// Return the entity yielded by a region, or a null value if the region
/// is not terminated by a yield.
static mlir::Value getYieldedEntity(mlir::Region &region) {
static mlir::OpOperand *getYieldedEntity(mlir::Region &region) {
if (region.empty() || region.back().empty())
return nullptr;
if (auto yield = mlir::dyn_cast<hlfir::YieldOp>(region.back().back()))
return yield.getEntity();
return &yield.getEntityMutable();
if (auto elementalAddr =
mlir::dyn_cast<hlfir::ElementalAddrOp>(region.back().back()))
return elementalAddr.getYieldOp().getEntity();
return &elementalAddr.getYieldOp().getEntityMutable();
return nullptr;
}
@@ -244,7 +244,7 @@ static void gatherAssignEffects(
hlfir::RegionAssignOp regionAssign,
bool userDefAssignmentMayOnlyWriteToAssignedVariable,
llvm::SmallVectorImpl<mlir::MemoryEffects::EffectInstance> &assignEffects) {
mlir::Value assignedVar = getYieldedEntity(regionAssign.getLhsRegion());
mlir::OpOperand *assignedVar = getYieldedEntity(regionAssign.getLhsRegion());
assert(assignedVar && "lhs cannot be an empty region");
assignEffects.emplace_back(mlir::MemoryEffects::Write::get(), assignedVar);
@@ -389,8 +389,8 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion,
// with a finalizer, or a user defined assignment where the LHS is
// intent(inout)).
if (yieldIsImplicitRead) {
mlir::Value entity = getYieldedEntity(yieldRegion);
if (entity && hlfir::isFortranVariableType(entity.getType()))
mlir::OpOperand *entity = getYieldedEntity(yieldRegion);
if (entity && hlfir::isFortranVariableType(entity->get().getType()))
effects.emplace_back(mlir::MemoryEffects::Read::get(), entity);
}
if (!leafRegionsMayOnlyRead && anyWrite(effects)) {
@@ -600,9 +600,9 @@ hlfir::buildEvaluationSchedule(hlfir::OrderedAssignmentTreeOpInterface root,
}
mlir::Value hlfir::SaveEntity::getSavedValue() {
mlir::Value saved = getYieldedEntity(*yieldRegion);
mlir::OpOperand *saved = getYieldedEntity(*yieldRegion);
assert(saved && "SaveEntity must contain region terminated by YieldOp");
return saved;
return saved->get();
}
//===----------------------------------------------------------------------===//

View File

@@ -3,214 +3,186 @@
func.func @concat(%arg0: !fir.ref<!fir.char<1,10>>, %arg1: !fir.ref<!fir.char<1, 20>>) {
// expected-remark@+1 {{operation has no memory effects}}
%c30 = arith.constant 30 : index
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.concat %arg0, %arg1 len %c30 : (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,20>>, index) -> (!hlfir.expr<!fir.char<1,30>>)
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @all_no_effects(%arg0: !hlfir.expr<2x!fir.logical<4>>) {
// expected-remark@+1 {{operation has no memory effects}}
%all = hlfir.all %arg0 : (!hlfir.expr<2x!fir.logical<4>>) -> !fir.logical<4>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @all_effects(%arg0: !fir.ref<!fir.array<2x10x!fir.logical<4>>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%all = hlfir.all %arg0 dim %arg1 : (!fir.ref<!fir.array<2x10x!fir.logical<4>>>, i32) -> !hlfir.expr<?x!fir.logical<4>>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @any_no_effects(%arg0: !hlfir.expr<2x!fir.logical<4>>) {
// expected-remark@+1 {{operation has no memory effects}}
%all = hlfir.any %arg0 : (!hlfir.expr<2x!fir.logical<4>>) -> !fir.logical<4>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @any_effects(%arg0: !fir.ref<!fir.array<2x10x!fir.logical<4>>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%all = hlfir.any %arg0 dim %arg1 : (!fir.ref<!fir.array<2x10x!fir.logical<4>>>, i32) -> !hlfir.expr<?x!fir.logical<4>>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @count_no_effects(%arg0: !hlfir.expr<2x!fir.logical<4>>) {
// expected-remark@+1 {{operation has no memory effects}}
%all = hlfir.count %arg0 : (!hlfir.expr<2x!fir.logical<4>>) -> i32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @count_effects(%arg0: !fir.ref<!fir.array<2x10x!fir.logical<4>>>, %arg1: i32) {
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%all = hlfir.count %arg0 dim %arg1 : (!fir.ref<!fir.array<2x10x!fir.logical<4>>>, i32) -> i32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @product_no_effects(%arg0: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{operation has no memory effects}}
%product = hlfir.product %arg0 : (!hlfir.expr<?xf32>) -> f32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @product_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%product = hlfir.product %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @set_length_read(%arg0: !fir.ref<!fir.char<1,10>>, %arg1: index) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.set_length %arg0 len %arg1 : (!fir.ref<!fir.char<1,10>>, index) -> !hlfir.expr<!fir.char<1,?>>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @sum_no_effects(%arg0: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{operation has no memory effects}}
%sum = hlfir.sum %arg0 : (!hlfir.expr<?xf32>) -> f32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @sum_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%sum = hlfir.sum %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @maxval_no_effects(%arg0: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{operation has no memory effects}}
%maxval = hlfir.maxval %arg0 : (!hlfir.expr<?xf32>) -> f32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @maxval_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%maxval = hlfir.maxval %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @minval_no_effects(%arg0: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{operation has no memory effects}}
%minval = hlfir.minval %arg0 : (!hlfir.expr<?xf32>) -> f32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @minval_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%minval = hlfir.minval %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @minloc_effects_simple(%arg0: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
%minloc = hlfir.minloc %arg0 : (!hlfir.expr<?xf32>) -> !hlfir.expr<?xi32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @minloc_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%minloc = hlfir.minloc %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xi32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @maxloc_effects_simple(%arg0: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
%maxloc = hlfir.maxloc %arg0 : (!hlfir.expr<?xf32>) -> !hlfir.expr<?xi32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @maxloc_effects(%arg0: !fir.ref<!fir.array<2x2xf32>>, %arg1: i32) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%maxloc = hlfir.maxloc %arg0 dim %arg1 : (!fir.ref<!fir.array<2x2xf32>>, i32) -> !hlfir.expr<2xi32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @dot_product_no_effects(%arg0: !hlfir.expr<?xf32>, %arg1: !hlfir.expr<?xf32>) {
// expected-remark@+1 {{operation has no memory effects}}
%0 = hlfir.dot_product %arg0 %arg1 : (!hlfir.expr<?xf32>, !hlfir.expr<?xf32>) -> f32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @dot_product_effects(%arg0: !fir.ref<!fir.array<10xf32>>, %arg1: !fir.ref<!fir.array<10xf32>>) {
// there are read effects on both arguments - the diagnostic verification just doesn't register duplicate identical diagnostics
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.dot_product %arg0 %arg1 : (!fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) -> f32
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @matmul_no_reads(%arg0: !hlfir.expr<?x?xf32>, %arg1: !hlfir.expr<?x?xf32>) {
// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
%0 = hlfir.matmul %arg0 %arg1 : (!hlfir.expr<?x?xf32>, !hlfir.expr<?x?xf32>) -> !hlfir.expr<?x?xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @matmul_reads(%arg0: !fir.ref<!fir.array<10x5xf32>>, %arg1: !fir.ref<!fir.array<5x10xf32>>) {
// expected-remark@+3 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+3 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// there are read effects on both arguments - the diagnostic verification just doesn't register duplicate identical diagnostics
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.matmul %arg0 %arg1 : (!fir.ref<!fir.array<10x5xf32>>, !fir.ref<!fir.array<5x10xf32>>) -> !hlfir.expr<10x10xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @transpose_no_reads(%arg0: !hlfir.expr<?x?xf32>) {
// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
%0 = hlfir.transpose %arg0 : (!hlfir.expr<?x?xf32>) -> !hlfir.expr<?x?xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @transpose_read(%arg0: !fir.ref<!fir.array<10x5xf32>>) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.transpose %arg0 : (!fir.ref<!fir.array<10x5xf32>>) -> !hlfir.expr<5x10xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @matmul_transpose_no_reads(%arg0: !hlfir.expr<?x?xf32>, %arg1: !hlfir.expr<?x?xf32>) {
// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
%0 = hlfir.matmul_transpose %arg0 %arg1 : (!hlfir.expr<?x?xf32>, !hlfir.expr<?x?xf32>) -> !hlfir.expr<?x?xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @matmul_transpose_reads(%arg0: !fir.ref<!fir.array<5x10xf32>>, %arg1: !fir.ref<!fir.array<5x10xf32>>) {
// expected-remark@+3 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+3 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// there are read effects on both arguments - the diagnostic verification just doesn't register duplicate identical diagnostics
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.matmul_transpose %arg0 %arg1 : (!fir.ref<!fir.array<5x10xf32>>, !fir.ref<!fir.array<5x10xf32>>) -> !hlfir.expr<10x10xf32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
@@ -219,46 +191,41 @@ func.func @associate(%arg0: i32) {
%0:3 = hlfir.associate %arg0 {uniq_name = "x"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
// expected-remark@+1 {{found an instance of 'free' on resource '<Default>'}}
hlfir.end_associate %0#1, %0#2 : !fir.ref<i32>, i1
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @as_expr_read(%arg0: !fir.ref<!fir.array<2xi32>>) {
// expected-remark@+2 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.as_expr %arg0 : (!fir.ref<!fir.array<2xi32>>) -> !hlfir.expr<?xi32>
// expected-remark@+1 {{found an instance of 'free' on resource '<Default>'}}
hlfir.destroy %0 : !hlfir.expr<?xi32>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @char_extremum(%arg0: !fir.ref<!fir.char<1,10>>, %arg1: !fir.ref<!fir.char<1,20>>) {
// expected-remark@+3 {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark@+3 {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
// there are read effects on both arguments - the diagnostic verification just doesn't register duplicate identical diagnostics
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
%0 = hlfir.char_extremum min, %arg0, %arg1 : (!fir.ref<!fir.char<1, 10>>, !fir.ref<!fir.char<1,20>>) -> !hlfir.expr<!fir.char<1,10>>
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @copy_in(%box: !fir.box<!fir.array<?xf64>>, %temp: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, %is_present: i1) {
// expected-remark@+3 {{found an instance of 'allocate' on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'write' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'write' on a op operand, on resource '<Default>'}}
%0:2 = hlfir.copy_in %box to %temp : (!fir.box<!fir.array<?xf64>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> (!fir.box<!fir.array<?xf64>>, i1)
// expected-remark@+1 {{operation has no memory effects}}
return
}
func.func @copy_out(%box: !fir.box<!fir.array<?xf64>>, %temp: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, %was_copied: i1) {
// expected-remark@+2 {{found an instance of 'free' on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
hlfir.copy_out %temp, %was_copied : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, i1) -> ()
// expected-remark@+3 {{found an instance of 'free' on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'write' on a value, on resource '<Default>'}}
// expected-remark@+2 {{found an instance of 'read' on a op operand, on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'write' on a op operand, on resource '<Default>'}}
hlfir.copy_out %temp, %was_copied to %box : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, i1, !fir.box<!fir.array<?xf64>>) -> ()
// expected-remark@+1 {{operation has no memory effects}}
return
}

View File

@@ -129,7 +129,7 @@ void mlir::transform::ChangeCallTargetOp::getEffects(
// Indicate that the `call` handle is only read by this operation because the
// associated operation is not erased but rather modified in-place, so the
// reference to it remains valid.
onlyReadsHandle(getCall(), effects);
onlyReadsHandle(getCallMutable(), effects);
// Indicate that the payload is modified by this operation.
modifiesPayload(effects);

View File

@@ -139,7 +139,7 @@ void mlir::transform::ChangeCallTargetOp::getEffects(
// Indicate that the `call` handle is only read by this operation because the
// associated operation is not erased but rather modified in-place, so the
// reference to it remains valid.
onlyReadsHandle(getCall(), effects);
onlyReadsHandle(getCallMutable(), effects);
// Indicate that the payload is modified by this operation.
modifiesPayload(effects);

View File

@@ -160,9 +160,8 @@ mlir::transform::HasOperandSatisfyingOp::apply(
void mlir::transform::HasOperandSatisfyingOp::getEffects(
llvm::SmallVectorImpl<mlir::MemoryEffects::EffectInstance> &effects) {
onlyReadsPayload(effects);
onlyReadsHandle(getOp(), effects);
producesHandle(getPosition(), effects);
producesHandle(getResults(), effects);
onlyReadsHandle(getOpMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
}
// Verify well-formedness of the operation and emit diagnostics if it is

View File

@@ -107,6 +107,9 @@ public:
/// Returns the source MemRefType for this DMA operation.
Value getSrcMemRef() { return getOperand(getSrcMemRefOperandIndex()); }
OpOperand &getSrcMemRefMutable() {
return getOperation()->getOpOperand(getSrcMemRefOperandIndex());
}
MemRefType getSrcMemRefType() {
return cast<MemRefType>(getSrcMemRef().getType());
}
@@ -117,7 +120,8 @@ public:
/// Returns the affine map used to access the source memref.
AffineMap getSrcMap() { return getSrcMapAttr().getValue(); }
AffineMapAttr getSrcMapAttr() {
return cast<AffineMapAttr>(*(*this)->getInherentAttr(getSrcMapAttrStrName()));
return cast<AffineMapAttr>(
*(*this)->getInherentAttr(getSrcMapAttrStrName()));
}
/// Returns the source memref affine map indices for this DMA operation.
@@ -139,6 +143,9 @@ public:
/// Returns the destination MemRefType for this DMA operation.
Value getDstMemRef() { return getOperand(getDstMemRefOperandIndex()); }
OpOperand &getDstMemRefMutable() {
return getOperation()->getOpOperand(getDstMemRefOperandIndex());
}
MemRefType getDstMemRefType() {
return cast<MemRefType>(getDstMemRef().getType());
}
@@ -156,7 +163,8 @@ public:
/// Returns the affine map used to access the destination memref.
AffineMap getDstMap() { return getDstMapAttr().getValue(); }
AffineMapAttr getDstMapAttr() {
return cast<AffineMapAttr>(*(*this)->getInherentAttr(getDstMapAttrStrName()));
return cast<AffineMapAttr>(
*(*this)->getInherentAttr(getDstMapAttrStrName()));
}
/// Returns the destination memref indices for this DMA operation.
@@ -173,6 +181,9 @@ public:
/// Returns the Tag MemRef for this DMA operation.
Value getTagMemRef() { return getOperand(getTagMemRefOperandIndex()); }
OpOperand &getTagMemRefMutable() {
return getOperation()->getOpOperand(getTagMemRefOperandIndex());
}
MemRefType getTagMemRefType() {
return cast<MemRefType>(getTagMemRef().getType());
}
@@ -185,7 +196,8 @@ public:
/// Returns the affine map used to access the tag memref.
AffineMap getTagMap() { return getTagMapAttr().getValue(); }
AffineMapAttr getTagMapAttr() {
return cast<AffineMapAttr>(*(*this)->getInherentAttr(getTagMapAttrStrName()));
return cast<AffineMapAttr>(
*(*this)->getInherentAttr(getTagMapAttrStrName()));
}
/// Returns the tag memref indices for this DMA operation.
@@ -300,6 +312,7 @@ public:
/// Returns the Tag MemRef associated with the DMA operation being waited on.
Value getTagMemRef() { return getOperand(0); }
OpOperand &getTagMemRefMutable() { return getOperation()->getOpOperand(0); }
MemRefType getTagMemRefType() {
return cast<MemRefType>(getTagMemRef().getType());
}
@@ -307,7 +320,8 @@ public:
/// Returns the affine map used to access the tag memref.
AffineMap getTagMap() { return getTagMapAttr().getValue(); }
AffineMapAttr getTagMapAttr() {
return cast<AffineMapAttr>(*(*this)->getInherentAttr(getTagMapAttrStrName()));
return cast<AffineMapAttr>(
*(*this)->getInherentAttr(getTagMapAttrStrName()));
}
/// Returns the tag memref index for this DMA operation.

View File

@@ -706,6 +706,7 @@ def MemRef_DmaStartOp : MemRef_Op<"dma_start"> {
let extraClassDeclaration = [{
// Returns the source MemRefType for this DMA operation.
Value getSrcMemRef() { return getOperand(0); }
OpOperand &getSrcMemRefMutable() { return getOperation()->getOpOperand(0); }
// Returns the rank (number of indices) of the source MemRefType.
unsigned getSrcMemRefRank() {
return ::llvm::cast<MemRefType>(getSrcMemRef().getType()).getRank();
@@ -718,6 +719,7 @@ def MemRef_DmaStartOp : MemRef_Op<"dma_start"> {
// Returns the destination MemRefType for this DMA operations.
Value getDstMemRef() { return getOperand(1 + getSrcMemRefRank()); }
OpOperand &getDstMemRefMutable() { return getOperation()->getOpOperand(1 + getSrcMemRefRank()); }
// Returns the rank (number of indices) of the destination MemRefType.
unsigned getDstMemRefRank() {
return ::llvm::cast<MemRefType>(getDstMemRef().getType()).getRank();
@@ -745,6 +747,9 @@ def MemRef_DmaStartOp : MemRef_Op<"dma_start"> {
Value getTagMemRef() {
return getOperand(1 + getSrcMemRefRank() + 1 + getDstMemRefRank() + 1);
}
OpOperand &getTagMemRefMutable() {
return getOperation()->getOpOperand(1 + getSrcMemRefRank() + 1 + getDstMemRefRank() + 1);
}
// Returns the rank (number of indices) of the tag MemRefType.
unsigned getTagMemRefRank() {
@@ -801,11 +806,11 @@ def MemRef_DmaStartOp : MemRef_Op<"dma_start"> {
void getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>> &
effects) {
effects.emplace_back(MemoryEffects::Read::get(), getSrcMemRef(),
effects.emplace_back(MemoryEffects::Read::get(), &getSrcMemRefMutable(),
SideEffects::DefaultResource::get());
effects.emplace_back(MemoryEffects::Write::get(), getDstMemRef(),
effects.emplace_back(MemoryEffects::Write::get(), &getDstMemRefMutable(),
SideEffects::DefaultResource::get());
effects.emplace_back(MemoryEffects::Read::get(), getTagMemRef(),
effects.emplace_back(MemoryEffects::Read::get(), &getTagMemRefMutable(),
SideEffects::DefaultResource::get());
}
}];
@@ -852,7 +857,7 @@ def MemRef_DmaWaitOp : MemRef_Op<"dma_wait"> {
void getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>> &
effects) {
effects.emplace_back(MemoryEffects::Read::get(), getTagMemRef(),
effects.emplace_back(MemoryEffects::Read::get(), &getTagMemRefMutable(),
SideEffects::DefaultResource::get());
}
}];

View File

@@ -102,8 +102,8 @@ public:
}
void getEffects(SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(this->getOperation()->getOperands(), effects);
producesHandle(this->getOperation()->getResults(), effects);
onlyReadsHandle(this->getOperation()->getOpOperands(), effects);
producesHandle(this->getOperation()->getOpResults(), effects);
onlyReadsPayload(effects);
}
};
@@ -163,8 +163,8 @@ public:
}
void getEffects(SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(this->getOperation()->getOperands(), effects);
producesHandle(this->getOperation()->getResults(), effects);
onlyReadsHandle(this->getOperation()->getOpOperands(), effects);
producesHandle(this->getOperation()->getOpResults(), effects);
onlyReadsPayload(effects);
}
};

View File

@@ -1261,11 +1261,13 @@ struct PayloadIRResource
/// - consumes = Read + Free,
/// - produces = Allocate + Write,
/// - onlyReads = Read.
void consumesHandle(ValueRange handles,
void consumesHandle(MutableArrayRef<OpOperand> handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects);
void producesHandle(ValueRange handles,
void producesHandle(ResultRange handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects);
void onlyReadsHandle(ValueRange handles,
void producesHandle(MutableArrayRef<BlockArgument> handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects);
void onlyReadsHandle(MutableArrayRef<OpOperand> handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects);
/// Checks whether the transform op consumes the given handle.
@@ -1296,8 +1298,8 @@ public:
/// the results by allocating and writing it and reads/writes the payload IR
/// in the process.
void getEffects(SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(this->getOperation()->getOperands(), effects);
producesHandle(this->getOperation()->getResults(), effects);
consumesHandle(this->getOperation()->getOpOperands(), effects);
producesHandle(this->getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -1322,8 +1324,8 @@ public:
/// This op produces handles to the Payload IR without consuming the original
/// handles and without modifying the IR itself.
void getEffects(SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(this->getOperation()->getOperands(), effects);
producesHandle(this->getOperation()->getResults(), effects);
onlyReadsHandle(this->getOperation()->getOpOperands(), effects);
producesHandle(this->getOperation()->getOpResults(), effects);
if (llvm::any_of(this->getOperation()->getOperandTypes(), [](Type t) {
return isa<TransformHandleTypeInterface,
TransformValueHandleTypeInterface>(t);

View File

@@ -145,12 +145,19 @@ public:
Resource *resource = DefaultResource::get())
: effect(effect), resource(resource), stage(stage),
effectOnFullRegion(effectOnFullRegion) {}
EffectInstance(EffectT *effect, Value value,
template <typename T,
std::enable_if_t<
llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
bool> = true>
EffectInstance(EffectT *effect, T value,
Resource *resource = DefaultResource::get())
: effect(effect), resource(resource), value(value), stage(0),
effectOnFullRegion(false) {}
EffectInstance(EffectT *effect, Value value, int stage,
bool effectOnFullRegion,
template <typename T,
std::enable_if_t<
llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
bool> = true>
EffectInstance(EffectT *effect, T value, int stage, bool effectOnFullRegion,
Resource *resource = DefaultResource::get())
: effect(effect), resource(resource), value(value), stage(stage),
effectOnFullRegion(effectOnFullRegion) {}
@@ -172,11 +179,19 @@ public:
Resource *resource = DefaultResource::get())
: effect(effect), resource(resource), parameters(parameters),
stage(stage), effectOnFullRegion(effectOnFullRegion) {}
EffectInstance(EffectT *effect, Value value, Attribute parameters,
template <typename T,
std::enable_if_t<
llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
bool> = true>
EffectInstance(EffectT *effect, T value, Attribute parameters,
Resource *resource = DefaultResource::get())
: effect(effect), resource(resource), value(value),
parameters(parameters), stage(0), effectOnFullRegion(false) {}
EffectInstance(EffectT *effect, Value value, Attribute parameters, int stage,
template <typename T,
std::enable_if_t<
llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
bool> = true>
EffectInstance(EffectT *effect, T value, Attribute parameters, int stage,
bool effectOnFullRegion,
Resource *resource = DefaultResource::get())
: effect(effect), resource(resource), value(value),
@@ -199,7 +214,26 @@ public:
/// Return the value the effect is applied on, or nullptr if there isn't a
/// known value being affected.
Value getValue() const {
return value ? llvm::dyn_cast_if_present<Value>(value) : Value();
if (!value || llvm::isa_and_present<SymbolRefAttr>(value)) {
return Value();
}
if (OpOperand *operand = llvm::dyn_cast_if_present<OpOperand *>(value)) {
return operand->get();
}
if (OpResult result = llvm::dyn_cast_if_present<OpResult>(value)) {
return result;
}
return cast_if_present<BlockArgument>(value);
}
/// Returns the OpOperand effect is applied on, or nullptr if there isn't a
/// known value being effected.
template <typename T,
std::enable_if_t<
llvm::is_one_of<T, OpOperand *, OpResult, BlockArgument>::value,
bool> = true>
T getEffectValue() const {
return value ? dyn_cast_if_present<T>(value) : nullptr;
}
/// Return the symbol reference the effect is applied on, or nullptr if there
@@ -228,8 +262,9 @@ private:
/// The resource that the given value resides in.
Resource *resource;
/// The Symbol or Value that the effect applies to. This is optionally null.
PointerUnion<SymbolRefAttr, Value> value;
/// The Symbol, OpOperand, OpResult or BlockArgument that the effect applies
/// to. This is optionally null.
PointerUnion<SymbolRefAttr, OpOperand *, OpResult, BlockArgument> value;
/// Additional parameters of the effect instance. An attribute is used for
/// type-safe structured storage and context-based uniquing. Concrete effects
@@ -348,17 +383,32 @@ struct Write : public Effect::Base<Write> {};
// SideEffect Utilities
//===----------------------------------------------------------------------===//
/// Returns true if `op` has only an effect of type `EffectTy` (and of no other
/// type) on `value`. If no value is provided, simply check if effects of that
/// type and only of that type are present.
/// Returns true if `op` has only an effect of type `EffectTy`.
template <typename EffectTy>
bool hasSingleEffect(Operation *op, Value value = nullptr);
bool hasSingleEffect(Operation *op);
/// Returns true if `op` has an effect of type `EffectTy` on `value`. If no
/// `value` is provided, simply check if effects of the given type(s) are
/// present.
/// Returns true if `op` has only an effect of type `EffectTy` (and of no other
/// type) on `value`.
template <typename EffectTy>
bool hasSingleEffect(Operation *op, Value value);
/// Returns true if `op` has only an effect of type `EffectTy` (and of no other
/// type) on `value` of type `ValueTy`.
template <typename ValueTy, typename EffectTy>
bool hasSingleEffect(Operation *op, ValueTy value);
/// Returns true if `op` has an effect of type `EffectTy`.
template <typename... EffectTys>
bool hasEffect(Operation *op, Value value = nullptr);
bool hasEffect(Operation *op);
/// Returns true if `op` has an effect of type `EffectTy` on `value`.
template <typename... EffectTys>
bool hasEffect(Operation *op, Value value);
/// Returns true if `op` has an effect of type `EffectTy` on `value` of type
/// `ValueTy`.
template <typename ValueTy, typename... EffectTys>
bool hasEffect(Operation *op, ValueTy value);
/// Return true if the given operation is unused, and has no side effects on
/// memory that prevent erasing.

View File

@@ -1707,11 +1707,11 @@ LogicalResult AffineDmaStartOp::fold(ArrayRef<Attribute> cstOperands,
void AffineDmaStartOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
effects.emplace_back(MemoryEffects::Read::get(), getSrcMemRef(),
effects.emplace_back(MemoryEffects::Read::get(), &getSrcMemRefMutable(),
SideEffects::DefaultResource::get());
effects.emplace_back(MemoryEffects::Write::get(), getDstMemRef(),
effects.emplace_back(MemoryEffects::Write::get(), &getDstMemRefMutable(),
SideEffects::DefaultResource::get());
effects.emplace_back(MemoryEffects::Read::get(), getTagMemRef(),
effects.emplace_back(MemoryEffects::Read::get(), &getTagMemRefMutable(),
SideEffects::DefaultResource::get());
}
@@ -1797,7 +1797,7 @@ LogicalResult AffineDmaWaitOp::fold(ArrayRef<Attribute> cstOperands,
void AffineDmaWaitOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
effects.emplace_back(MemoryEffects::Read::get(), getTagMemRef(),
effects.emplace_back(MemoryEffects::Read::get(), &getTagMemRefMutable(),
SideEffects::DefaultResource::get());
}

View File

@@ -142,9 +142,9 @@ SimplifyBoundedAffineOpsOp::apply(transform::TransformRewriter &rewriter,
void SimplifyBoundedAffineOpsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
for (Value v : getBoundedValues())
onlyReadsHandle(v, effects);
consumesHandle(getTargetMutable(), effects);
for (OpOperand &operand : getBoundedValuesMutable())
onlyReadsHandle(operand, effects);
modifiesPayload(effects);
}

View File

@@ -728,7 +728,7 @@ void MaterializeInDestinationOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
if (isa<BaseMemRefType>(getDest().getType()))
effects.emplace_back(MemoryEffects::Write::get(), getDest(),
effects.emplace_back(MemoryEffects::Write::get(), &getDestMutable(),
SideEffects::DefaultResource::get());
}

View File

@@ -36,7 +36,7 @@ DiagnosedSilenceableFailure transform::BufferLoopHoistingOp::applyToOne(
void transform::BufferLoopHoistingOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getTarget(), effects);
onlyReadsHandle(getTargetMutable(), effects);
modifiesPayload(effects);
}
@@ -110,7 +110,7 @@ transform::OneShotBufferizeOp::apply(transform::TransformRewriter &rewriter,
void transform::EliminateEmptyTensorsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getTarget(), effects);
onlyReadsHandle(getTargetMutable(), effects);
modifiesPayload(effects);
}

View File

@@ -216,14 +216,14 @@ LogicalResult transform::CastAndCallOp::verify() {
void transform::CastAndCallOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getInsertionPoint(), effects);
transform::onlyReadsHandle(getInsertionPointMutable(), effects);
if (getInputs())
transform::onlyReadsHandle(getInputs(), effects);
transform::onlyReadsHandle(getInputsMutable(), effects);
if (getOutputs())
transform::onlyReadsHandle(getOutputs(), effects);
transform::onlyReadsHandle(getOutputsMutable(), effects);
if (getFunction())
transform::onlyReadsHandle(getFunction(), effects);
transform::producesHandle(getResult(), effects);
transform::onlyReadsHandle(getFunctionMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::modifiesPayload(effects);
}

View File

@@ -825,7 +825,7 @@ Type GEPOp::getResultPtrElementType() {
void LoadOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
effects.emplace_back(MemoryEffects::Read::get(), getAddr());
effects.emplace_back(MemoryEffects::Read::get(), &getAddrMutable());
// Volatile operations can have target-specific read-write effects on
// memory besides the one referred to by the pointer operand.
// Similarly, atomic operations that are monotonic or stricter cause
@@ -902,7 +902,7 @@ void LoadOp::build(OpBuilder &builder, OperationState &state, Type type,
void StoreOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
effects.emplace_back(MemoryEffects::Write::get(), getAddr());
effects.emplace_back(MemoryEffects::Write::get(), &getAddrMutable());
// Volatile operations can have target-specific read-write effects on
// memory besides the one referred to by the pointer operand.
// Similarly, atomic operations that are monotonic or stricter cause

View File

@@ -1123,28 +1123,23 @@ static void getGenericEffectsImpl(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects,
LinalgOp linalgOp) {
SmallVector<Value> inputOperands = linalgOp.getDpsInputs();
for (auto [index, operand] : llvm::enumerate(inputOperands)) {
for (auto [index, operand] : llvm::enumerate(linalgOp.getDpsInputs())) {
if (!llvm::isa<MemRefType>(operand.getType()))
continue;
if (linalgOp.payloadUsesValueFromOperand(&linalgOp->getOpOperand(index))) {
effects.emplace_back(MemoryEffects::Read::get(), operand, /*stage=*/0,
/*effectOnFullRegion=*/true,
SideEffects::DefaultResource::get());
}
effects.emplace_back(
MemoryEffects::Read::get(), &linalgOp->getOpOperand(index), /*stage=*/0,
/*effectOnFullRegion=*/true, SideEffects::DefaultResource::get());
}
unsigned inputOperandSize = inputOperands.size();
for (auto [index, operand] : llvm::enumerate(linalgOp.getDpsInits())) {
if (!llvm::isa<MemRefType>(operand.getType()))
for (OpOperand &operand : linalgOp.getDpsInitsMutable()) {
if (!llvm::isa<MemRefType>(operand.get().getType()))
continue;
if (linalgOp.payloadUsesValueFromOperand(
&linalgOp->getOpOperand(index + inputOperandSize))) {
effects.emplace_back(MemoryEffects::Read::get(), operand, /*stage=*/0,
if (linalgOp.payloadUsesValueFromOperand(&operand)) {
effects.emplace_back(MemoryEffects::Read::get(), &operand, /*stage=*/0,
/*effectOnFullRegion=*/true,
SideEffects::DefaultResource::get());
}
effects.emplace_back(MemoryEffects::Write::get(), operand, /*stage=*/0,
effects.emplace_back(MemoryEffects::Write::get(), &operand, /*stage=*/0,
/*effectOnFullRegion=*/true,
SideEffects::DefaultResource::get());
}
@@ -2546,20 +2541,22 @@ SoftmaxOp::reifyResultShapes(OpBuilder &b,
void SoftmaxOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
for (Value operand : getDpsInputs()) {
for (auto [index, operand] : llvm::enumerate(getDpsInputs())) {
if (!llvm::isa<MemRefType>(operand.getType()))
continue;
effects.emplace_back(MemoryEffects::Read::get(), operand, /*stage=*/0,
effects.emplace_back(MemoryEffects::Read::get(),
&getOperation()->getOpOperand(index), /*stage=*/0,
/*effectOnFullRegion=*/true,
SideEffects::DefaultResource::get());
}
for (Value operand : getDpsInits()) {
if (!llvm::isa<MemRefType>(operand.getType()))
for (OpOperand &operand : getDpsInitsMutable()) {
if (!llvm::isa<MemRefType>(operand.get().getType()))
continue;
effects.emplace_back(MemoryEffects::Read::get(), operand, /*stage=*/0,
effects.emplace_back(MemoryEffects::Read::get(), &operand, /*stage=*/0,
/*effectOnFullRegion=*/true,
SideEffects::DefaultResource::get());
effects.emplace_back(MemoryEffects::Write::get(), operand, /*stage=*/0,
effects.emplace_back(MemoryEffects::Write::get(), &operand, /*stage=*/0,
/*effectOnFullRegion=*/true,
SideEffects::DefaultResource::get());
}

View File

@@ -115,9 +115,9 @@ DiagnosedSilenceableFailure transform::MatchStructuredOp::matchOperation(
void transform::MatchStructuredOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getCurrent(), effects);
onlyReadsHandle(getCurrentMutable(), effects);
onlyReadsPayload(effects);
producesHandle(getOutputs(), effects);
producesHandle(getOperation()->getOpResults(), effects);
}
LogicalResult transform::MatchStructuredOp::verify() {
@@ -707,7 +707,7 @@ LogicalResult transform::MatchStructuredResultOp::verify() {
void transform::MatchStructuredYieldOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getHandles(), effects);
onlyReadsHandle(getHandlesMutable(), effects);
onlyReadsPayload(effects);
}

View File

@@ -369,12 +369,11 @@ void transform::BufferizeToAllocationOp::getEffects(
if (getBufferizeDestinationOnly()) {
// The destination is replaced with a newly allocated buffer, but the op
// itself remains in place.
onlyReadsHandle(getTarget(), effects);
onlyReadsHandle(getTargetMutable(), effects);
} else {
consumesHandle(getTarget(), effects);
consumesHandle(getTargetMutable(), effects);
}
producesHandle(getAllocatedBuffer(), effects);
producesHandle(getNewOps(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -463,7 +462,7 @@ DiagnosedSilenceableFailure transform::DecomposeInterfaceOp::applyToOne(
void transform::EliminateLinalgOpAnchoredEmptyTensorsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getTarget(), effects);
onlyReadsHandle(getTargetMutable(), effects);
modifiesPayload(effects);
}
@@ -1040,9 +1039,9 @@ transform::FuseIntoContainingOp::apply(transform::TransformRewriter &rewriter,
void transform::FuseIntoContainingOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getProducerOp(), effects);
onlyReadsHandle(getContainingOp(), effects);
producesHandle(getResults(), effects);
consumesHandle(getProducerOpMutable(), effects);
onlyReadsHandle(getContainingOpMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -1391,8 +1390,8 @@ DiagnosedSilenceableFailure transform::MultiTileSizesOp::applyToOne(
void transform::MultiTileSizesOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getTarget(), effects);
producesHandle(getResults(), effects);
onlyReadsHandle(getTargetMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
if (isa<TransformParamTypeInterface>(getLowSize().getType()))
onlyReadsPayload(effects);
else
@@ -1478,9 +1477,9 @@ transform::PackOp::apply(transform::TransformRewriter &rewriter,
void transform::PackOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getTarget(), effects);
transform::onlyReadsHandle(getPackedSizes(), effects);
transform::producesHandle(getPackedOp(), effects);
transform::consumesHandle(getTargetMutable(), effects);
transform::onlyReadsHandle(getPackedSizesMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::modifiesPayload(effects);
}
@@ -1549,9 +1548,9 @@ SmallVector<OpFoldResult> PackGreedilyOp::getMixedMatmulPackedSizes() {
void transform::PackGreedilyOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getTarget(), effects);
transform::onlyReadsHandle(getMatmulPackedSizes(), effects);
transform::producesHandle(getPackedOp(), effects);
transform::consumesHandle(getTargetMutable(), effects);
transform::onlyReadsHandle(getMatmulPackedSizesMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::modifiesPayload(effects);
}
@@ -1761,11 +1760,9 @@ void transform::PadOp::build(OpBuilder &b, OperationState &result, Value target,
void PadOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
onlyReadsHandle(getPadToMultipleOf(), effects);
producesHandle(getPadded(), effects);
producesHandle(getPad(), effects);
producesHandle(getCopy(), effects);
consumesHandle(getTargetMutable(), effects);
onlyReadsHandle(getPadToMultipleOfMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -1992,9 +1989,9 @@ LogicalResult transform::HoistPadBuildPackingLoopNestOp::verify() {
void transform::HoistPadBuildPackingLoopNestOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getLoop(), effects);
transform::producesHandle(getPackingLoop(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::onlyReadsHandle(getLoopMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::modifiesPayload(effects);
}
@@ -2135,8 +2132,8 @@ transform::ReplaceOp::apply(transform::TransformRewriter &rewriter,
void transform::ReplaceOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
producesHandle(getReplacement(), effects);
consumesHandle(getTargetMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -2361,10 +2358,10 @@ SplitOp::apply(transform::TransformRewriter &rewriter,
void SplitOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
consumesHandle(getTargetMutable(), effects);
if (getDynamicSplitPoint())
onlyReadsHandle(getDynamicSplitPoint(), effects);
producesHandle(getResults(), effects);
onlyReadsHandle(getDynamicSplitPointMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -2831,10 +2828,9 @@ SmallVector<OpFoldResult> transform::TileUsingForOp::getMixedSizes() {
void transform::TileUsingForOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
onlyReadsHandle(getDynamicSizes(), effects);
producesHandle(getTiledLinalgOp(), effects);
producesHandle(getLoops(), effects);
consumesHandle(getTargetMutable(), effects);
onlyReadsHandle(getDynamicSizesMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -2999,12 +2995,12 @@ DiagnosedSilenceableFailure transform::TileUsingForallOp::apply(
void transform::TileUsingForallOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
onlyReadsHandle(getTileSizes(), effects);
onlyReadsHandle(getNumThreads(), effects);
onlyReadsHandle(getPackedNumThreads(), effects);
onlyReadsHandle(getPackedTileSizes(), effects);
producesHandle(getResults(), effects);
consumesHandle(getTargetMutable(), effects);
onlyReadsHandle(getTileSizesMutable(), effects);
onlyReadsHandle(getNumThreadsMutable(), effects);
onlyReadsHandle(getPackedNumThreadsMutable(), effects);
onlyReadsHandle(getPackedTileSizesMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -3182,8 +3178,8 @@ DiagnosedSilenceableFailure transform::VectorizeOp::apply(
void transform::VectorizeOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
onlyReadsHandle(getVectorSizes(), effects);
consumesHandle(getTargetMutable(), effects);
onlyReadsHandle(getVectorSizesMutable(), effects);
modifiesPayload(effects);
}

View File

@@ -181,9 +181,8 @@ transform::MemRefAllocaToGlobalOp::apply(transform::TransformRewriter &rewriter,
void transform::MemRefAllocaToGlobalOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
producesHandle(getGlobal(), effects);
producesHandle(getGetGlobal(), effects);
consumesHandle(getAlloca(), effects);
producesHandle(getOperation()->getOpResults(), effects);
consumesHandle(getAllocaMutable(), effects);
modifiesPayload(effects);
}
@@ -249,7 +248,7 @@ transform::MemRefEraseDeadAllocAndStoresOp::applyToOne(
void transform::MemRefEraseDeadAllocAndStoresOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}
void transform::MemRefEraseDeadAllocAndStoresOp::build(OpBuilder &builder,

View File

@@ -134,8 +134,8 @@ transform::ApplyNVGPUToNVVMConversionPatternsOp::verifyTypeConverter(
void transform::CreateAsyncGroupsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getTarget(), effects);
transform::producesHandle(getResult(), effects);
transform::consumesHandle(getTargetMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::modifiesPayload(effects);
}

View File

@@ -330,7 +330,7 @@ DiagnosedSilenceableFailure transform::LoopPromoteIfOneIterationOp::applyToOne(
void transform::LoopPromoteIfOneIterationOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
consumesHandle(getTargetMutable(), effects);
modifiesPayload(effects);
}
@@ -415,7 +415,7 @@ DiagnosedSilenceableFailure transform::TakeAssumedBranchOp::applyToOne(
void transform::TakeAssumedBranchOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getTarget(), effects);
onlyReadsHandle(getTargetMutable(), effects);
modifiesPayload(effects);
}

View File

@@ -211,8 +211,8 @@ transform::AlternativesOp::apply(transform::TransformRewriter &rewriter,
void transform::AlternativesOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getOperands(), effects);
producesHandle(getResults(), effects);
consumesHandle(getOperation()->getOpOperands(), effects);
producesHandle(getOperation()->getOpResults(), effects);
for (Region *region : getRegions()) {
if (!region->empty())
producesHandle(region->front().getArguments(), effects);
@@ -269,8 +269,8 @@ transform::AnnotateOp::apply(transform::TransformRewriter &rewriter,
void transform::AnnotateOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getTarget(), effects);
onlyReadsHandle(getParam(), effects);
onlyReadsHandle(getTargetMutable(), effects);
onlyReadsHandle(getParamMutable(), effects);
modifiesPayload(effects);
}
@@ -296,7 +296,7 @@ transform::ApplyCommonSubexpressionEliminationOp::applyToOne(
void transform::ApplyCommonSubexpressionEliminationOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}
@@ -361,7 +361,7 @@ DiagnosedSilenceableFailure transform::ApplyDeadCodeEliminationOp::applyToOne(
void transform::ApplyDeadCodeEliminationOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}
@@ -469,7 +469,7 @@ LogicalResult transform::ApplyPatternsOp::verify() {
void transform::ApplyPatternsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}
@@ -674,9 +674,9 @@ LogicalResult transform::ApplyConversionPatternsOp::verify() {
void transform::ApplyConversionPatternsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
if (!getPreserveHandles()) {
transform::consumesHandle(getTarget(), effects);
transform::consumesHandle(getTargetMutable(), effects);
} else {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
}
transform::modifiesPayload(effects);
}
@@ -757,7 +757,7 @@ transform::ApplyLoopInvariantCodeMotionOp::applyToOne(
void transform::ApplyLoopInvariantCodeMotionOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}
@@ -820,8 +820,8 @@ transform::CastOp::applyToOne(transform::TransformRewriter &rewriter,
void transform::CastOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsPayload(effects);
onlyReadsHandle(getInput(), effects);
producesHandle(getOutput(), effects);
onlyReadsHandle(getInputMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
}
bool transform::CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
@@ -964,8 +964,8 @@ transform::CollectMatchingOp::apply(transform::TransformRewriter &rewriter,
void transform::CollectMatchingOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getRoot(), effects);
producesHandle(getResults(), effects);
onlyReadsHandle(getRootMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
onlyReadsPayload(effects);
}
@@ -1159,9 +1159,9 @@ void transform::ForeachMatchOp::getEffects(
return modifiesPayload(effects);
}
consumesHandle(getRoot(), effects);
onlyReadsHandle(getForwardedInputs(), effects);
producesHandle(getResults(), effects);
consumesHandle(getRootMutable(), effects);
onlyReadsHandle(getForwardedInputsMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -1458,7 +1458,7 @@ void transform::ForeachOp::getEffects(
// NB: this `zip` should be `zip_equal` - while this op's verifier catches
// arity errors, this method might get called before/in absence of `verify()`.
for (auto &&[target, blockArg] :
llvm::zip(getTargets(), getBody().front().getArguments())) {
llvm::zip(getTargetsMutable(), getBody().front().getArguments())) {
BlockArgument blockArgument = blockArg;
if (any_of(getBody().front().without_terminator(), [&](Operation &op) {
return isHandleConsumed(blockArgument,
@@ -1480,8 +1480,7 @@ void transform::ForeachOp::getEffects(
onlyReadsPayload(effects);
}
for (Value result : getResults())
producesHandle(result, effects);
producesHandle(getOperation()->getOpResults(), effects);
}
void transform::ForeachOp::getSuccessorRegions(
@@ -1733,8 +1732,8 @@ LogicalResult transform::GetResultOp::verify() {
void transform::GetTypeOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getValue(), effects);
producesHandle(getResult(), effects);
onlyReadsHandle(getValueMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
onlyReadsPayload(effects);
}
@@ -1833,12 +1832,14 @@ void transform::IncludeOp::getEffects(
modifiesPayload(effects);
// Results are always produced.
producesHandle(getResults(), effects);
producesHandle(getOperation()->getOpResults(), effects);
// Adds default effects to operands and results. This will be added if
// preconditions fail so the trait verifier doesn't complain about missing
// effects and the real precondition failure is reported later on.
auto defaultEffects = [&] { onlyReadsHandle(getOperands(), effects); };
auto defaultEffects = [&] {
onlyReadsHandle(getOperation()->getOpOperands(), effects);
};
// Bail if the callee is unknown. This may run as part of the verification
// process before we verified the validity of the callee or of this op.
@@ -1859,9 +1860,9 @@ void transform::IncludeOp::getEffects(
for (unsigned i = 0, e = getNumOperands(); i < e; ++i) {
if (callee.getArgAttr(i, TransformDialect::kArgConsumedAttrName))
consumesHandle(getOperand(i), effects);
consumesHandle(getOperation()->getOpOperand(i), effects);
else
onlyReadsHandle(getOperand(i), effects);
onlyReadsHandle(getOperation()->getOpOperand(i), effects);
}
}
@@ -2022,8 +2023,8 @@ transform::MatchParamCmpIOp::apply(transform::TransformRewriter &rewriter,
void transform::MatchParamCmpIOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getParam(), effects);
onlyReadsHandle(getReference(), effects);
onlyReadsHandle(getParamMutable(), effects);
onlyReadsHandle(getReferenceMutable(), effects);
}
//===----------------------------------------------------------------------===//
@@ -2098,8 +2099,8 @@ bool transform::MergeHandlesOp::allowsRepeatedHandleOperands() {
void transform::MergeHandlesOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getHandles(), effects);
producesHandle(getResult(), effects);
onlyReadsHandle(getHandlesMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
// There are no effects on the Payload IR as this is only a handle
// manipulation.
@@ -2440,8 +2441,8 @@ transform::SplitHandleOp::apply(transform::TransformRewriter &rewriter,
void transform::SplitHandleOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getHandle(), effects);
producesHandle(getResults(), effects);
onlyReadsHandle(getHandleMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
// There are no effects on the Payload IR as this is only a handle
// manipulation.
}
@@ -2489,9 +2490,9 @@ transform::ReplicateOp::apply(transform::TransformRewriter &rewriter,
void transform::ReplicateOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getPattern(), effects);
onlyReadsHandle(getHandles(), effects);
producesHandle(getReplicated(), effects);
onlyReadsHandle(getPatternMutable(), effects);
onlyReadsHandle(getHandlesMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
}
//===----------------------------------------------------------------------===//
@@ -2802,7 +2803,7 @@ void transform::PrintOp::getEffects(
// unconditionally casts to a specific type before verification could run
// here.
if (!getTargetMutable().empty())
onlyReadsHandle(getTargetMutable()[0].get(), effects);
onlyReadsHandle(getTargetMutable()[0], effects);
onlyReadsPayload(effects);
// There is no resource for stderr file descriptor, so just declare print
@@ -2830,7 +2831,7 @@ transform::VerifyOp::applyToOne(transform::TransformRewriter &rewriter,
void transform::VerifyOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
}
//===----------------------------------------------------------------------===//
@@ -2839,5 +2840,5 @@ void transform::VerifyOp::getEffects(
void transform::YieldOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getOperands(), effects);
onlyReadsHandle(getOperandsMutable(), effects);
}

View File

@@ -50,8 +50,8 @@ IRDLCollectMatchingOp::apply(TransformRewriter &rewriter,
void IRDLCollectMatchingOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getRoot(), effects);
producesHandle(getMatched(), effects);
onlyReadsHandle(getRootMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
onlyReadsPayload(effects);
}

View File

@@ -1603,7 +1603,8 @@ transform::detail::makeTransformStateForTesting(Region *region,
/// Appends to `effects` the memory effect instances on `target` with the same
/// resource and effect as the ones the operation `iface` having on `source`.
static void
remapEffects(MemoryEffectOpInterface iface, BlockArgument source, Value target,
remapEffects(MemoryEffectOpInterface iface, BlockArgument source,
OpOperand *target,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
SmallVector<MemoryEffects::EffectInstance> nestedEffects;
iface.getEffectsOnValue(source, nestedEffects);
@@ -1614,7 +1615,7 @@ remapEffects(MemoryEffectOpInterface iface, BlockArgument source, Value target,
/// Appends to `effects` the same effects as the operations of `block` have on
/// block arguments but associated with `operands.`
static void
remapArgumentEffects(Block &block, ValueRange operands,
remapArgumentEffects(Block &block, MutableArrayRef<OpOperand> operands,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
for (Operation &op : block) {
auto iface = dyn_cast<MemoryEffectOpInterface>(&op);
@@ -1622,7 +1623,7 @@ remapArgumentEffects(Block &block, ValueRange operands,
continue;
for (auto &&[source, target] : llvm::zip(block.getArguments(), operands)) {
remapEffects(iface, source, target, effects);
remapEffects(iface, source, &target, effects);
}
SmallVector<MemoryEffects::EffectInstance> nestedEffects;
@@ -1635,8 +1636,8 @@ remapArgumentEffects(Block &block, ValueRange operands,
void transform::detail::getPotentialTopLevelEffects(
Operation *operation, Value root, Block &body,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(operation->getOperands(), effects);
transform::producesHandle(operation->getResults(), effects);
transform::onlyReadsHandle(operation->getOpOperands(), effects);
transform::producesHandle(operation->getOpResults(), effects);
if (!root) {
for (Operation &op : body) {
@@ -1652,7 +1653,7 @@ void transform::detail::getPotentialTopLevelEffects(
// Carry over all effects on arguments of the entry block as those on the
// operands, this is the same value just remapped.
remapArgumentEffects(body, operation->getOperands(), effects);
remapArgumentEffects(body, operation->getOpOperands(), effects);
}
LogicalResult transform::detail::mapPossibleTopLevelTransformOpBlockArguments(
@@ -1761,10 +1762,10 @@ void transform::detail::getParamProducerTransformOpTraitEffects(
Operation *op, SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
producesHandle(op->getResults(), effects);
bool hasPayloadOperands = false;
for (Value operand : op->getOperands()) {
for (OpOperand &operand : op->getOpOperands()) {
onlyReadsHandle(operand, effects);
if (llvm::isa<TransformHandleTypeInterface,
TransformValueHandleTypeInterface>(operand.getType()))
TransformValueHandleTypeInterface>(operand.get().getType()))
hasPayloadOperands = true;
}
if (hasPayloadOperands)
@@ -1796,12 +1797,12 @@ transform::detail::verifyParamProducerTransformOpTrait(Operation *op) {
//===----------------------------------------------------------------------===//
void transform::consumesHandle(
ValueRange handles,
MutableArrayRef<OpOperand> handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
for (Value handle : handles) {
effects.emplace_back(MemoryEffects::Read::get(), handle,
for (OpOperand &handle : handles) {
effects.emplace_back(MemoryEffects::Read::get(), &handle,
TransformMappingResource::get());
effects.emplace_back(MemoryEffects::Free::get(), handle,
effects.emplace_back(MemoryEffects::Free::get(), &handle,
TransformMappingResource::get());
}
}
@@ -1826,9 +1827,20 @@ bool transform::isHandleConsumed(Value handle,
}
void transform::producesHandle(
ValueRange handles,
ResultRange handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
for (Value handle : handles) {
for (OpResult handle : handles) {
effects.emplace_back(MemoryEffects::Allocate::get(), handle,
TransformMappingResource::get());
effects.emplace_back(MemoryEffects::Write::get(), handle,
TransformMappingResource::get());
}
}
void transform::producesHandle(
MutableArrayRef<BlockArgument> handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
for (BlockArgument handle : handles) {
effects.emplace_back(MemoryEffects::Allocate::get(), handle,
TransformMappingResource::get());
effects.emplace_back(MemoryEffects::Write::get(), handle,
@@ -1837,10 +1849,10 @@ void transform::producesHandle(
}
void transform::onlyReadsHandle(
ValueRange handles,
MutableArrayRef<OpOperand> handles,
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
for (Value handle : handles) {
effects.emplace_back(MemoryEffects::Read::get(), handle,
for (OpOperand &handle : handles) {
effects.emplace_back(MemoryEffects::Read::get(), &handle,
TransformMappingResource::get());
}
}

View File

@@ -31,6 +31,6 @@ DiagnosedSilenceableFailure transform::HoistLoopInvariantSubsetsOp::applyToOne(
void transform::HoistLoopInvariantSubsetsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}

View File

@@ -158,8 +158,8 @@ transform::PDLMatchOp::apply(transform::TransformRewriter &rewriter,
void transform::PDLMatchOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
onlyReadsHandle(getRoot(), effects);
producesHandle(getMatched(), effects);
onlyReadsHandle(getRootMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
onlyReadsPayload(effects);
}

View File

@@ -4232,7 +4232,7 @@ void TransferReadOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
if (llvm::isa<MemRefType>(getShapedType()))
effects.emplace_back(MemoryEffects::Read::get(), getSource(),
effects.emplace_back(MemoryEffects::Read::get(), &getSourceMutable(),
SideEffects::DefaultResource::get());
}
@@ -4606,7 +4606,7 @@ void TransferWriteOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
if (llvm::isa<MemRefType>(getShapedType()))
effects.emplace_back(MemoryEffects::Write::get(), getSource(),
effects.emplace_back(MemoryEffects::Write::get(), &getSourceMutable(),
SideEffects::DefaultResource::get());
}

View File

@@ -103,6 +103,28 @@ static bool wouldOpBeTriviallyDeadImpl(Operation *rootOp) {
return true;
}
template <typename EffectTy>
bool mlir::hasSingleEffect(Operation *op) {
auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
if (!memOp)
return false;
SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4> effects;
memOp.getEffects(effects);
bool hasSingleEffectOnVal = false;
// Iterate through `effects` and check if an effect of type `EffectTy` and
// only of that type is present.
for (auto &effect : effects) {
hasSingleEffectOnVal = isa<EffectTy>(effect.getEffect());
if (!hasSingleEffectOnVal)
return false;
}
return hasSingleEffectOnVal;
}
template bool mlir::hasSingleEffect<MemoryEffects::Allocate>(Operation *);
template bool mlir::hasSingleEffect<MemoryEffects::Free>(Operation *);
template bool mlir::hasSingleEffect<MemoryEffects::Read>(Operation *);
template bool mlir::hasSingleEffect<MemoryEffects::Write>(Operation *);
template <typename EffectTy>
bool mlir::hasSingleEffect(Operation *op, Value value) {
auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
@@ -112,10 +134,9 @@ bool mlir::hasSingleEffect(Operation *op, Value value) {
memOp.getEffects(effects);
bool hasSingleEffectOnVal = false;
// Iterate through `effects` and check if an effect of type `EffectTy` and
// only of that type is present. A `value` to check the effect on may or may
// not have been provided.
// only of that type is present.
for (auto &effect : effects) {
if (value && effect.getValue() != value)
if (effect.getValue() != value)
continue;
hasSingleEffectOnVal = isa<EffectTy>(effect.getEffect());
if (!hasSingleEffectOnVal)
@@ -125,10 +146,84 @@ bool mlir::hasSingleEffect(Operation *op, Value value) {
}
template bool mlir::hasSingleEffect<MemoryEffects::Allocate>(Operation *,
Value);
template bool mlir::hasSingleEffect<MemoryEffects::Free>(Operation *, Value);
template bool mlir::hasSingleEffect<MemoryEffects::Read>(Operation *, Value);
template bool mlir::hasSingleEffect<MemoryEffects::Write>(Operation *, Value);
Value value);
template bool mlir::hasSingleEffect<MemoryEffects::Free>(Operation *,
Value value);
template bool mlir::hasSingleEffect<MemoryEffects::Read>(Operation *,
Value value);
template bool mlir::hasSingleEffect<MemoryEffects::Write>(Operation *,
Value value);
template <typename ValueTy, typename EffectTy>
bool mlir::hasSingleEffect(Operation *op, ValueTy value) {
auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
if (!memOp)
return false;
SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4> effects;
memOp.getEffects(effects);
bool hasSingleEffectOnVal = false;
// Iterate through `effects` and check if an effect of type `EffectTy` and
// only of that type is present on value.
for (auto &effect : effects) {
if (effect.getEffectValue<ValueTy>() != value)
continue;
hasSingleEffectOnVal = isa<EffectTy>(effect.getEffect());
if (!hasSingleEffectOnVal)
return false;
}
return hasSingleEffectOnVal;
}
template bool
mlir::hasSingleEffect<OpOperand *, MemoryEffects::Allocate>(Operation *,
OpOperand *);
template bool
mlir::hasSingleEffect<OpOperand *, MemoryEffects::Free>(Operation *,
OpOperand *);
template bool
mlir::hasSingleEffect<OpOperand *, MemoryEffects::Read>(Operation *,
OpOperand *);
template bool
mlir::hasSingleEffect<OpOperand *, MemoryEffects::Write>(Operation *,
OpOperand *);
template bool
mlir::hasSingleEffect<OpResult, MemoryEffects::Allocate>(Operation *, OpResult);
template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Free>(Operation *,
OpResult);
template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Read>(Operation *,
OpResult);
template bool mlir::hasSingleEffect<OpResult, MemoryEffects::Write>(Operation *,
OpResult);
template bool
mlir::hasSingleEffect<BlockArgument, MemoryEffects::Allocate>(Operation *,
BlockArgument);
template bool
mlir::hasSingleEffect<BlockArgument, MemoryEffects::Free>(Operation *,
BlockArgument);
template bool
mlir::hasSingleEffect<BlockArgument, MemoryEffects::Read>(Operation *,
BlockArgument);
template bool
mlir::hasSingleEffect<BlockArgument, MemoryEffects::Write>(Operation *,
BlockArgument);
template <typename... EffectTys>
bool mlir::hasEffect(Operation *op) {
auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
if (!memOp)
return false;
SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4> effects;
memOp.getEffects(effects);
return llvm::any_of(effects, [&](MemoryEffects::EffectInstance &effect) {
return isa<EffectTys...>(effect.getEffect());
});
}
template bool mlir::hasEffect<MemoryEffects::Allocate>(Operation *);
template bool mlir::hasEffect<MemoryEffects::Free>(Operation *);
template bool mlir::hasEffect<MemoryEffects::Read>(Operation *);
template bool mlir::hasEffect<MemoryEffects::Write>(Operation *);
template bool
mlir::hasEffect<MemoryEffects::Write, MemoryEffects::Free>(Operation *);
template <typename... EffectTys>
bool mlir::hasEffect(Operation *op, Value value) {
@@ -138,17 +233,70 @@ bool mlir::hasEffect(Operation *op, Value value) {
SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4> effects;
memOp.getEffects(effects);
return llvm::any_of(effects, [&](MemoryEffects::EffectInstance &effect) {
if (value && effect.getValue() != value)
if (effect.getValue() != value)
return false;
return isa<EffectTys...>(effect.getEffect());
});
}
template bool mlir::hasEffect<MemoryEffects::Allocate>(Operation *, Value);
template bool mlir::hasEffect<MemoryEffects::Free>(Operation *, Value);
template bool mlir::hasEffect<MemoryEffects::Read>(Operation *, Value);
template bool mlir::hasEffect<MemoryEffects::Write>(Operation *, Value);
template bool mlir::hasEffect<MemoryEffects::Allocate>(Operation *,
Value value);
template bool mlir::hasEffect<MemoryEffects::Free>(Operation *, Value value);
template bool mlir::hasEffect<MemoryEffects::Read>(Operation *, Value value);
template bool mlir::hasEffect<MemoryEffects::Write>(Operation *, Value value);
template bool
mlir::hasEffect<MemoryEffects::Write, MemoryEffects::Free>(Operation *, Value);
mlir::hasEffect<MemoryEffects::Write, MemoryEffects::Free>(Operation *,
Value value);
template <typename ValueTy, typename... EffectTys>
bool mlir::hasEffect(Operation *op, ValueTy value) {
auto memOp = dyn_cast<MemoryEffectOpInterface>(op);
if (!memOp)
return false;
SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4> effects;
memOp.getEffects(effects);
return llvm::any_of(effects, [&](MemoryEffects::EffectInstance &effect) {
if (effect.getEffectValue<ValueTy>() != value)
return false;
return isa<EffectTys...>(effect.getEffect());
});
}
template bool
mlir::hasEffect<OpOperand *, MemoryEffects::Allocate>(Operation *, OpOperand *);
template bool mlir::hasEffect<OpOperand *, MemoryEffects::Free>(Operation *,
OpOperand *);
template bool mlir::hasEffect<OpOperand *, MemoryEffects::Read>(Operation *,
OpOperand *);
template bool mlir::hasEffect<OpOperand *, MemoryEffects::Write>(Operation *,
OpOperand *);
template bool
mlir::hasEffect<OpOperand *, MemoryEffects::Write, MemoryEffects::Free>(
Operation *, OpOperand *);
template bool mlir::hasEffect<OpResult, MemoryEffects::Allocate>(Operation *,
OpResult);
template bool mlir::hasEffect<OpResult, MemoryEffects::Free>(Operation *,
OpResult);
template bool mlir::hasEffect<OpResult, MemoryEffects::Read>(Operation *,
OpResult);
template bool mlir::hasEffect<OpResult, MemoryEffects::Write>(Operation *,
OpResult);
template bool
mlir::hasEffect<OpResult, MemoryEffects::Write, MemoryEffects::Free>(
Operation *, OpResult);
template bool
mlir::hasEffect<BlockArgument, MemoryEffects::Allocate>(Operation *,
BlockArgument);
template bool
mlir::hasEffect<BlockArgument, MemoryEffects::Free>(Operation *, BlockArgument);
template bool
mlir::hasEffect<BlockArgument, MemoryEffects::Read>(Operation *, BlockArgument);
template bool
mlir::hasEffect<BlockArgument, MemoryEffects::Write>(Operation *,
BlockArgument);
template bool
mlir::hasEffect<BlockArgument, MemoryEffects::Write, MemoryEffects::Free>(
Operation *, BlockArgument);
bool mlir::wouldOpBeTriviallyDead(Operation *op) {
if (op->mightHaveTrait<OpTrait::IsTerminator>())

View File

@@ -1,10 +1,9 @@
// RUN: mlir-opt %s --test-side-effects --verify-diagnostics
func.func @test_side_effects(%arg0: memref<2xi32>) -> memref<2xi32> {
// expected-remark @below {{found an instance of 'read' on a value, on resource '<Default>'}}
// expected-remark @below {{found an instance of 'write' on a value, on resource '<Default>'}}
// expected-remark @below {{found an instance of 'allocate' on a value, on resource '<Default>'}}
// expected-remark @below {{found an instance of 'read' on a op operand, on resource '<Default>'}}
// expected-remark @below {{found an instance of 'write' on a op result, on resource '<Default>'}}
// expected-remark @below {{found an instance of 'allocate' on a op result, on resource '<Default>'}}
%0 = bufferization.clone %arg0 : memref<2xi32> to memref<2xi32>
// expected-remark @below {{operation has no memory effects}}
return %0 : memref<2xi32>
}

View File

@@ -1,38 +1,60 @@
// RUN: mlir-opt %s -test-side-effects -verify-diagnostics
// expected-remark@+1 {{operation has no memory effects}}
%0 = "test.side_effect_op"() {} : () -> i32
func.func @side_effect(%arg : index) {
// expected-remark@+1 {{operation has no memory effects}}
%0 = "test.side_effect_op"() {} : () -> i32
// expected-remark@+2 {{found an instance of 'read' on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'free' on resource '<Default>'}}
%1 = "test.side_effect_op"() {effects = [
{effect="read"}, {effect="free"}
]} : () -> i32
// expected-remark@+1 {{found an instance of 'write' on resource '<Test>'}}
%2 = "test.side_effect_op"() {effects = [
{effect="write", test_resource}
]} : () -> i32
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Test>'}}
%3 = "test.side_effect_op"() {effects = [
{effect="allocate", on_result, test_resource}
]} : () -> i32
// expected-remark@+1 {{found an instance of 'read' on a symbol '@foo_ref', on resource '<Test>'}}
"test.side_effect_op"() {effects = [
{effect="read", on_reference = @foo_ref, test_resource}
]} : () -> i32
// No _memory_ effects, but a parametric test effect.
// expected-remark@+2 {{operation has no memory effects}}
// expected-remark@+1 {{found a parametric effect with affine_map<(d0, d1) -> (d1, d0)>}}
%4 = "test.side_effect_op"() {
effect_parameter = affine_map<(i, j) -> (j, i)>
} : () -> i32
// Check with this unregistered operation to test the fallback on the dialect.
// expected-remark@+1 {{found a parametric effect with affine_map<(d0, d1) -> (d1, d0)>}}
%5 = "test.unregistered_side_effect_op"() {
effect_parameter = affine_map<(i, j) -> (j, i)>
} : () -> i32
// expected-remark@+2 {{found an instance of 'read' on resource '<Default>'}}
// expected-remark@+1 {{found an instance of 'free' on resource '<Default>'}}
%1 = "test.side_effect_op"() {effects = [
{effect="read"}, {effect="free"}
]} : () -> i32
// expected-remark@+1 {{found an instance of 'allocate' on a op operand, on resource '<Test>'}}
%6 = test.side_effect_with_region_op (%arg) {
^bb0(%arg0 : index):
test.region_yield %arg0 : index
} {effects = [ {effect="allocate", on_operand, test_resource} ]} : index -> index
// expected-remark@+1 {{found an instance of 'write' on resource '<Test>'}}
%2 = "test.side_effect_op"() {effects = [
{effect="write", test_resource}
]} : () -> i32
// expected-remark@+1 {{found an instance of 'allocate' on a op result, on resource '<Test>'}}
%7 = test.side_effect_with_region_op (%arg) {
^bb0(%arg0 : index):
test.region_yield %arg0 : index
} {effects = [ {effect="allocate", on_result, test_resource} ]} : index -> index
// expected-remark@+1 {{found an instance of 'allocate' on a value, on resource '<Test>'}}
%3 = "test.side_effect_op"() {effects = [
{effect="allocate", on_result, test_resource}
]} : () -> i32
// expected-remark@+1 {{found an instance of 'allocate' on a block argument, on resource '<Test>'}}
%8 = test.side_effect_with_region_op (%arg) {
^bb0(%arg0 : index):
test.region_yield %arg0 : index
} {effects = [ {effect="allocate", on_argument, test_resource} ]} : index -> index
// expected-remark@+1 {{found an instance of 'read' on a symbol '@foo_ref', on resource '<Test>'}}
"test.side_effect_op"() {effects = [
{effect="read", on_reference = @foo_ref, test_resource}
]} : () -> i32
// No _memory_ effects, but a parametric test effect.
// expected-remark@+2 {{operation has no memory effects}}
// expected-remark@+1 {{found a parametric effect with affine_map<(d0, d1) -> (d1, d0)>}}
%4 = "test.side_effect_op"() {
effect_parameter = affine_map<(i, j) -> (j, i)>
} : () -> i32
// Check with this unregistered operation to test the fallback on the dialect.
// expected-remark@+1 {{found a parametric effect with affine_map<(d0, d1) -> (d1, d0)>}}
%5 = "test.unregistered_side_effect_op"() {
effect_parameter = affine_map<(i, j) -> (j, i)>
} : () -> i32
func.return
}

View File

@@ -329,8 +329,6 @@ void SideEffectOp::getEffects(
if (!effectsAttr)
return;
// If there is one, it is an array of dictionary attributes that hold
// information on the effects of this operation.
for (Attribute element : effectsAttr) {
DictionaryAttr effectElement = cast<DictionaryAttr>(element);
@@ -350,7 +348,7 @@ void SideEffectOp::getEffects(
// Check for a result to affect.
if (effectElement.get("on_result"))
effects.emplace_back(effect, getResult(), resource);
effects.emplace_back(effect, getOperation()->getOpResults()[0], resource);
else if (Attribute ref = effectElement.get("on_reference"))
effects.emplace_back(effect, cast<SymbolRefAttr>(ref), resource);
else
@@ -363,6 +361,51 @@ void SideEffectOp::getEffects(
testSideEffectOpGetEffect(getOperation(), effects);
}
void SideEffectWithRegionOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
// Check for an effects attribute on the op instance.
ArrayAttr effectsAttr = (*this)->getAttrOfType<ArrayAttr>("effects");
if (!effectsAttr)
return;
for (Attribute element : effectsAttr) {
DictionaryAttr effectElement = cast<DictionaryAttr>(element);
// Get the specific memory effect.
MemoryEffects::Effect *effect =
StringSwitch<MemoryEffects::Effect *>(
cast<StringAttr>(effectElement.get("effect")).getValue())
.Case("allocate", MemoryEffects::Allocate::get())
.Case("free", MemoryEffects::Free::get())
.Case("read", MemoryEffects::Read::get())
.Case("write", MemoryEffects::Write::get());
// Check for a non-default resource to use.
SideEffects::Resource *resource = SideEffects::DefaultResource::get();
if (effectElement.get("test_resource"))
resource = TestResource::get();
// Check for a result to affect.
if (effectElement.get("on_result"))
effects.emplace_back(effect, getOperation()->getOpResults()[0], resource);
else if (effectElement.get("on_operand"))
effects.emplace_back(effect, &getOperation()->getOpOperands()[0],
resource);
else if (effectElement.get("on_argument"))
effects.emplace_back(effect, getOperation()->getRegion(0).getArgument(0),
resource);
else if (Attribute ref = effectElement.get("on_reference"))
effects.emplace_back(effect, cast<SymbolRefAttr>(ref), resource);
else
effects.emplace_back(effect, resource);
}
}
void SideEffectWithRegionOp::getEffects(
SmallVectorImpl<TestEffects::EffectInstance> &effects) {
testSideEffectOpGetEffect(getOperation(), effects);
}
//===----------------------------------------------------------------------===//
// StringAttrPrettyNameOp
//===----------------------------------------------------------------------===//
@@ -1027,7 +1070,7 @@ void ReadBufferOp::getEffects(
SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
&effects) {
// The buffer operand is read.
effects.emplace_back(MemoryEffects::Read::get(), getBuffer(),
effects.emplace_back(MemoryEffects::Read::get(), &getBufferMutable(),
SideEffects::DefaultResource::get());
// The buffer contents are dumped.
effects.emplace_back(MemoryEffects::Write::get(),

View File

@@ -2105,6 +2105,17 @@ def SideEffectOp : TEST_Op<"side_effect_op",
let results = (outs AnyType:$result);
}
def SideEffectWithRegionOp : TEST_Op<"side_effect_with_region_op",
[DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
DeclareOpInterfaceMethods<TestEffectOpInterface>]> {
let arguments = (ins AnyType:$operand);
let results = (outs AnyType:$result);
let regions = (region AnyRegion:$region);
let assemblyFormat = [{
`(` $operand`)` $region attr-dict `:` type($operand) `->` type($result)
}];
}
//===----------------------------------------------------------------------===//
// Test CopyOpInterface
//===----------------------------------------------------------------------===//

View File

@@ -128,8 +128,8 @@ mlir::test::TestProduceSelfHandleOrForwardOperandOp::apply(
void mlir::test::TestProduceSelfHandleOrForwardOperandOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
if (getOperand())
transform::onlyReadsHandle(getOperand(), effects);
transform::producesHandle(getRes(), effects);
transform::onlyReadsHandle(getOperandMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
}
DiagnosedSilenceableFailure
@@ -142,8 +142,8 @@ mlir::test::TestProduceValueHandleToSelfOperand::apply(
void mlir::test::TestProduceValueHandleToSelfOperand::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getIn(), effects);
transform::producesHandle(getOut(), effects);
transform::onlyReadsHandle(getInMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::onlyReadsPayload(effects);
}
@@ -160,8 +160,8 @@ mlir::test::TestProduceValueHandleToResult::applyToOne(
void mlir::test::TestProduceValueHandleToResult::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getIn(), effects);
transform::producesHandle(getOut(), effects);
transform::onlyReadsHandle(getInMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::onlyReadsPayload(effects);
}
@@ -181,8 +181,8 @@ mlir::test::TestProduceValueHandleToArgumentOfParentBlock::applyToOne(
void mlir::test::TestProduceValueHandleToArgumentOfParentBlock::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getIn(), effects);
transform::producesHandle(getOut(), effects);
transform::onlyReadsHandle(getInMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::onlyReadsPayload(effects);
}
@@ -199,9 +199,9 @@ mlir::test::TestConsumeOperand::apply(transform::TransformRewriter &rewriter,
void mlir::test::TestConsumeOperand::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getOperand(), effects);
transform::consumesHandle(getOperation()->getOpOperands(), effects);
if (getSecondOperand())
transform::consumesHandle(getSecondOperand(), effects);
transform::consumesHandle(getSecondOperandMutable(), effects);
transform::modifiesPayload(effects);
}
@@ -223,7 +223,7 @@ DiagnosedSilenceableFailure mlir::test::TestConsumeOperandOfOpKindOrFail::apply(
void mlir::test::TestConsumeOperandOfOpKindOrFail::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getOperand(), effects);
transform::consumesHandle(getOperation()->getOpOperands(), effects);
transform::modifiesPayload(effects);
}
@@ -242,7 +242,7 @@ mlir::test::TestSucceedIfOperandOfOpKind::matchOperation(
void mlir::test::TestSucceedIfOperandOfOpKind::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getOperand(), effects);
transform::onlyReadsHandle(getOperation()->getOpOperands(), effects);
transform::onlyReadsPayload(effects);
}
@@ -281,7 +281,7 @@ mlir::test::TestCheckIfTestExtensionPresentOp::apply(
void mlir::test::TestCheckIfTestExtensionPresentOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getOperand(), effects);
transform::onlyReadsHandle(getOperation()->getOpOperands(), effects);
transform::onlyReadsPayload(effects);
}
@@ -302,8 +302,8 @@ DiagnosedSilenceableFailure mlir::test::TestRemapOperandPayloadToSelfOp::apply(
void mlir::test::TestRemapOperandPayloadToSelfOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getOperand(), effects);
transform::producesHandle(getOut(), effects);
transform::onlyReadsHandle(getOperation()->getOpOperands(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::onlyReadsPayload(effects);
}
@@ -356,7 +356,7 @@ DiagnosedSilenceableFailure mlir::test::TestEmitRemarkAndEraseOperandOp::apply(
void mlir::test::TestEmitRemarkAndEraseOperandOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getTarget(), effects);
transform::consumesHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}
@@ -425,8 +425,8 @@ mlir::test::TestCopyPayloadOp::apply(transform::TransformRewriter &rewriter,
void mlir::test::TestCopyPayloadOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getHandle(), effects);
transform::producesHandle(getCopy(), effects);
transform::onlyReadsHandle(getHandleMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
transform::onlyReadsPayload(effects);
}
@@ -460,7 +460,7 @@ DiagnosedSilenceableFailure mlir::transform::TestDialectParamType::checkPayload(
void mlir::test::TestReportNumberOfTrackedHandlesNestedUnder::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
}
DiagnosedSilenceableFailure
@@ -530,9 +530,8 @@ mlir::test::TestProduceParamOp::apply(transform::TransformRewriter &rewriter,
void mlir::test::TestProduceTransformParamOrForwardOperandOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getIn(), effects);
transform::producesHandle(getOut(), effects);
transform::producesHandle(getParam(), effects);
transform::onlyReadsHandle(getInMutable(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
}
DiagnosedSilenceableFailure
@@ -560,7 +559,7 @@ mlir::test::TestProduceTransformParamOrForwardOperandOp::applyToOne(
void mlir::test::TestProduceNullPayloadOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::producesHandle(getOut(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
}
DiagnosedSilenceableFailure mlir::test::TestProduceNullPayloadOp::apply(
@@ -580,7 +579,7 @@ DiagnosedSilenceableFailure mlir::test::TestProduceEmptyPayloadOp::apply(
void mlir::test::TestProduceNullParamOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::producesHandle(getOut(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
}
DiagnosedSilenceableFailure mlir::test::TestProduceNullParamOp::apply(
@@ -592,7 +591,7 @@ DiagnosedSilenceableFailure mlir::test::TestProduceNullParamOp::apply(
void mlir::test::TestProduceNullValueOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::producesHandle(getOut(), effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
}
DiagnosedSilenceableFailure mlir::test::TestProduceNullValueOp::apply(
@@ -605,12 +604,15 @@ DiagnosedSilenceableFailure mlir::test::TestProduceNullValueOp::apply(
void mlir::test::TestRequiredMemoryEffectsOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
if (getHasOperandEffect())
transform::consumesHandle(getIn(), effects);
transform::consumesHandle(getInMutable(), effects);
if (getHasResultEffect())
transform::producesHandle(getOut(), effects);
else
transform::onlyReadsHandle(getOut(), effects);
if (getHasResultEffect()) {
transform::producesHandle(getOperation()->getOpResults(), effects);
} else {
effects.emplace_back(MemoryEffects::Read::get(),
llvm::cast<OpResult>(getOut()),
transform::TransformMappingResource::get());
}
if (getModifiesPayload())
transform::modifiesPayload(effects);
@@ -625,14 +627,13 @@ DiagnosedSilenceableFailure mlir::test::TestRequiredMemoryEffectsOp::apply(
void mlir::test::TestTrackedRewriteOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getIn(), effects);
transform::onlyReadsHandle(getInMutable(), effects);
transform::modifiesPayload(effects);
}
void mlir::test::TestDummyPayloadOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
for (OpResult result : getResults())
transform::producesHandle(result, effects);
transform::producesHandle(getOperation()->getOpResults(), effects);
}
LogicalResult mlir::test::TestDummyPayloadOp::verify() {
@@ -719,7 +720,7 @@ void mlir::test::ApplyTestPatternsOp::populatePatterns(
void mlir::test::TestReEnterRegionOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::consumesHandle(getOperands(), effects);
transform::consumesHandle(getOperation()->getOpOperands(), effects);
transform::modifiesPayload(effects);
}
@@ -782,8 +783,8 @@ DiagnosedSilenceableFailure mlir::test::TestNotifyPayloadOpReplacedOp::apply(
void mlir::test::TestNotifyPayloadOpReplacedOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getOriginal(), effects);
transform::onlyReadsHandle(getReplacement(), effects);
transform::onlyReadsHandle(getOriginalMutable(), effects);
transform::onlyReadsHandle(getReplacementMutable(), effects);
}
DiagnosedSilenceableFailure mlir::test::TestProduceInvalidIR::applyToOne(
@@ -799,7 +800,7 @@ DiagnosedSilenceableFailure mlir::test::TestProduceInvalidIR::applyToOne(
void mlir::test::TestProduceInvalidIR::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
transform::onlyReadsHandle(getTarget(), effects);
transform::onlyReadsHandle(getTargetMutable(), effects);
transform::modifiesPayload(effects);
}

View File

@@ -29,6 +29,10 @@ struct SideEffectsPass
effects.clear();
op.getEffects(effects);
if (op->hasTrait<OpTrait::IsTerminator>()) {
return;
}
// Check to see if this operation has any memory effects.
if (effects.empty()) {
op.emitRemark() << "operation has no memory effects";
@@ -47,9 +51,14 @@ struct SideEffectsPass
else if (isa<MemoryEffects::Write>(instance.getEffect()))
diag << "'write'";
if (instance.getValue())
diag << " on a value,";
else if (SymbolRefAttr symbolRef = instance.getSymbolRef())
if (instance.getValue()) {
if (instance.getEffectValue<OpOperand *>())
diag << " on a op operand,";
else if (instance.getEffectValue<OpResult>())
diag << " on a op result,";
else if (instance.getEffectValue<BlockArgument>())
diag << " on a block argument,";
} else if (SymbolRefAttr symbolRef = instance.getSymbolRef())
diag << " on a symbol '" << symbolRef << "',";
diag << " on resource '" << instance.getResource()->getName() << "'";

View File

@@ -207,9 +207,8 @@ transform::TestFuseConsumerOp::apply(TransformRewriter &rewriter,
void transform::TestFuseConsumerOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
producesHandle(getConsumer(), effects);
producesHandle(getFusedConsumer(), effects);
consumesHandle(getTargetMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -285,9 +284,8 @@ transform::TestTileUsingForallOp::apply(TransformRewriter &rewriter,
void transform::TestTileUsingForallOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getTarget(), effects);
producesHandle(getTiledOp(), effects);
producesHandle(getLoops(), effects);
consumesHandle(getTargetMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}
@@ -375,9 +373,8 @@ transform::TestFuseUsingForallOp::apply(TransformRewriter &rewriter,
void transform::TestFuseUsingForallOp::getEffects(
SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
consumesHandle(getRootOp(), effects);
producesHandle(getTiledOps(), effects);
producesHandle(getLoops(), effects);
consumesHandle(getRootOpMutable(), effects);
producesHandle(getOperation()->getOpResults(), effects);
modifiesPayload(effects);
}

View File

@@ -25,16 +25,28 @@ def SideEffectOpB : TEST_Op<"side_effect_op_b",
[MemoryEffects<[MemWrite<CustomResource, 0>]>]>;
// CHECK: void SideEffectOpA::getEffects
// CHECK: for (::mlir::Value value : getODSOperands(0))
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Read::get(), value, 0, false, ::mlir::SideEffects::DefaultResource::get());
// CHECK: for (::mlir::Value value : getODSOperands(1))
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Write::get(), value, 1, true, ::mlir::SideEffects::DefaultResource::get());
// CHECK: {
// CHECK: auto valueRange = getODSOperandIndexAndLength(0);
// CHECK: for (unsigned idx = valueRange.first; idx < valueRange.first + valueRange.second; idx++) {
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Read::get(), &getOperation()->getOpOperand(idx), 0, false, ::mlir::SideEffects::DefaultResource::get());
// CHECK: }
// CHECK: }
// CHECK: {
// CHECK: auto valueRange = getODSOperandIndexAndLength(1);
// CHECK: for (unsigned idx = valueRange.first; idx < valueRange.first + valueRange.second; idx++) {
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Write::get(), &getOperation()->getOpOperand(idx), 1, true, ::mlir::SideEffects::DefaultResource::get());
// CHECK: }
// CHECK: }
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Read::get(), getSymbolAttr(), 0, false, ::mlir::SideEffects::DefaultResource::get());
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Write::get(), getFlatSymbolAttr(), 0, false, ::mlir::SideEffects::DefaultResource::get());
// CHECK: if (auto symbolRef = getOptionalSymbolAttr())
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Read::get(), symbolRef, 0, false, ::mlir::SideEffects::DefaultResource::get());
// CHECK: for (::mlir::Value value : getODSResults(0))
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Allocate::get(), value, 0, false, CustomResource::get());
// CHECK: {
// CHECK: auto valueRange = getODSResultIndexAndLength(0);
// CHECK: for (unsigned idx = valueRange.first; idx < valueRange.first + valueRange.second; idx++) {
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Allocate::get(), getOperation()->getOpResult(idx), 0, false, CustomResource::get());
// CHECK: }
// CHECK: }
// CHECK: void SideEffectOpB::getEffects
// CHECK: effects.emplace_back(::mlir::MemoryEffects::Write::get(), 0, false, CustomResource::get());

View File

@@ -3423,12 +3423,18 @@ void OpEmitter::genSideEffectInterfaceMethods() {
}
} else {
// Otherwise this is an operand/result, so we need to attach the Value.
body << " for (::mlir::Value value : getODS"
<< (location.kind == EffectKind::Operand ? "Operands" : "Results")
<< "(" << location.index << "))\n "
<< llvm::formatv(addEffectCode, effect, "value, ", stage,
effectOnFullRegion, resource)
.str();
body << " {\n auto valueRange = getODS"
<< (location.kind == EffectKind::Operand ? "Operand" : "Result")
<< "IndexAndLength(" << location.index << ");\n"
<< " for (unsigned idx = valueRange.first; idx < "
"valueRange.first"
<< " + valueRange.second; idx++) {\n "
<< llvm::formatv(addEffectCode, effect,
(location.kind == EffectKind::Operand
? "&getOperation()->getOpOperand(idx), "
: "getOperation()->getOpResult(idx), "),
stage, effectOnFullRegion, resource)
<< " }\n }\n";
}
}
}