void ReturnByRef::returnByRefCollectCalls(RefMap& calls) { RefMap::iterator iter; forv_Vec(CallExpr, call, gCallExprs) { if (FnSymbol* fn = theTransformableFunction(call)) { RefMap::iterator iter = calls.find(fn->id); ReturnByRef* info = NULL; if (iter == calls.end()) { info = new ReturnByRef(fn); calls[fn->id] = info; } else { info = iter->second; } info->addCall(call); } } }
void ReturnByRef::apply() { RefMap map; RefMap::iterator iter; returnByRefCollectCalls(map); for (iter = map.begin(); iter != map.end(); iter++) iter->second->transform(); for (int i = 0; i < virtualMethodTable.n; i++) { if (virtualMethodTable.v[i].key) { int numFns = virtualMethodTable.v[i].value->n; for (int j = 0; j < numFns; j++) { FnSymbol* fn = virtualMethodTable.v[i].value->v[j]; if (isTransformableFunction(fn)) transformFunction(fn); } } } }
void ReturnByRef::apply() { RefMap map; RefMap::iterator iter; FnSet asgnUpdates; returnByRefCollectCalls(map, asgnUpdates); for (iter = map.begin(); iter != map.end(); iter++) iter->second->transform(); for_set(FnSymbol, fn, asgnUpdates) updateAssignments(fn); for (int i = 0; i < virtualMethodTable.n; i++) { if (virtualMethodTable.v[i].key) { int numFns = virtualMethodTable.v[i].value->n; for (int j = 0; j < numFns; j++) { FnSymbol* fn = virtualMethodTable.v[i].value->v[j]; TransformationKind tfKind = transformableFunctionKind(fn); if (tfKind == TF_FULL) transformFunction(fn); else if (tfKind == TF_ASGN) updateAssignments(fn); } } } }
void CacheGitDirectory::registerEntryInRefMap(const std::string& hash, RefMap& refMap) { assert(isInRef()); /* Find the cache entry that corresponds to this hash. * Create a new entry if not found. */ auto itFind = gitHashMap_.find(hash); GitCacheEntry* entry; if (itFind == gitHashMap_.end()) { entry = new GitCacheEntry(); entry->hash = hash; gitHashMap_[hash] = entry; } else { entry = itFind->second; } /* Look in the refMap for any CacheEntry that was already linked to the * current git ref. */ auto itPrevEntry = refMap.find(currentGitRef_); if (itPrevEntry != refMap.end()) { GitCacheEntry* prevEntry = itPrevEntry->second; assert(prevEntry->numGitRefs > 0); prevEntry->numGitRefs--; if (prevEntry->numGitRefs == 0 && prevEntry != entry) { DLOG(INFO) << "deleting " << prevEntry->hash; cacheFs_.delEntry(prevEntry->hash); gitHashMap_.erase(prevEntry->hash); delete prevEntry; } } refMap[currentGitRef_] = entry; entry->numGitRefs++; }
// Insert pairs into available copies map // Also, record references when they are created. static void extractReferences(Expr* expr, RefMap& refs) { // We're only interested in call expressions. if (CallExpr* call = toCallExpr(expr)) { // Only the move primitive creates an available pair. if (call->isPrimitive(PRIM_MOVE) || call->isPrimitive(PRIM_ASSIGN)) { SymExpr* lhe = toSymExpr(call->get(1)); // Left-Hand Expression Symbol* lhs = lhe->var; // Left-Hand Symbol if (SymExpr* rhe = toSymExpr(call->get(2))) // Right-Hand Expression { Symbol* rhs = rhe->var; // Right-Hand Symbol if (lhs->type->symbol->hasFlag(FLAG_REF) && rhs->type->symbol->hasFlag(FLAG_REF)) { // This is a ref <- ref assignment. // Which means that the lhs is now also a reference to whatever the // rhs refers to. RefMap::iterator refDef = refs.find(rhs); // Refs can come from outside the function (e.g. through arguments), // so are not necessarily defined within the function. if (refDef != refs.end()) { Symbol* val = refDef->second; #if DEBUG_CP if (debug > 0) printf("Creating ref (%s[%d], %s[%d])\n", lhs->name, lhs->id, val->name, val->id); #endif refs.insert(RefMapElem(lhs, val)); } } } if (CallExpr* rhc = toCallExpr(call->get(2))) { if (rhc->isPrimitive(PRIM_ADDR_OF)) { SymExpr* rhe = toSymExpr(rhc->get(1)); // Create the pair lhs <- &rhs. Symbol* lhs = lhe->var; Symbol* rhs = rhe->var; #if DEBUG_CP if (debug > 0) printf("Creating ref (%s[%d], %s[%d])\n", lhs->name, lhs->id, rhs->name, rhs->id); #endif refs.insert(RefMapElem(lhs, rhs)); } } } } }
void ReturnByRef::returnByRefCollectCalls(RefMap& calls, FnSet& fns) { RefMap::iterator iter; forv_Vec(CallExpr, call, gCallExprs) { // Only transform calls that are still in the AST tree // (defer statement bodies have been removed at this point // in this pass) if (call->inTree()) { // Only transform calls to transformable functions // The common case is a user-level call to a resolved function // Also handle the PRIMOP for a virtual method call if (FnSymbol* fn = call->resolvedOrVirtualFunction()) { TransformationKind tfKind = transformableFunctionKind(fn); if (tfKind == TF_FULL) { RefMap::iterator iter = calls.find(fn->id); ReturnByRef* info = NULL; if (iter == calls.end()) { info = new ReturnByRef(fn); calls[fn->id] = info; } else { info = iter->second; } info->addCall(call); } else if (tfKind == TF_ASGN) { fns.insert(fn); } } } } }
void Liveness::emptify(RefMap &M) { for (auto I = M.begin(), E = M.end(); I != E; ) I = I->second.empty() ? M.erase(I) : std::next(I); }