@@ -215,11 +215,13 @@ def SairDecisionsAttr : SairStructAttr<"DecisionsAttr", [
215215 StructFieldAttr<"expansion", OptionalAttr<StrAttr>>
216216]>;
217217
218- // An attribute that species copies of the result of an operation.
218+ // An attribute that specifies instances of an operation.
219+ def SairInstancesAttr
220+ : TypedArrayAttrBase<SairDecisionsAttr, "array of Sair decisions">;
221+
222+ // An attribute that specifies copies of the result of an operation.
219223def SairCopiesAttr
220- : TypedArrayAttrBase<
221- TypedArrayAttrBase<SairDecisionsAttr, "array of Sair decisions">,
222- "array of array of Sair decisions">;
224+ : TypedArrayAttrBase<SairInstancesAttr, "array of array of Sair decisions">;
223225
224226//===----------------------------------------------------------------------===//
225227// Sair Types
@@ -352,8 +354,7 @@ def SairOpInterface : OpInterface<"SairOp"> {
352354 dependencies accross iterations for the given !sair.value operand}],
353355 "llvm::SmallBitVector", "CarryingDimensions",
354356 (ins "int":$sair_operand), [{}], [{
355- int size = cast<ConcreteOp>(this->getOperation()).domain().size();
356- return llvm::SmallBitVector(size);
357+ return llvm::SmallBitVector($_op.domain().size());
357358 }]
358359 >,
359360 InterfaceMethod<
@@ -370,7 +371,12 @@ def SairOpInterface : OpInterface<"SairOp"> {
370371 [{Indicates the size of each sub-domain. The first sub-domain is always
371372 the parallel domain}],
372373 "llvm::SmallVector<int, 2>", "SubDomains", (ins), [{}]
373- >
374+ >,
375+ InterfaceMethod<
376+ [{Indicates if the operation has exactly one instance and no copy.}],
377+ "bool", "HasExactlyOneInstance", (ins), [{}], [{
378+ return sair::HasExactlyOneInstance(this->getOperation());
379+ }]>
374380 ];
375381
376382 let verify = [{return VerifySairOp(op);}];
@@ -410,34 +416,59 @@ def SairComputeOp : OpInterface<"ComputeOp"> {
410416
411417 let methods = [
412418 InterfaceMethod<
413- "Returns lowering decisions for the operation",
414- "DecisionsAttr", "GetDecisions", (ins), [{}], [{
415- if (!$_op.decisions().hasValue()) {
416- return DecisionsAttr::get(
417- nullptr, nullptr, nullptr, nullptr, $_op.getContext());
418- }
419- return *$_op.decisions();
419+ "Returns the number of instances of the operation",
420+ "int", "NumInstances", (ins), [{}], [{
421+ llvm::Optional<mlir::ArrayAttr> instances = $_op.instances();
422+ if (!instances.hasValue()) return 0;
423+ return instances.getValue().size();
424+ }]>,
425+ InterfaceMethod<
426+ "Returns lowering decisions for the given operation instance",
427+ "DecisionsAttr", "GetDecisions", (ins "int":$instance), [{}], [{
428+ mlir::ArrayAttr instances = $_op.instances().getValue();
429+ return instances.getValue()[instance].cast<DecisionsAttr>();
420430 }]
421431 >,
422432 InterfaceMethod<
423433 "Sets lowering decisions for the operation",
424- "void", "SetDecisions", (ins "DecisionsAttr":$value), [{}], [{
425- $_op.decisionsAttr(value);
434+ "void", "SetDecisions", (ins "int":$instance, "DecisionsAttr":$value),
435+ [{}], [{
436+ auto instances = llvm::to_vector<4>(
437+ $_op.instances().getValue().getValue());
438+ instances[instance] = value;
439+ $_op.instancesAttr(mlir::ArrayAttr::get($_op.getContext(), instances));
426440 }]
427441 >,
442+ InterfaceMethod<
443+ "Appends an instance to the list of instances",
444+ "void", "AddInstance", (ins "DecisionsAttr":$value),
445+ [{}], [{
446+ llvm::SmallVector<mlir::Attribute> instances;
447+ if ($_op.instances().hasValue()) {
448+ instances = llvm::to_vector<4>(
449+ $_op.instances().getValue().getValue());
450+ }
451+ instances.push_back(value);
452+ $_op.instancesAttr(mlir::ArrayAttr::get($_op.getContext(), instances));
453+ }]
454+ >,
455+
456+ // TODO(ulysse): Legacy interface that returns decisions for the first
457+ // instance. This will be removed.
428458 InterfaceMethod<
429459 "Returns the loop nest to generate when lowering the operation",
430460 "llvm::Optional<mlir::ArrayAttr>", "loop_nest", (ins), [{}], [{
431- if (!$_op.decisions().hasValue()) return llvm::None;
432- if ($_op.decisions()->loop_nest() == nullptr) return llvm::None;
433- return $_op.decisions()->loop_nest();
461+ if ($_op.NumInstances() < 1) return llvm::None;
462+ DecisionsAttr decisions = $_op.GetDecisions(0);
463+ if (decisions.loop_nest() == nullptr) return llvm::None;
464+ return decisions.loop_nest();
434465 }]
435466 >,
436467 InterfaceMethod<
437468 "Sets the loop nest to generate when lowering the operation",
438469 "void", "setLoopNest", (ins "mlir::ArrayAttr":$loop_nest), [{
439- DecisionsAttr decisions = $_op.GetDecisions();
440- $_op.SetDecisions(DecisionsAttr::get(
470+ DecisionsAttr decisions = $_op.GetDecisions(0 );
471+ $_op.SetDecisions(0, DecisionsAttr::get(
441472 decisions.sequence(), loop_nest, decisions.storage(),
442473 decisions.expansion(), $_op.getContext()));
443474 }]
@@ -455,9 +486,10 @@ def SairComputeOp : OpInterface<"ComputeOp"> {
455486 InterfaceMethod<
456487 "Returns the storage of the values produced by the operation",
457488 "Optional<mlir::ArrayAttr>", "storage", (ins), [{}], [{
458- if (!$_op.decisions().hasValue()) return llvm::None;
459- if ($_op.decisions()->storage() == nullptr) return llvm::None;
460- return $_op.decisions()->storage();
489+ if ($_op.NumInstances() < 1) return llvm::None;
490+ DecisionsAttr decisions = $_op.GetDecisions(0);
491+ if (decisions.storage() == nullptr) return llvm::None;
492+ return decisions.storage();
461493 }]
462494 >,
463495 InterfaceMethod<
@@ -472,7 +504,7 @@ def SairComputeOp : OpInterface<"ComputeOp"> {
472504 InterfaceMethod<
473505 "Sets the storage of the values produced by the operation",
474506 "void", "SetStorage", (ins "int":$result, "BufferAttr":$buffer), [{}], [{
475- DecisionsAttr decisions = $_op.GetDecisions();
507+ DecisionsAttr decisions = $_op.GetDecisions(0 );
476508 llvm::SmallVector<mlir::Attribute> values;
477509 int num_results = $_op->getNumResults();
478510 if (decisions.storage() == nullptr) {
@@ -482,25 +514,26 @@ def SairComputeOp : OpInterface<"ComputeOp"> {
482514 }
483515 values[result] = buffer;
484516 auto new_storage = mlir::ArrayAttr::get($_op.getContext(), values);
485- $_op.SetDecisions(DecisionsAttr::get(
517+ $_op.SetDecisions(0, DecisionsAttr::get(
486518 decisions.sequence(), decisions.loop_nest(), new_storage,
487519 decisions.expansion(), $_op.getContext()));
488520 }]
489521 >,
490522 InterfaceMethod<
491523 "Returns the sequence number of this operation as signed integer.",
492524 "::llvm::Optional<int64_t>", "Sequence", (ins), [{}], [{
493- if (!$_op.decisions().hasValue()) return llvm::None;
494- if ($_op.decisions()->sequence() == nullptr) return llvm::None;
495- return $_op.decisions()->sequence().getInt();
525+ if ($_op.NumInstances() < 1) return llvm::None;
526+ DecisionsAttr decisions = $_op.GetDecisions(0);
527+ if (decisions.sequence() == nullptr) return ::llvm::None;
528+ return decisions.sequence().getInt();
496529 }]
497530 >,
498531 InterfaceMethod<
499532 "Sets the sequence number of the operation to the given value.",
500533 "void", "SetSequence", (ins "int64_t":$seq), [{}], [{
501534 ::mlir::Builder builder($_op->getContext());
502- DecisionsAttr decisions = GetDecisions();
503- $_op.SetDecisions(DecisionsAttr::get(
535+ DecisionsAttr decisions = GetDecisions(0 );
536+ $_op.SetDecisions(0, DecisionsAttr::get(
504537 builder.getI64IntegerAttr(seq), decisions.loop_nest(),
505538 decisions.storage(), decisions.expansion(),
506539 $_op.getContext()));
@@ -511,7 +544,7 @@ def SairComputeOp : OpInterface<"ComputeOp"> {
511544 let verify = [{return sair::VerifyComputeOp(op);}];
512545
513546 let extraClassDeclaration = [{
514- static constexpr llvm::StringRef kDecisionsAttrName = "decisions ";
547+ static constexpr llvm::StringRef kInstancesAttrName = "instances ";
515548 }];
516549}
517550
0 commit comments