void deadVariableElimination(FnSymbol* fn) {
  Vec<Symbol*> symSet;
  Vec<SymExpr*> symExprs;
  collectSymbolSetSymExprVec(fn, symSet, symExprs);

  Map<Symbol*,Vec<SymExpr*>*> defMap;
  Map<Symbol*,Vec<SymExpr*>*> useMap;
  buildDefUseMaps(symSet, symExprs, defMap, useMap);

  forv_Vec(Symbol, sym, symSet)
  {
    // We're interested only in VarSymbols.
    if (!isVarSymbol(sym))
      continue;

    // A method must have a _this symbol, even if it is not used.
    if (sym == fn->_this)
      continue;

    if (isDeadVariable(sym, defMap, useMap)) {
      for_defs(se, defMap, sym) {
        CallExpr* call = toCallExpr(se->parentExpr);
        INT_ASSERT(call &&
                   (call->isPrimitive(PRIM_MOVE) ||
                    call->isPrimitive(PRIM_ASSIGN)));
        Expr* rhs = call->get(2)->remove();
        if (!isSymExpr(rhs))
          call->replace(rhs);
        else
          call->remove();
      }
      sym->defPoint->remove();
    }
  }
Exemple #2
0
/*
 * Returns true if `e` has no side effects. Checked side effects are:
 *  - Read/write to a global
 *  - Is/contains essential primitive
 *  - If it's a call to functions with ref arguments
 *  - If the LHS of a PRIM_MOVE appears in the exprToMove
 *
 * For now, this is a very conservative analysis. A more precise analysis
 * could distinguish between reads and writes to memory and to take into
 * account alias analysis.
 */
bool SafeExprAnalysis::exprHasNoSideEffects(Expr* e, Expr* exprToMove) {
  if(safeExprCache.count(e) > 0) {
    return safeExprCache[e];
  }
  if(CallExpr* ce = toCallExpr(e)) {
    if(!ce->isPrimitive()) {
      FnSymbol* fnSym = ce->theFnSymbol();
      const bool cachedSafeFn = safeFnCache.count(fnSym);
      if(!cachedSafeFn) {
        const bool retval = fnHasNoSideEffects(fnSym);
        safeFnCache[fnSym] = retval;
        return retval;
      }
      return safeFnCache[fnSym];
    }
    else {
      //primitive
      if(! isSafePrimitive(ce)){
        safeExprCache[e] = false;
        return false;
      }
      else if (exprToMove != NULL) {
        //
        // Exposed by AST pattern like this:
        //          |---|------- `exprToMove`
        // (move T (+ A B))
        // (move A B) -------- `ce`
        // (move B T)
        //
        // Without this check could turn into:
        //
        // (move A B)
        // (move B (+ A B))
        //
        // Which is incorrect.
        //
        if (ce->isPrimitive(PRIM_MOVE)) {
          INT_ASSERT(isSymExpr(ce->get(1)));
          std::vector<SymExpr*> syms;
          collectSymExprs(exprToMove, syms);
          for_vector(SymExpr, s, syms) {
            if (s->symbol() == toSymExpr(ce->get(1))->symbol()) {
              safeExprCache[e] = false;
              return false;
            }
          }
        }
      }
    }
  }
Exemple #3
0
void BlockStmt::verify() {
  Expr::verify();

  if (astTag != E_BlockStmt) {
    INT_FATAL(this, "BlockStmt::verify. Bad astTag");
  }

  if (body.parent != this)
    INT_FATAL(this, "BlockStmt::verify. Bad body.parent");

  for_alist(expr, body) {
    if (expr->parentExpr != this)
      INT_FATAL(this, "BlockStmt::verify. Bad body.expr->parentExpr");
  }

  if (blockInfo != NULL && blockInfo->parentExpr != this) {
    INT_FATAL(this, "BlockStmt::verify. Bad blockInfo->parentExpr");
  }

  if (useList   != NULL && useList->parentExpr   != this) {
    INT_FATAL(this, "BlockStmt::verify. Bad useList->parentExpr");
  }

  if (byrefVars) {
    if (byrefVars->parentExpr != this) {
      INT_FATAL(this, "BlockStmt::verify. Bad byrefVars->parentExpr");
    }

    if (!byrefVars->isPrimitive(PRIM_ACTUALS_LIST)) {
      INT_FATAL(this, "BlockStmt::byrefVars not PRIM_ACTUALS_LIST");
    }

    for_actuals(varExp, byrefVars) {
      if (!isSymExpr(varExp) && !isUnresolvedSymExpr(varExp)) {
        INT_FATAL(this, "BlockStmt::verify. Bad expression kind in byrefVars");
      }
    }
  }

  verifyNotOnList(useList);
  verifyNotOnList(byrefVars);
  verifyNotOnList(blockInfo);
}