17
17
#include " swift/SILOptimizer/Analysis/ValueTracking.h"
18
18
#include " swift/SILOptimizer/PassManager/PassManager.h"
19
19
#include " swift/SIL/SILArgument.h"
20
+ #include " swift/SIL/DebugUtils.h"
20
21
#include " llvm/Support/GraphWriter.h"
21
22
#include " llvm/Support/raw_ostream.h"
22
23
@@ -30,13 +31,23 @@ static bool isProjection(ValueBase *V) {
30
31
case ValueKind::TupleElementAddrInst:
31
32
case ValueKind::UncheckedTakeEnumDataAddrInst:
32
33
case ValueKind::StructExtractInst:
33
- case ValueKind::TupleExtractInst:
34
34
case ValueKind::UncheckedEnumDataInst:
35
35
case ValueKind::MarkDependenceInst:
36
36
case ValueKind::PointerToAddressInst:
37
37
case ValueKind::AddressToPointerInst:
38
38
case ValueKind::InitEnumDataAddrInst:
39
39
return true ;
40
+ case ValueKind::TupleExtractInst: {
41
+ auto *TEI = cast<TupleExtractInst>(V);
42
+ // Special handling for extracting the pointer-result from an
43
+ // array construction. We handle this like a ref_element_addr
44
+ // rather than a projection. See the handling of tuple_extract
45
+ // in analyzeInstruction().
46
+ if (TEI->getFieldNo () == 1 &&
47
+ ArraySemanticsCall (TEI->getOperand (), " array.uninitialized" , false ))
48
+ return false ;
49
+ return true ;
50
+ }
40
51
default :
41
52
return false ;
42
53
}
@@ -1095,6 +1106,15 @@ void EscapeAnalysis::buildConnectionGraph(FunctionInfo *FInfo,
1095
1106
FInfo->Graph .F ->getName () << ' \n ' );
1096
1107
}
1097
1108
1109
+ // / Returns true if all uses of \p I are tuple_extract instructions.
1110
+ static bool onlyUsedInTupleExtract (SILInstruction *I) {
1111
+ for (Operand *Use : getNonDebugUses (I)) {
1112
+ if (!isa<TupleExtractInst>(Use->getUser ()))
1113
+ return false ;
1114
+ }
1115
+ return true ;
1116
+ }
1117
+
1098
1118
void EscapeAnalysis::analyzeInstruction (SILInstruction *I,
1099
1119
FunctionInfo *FInfo,
1100
1120
FunctionOrder &BottomUpOrder,
@@ -1113,13 +1133,20 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
1113
1133
// These array semantics calls do not capture anything.
1114
1134
return ;
1115
1135
case ArrayCallKind::kArrayUninitialized :
1116
- // array.uninitialized may have a first argument which is the
1117
- // allocated array buffer. The call is like a struct(buffer)
1118
- // instruction.
1119
- if (CGNode *BufferNode = ConGraph->getNode (FAS.getArgument (0 ), this )) {
1120
- ConGraph->defer (ConGraph->getNode (I, this ), BufferNode);
1136
+ // Check if the result is used in the usual way: extracting the
1137
+ // array and the element pointer with tuple_extract.
1138
+ if (onlyUsedInTupleExtract (I)) {
1139
+ // array.uninitialized may have a first argument which is the
1140
+ // allocated array buffer. The call is like a struct(buffer)
1141
+ // instruction.
1142
+ if (CGNode *BufferNode = ConGraph->getNode (FAS.getArgument (0 ), this )) {
1143
+ CGNode *ArrayNode = ConGraph->getNode (I, this );
1144
+ CGNode *ArrayContent = ConGraph->getContentNode (ArrayNode);
1145
+ ConGraph->defer (ArrayContent, BufferNode);
1146
+ }
1147
+ return ;
1121
1148
}
1122
- return ;
1149
+ break ;
1123
1150
case ArrayCallKind::kGetArrayOwner :
1124
1151
if (CGNode *BufferNode = ConGraph->getNode (ASC.getSelf (), this )) {
1125
1152
ConGraph->defer (ConGraph->getNode (I, this ), BufferNode);
@@ -1388,6 +1415,21 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
1388
1415
}
1389
1416
return ;
1390
1417
}
1418
+ case ValueKind::TupleExtractInst: {
1419
+ // This is a tuple_extract which extracts the second result of an
1420
+ // array.uninitialized call. The first result is the array itself.
1421
+ // The second result (which is a pointer to the array elements) must be
1422
+ // the content node of the first result. It's just like a ref_element_addr
1423
+ // instruction.
1424
+ auto *TEI = cast<TupleExtractInst>(I);
1425
+ assert (TEI->getFieldNo () == 1 &&
1426
+ ArraySemanticsCall (TEI->getOperand (), " array.uninitialized" , false )
1427
+ && " tuple_extract should be handled as projection" );
1428
+ CGNode *ArrayNode = ConGraph->getNode (TEI->getOperand (), this );
1429
+ CGNode *ArrayElements = ConGraph->getContentNode (ArrayNode);
1430
+ ConGraph->setNode (I, ArrayElements);
1431
+ return ;
1432
+ }
1391
1433
case ValueKind::UncheckedRefCastInst:
1392
1434
case ValueKind::ConvertFunctionInst:
1393
1435
case ValueKind::UpcastInst:
0 commit comments