@@ -145,12 +145,30 @@ struct UseDefChainVisitor
145
145
case ProjectionKind::Tuple: {
146
146
// These are merges if we have multiple fields.
147
147
auto *tti = cast<TupleElementAddrInst>(inst);
148
+
149
+ // See if our result type is a sendable type. In such a case, we do not
150
+ // want to look through the tuple_element_addr since we do not want to
151
+ // identify the sendable type with the non-sendable operand. These we
152
+ // are always going to ignore anyways since a sendable let/var field of
153
+ // a struct can always be used.
154
+ if (!isNonSendableType (tti->getType (), tti->getFunction ()))
155
+ return SILValue ();
156
+
148
157
isMerge |= tti->getOperand ()->getType ().getNumTupleElements () > 1 ;
149
158
break ;
150
159
}
151
160
case ProjectionKind::Struct:
152
- // These are merges if we have multiple fields.
153
161
auto *sea = cast<StructElementAddrInst>(inst);
162
+
163
+ // See if our result type is a sendable type. In such a case, we do not
164
+ // want to look through the struct_element_addr since we do not want to
165
+ // identify the sendable type with the non-sendable operand. These we
166
+ // are always going to ignore anyways since a sendable let/var field of
167
+ // a struct can always be used.
168
+ if (!isNonSendableType (sea->getType (), sea->getFunction ()))
169
+ return SILValue ();
170
+
171
+ // These are merges if we have multiple fields.
154
172
isMerge |= sea->getOperand ()->getType ().getNumNominalFields () > 1 ;
155
173
break ;
156
174
}
@@ -1147,13 +1165,21 @@ class PartitionOpTranslator {
1147
1165
case SILInstructionKind::EndInitLetRefInst:
1148
1166
case SILInstructionKind::InitEnumDataAddrInst:
1149
1167
case SILInstructionKind::OpenExistentialAddrInst:
1150
- case SILInstructionKind::StructElementAddrInst:
1151
- case SILInstructionKind::TupleElementAddrInst:
1152
1168
case SILInstructionKind::UncheckedRefCastInst:
1153
1169
case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
1154
1170
case SILInstructionKind::UpcastInst:
1155
1171
return translateSILLookThrough (inst->getResult (0 ), inst->getOperand (0 ));
1156
1172
1173
+ case SILInstructionKind::TupleElementAddrInst:
1174
+ case SILInstructionKind::StructElementAddrInst: {
1175
+ auto *svi = cast<SingleValueInstruction>(inst);
1176
+ // If we have a sendable field... we can always access it after
1177
+ // transferring... so do not track this.
1178
+ if (!isNonSendableType (svi->getType ()))
1179
+ return ;
1180
+ return translateSILLookThrough (svi->getResult (0 ), svi->getOperand (0 ));
1181
+ }
1182
+
1157
1183
// We identify tuple results with their operand's id.
1158
1184
case SILInstructionKind::DestructureTupleInst:
1159
1185
case SILInstructionKind::DestructureStructInst:
@@ -1183,23 +1209,44 @@ class PartitionOpTranslator {
1183
1209
case SILInstructionKind::PointerToAddressInst:
1184
1210
case SILInstructionKind::ProjectBlockStorageInst:
1185
1211
case SILInstructionKind::RefToUnmanagedInst:
1186
- case SILInstructionKind::StructExtractInst:
1187
1212
case SILInstructionKind::TailAddrInst:
1188
1213
case SILInstructionKind::ThickToObjCMetatypeInst:
1189
1214
case SILInstructionKind::ThinToThickFunctionInst:
1190
1215
case SILInstructionKind::UncheckedAddrCastInst:
1191
1216
case SILInstructionKind::UncheckedEnumDataInst:
1192
1217
case SILInstructionKind::UncheckedOwnershipConversionInst:
1193
1218
case SILInstructionKind::UnmanagedToRefInst:
1219
+ return translateSILAssign (inst);
1194
1220
1195
1221
// RefElementAddrInst is not considered to be a lookThrough since we want to
1196
1222
// consider the address projected from the class to be a separate value that
1197
1223
// is in the same region as the parent operand. The reason that we want to
1198
1224
// do this is to ensure that if we assign into the ref_element_addr memory,
1199
1225
// we do not consider writes into the struct that contains the
1200
1226
// ref_element_addr to be merged into.
1201
- case SILInstructionKind::RefElementAddrInst:
1227
+ case SILInstructionKind::RefElementAddrInst: {
1228
+ auto *reai = cast<RefElementAddrInst>(inst);
1229
+ // If we are accessing a let of a Sendable type, do not treat the
1230
+ // ref_element_addr as a require use.
1231
+ if (reai->getField ()->isLet () && !isNonSendableType (reai->getType ())) {
1232
+ LLVM_DEBUG (llvm::dbgs () << " Found a let! Not tracking!\n " );
1233
+ return ;
1234
+ }
1235
+ return translateSILAssign (inst);
1236
+ }
1237
+
1238
+ case SILInstructionKind::TupleExtractInst:
1239
+ case SILInstructionKind::StructExtractInst: {
1240
+ auto *svi = cast<SingleValueInstruction>(inst);
1241
+ // If our result is a Sendable type regardless of if it is a let or a var,
1242
+ // we do not need to track it.
1243
+ if (!isNonSendableType (svi->getType ())) {
1244
+ LLVM_DEBUG (llvm::dbgs ()
1245
+ << " Found a sendable field... Not Tracking!\n " );
1246
+ return ;
1247
+ }
1202
1248
return translateSILAssign (inst);
1249
+ }
1203
1250
1204
1251
// / Enum inst is handled specially since if it does not have an argument,
1205
1252
// / we must assign fresh. Otherwise, we must propagate.
0 commit comments