Skip to content

Commit deaf026

Browse files
authored
Adding tryLookupResourceUsageAffinity. (#20891)
This will be used to lower into the new `#hal.device.optimal` attr added in #20879. Progress on #20855 (still needs usage, this is just the analysis). Progress on #20851.
1 parent 96829a4 commit deaf026

File tree

5 files changed

+196
-6
lines changed

5 files changed

+196
-6
lines changed

compiler/src/iree/compiler/Dialect/Stream/Analysis/Affinity.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,15 @@ TraversalResult ValueConsumerAffinityPVS::updateFromUse(Value value,
385385
return TraversalResult::INCOMPLETE;
386386
}
387387
})
388+
.Case([&](IREE::Stream::YieldOp op) {
389+
auto parentOp = op->getParentOp();
390+
auto &resultPVS = solver.getElementFor<ValueConsumerAffinityPVS>(
391+
*this,
392+
Position::forValue(parentOp->getResult(operand.getOperandNumber())),
393+
DFX::Resolution::REQUIRED);
394+
newState ^= resultPVS.getState();
395+
return TraversalResult::COMPLETE;
396+
})
388397
.Case([&](IREE::Util::ReturnOp op) {
389398
return solver.getExplorer().walkIncomingCalls(
390399
op->getParentOfType<mlir::CallableOpInterface>(),
@@ -985,6 +994,41 @@ bool AffinityAnalysis::tryLookupResourceAffinity(
985994
return true;
986995
}
987996

997+
bool AffinityAnalysis::tryLookupResourceUsageAffinity(
998+
Value value, SmallVectorImpl<IREE::Stream::AffinityAttr> &affinities) {
999+
auto producerPVS = solver.lookupElementFor<ValueProducerAffinityPVS>(
1000+
Position::forValue(value));
1001+
if (producerPVS && producerPVS->isValidState() &&
1002+
!producerPVS->isUndefContained()) {
1003+
if (!producerPVS->getAssumedSet().empty()) {
1004+
llvm::append_range(affinities, producerPVS->getAssumedSet());
1005+
}
1006+
}
1007+
auto consumerPVS = solver.lookupElementFor<ValueConsumerAffinityPVS>(
1008+
Position::forValue(value));
1009+
if (consumerPVS && consumerPVS->isValidState() &&
1010+
!consumerPVS->isUndefContained()) {
1011+
if (!consumerPVS->getAssumedSet().empty()) {
1012+
// There's probably a better way to do this but the template f*ckery
1013+
// required is too painful. I suspect a concat + sort + unique would do
1014+
// it, but not be any more efficient as we'd have to do the sort twice. We
1015+
// should probably change the functions to take a SetVectorImpl instead.
1016+
for (auto affinity : consumerPVS->getAssumedSet()) {
1017+
if (!producerPVS->getAssumedSet().contains(affinity)) {
1018+
affinities.push_back(affinity);
1019+
}
1020+
}
1021+
}
1022+
}
1023+
if (affinities.empty()) {
1024+
// Analysis completed but no affinity was specified; try to find a default.
1025+
return tryLookupDefaultAffinity(value.getParentBlock()->getParentOp(),
1026+
affinities);
1027+
}
1028+
sortAffinities(affinities);
1029+
return true;
1030+
}
1031+
9881032
LogicalResult AffinityAnalysis::run() {
9891033
// Initialize globals so that we can assign them affinity.
9901034
explorer.forEachGlobal([&](const auto *globalInfo) {
@@ -1029,6 +1073,8 @@ LogicalResult AffinityAnalysis::run() {
10291073
if (isa<IREE::Stream::AffinityTypeInterface>(result.getType())) {
10301074
solver.getOrCreateElementFor<ValueProducerAffinityPVS>(
10311075
Position::forValue(result));
1076+
solver.getOrCreateElementFor<ValueConsumerAffinityPVS>(
1077+
Position::forValue(result));
10321078
}
10331079
}
10341080
});

compiler/src/iree/compiler/Dialect/Stream/Analysis/Affinity.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,16 @@ class AffinityAnalysis {
8686
// If all affinities are compatible one will be chosen in an unspecified way.
8787
IREE::Stream::AffinityAttr lookupResourceAffinity(Value value);
8888

89-
// Populates all potential affinities of |value| in |affinities|.
89+
// Populates all potential producer affinities of |value| in |affinities|.
9090
// Returns false if analysis failed and the set of affinities is unknown.
9191
bool tryLookupResourceAffinity(
9292
Value value, SmallVectorImpl<IREE::Stream::AffinityAttr> &affinities);
9393

94+
// Populates all potential consumer affinities of |value| in |affinities|.
95+
// Returns false if analysis failed and the set of affinities is unknown.
96+
bool tryLookupResourceUsageAffinity(
97+
Value value, SmallVectorImpl<IREE::Stream::AffinityAttr> &affinities);
98+
9499
private:
95100
Explorer explorer;
96101
llvm::BumpPtrAllocator allocator;

compiler/src/iree/compiler/Dialect/Stream/IR/StreamBase.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,9 @@ def Stream_Resource : TypeDef<Stream_Dialect, "Resource", [
528528
them does not extend outside of the invocation they are provided to.
529529

530530
Stream values are not usable directly outside of a stream execution or
531-
transfer operation. If the contents of the value are needed they must first
532-
be transferred via `stream.transfer` - which may incur a copy.
531+
transfer operation. If the contents of the value are needed for host access
532+
or access from a device without memory compatibility they must first
533+
be transferred via a transfer operation (e.g. `stream.async.transfer`).
533534
}];
534535

535536
let parameters = (ins

compiler/src/iree/compiler/Dialect/Stream/Transforms/AnnotateAffinities.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ static void annotateOperandsAndResults(Operation *op,
5555
AffinityAnalysis &affinityAnalysis) {
5656
auto emptyArray = ArrayAttr::get(op->getContext(), {});
5757
SmallVector<Attribute> operandAttrs;
58+
SmallVector<Attribute> operandUsageAttrs;
5859
for (auto operand : op->getOperands()) {
5960
if (isa<IREE::Stream::AffinityTypeInterface>(operand.getType())) {
6061
SmallVector<IREE::Stream::AffinityAttr> affinities;
@@ -64,9 +65,18 @@ static void annotateOperandsAndResults(Operation *op,
6465
} else {
6566
operandAttrs.push_back(emptyArray);
6667
}
68+
SmallVector<IREE::Stream::AffinityAttr> usageAffinities;
69+
if (affinityAnalysis.tryLookupResourceUsageAffinity(operand,
70+
usageAffinities)) {
71+
operandUsageAttrs.push_back(ArrayAttr::get(
72+
op->getContext(), llvm::to_vector_of<Attribute>(usageAffinities)));
73+
} else {
74+
operandUsageAttrs.push_back(emptyArray);
75+
}
6776
}
6877
}
6978
SmallVector<Attribute> resultAttrs;
79+
SmallVector<Attribute> resultUsageAttrs;
7080
for (auto result : op->getResults()) {
7181
if (isa<IREE::Stream::AffinityTypeInterface>(result.getType())) {
7282
SmallVector<IREE::Stream::AffinityAttr> affinities;
@@ -76,16 +86,32 @@ static void annotateOperandsAndResults(Operation *op,
7686
} else {
7787
resultAttrs.push_back(emptyArray);
7888
}
89+
SmallVector<IREE::Stream::AffinityAttr> usageAffinities;
90+
if (affinityAnalysis.tryLookupResourceUsageAffinity(result,
91+
usageAffinities)) {
92+
resultUsageAttrs.push_back(ArrayAttr::get(
93+
op->getContext(), llvm::to_vector_of<Attribute>(usageAffinities)));
94+
} else {
95+
resultUsageAttrs.push_back(emptyArray);
96+
}
7997
}
8098
}
8199
if (!operandAttrs.empty()) {
82100
op->setAttr("stream.affinities.operands",
83101
ArrayAttr::get(op->getContext(), operandAttrs));
84102
}
103+
if (!operandUsageAttrs.empty()) {
104+
op->setAttr("stream.affinities.operands.usage",
105+
ArrayAttr::get(op->getContext(), operandUsageAttrs));
106+
}
85107
if (!resultAttrs.empty()) {
86108
op->setAttr("stream.affinities.results",
87109
ArrayAttr::get(op->getContext(), resultAttrs));
88110
}
111+
if (!resultUsageAttrs.empty()) {
112+
op->setAttr("stream.affinities.results.usage",
113+
ArrayAttr::get(op->getContext(), resultUsageAttrs));
114+
}
89115
}
90116

91117
static void annotateFuncOp(FunctionOpInterface funcOp,

0 commit comments

Comments
 (0)