bool RLEContext::gatherValues(SILBasicBlock *BB, MemLocation &L, MemLocationValueMap &Values, bool UseForwardValOut) { MemLocationSet CSLocs; MemLocationList Locs; MemLocation::expand(L, &BB->getModule(), Locs, getTypeExpansionCache()); // Are we using the ForwardVal at the end of the basic block or not. // If we are collecting values at the end of the basic block, we can // use its ForwardValOut. // BBState &Forwarder = getBBLocState(BB); ValueTableMap &OTM = UseForwardValOut ? Forwarder.getForwardValOut() : Forwarder.getForwardValIn(); for (auto &X : Locs) { Values[X] = OTM[getMemLocationBit(X)]; if (!Values[X].isCoveringValue()) continue; CSLocs.insert(X); } // Try to reduce it to the minimum # of locations possible, this will help // us to generate as few extractions as possible. MemLocation::reduce(L, &BB->getModule(), CSLocs); // To handle covering value, we need to go to the predecessors and // materialize them there. for (auto &X : CSLocs) { SILValue V = computePredecessorCoveringValue(BB, X); if (!V) return false; // We've constructed a concrete value for the covering value. Expand and // collect the newly created forwardable values. MemLocationList Locs; LoadStoreValueList Vals; MemLocation::expandWithValues(X, V, &BB->getModule(), Locs, Vals); for (unsigned i = 0; i < Locs.size(); ++i) { Values[Locs[i]] = Vals[i]; assert(Values[Locs[i]].isValid() && "Invalid load store value"); } } // Sanity check to make sure we have valid load store values for each // MemLocation. #ifndef NDEBUG for (auto &X : Locs) { (void)X; assert(Values[X].isValid() && "Invalid load store value"); } #endif return true; }
void MemLocation::reduce(MemLocation &Base, SILModule *Mod, MemLocationSet &Locs) { // First, construct the MemLocation by appending the projection path from the // accessed node to the leaf nodes. MemLocationList ALocs; ProjectionPathList Paths; ProjectionPath::expandTypeIntoLeafProjectionPaths(Base.getType(), Mod, Paths, false); for (auto &X : Paths) { ALocs.push_back(MemLocation::createMemLocation(Base.getBase(), X.getValue(), Base.getPath().getValue())); } // Second, go from leaf nodes to their parents. This guarantees that at the // point the parent is processed, its children have been processed already. for (auto I = ALocs.rbegin(), E = ALocs.rend(); I != E; ++I) { MemLocationList FirstLevel; I->getFirstLevelMemLocations(FirstLevel, Mod); // Reached the end of the projection tree, this is a leaf node. if (FirstLevel.empty()) continue; // If this is a class reference type, we have reached end of the type tree. if (I->getType().getClassOrBoundGenericClass()) continue; // This is NOT a leaf node, check whether all its first level children are // alive. bool Alive = true; for (auto &X : FirstLevel) { if (Locs.find(X) != Locs.end()) continue; Alive = false; } // All first level locations are alive, create the new aggregated location. if (Alive) { for (auto &X : FirstLevel) Locs.erase(X); Locs.insert(*I); } } }