Lib/Liveness/Liveness.cpp
/**
 * Determine the liveness sets for each instruction.
 */
Determine the liveness sets for each instruction.
Determine the liveness sets for each instruction .
void Liveness::compute_liveness(Instr::List &instrs) {
  setSize(instrs.size());
  RegIdSet liveIn;
  RegIdSet liveOut;
  bool changed = true;
  int count = 0;
  while (changed) {
    changed = false;
    for (int i = instrs.size() - 1; i >= 0; i--) {
      auto &instr = instrs[i];
      bool also_set_used = false;
      if (instr.isCondAssign()) {  
        Reg dst = instr.dst_a_reg();
        if (dst.tag != NONE) {
          auto &item = m_reg_usage[dst.regId];
          assert(item.first_dst() <= i);
          also_set_used = (item.first_dst() < i);
          if (!also_set_used) {
             Sanity check: in this case, we expect the variable to be in the condition assign block only
             Notably, this assertion fails for init of variables without an explicit init value.
             This can be extremely confusing, hence this comment.
            AssignCond assign_cond = instr.assign_cond();
            for (int j = item.first_usage(); j <= item.last_usage(); j++) {
              assertq((assign_cond == instrs[j].assign_cond())             expected usage
                   || (instrs[j].is_always() && !instrs[j].is_branch()),   Interim basic usage allowed (happens)
                "Expected variable to be in condition assign block only", true
              );
            }
          }
        }
      }
      t2.start();
       Compute 'use' and 'def' sets
      UseDef useDef(instr, also_set_used);
      t3.start();
      computeLiveOut(i, liveOut);
      t3.stop();
      t4.start();
      liveIn = liveOut;
      if (useDef.def.tag != NONE) {
        liveIn.remove(useDef.def.regId);   Remove the 'def' set from the live-out set to give live-in set
      }
      liveIn.add(useDef.use);
      t4.stop();
      t5.start();
      if (insert(i, liveIn)) {
        changed = true;
      }
      t5.stop();
      t2.stop();
    }
    count++;
  }
  t2.end();
  t3.end();
  t4.end();
  t5.end();
}
void Liveness :: compute_liveness ( Instr :: List & instrs ) { setSize ( instrs . size ( ) ) ; RegIdSet liveIn ; RegIdSet liveOut ; bool changed = true ; int count = 0 ; while ( changed ) { changed = false ; for ( int i = instrs . size ( ) - 1 ; i >= 0 ; i -- ) { auto & instr = instrs [ i ] ; bool also_set_used = false ; if ( instr . isCondAssign ( ) ) { Reg dst = instr . dst_a_reg ( ) ; if ( dst . tag != NONE ) { auto & item = m_reg_usage [ dst . regId ] ; assert ( item . first_dst ( ) <= i ) ; also_set_used = ( item . first_dst ( ) < i ) ; if ( ! also_set_used ) { AssignCond assign_cond = instr . assign_cond ( ) ; for ( int j = item . first_usage ( ) ; j <= item . last_usage ( ) ; j ++ ) { assertq ( ( assign_cond == instrs [ j ] . assign_cond ( ) ) || ( instrs [ j ] . is_always ( ) && ! instrs [ j ] . is_branch ( ) ) , " " , true ) ; } } } } UseDef useDef ( instr , also_set_used ) ; computeLiveOut ( i , liveOut ) ; liveIn = liveOut ; if ( useDef . def . tag != NONE ) { liveIn . remove ( useDef . def . regId ) ; } liveIn . add ( useDef . use ) ; if ( insert ( i , liveIn ) ) { changed = true ; } } count ++ ; } }
Determine the liveness sets for each instruction.
Determine the liveness sets for each instruction .
//Timer t("compute_liveness", true); // Initialise live mapping to have one entry per instruction /*
  // Went wrong with Seq<>, you never know later on
  for (int i = 0; i < (int) m_set.size(); i++) {
    assert(m_set[i].empty());
  }
*/ // For temporarily storing live-in and live-out variables //Timer t2("compute_liveness loop intern"); //Timer t3("compute liveOut"); //Timer t4("compute use/def rest"); //Timer t5("compute insert"); // Iterate until no change, i.e. fixed point // Propagate live variables backwards // no performance impact ~ 1.5% // If the dst variable is not used before, it should not be set as used as well // // Sanity check: in this case, we expect the variable to be in the condition assign block only // // Notably, this assertion fails for init of variables without an explicit init value. // This can be extremely confusing, hence this comment. // // expected usage // Interim basic usage allowed (happens) //t2.start(); // Compute 'use' and 'def' sets //t3.start(); //t3.stop(); //t4.start(); // Remove the 'def' set from the live-out set to give live-in set //t4.stop(); //t5.start(); //t5.stop(); //t2.stop(); //t2.end(); //t3.end(); //t4.end(); //t5.end(); /*
  std::string msg;
  msg << "compute_liveness num iterations: " << count;
  debug(msg);
*/