@@ -1915,12 +1915,193 @@ void DataflowState::init() {
1915
1915
}
1916
1916
}
1917
1917
1918
+ // ===----------------------------------------------------------------------===//
1919
+ // Address Checker
1920
+ // ===----------------------------------------------------------------------===//
1921
+
1922
+ namespace {
1923
+
1924
+ struct MoveKillsCopyableAddressesChecker {
1925
+ SILFunction *fn;
1926
+ UseState useState;
1927
+ DataflowState dataflowState;
1928
+ UseState closureUseState;
1929
+ ClosureArgDataflowState closureUseDataflowState;
1930
+ SILOptFunctionBuilder &funcBuilder;
1931
+ llvm::SmallMapVector<FullApplySite, SmallBitVector, 8 >
1932
+ applySiteToPromotedArgIndices;
1933
+ SmallBlotSetVector<SILInstruction *, 8 > closureConsumes;
1934
+
1935
+ // / A list of instructions where to work around the behavior of SelectionDAG,
1936
+ // / we break the block. These are debug var carrying insts or debug_value
1937
+ // / associated with reinits. This is initialized when we process all of the
1938
+ // / addresses. Then as a final step after wards we use this as a worklist and
1939
+ // / break blocks at each of these instructions. We update DebugInfo, LoopInfo
1940
+ // / if we found that they already exist.
1941
+ // /
1942
+ // / We on purpose use a set vector to ensure that we only ever split a block
1943
+ // / once.
1944
+ SmallSetVector<SILInstruction *, 8 > debugInfoBlockSplitPoints;
1945
+ DominanceInfo *dominanceToUpdate = nullptr ;
1946
+ SILLoopInfo *loopInfoToUpdate = nullptr ;
1947
+
1948
+ MoveKillsCopyableAddressesChecker (SILFunction *fn,
1949
+ SILOptFunctionBuilder &funcBuilder)
1950
+ : fn(fn), useState(),
1951
+ dataflowState (funcBuilder, useState, applySiteToPromotedArgIndices,
1952
+ closureConsumes),
1953
+ closureUseState(), closureUseDataflowState(closureUseState),
1954
+ funcBuilder(funcBuilder) {}
1955
+
1956
+ void setDominanceToUpdate (DominanceInfo *newInfo) {
1957
+ dominanceToUpdate = newInfo;
1958
+ }
1959
+
1960
+ void setLoopInfoToUpdate (SILLoopInfo *newInfo) { loopInfoToUpdate = newInfo; }
1961
+
1962
+ void cloneDeferCalleeAndRewriteUses (
1963
+ SmallVectorImpl<SILValue> &temporaryStorage,
1964
+ const SmallBitVector &bitVector, FullApplySite oldApplySite,
1965
+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
1966
+
1967
+ bool check (SILValue address);
1968
+ bool performClosureDataflow (Operand *callerOperand,
1969
+ ClosureOperandState &calleeOperandState);
1970
+
1971
+ void emitDiagnosticForMove (SILValue borrowedValue,
1972
+ StringRef borrowedValueName, MoveValueInst *mvi);
1973
+ bool splitBlocksAfterDebugInfoCarryingInst (SILModule &mod) {
1974
+ if (debugInfoBlockSplitPoints.empty ())
1975
+ return false ;
1976
+
1977
+ SILBuilderContext ctx (mod);
1978
+ do {
1979
+ auto *next = debugInfoBlockSplitPoints.pop_back_val ();
1980
+ splitBasicBlockAndBranch (ctx, next->getNextInstruction (),
1981
+ dominanceToUpdate, loopInfoToUpdate);
1982
+ } while (!debugInfoBlockSplitPoints.empty ());
1983
+
1984
+ return true ;
1985
+ }
1986
+
1987
+ bool performSingleBasicBlockAnalysis (SILValue address,
1988
+ MarkUnresolvedMoveAddrInst *mvi);
1989
+
1990
+ ASTContext &getASTContext () const { return fn->getASTContext (); }
1991
+ };
1992
+
1993
+ } // namespace
1994
+
1995
+ void MoveKillsCopyableAddressesChecker::cloneDeferCalleeAndRewriteUses (
1996
+ SmallVectorImpl<SILValue> &newArgs, const SmallBitVector &bitVector,
1997
+ FullApplySite oldApplySite,
1998
+ SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
1999
+ auto *origCallee = oldApplySite.getReferencedFunctionOrNull ();
2000
+ assert (origCallee);
2001
+
2002
+ auto name = getClonedName (origCallee, origCallee->isSerialized (), bitVector);
2003
+
2004
+ SILFunction *newCallee = nullptr ;
2005
+ if (auto *fn = origCallee->getModule ().lookUpFunction (name)) {
2006
+ newCallee = fn;
2007
+ } else {
2008
+ ClosureArgumentInOutToOutCloner cloner (
2009
+ funcBuilder, origCallee, origCallee->isSerialized (),
2010
+ postDominatingConsumingUsers, bitVector, name);
2011
+ cloner.populateCloned ();
2012
+ newCallee = cloner.getCloned ();
2013
+ }
2014
+ assert (newCallee);
2015
+
2016
+ // Ok, we now have populated our new callee. We need to create a new full
2017
+ // apply site that calls the new function appropriately.
2018
+ SWIFT_DEFER { newArgs.clear (); };
2019
+
2020
+ // First add all of our old results to newArgs.
2021
+ auto oldConv = oldApplySite.getSubstCalleeConv ();
2022
+ for (unsigned i : range (oldConv.getSILArgIndexOfFirstIndirectResult (),
2023
+ oldConv.getSILArgIndexOfFirstParam ())) {
2024
+ newArgs.push_back (oldApplySite->getOperand (i));
2025
+ }
2026
+
2027
+ // Now add all of our new out params.
2028
+ for (int i = bitVector.find_first (); i != -1 ; i = bitVector.find_next (i)) {
2029
+ unsigned appliedArgIndex =
2030
+ oldApplySite.getOperandIndexOfFirstArgument () + i;
2031
+ newArgs.push_back (oldApplySite->getOperand (appliedArgIndex));
2032
+ }
2033
+
2034
+ // Finally, add all of the rest of our arguments, skipping our new out
2035
+ // parameters.
2036
+ for (unsigned i : range (oldConv.getSILArgIndexOfFirstParam (),
2037
+ oldConv.getNumSILArguments ())) {
2038
+ if (bitVector.test (i))
2039
+ continue ;
2040
+ unsigned appliedArgIndex =
2041
+ oldApplySite.getOperandIndexOfFirstArgument () + i;
2042
+ newArgs.push_back (oldApplySite->getOperand (appliedArgIndex));
2043
+ }
2044
+
2045
+ // Then create our new apply.
2046
+ SILBuilderWithScope builder (*oldApplySite);
2047
+ auto *newCalleeRef =
2048
+ builder.createFunctionRef (oldApplySite->getLoc (), newCallee);
2049
+ auto *newApply =
2050
+ builder.createApply (oldApplySite->getLoc (), newCalleeRef,
2051
+ oldApplySite.getSubstitutionMap (), newArgs);
2052
+ oldApplySite->replaceAllUsesPairwiseWith (newApply);
2053
+ oldApplySite->eraseFromParent ();
2054
+ }
2055
+
2056
+ bool MoveKillsCopyableAddressesChecker::performClosureDataflow (
2057
+ Operand *callerOperand, ClosureOperandState &calleeOperandState) {
2058
+ auto fas = FullApplySite::isa (callerOperand->getUser ());
2059
+ auto *func = fas.getCalleeFunction ();
2060
+ auto *address =
2061
+ func->begin ()->getArgument (fas.getCalleeArgIndex (*callerOperand));
2062
+
2063
+ LLVM_DEBUG (llvm::dbgs () << " Performing closure dataflow on caller use: "
2064
+ << *callerOperand->getUser ());
2065
+ LLVM_DEBUG (llvm::dbgs () << " Callee: " << func->getName () << ' \n ' );
2066
+ LLVM_DEBUG (llvm::dbgs () << " Callee Argument: " << *address);
2067
+ // We emit an end closure dataflow to make it easier when reading debug output
2068
+ // to make it easy to see when we have returned to analyzing the caller.
2069
+ SWIFT_DEFER {
2070
+ LLVM_DEBUG (llvm::dbgs ()
2071
+ << " Finished performing closure dataflow on Callee: "
2072
+ << func->getName () << ' \n ' ;);
2073
+ };
2074
+ auto accessPathWithBase = AccessPathWithBase::compute (address);
2075
+ auto accessPath = accessPathWithBase.accessPath ;
2076
+
2077
+ // Bail on an invalid AccessPath.
2078
+ //
2079
+ // AccessPath completeness is verified independently--it may be invalid in
2080
+ // extraordinary situations. When AccessPath is valid, we know all its uses
2081
+ // are recognizable.
2082
+ //
2083
+ // NOTE: If due to an invalid access path we fail here, we will just error
2084
+ // on the _move since the _move would not have been handled.
2085
+ if (!accessPath.isValid ())
2086
+ return false ;
2087
+
2088
+ // TODO: Hoist this useState into an ivar that we can reuse in between closure
2089
+ // operands?
2090
+ GatherClosureUseVisitor visitor (closureUseState);
2091
+ SWIFT_DEFER { visitor.clear (); };
2092
+ visitor.reset (address);
2093
+ if (!visitAccessPathUses (visitor, accessPath, fn))
2094
+ return false ;
2095
+
2096
+ SWIFT_DEFER { closureUseDataflowState.clear (); };
2097
+ return closureUseDataflowState.process (address, calleeOperandState,
2098
+ closureConsumes);
2099
+ }
2100
+
1918
2101
// Returns true if we emitted a diagnostic and handled the single block
1919
2102
// case. Returns false if we visited all of the uses and seeded the UseState
1920
2103
// struct with the information needed to perform our interprocedural dataflow.
1921
- static bool performSingleBasicBlockAnalysis (
1922
- DataflowState &dataflowState,
1923
- SmallSetVector<SILInstruction *, 8 > &debugInfoBlockSplitPoints,
2104
+ bool MoveKillsCopyableAddressesChecker::performSingleBasicBlockAnalysis (
1924
2105
SILValue address, MarkUnresolvedMoveAddrInst *mvi) {
1925
2106
// First scan downwards to make sure we are move out of this block.
1926
2107
auto &useState = dataflowState.useState ;
@@ -2150,186 +2331,6 @@ static bool performSingleBasicBlockAnalysis(
2150
2331
return false ;
2151
2332
}
2152
2333
2153
- // ===----------------------------------------------------------------------===//
2154
- // Address Checker
2155
- // ===----------------------------------------------------------------------===//
2156
-
2157
- namespace {
2158
-
2159
- struct MoveKillsCopyableAddressesChecker {
2160
- SILFunction *fn;
2161
- UseState useState;
2162
- DataflowState dataflowState;
2163
- UseState closureUseState;
2164
- ClosureArgDataflowState closureUseDataflowState;
2165
- SILOptFunctionBuilder &funcBuilder;
2166
- llvm::SmallMapVector<FullApplySite, SmallBitVector, 8 >
2167
- applySiteToPromotedArgIndices;
2168
- SmallBlotSetVector<SILInstruction *, 8 > closureConsumes;
2169
-
2170
- // / A list of instructions where to work around the behavior of SelectionDAG,
2171
- // / we break the block. These are debug var carrying insts or debug_value
2172
- // / associated with reinits. This is initialized when we process all of the
2173
- // / addresses. Then as a final step after wards we use this as a worklist and
2174
- // / break blocks at each of these instructions. We update DebugInfo, LoopInfo
2175
- // / if we found that they already exist.
2176
- // /
2177
- // / We on purpose use a set vector to ensure that we only ever split a block
2178
- // / once.
2179
- SmallSetVector<SILInstruction *, 8 > debugInfoBlockSplitPoints;
2180
- DominanceInfo *dominanceToUpdate = nullptr ;
2181
- SILLoopInfo *loopInfoToUpdate = nullptr ;
2182
-
2183
- MoveKillsCopyableAddressesChecker (SILFunction *fn,
2184
- SILOptFunctionBuilder &funcBuilder)
2185
- : fn(fn), useState(),
2186
- dataflowState (funcBuilder, useState, applySiteToPromotedArgIndices,
2187
- closureConsumes),
2188
- closureUseState(), closureUseDataflowState(closureUseState),
2189
- funcBuilder(funcBuilder) {}
2190
-
2191
- void setDominanceToUpdate (DominanceInfo *newInfo) {
2192
- dominanceToUpdate = newInfo;
2193
- }
2194
-
2195
- void setLoopInfoToUpdate (SILLoopInfo *newInfo) { loopInfoToUpdate = newInfo; }
2196
-
2197
- void cloneDeferCalleeAndRewriteUses (
2198
- SmallVectorImpl<SILValue> &temporaryStorage,
2199
- const SmallBitVector &bitVector, FullApplySite oldApplySite,
2200
- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
2201
-
2202
- bool check (SILValue address);
2203
- bool performClosureDataflow (Operand *callerOperand,
2204
- ClosureOperandState &calleeOperandState);
2205
-
2206
- void emitDiagnosticForMove (SILValue borrowedValue,
2207
- StringRef borrowedValueName, MoveValueInst *mvi);
2208
- bool splitBlocksAfterDebugInfoCarryingInst (SILModule &mod) {
2209
- if (debugInfoBlockSplitPoints.empty ())
2210
- return false ;
2211
-
2212
- SILBuilderContext ctx (mod);
2213
- do {
2214
- auto *next = debugInfoBlockSplitPoints.pop_back_val ();
2215
- splitBasicBlockAndBranch (ctx, next->getNextInstruction (),
2216
- dominanceToUpdate, loopInfoToUpdate);
2217
- } while (!debugInfoBlockSplitPoints.empty ());
2218
-
2219
- return true ;
2220
- }
2221
-
2222
- ASTContext &getASTContext () const { return fn->getASTContext (); }
2223
- };
2224
-
2225
- } // namespace
2226
-
2227
- void MoveKillsCopyableAddressesChecker::cloneDeferCalleeAndRewriteUses (
2228
- SmallVectorImpl<SILValue> &newArgs, const SmallBitVector &bitVector,
2229
- FullApplySite oldApplySite,
2230
- SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
2231
- auto *origCallee = oldApplySite.getReferencedFunctionOrNull ();
2232
- assert (origCallee);
2233
-
2234
- auto name = getClonedName (origCallee, origCallee->isSerialized (), bitVector);
2235
-
2236
- SILFunction *newCallee = nullptr ;
2237
- if (auto *fn = origCallee->getModule ().lookUpFunction (name)) {
2238
- newCallee = fn;
2239
- } else {
2240
- ClosureArgumentInOutToOutCloner cloner (
2241
- funcBuilder, origCallee, origCallee->isSerialized (),
2242
- postDominatingConsumingUsers, bitVector, name);
2243
- cloner.populateCloned ();
2244
- newCallee = cloner.getCloned ();
2245
- }
2246
- assert (newCallee);
2247
-
2248
- // Ok, we now have populated our new callee. We need to create a new full
2249
- // apply site that calls the new function appropriately.
2250
- SWIFT_DEFER { newArgs.clear (); };
2251
-
2252
- // First add all of our old results to newArgs.
2253
- auto oldConv = oldApplySite.getSubstCalleeConv ();
2254
- for (unsigned i : range (oldConv.getSILArgIndexOfFirstIndirectResult (),
2255
- oldConv.getSILArgIndexOfFirstParam ())) {
2256
- newArgs.push_back (oldApplySite->getOperand (i));
2257
- }
2258
-
2259
- // Now add all of our new out params.
2260
- for (int i = bitVector.find_first (); i != -1 ; i = bitVector.find_next (i)) {
2261
- unsigned appliedArgIndex =
2262
- oldApplySite.getOperandIndexOfFirstArgument () + i;
2263
- newArgs.push_back (oldApplySite->getOperand (appliedArgIndex));
2264
- }
2265
-
2266
- // Finally, add all of the rest of our arguments, skipping our new out
2267
- // parameters.
2268
- for (unsigned i : range (oldConv.getSILArgIndexOfFirstParam (),
2269
- oldConv.getNumSILArguments ())) {
2270
- if (bitVector.test (i))
2271
- continue ;
2272
- unsigned appliedArgIndex =
2273
- oldApplySite.getOperandIndexOfFirstArgument () + i;
2274
- newArgs.push_back (oldApplySite->getOperand (appliedArgIndex));
2275
- }
2276
-
2277
- // Then create our new apply.
2278
- SILBuilderWithScope builder (*oldApplySite);
2279
- auto *newCalleeRef =
2280
- builder.createFunctionRef (oldApplySite->getLoc (), newCallee);
2281
- auto *newApply =
2282
- builder.createApply (oldApplySite->getLoc (), newCalleeRef,
2283
- oldApplySite.getSubstitutionMap (), newArgs);
2284
- oldApplySite->replaceAllUsesPairwiseWith (newApply);
2285
- oldApplySite->eraseFromParent ();
2286
- }
2287
-
2288
- bool MoveKillsCopyableAddressesChecker::performClosureDataflow (
2289
- Operand *callerOperand, ClosureOperandState &calleeOperandState) {
2290
- auto fas = FullApplySite::isa (callerOperand->getUser ());
2291
- auto *func = fas.getCalleeFunction ();
2292
- auto *address =
2293
- func->begin ()->getArgument (fas.getCalleeArgIndex (*callerOperand));
2294
-
2295
- LLVM_DEBUG (llvm::dbgs () << " Performing closure dataflow on caller use: "
2296
- << *callerOperand->getUser ());
2297
- LLVM_DEBUG (llvm::dbgs () << " Callee: " << func->getName () << ' \n ' );
2298
- LLVM_DEBUG (llvm::dbgs () << " Callee Argument: " << *address);
2299
- // We emit an end closure dataflow to make it easier when reading debug output
2300
- // to make it easy to see when we have returned to analyzing the caller.
2301
- SWIFT_DEFER {
2302
- LLVM_DEBUG (llvm::dbgs ()
2303
- << " Finished performing closure dataflow on Callee: "
2304
- << func->getName () << ' \n ' ;);
2305
- };
2306
- auto accessPathWithBase = AccessPathWithBase::compute (address);
2307
- auto accessPath = accessPathWithBase.accessPath ;
2308
-
2309
- // Bail on an invalid AccessPath.
2310
- //
2311
- // AccessPath completeness is verified independently--it may be invalid in
2312
- // extraordinary situations. When AccessPath is valid, we know all its uses
2313
- // are recognizable.
2314
- //
2315
- // NOTE: If due to an invalid access path we fail here, we will just error
2316
- // on the _move since the _move would not have been handled.
2317
- if (!accessPath.isValid ())
2318
- return false ;
2319
-
2320
- // TODO: Hoist this useState into an ivar that we can reuse in between closure
2321
- // operands?
2322
- GatherClosureUseVisitor visitor (closureUseState);
2323
- SWIFT_DEFER { visitor.clear (); };
2324
- visitor.reset (address);
2325
- if (!visitAccessPathUses (visitor, accessPath, fn))
2326
- return false ;
2327
-
2328
- SWIFT_DEFER { closureUseDataflowState.clear (); };
2329
- return closureUseDataflowState.process (address, calleeOperandState,
2330
- closureConsumes);
2331
- }
2332
-
2333
2334
bool MoveKillsCopyableAddressesChecker::check (SILValue address) {
2334
2335
auto accessPathWithBase = AccessPathWithBase::compute (address);
2335
2336
auto accessPath = accessPathWithBase.accessPath ;
@@ -2394,8 +2395,7 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
2394
2395
// diagnostic.
2395
2396
bool emittedSingleBBDiagnostic = false ;
2396
2397
for (auto *mvi : useState.markMoves ) {
2397
- emittedSingleBBDiagnostic |= performSingleBasicBlockAnalysis (
2398
- dataflowState, debugInfoBlockSplitPoints, address, mvi);
2398
+ emittedSingleBBDiagnostic |= performSingleBasicBlockAnalysis (address, mvi);
2399
2399
}
2400
2400
2401
2401
if (emittedSingleBBDiagnostic) {
0 commit comments