<commit_before>#include "astutil.h"
#include "bb.h"
#include "expr.h"
#include "optimizations.h"
#include "stmt.h"
#include "view.h"

//
// Removes local variables that are only targets for moves, but are
// never used anywhere.
//
static bool isDeadVariable(DefExpr* def) {
  if (isReference(def->sym->type)) {
    return def->sym->uses.n == 0 && def->sym->defs.n <= 1;
  } else {
    return def->sym->uses.n == 0;
  }
}

void deadVariableElimination(FnSymbol* fn) {
  bool change = true;
  while (change) {
    Vec<BaseAST*> asts;
    collect_asts(&asts, fn);
    compute_sym_uses(fn);
    change = false;
    forv_Vec(BaseAST, ast, asts) {
      if (DefExpr* def = dynamic_cast<DefExpr*>(ast)) {
        if (def->sym->astType != SYMBOL_VAR || def->parentSymbol != fn)
          continue; // only variables, no fields of nested types
        if (isDeadVariable(def)) {
          forv_Vec(SymExpr, se, def->sym->defs) {
            CallExpr* call = dynamic_cast<CallExpr*>(se->parentExpr);
            Expr* rhs = call->get(2);
            if (rhs->astType == EXPR_SYM)
              call->remove();
            else
              call->replace(rhs->remove());
          }
          def->remove();
          change = true;
        }
      }
    }
  }
}<commit_msg>Improved the performance of deadVariableElimination greatly.  It is no longer iterative in a general way but rather specifically tries to eliminate other variables as their uses are removed.<commit_after>#include "astutil.h"
#include "bb.h"
#include "expr.h"
#include "optimizations.h"
#include "stmt.h"
#include "view.h"

//
// Removes local variables that are only targets for moves, but are
// never used anywhere.
//
static bool isDeadVariable(Symbol* var) {
  if (isReference(var->type)) {
    return var->uses.n == 0 && var->defs.n <= 1;
  } else {
    return var->uses.n == 0;
  }
}

void deadVariableEliminationHelp(FnSymbol* fn, Symbol* var) {
  if (var->astType == SYMBOL_VAR &&
      var->defPoint &&
      var->defPoint->parentSymbol == fn &&
      isDeadVariable(var)) {
    forv_Vec(SymExpr, se, var->defs) {
      CallExpr* call = dynamic_cast<CallExpr*>(se->parentExpr);
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* rhs = dynamic_cast<SymExpr*>(call->get(2))) {
          call->remove();
          rhs->var->uses.n--;
          deadVariableEliminationHelp(fn, rhs->var);
        } else {
          call->replace(call->get(2)->remove());
        }
      } else
        INT_FATAL("unexpected case");
    }
    var->defPoint->remove();
  }
}

void deadVariableElimination(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  compute_sym_uses(fn);
  forv_Vec(BaseAST, ast, asts) {
    if (DefExpr* def = dynamic_cast<DefExpr*>(ast)) {
      deadVariableEliminationHelp(fn, def->sym);
    }
  }
}
{'fraction_non_alphanumeric': 0.15307938768244927, 'fraction_numerical': 0.003203987184051264, 'mean_word_length': 2.7466666666666666, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3740147', 'n_tokens_mistral': 937, 'n_tokens_neox': 932, 'n_words': 215}