Example #1
0
/* Useful for printing annotations as comments.  Expects that
 * the annotation is a BrickAnnote. */
  void
Printer::print_annote(Annote *annote)
{
  start_comment();

  IdString name = annote->get_name();

  if (name != k_comment)
    fprintf(out, "[%s", name.chars());

  if (is_kind_of<BrickAnnote>(annote)) {
    BrickAnnote *an = (BrickAnnote *)(annote);
    char *separator = ": ";

    for (Iter<SuifBrick*> iter = an->get_brick_iterator();
        iter.is_valid(); iter.next())
    {
      fputs(separator, out);
      separator = ", ";

      SuifBrick *brick = iter.current();
      if (is_a<IntegerBrick>(brick)) {
        Integer i = ((IntegerBrick*)iter.current())->get_value();
        if (i.is_c_string_int())
          fputs(i.chars(), out);
        else
          fprintf(out, "%ld", i.c_long());
      }
      else if (is_a<StringBrick>(brick)) {
        putc('"', out);
        for (const char *p =
            ((StringBrick*)iter.current())->get_value().c_str();
            *p != '\0'; ++p)
        {
          if (*p == '"' || *p == '\\')
            putc('\\', out);
          putc(*p, out);
        }
        putc('"', out);
      }
      else {
        claim(is_a<SuifObjectBrick>(brick));
        SuifObject *so = ((SuifObjectBrick*)brick)->get_object();
        if (is_kind_of<Type>(so))
          fprint(out, (TypeId)so);
        else {
          const char *kind = so ? get_class_name(so) : "NULL";
          fprintf(out, "<<<%s object>>>", kind);
        }
      }
    }
  } else {
    claim(is_kind_of<GeneralAnnote>(annote), "Unexpected kind of Annote");
  }
  if (name != k_comment)
    fputs("]", out);
  fputs("\n", out);
}
void CopyPropagationPass2::ProcessSpecialIfs()
{
  list<IfStatement*>* allIfs = 
    collect_objects<IfStatement>(procDef->get_body()) ;

  assert(allIfs != NULL) ;

  list<IfStatement*>::iterator ifIter = allIfs->begin() ;
  while (ifIter != allIfs->end())
  {

    Statement* elsePart = (*ifIter)->get_else_part() ;
    assert(elsePart != NULL) ;

    StatementList* elseList = dynamic_cast<StatementList*>(elsePart) ;
    if (elseList == NULL)
    {
      ++ifIter ;
      continue ;
    }

    assert(elseList != NULL) ;

    if (elseList->get_statement_count() == 2)
    {
      // Process this if statement
      Statement* thenPart = (*ifIter)->get_then_part() ;
      assert(thenPart != NULL) ;
      /*
      StatementList* thenList = dynamic_cast<StatementList*>(thenPart) ;
      assert(thenList != NULL) ;

      assert(thenList->get_statement_count() == 1) ;
      Statement* thenStatement = thenList->get_statement(0) ;
      assert(thenStatement != NULL) ;
      */
      StoreVariableStatement* thenStoreVar = 
	dynamic_cast<StoreVariableStatement*>(thenPart) ;
      assert(thenStoreVar != NULL) ;
      
      Statement* firstElseStatement = elseList->get_statement(0) ;
      Statement* secondElseStatement = elseList->get_statement(1) ;
      assert(firstElseStatement != NULL && secondElseStatement != NULL) ;

      // We are definitely going to break the rules here
      //  We know that the destination has to be replaced with 
      //  the source

      StoreVariableStatement* secondElseStore = 
	dynamic_cast<StoreVariableStatement*>(secondElseStatement) ;

      assert(secondElseStore != NULL) ;

      Expression* source = secondElseStore->get_value() ;
      assert(source != NULL) ;
      
      LoadVariableExpression* sourceLoadExp = 
	dynamic_cast<LoadVariableExpression*>(source) ;
      assert(sourceLoadExp != NULL) ;

      VariableSymbol* sourceVariable = sourceLoadExp->get_source() ;
      assert(sourceVariable != NULL) ;

      // First, find the use of the then portion and replace that use
      //  with the source variable
      BrickAnnote* ba = 
	to<BrickAnnote>(thenStoreVar->lookup_annote_by_name("reached_uses")) ;
      assert(ba != NULL) ;

      assert(ba->get_brick_count() == 1) ;

      Iter<SuifBrick*> tmpIter = ba->get_brick_iterator() ;
      
      SuifObjectBrick* sob = 
	to<SuifObjectBrick>(tmpIter.current()) ;
      assert(sob != NULL) ;

      SuifObject* finalDest = sob->get_object() ;

      LoadVariableExpression* finalLoad =
	dynamic_cast<LoadVariableExpression*>(finalDest) ;
      assert(finalLoad != NULL) ;

      // Before we make the change, mark the variable we are replacing as
      //  removed.
      finalLoad->get_source()->append_annote(create_brick_annote(theEnv, "RemovedVariable")) ;

      finalLoad->set_source(sourceVariable) ;

      // Now, change the then portion
      thenStoreVar->set_destination(sourceVariable) ;

      // Now, remove the second else statement
      elseList->remove_statement(1) ;

      // We should be done.

    }

    ++ifIter ;
  }

  delete allIfs ;
}
void CopyPropagationPass2::ProcessPossibleCopy(StoreVariableStatement* c)
{
  assert(c != NULL) ;
  // If this isn't a straight copy, just return
  LoadVariableExpression* replacement = 
    dynamic_cast<LoadVariableExpression*>(c->get_value()) ;
  if (replacement == NULL)
  {
    return ;
  }

  // If the variables are different types, don't propagate this away 
  //  (it is a cast)
  DataType* destType = c->get_destination()->get_type()->get_base_type() ;
  DataType* sourceType = replacement->get_source()->get_type()->get_base_type();
  if (!EquivalentTypes(destType, sourceType))
  {
    return ;
  }
     
  // Find all the reached uses
  BrickAnnote* reachedUses = 
    to<BrickAnnote>(c->lookup_annote_by_name("reached_uses")) ;

  assert(reachedUses != NULL) ;

  // Just in case we have no reached uses, we don't want to do 
  //  dead code elimination in this pass as well...
  bool removable = false ;

  Iter<SuifBrick*> useIter = reachedUses->get_brick_iterator() ;

  // First verify that we are the only definition for all of our uses.
  //  If we aren't then we can't make the replacement
  while(useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert (sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;
    if (IsOnlyDefinition(c, nextLoad) == false)
    {
      return ;
    }
    useIter.next() ;
  }

  // We also need to make sure that for each reached use, the copy is
  //  not redefined.  We do this by checking to make sure all of the
  //  definitions associated with it in the kill map are identical.
  //  This is a little conservative, but will make sure that no incorrect
  //  code is created.


  // Get the bit vector associated with all the reaching definitions
  //  coming into this statement
  BrickAnnote* inStatements = 
    dynamic_cast<BrickAnnote*>(c->lookup_annote_by_name("in_stmts")) ;
  assert(inStatements != NULL) ;
  SuifBrick* inBrick = inStatements->get_brick(0) ;
  assert(inBrick != NULL) ;
  SuifObjectBrick* inSOB = dynamic_cast<SuifObjectBrick*>(inBrick) ;
  assert(inSOB != NULL) ;
  SuifObject* inObj = inSOB->get_object() ;
  assert(inObj != NULL) ;
  BitVector2* inBits = dynamic_cast<BitVector2*>(inObj) ;
  assert(inBits != NULL) ;

  VariableSymbol* replacementVariable = replacement->get_source() ;
  assert(replacementVariable != NULL) ;

  list<std::pair<Statement*, int> >* definitions =killMap[replacementVariable];
  assert(definitions != NULL) ;

  list<bool> activeDefinitions ;
  list<std::pair<Statement*, int> >::iterator defIter = definitions->begin() ;
  while (defIter != definitions->end())
  {
    activeDefinitions.push_back(inBits->isMarked((*defIter).second)) ;
    ++defIter ;
  }

  useIter = reachedUses->get_brick_iterator() ;
  while (useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert(sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;
    SuifObject* loadParent = nextLoad->get_parent() ;
    while (dynamic_cast<Statement*>(loadParent) == NULL && loadParent != NULL)
    {
      loadParent = loadParent->get_parent() ;
    }
    assert(loadParent != NULL) ;
    Statement* parentStatement = dynamic_cast<Statement*>(loadParent) ;
    assert(parentStatement != NULL) ;
    BrickAnnote* parentInAnnote = dynamic_cast<BrickAnnote*>
      (parentStatement->lookup_annote_by_name("in_stmts")) ;
    assert(parentInAnnote != NULL) ;
    SuifBrick* parentInBrick = parentInAnnote->get_brick(0) ;
    assert(parentInBrick != NULL) ;
    SuifObjectBrick* parentInSOB = 
      dynamic_cast<SuifObjectBrick*>(parentInBrick) ;
    assert(parentInSOB != NULL) ;
    SuifObject* parentInObj = parentInSOB->get_object() ;
    assert(parentInObj != NULL) ;
    BitVector2* parentInBits = dynamic_cast<BitVector2*>(parentInObj) ;
    assert(parentInBits != NULL) ;

    defIter = definitions->begin() ;
    list<bool>::iterator activeIter = activeDefinitions.begin() ;
    while (defIter != definitions->end())
    {
      if ((*activeIter) != parentInBits->isMarked((*defIter).second))
      {
	// They are different, so don't do the replacement.
	return ;
      }
      ++activeIter ;
      ++defIter ;
    }

    useIter.next() ; 
  }
  
  // Now go through each reached use and replace it with the copy.
  //  Each reached use should be a load variable expression.
  //  We also have to deal with any feedback variables
  useIter = reachedUses->get_brick_iterator() ;
  while (useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert(sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;

    // Keep track of if we need to handle feedback variables
    HandleFeedbackVariables(nextLoad, replacement->get_source()) ;
    
    nextLoad->set_source(replacement->get_source()) ;

    removable = true ;

    useIter.next() ;
  }

  if (removable)
  {
    toBeRemoved.push_back(c) ;
  }  

}