@@ -1915,12 +1915,193 @@ void DataflowState::init() {
19151915 }
19161916}
19171917
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+
19182101// Returns true if we emitted a diagnostic and handled the single block
19192102// case. Returns false if we visited all of the uses and seeded the UseState
19202103// 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 (
19242105 SILValue address, MarkUnresolvedMoveAddrInst *mvi) {
19252106 // First scan downwards to make sure we are move out of this block.
19262107 auto &useState = dataflowState.useState ;
@@ -2150,186 +2331,6 @@ static bool performSingleBasicBlockAnalysis(
21502331 return false ;
21512332}
21522333
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-
23332334bool MoveKillsCopyableAddressesChecker::check (SILValue address) {
23342335 auto accessPathWithBase = AccessPathWithBase::compute (address);
23352336 auto accessPath = accessPathWithBase.accessPath ;
@@ -2394,8 +2395,7 @@ bool MoveKillsCopyableAddressesChecker::check(SILValue address) {
23942395 // diagnostic.
23952396 bool emittedSingleBBDiagnostic = false ;
23962397 for (auto *mvi : useState.markMoves ) {
2397- emittedSingleBBDiagnostic |= performSingleBasicBlockAnalysis (
2398- dataflowState, debugInfoBlockSplitPoints, address, mvi);
2398+ emittedSingleBBDiagnostic |= performSingleBasicBlockAnalysis (address, mvi);
23992399 }
24002400
24012401 if (emittedSingleBBDiagnostic) {
0 commit comments