@@ -88,6 +88,46 @@ bool TransferOptimization::isReachable(Operation *start, Operation *dest) {
88
88
return false ;
89
89
}
90
90
91
+ // / Walk up the source chain until an operation that changes/defines the view of
92
+ // / memory is found (i.e. skip operations that alias the entire view).
93
+ Value skipFullyAliasingOperations (Value source) {
94
+ while (auto op = source.getDefiningOp ()) {
95
+ if (auto subViewOp = dyn_cast<memref::SubViewOp>(op);
96
+ subViewOp && subViewOp.hasZeroOffset () && subViewOp.hasUnitStride ()) {
97
+ // A `memref.subview` with an all zero offset, and all unit strides, still
98
+ // points to the same memory.
99
+ source = subViewOp.getSource ();
100
+ } else if (auto castOp = dyn_cast<memref::CastOp>(op)) {
101
+ // A `memref.cast` still points to the same memory.
102
+ source = castOp.getSource ();
103
+ } else {
104
+ return source;
105
+ }
106
+ }
107
+ return source;
108
+ }
109
+
110
+ // / Checks if two (memref) values are are the same, or are statically known to
111
+ // / alias the same region of memory.
112
+ bool isSameViewOrTrivialAlias (Value a, Value b) {
113
+ return skipFullyAliasingOperations (a) == skipFullyAliasingOperations (b);
114
+ }
115
+
116
+ // / Walk up the source chain until something an op other than a `memref.subview`
117
+ // / or `memref.cast` is found.
118
+ Value skipSubViewsAndCasts (Value source) {
119
+ while (auto op = source.getDefiningOp ()) {
120
+ if (auto subView = dyn_cast<memref::SubViewOp>(op)) {
121
+ source = subView.getSource ();
122
+ } else if (auto cast = dyn_cast<memref::CastOp>(op)) {
123
+ source = cast.getSource ();
124
+ } else {
125
+ return source;
126
+ }
127
+ }
128
+ return source;
129
+ }
130
+
91
131
// / For transfer_write to overwrite fully another transfer_write must:
92
132
// / 1. Access the same memref with the same indices and vector type.
93
133
// / 2. Post-dominate the other transfer_write operation.
@@ -104,10 +144,7 @@ void TransferOptimization::deadStoreOp(vector::TransferWriteOp write) {
104
144
<< " \n " );
105
145
llvm::SmallVector<Operation *, 8 > blockingAccesses;
106
146
Operation *firstOverwriteCandidate = nullptr ;
107
- Value source = write.getSource ();
108
- // Skip subview ops.
109
- while (auto subView = source.getDefiningOp <memref::SubViewOp>())
110
- source = subView.getSource ();
147
+ Value source = skipSubViewsAndCasts (write.getSource ());
111
148
llvm::SmallVector<Operation *, 32 > users (source.getUsers ().begin (),
112
149
source.getUsers ().end ());
113
150
llvm::SmallDenseSet<Operation *, 32 > processed;
@@ -116,8 +153,8 @@ void TransferOptimization::deadStoreOp(vector::TransferWriteOp write) {
116
153
// If the user has already been processed skip.
117
154
if (!processed.insert (user).second )
118
155
continue ;
119
- if (auto subView = dyn_cast <memref::SubViewOp>(user)) {
120
- users.append (subView ->getUsers ().begin (), subView ->getUsers ().end ());
156
+ if (isa <memref::SubViewOp, memref::CastOp >(user)) {
157
+ users.append (user ->getUsers ().begin (), user ->getUsers ().end ());
121
158
continue ;
122
159
}
123
160
if (isMemoryEffectFree (user))
@@ -126,7 +163,7 @@ void TransferOptimization::deadStoreOp(vector::TransferWriteOp write) {
126
163
continue ;
127
164
if (auto nextWrite = dyn_cast<vector::TransferWriteOp>(user)) {
128
165
// Check candidate that can override the store.
129
- if (write .getSource () == nextWrite .getSource () &&
166
+ if (isSameViewOrTrivialAlias (nextWrite .getSource (), write .getSource () ) &&
130
167
checkSameValueWAW (nextWrite, write) &&
131
168
postDominators.postDominates (nextWrite, write)) {
132
169
if (firstOverwriteCandidate == nullptr ||
@@ -191,10 +228,7 @@ void TransferOptimization::storeToLoadForwarding(vector::TransferReadOp read) {
191
228
<< " \n " );
192
229
SmallVector<Operation *, 8 > blockingWrites;
193
230
vector::TransferWriteOp lastwrite = nullptr ;
194
- Value source = read.getSource ();
195
- // Skip subview ops.
196
- while (auto subView = source.getDefiningOp <memref::SubViewOp>())
197
- source = subView.getSource ();
231
+ Value source = skipSubViewsAndCasts (read.getSource ());
198
232
llvm::SmallVector<Operation *, 32 > users (source.getUsers ().begin (),
199
233
source.getUsers ().end ());
200
234
llvm::SmallDenseSet<Operation *, 32 > processed;
@@ -203,12 +237,8 @@ void TransferOptimization::storeToLoadForwarding(vector::TransferReadOp read) {
203
237
// If the user has already been processed skip.
204
238
if (!processed.insert (user).second )
205
239
continue ;
206
- if (auto subView = dyn_cast<memref::SubViewOp>(user)) {
207
- users.append (subView->getUsers ().begin (), subView->getUsers ().end ());
208
- continue ;
209
- }
210
- if (auto collapsed = dyn_cast<memref::CollapseShapeOp>(user)) {
211
- users.append (collapsed->getUsers ().begin (), collapsed->getUsers ().end ());
240
+ if (isa<memref::SubViewOp, memref::CollapseShapeOp, memref::CastOp>(user)) {
241
+ users.append (user->getUsers ().begin (), user->getUsers ().end ());
212
242
continue ;
213
243
}
214
244
if (isMemoryEffectFree (user) || isa<vector::TransferReadOp>(user))
@@ -221,7 +251,7 @@ void TransferOptimization::storeToLoadForwarding(vector::TransferReadOp read) {
221
251
cast<VectorTransferOpInterface>(read.getOperation ()),
222
252
/* testDynamicValueUsingBounds=*/ true ))
223
253
continue ;
224
- if (write .getSource () == read .getSource () &&
254
+ if (isSameViewOrTrivialAlias (read .getSource (), write .getSource () ) &&
225
255
dominators.dominates (write, read) && checkSameValueRAW (write, read)) {
226
256
if (lastwrite == nullptr || dominators.dominates (lastwrite, write))
227
257
lastwrite = write;
0 commit comments