=== osprey/be/opt/wssa_emitter.cxx
==================================================================
--- osprey/be/opt/wssa_emitter.cxx	(/mirror/open64-trunk)	(revision 2914)
+++ osprey/be/opt/wssa_emitter.cxx	(/ssa-whirl)	(revision 2914)
@@ -485,6 +485,16 @@
     Update_def_ver(res_idx, wn, WSSA::WSSA_CHI);
   }
 
+  WSSA::WST_IDX wst_idx = _opt_stab->Aux_stab_entry(chi_node->Aux_id())->Get_wst_idx();
+  Is_True(_wssa_mgr->Get_ver_wst(res_idx) == wst_idx&&
+          _wssa_mgr->Get_ver_wst(opnd_idx) == wst_idx,
+          ("wst_idx of chi node and coderep mismatch"));
+  if (_wssa_mgr->WN_chi_node(wn, wst_idx) != NULL) {
+    if (_trace)
+      fprintf(TFile, "skip copy for duplicated chi node\n");
+    return;
+  }
+
   if (res_idx == opnd_idx) {
     if (_trace)
       fprintf(TFile, "skip copy for result and opnd same chi node\n");
@@ -524,6 +534,15 @@
     opnd_idx = New_use_ver(mu_node->OPND(), wn);
   }
   wssa_mu->Set_opnd(opnd_idx);
+  WSSA::WST_IDX wst_idx = _opt_stab->Aux_stab_entry(mu_node->Aux_id())->Get_wst_idx();
+  Is_True(_wssa_mgr->Get_ver_wst(opnd_idx) == wst_idx,
+          ("wst_idx of mu node and coderep mismatch"));
+  if (_wssa_mgr->WN_mu_node(wn, wst_idx) != NULL) {
+    if (_trace)
+      fprintf(TFile, "skip copy for duplicated mu node\n");
+    return;
+  }
+
   _wssa_mgr->Add_mu(wn, wssa_mu);
 
   if (_trace) {
@@ -593,6 +612,17 @@
   for (INT32 i = 0; i < opnd_count; ++i) {
     wssa_phi->Set_opnd(i, ver_list[i]);
   }
+
+  WSSA::WST_IDX wst_idx = _opt_stab->Aux_stab_entry(phi_node->Aux_id())->Get_wst_idx();
+  Is_True(_wssa_mgr->Get_ver_wst(res_idx) == wst_idx&&
+          _wssa_mgr->Get_ver_wst(ver_list[0]) == wst_idx,
+          ("wst_idx of phi node and coderep mismatch"));
+  if (_wssa_mgr->WN_phi_node(wn, wst_idx) != NULL) {
+    if (_trace)
+      fprintf(TFile, "skip copy for duplicated phi node\n");
+    return;
+  }
+
   _wssa_mgr->Add_phi(wn, wssa_phi);
 
   if (_trace) {
=== osprey/be/com/wn_cfg.h
==================================================================
--- osprey/be/com/wn_cfg.h	(/mirror/open64-trunk)	(revision 2914)
+++ osprey/be/com/wn_cfg.h	(/ssa-whirl)	(revision 2914)
@@ -238,8 +238,9 @@
   friend class WN_CFG_BUILDER;
   template<typename _Tcfg> friend class WN_CFG_BUILD_ACTION;
   template<typename _Tcfg> friend class WN_CFG_VERIFIER;
-  template<typename _Tcfg> friend class PARENTIZE_ACTION;
-  template<typename _Tcfg> friend class PARENTIZE_VERIFIER;
+  template<typename _Tcfg> friend class PARENTMAP_BUILD_ACTION;
+  template<typename _Tcfg> friend class PARENTMAP_VERIFY_VERIFIER;
+
   // only accessable for WN_CFG_BUILDER
   void Set_parent(WN* parent, WN* kid);
   void Remove_parent(WN* wn);
@@ -281,6 +282,10 @@
   WN* Get_branch_stmt(BB_NODE* node) const;
 
 public:
+  void Build();
+  void Verify();
+
+public:
   // update interface
   void Insert_before(WN* before, WN* stmt, BOOL reparentize = TRUE) {
     CFG::Insert_before(before, stmt);
@@ -429,9 +434,5 @@
 
 } /* namespace CFG_UTIL */
 
-#ifdef Is_True_On
-void Test_CFG(WN* wn);
-#endif
-
 #endif /* wn_cfg_INCLUDED */
 
=== osprey/be/com/cfg_base.h
==================================================================
--- osprey/be/com/cfg_base.h	(/mirror/open64-trunk)	(revision 2914)
+++ osprey/be/com/cfg_base.h	(/ssa-whirl)	(revision 2914)
@@ -52,6 +52,8 @@
 #include <algorithm>
 using namespace std;
 
+#define POS_INVALID -1
+
 namespace CFG_UTIL {
 
 // Forward declaration of DOM_BUILDER, DF_BUILDER, CFG_BASE, DFS_ITERATOR
@@ -221,6 +223,8 @@
   STMT First_stmt() const  { return _stmts.First_stmt(); }
   STMT Last_stmt() const   { return _stmts.Last_stmt();  }
   BOOL Is_empty() const    { return _stmts.Is_empty();   }
+  STMT Next_stmt(STMT stmt) const  { return _stmts.Next_stmt(stmt); }
+  STMT Prev_stmt(STMT stmt) const  { return _stmts.Prev_stmt(stmt); }
   void Insert_before(STMT before, STMT stmt) {
     _stmts.Insert_before(before, stmt);
   }
@@ -283,7 +287,7 @@
         return pos;
       ++pos;
     }
-    FmtAssert(FALSE, ("can not find pred pos"));
+    return POS_INVALID;
   }
   INT32 Succ_pos(BB_NODE* succ) {
     INT32 pos = 0;
@@ -294,7 +298,7 @@
         return pos;
       ++pos;
     }
-    FmtAssert(FALSE, ("can not find succ pos"));
+    return POS_INVALID;
   }
 
   // dominator and post-dominator related methods
=== osprey/be/com/wn_cfg.cxx
==================================================================
--- osprey/be/com/wn_cfg.cxx	(/mirror/open64-trunk)	(revision 2914)
+++ osprey/be/com/wn_cfg.cxx	(/ssa-whirl)	(revision 2914)
@@ -39,6 +39,7 @@
 //====================================================================
 
 #include "wn_cfg.h"
+#include "wn_cfg_template.h"
 #include "cfg_util.h"
 #include "ir_reader.h"
 #include <ext/hash_set>
@@ -522,6 +523,40 @@
   }
 }
 
+void
+WN_CFG::Build() {
+  Is_True(_root != NULL, ("root wn is NULL"));
+
+  // build parent map
+  PARENTMAP_BUILD_ACTION<WN_CFG> map_helper(*this);
+  WN_TREE_TRAVERSE<PARENTMAP_BUILD_ACTION<WN_CFG> > map_traveler(map_helper);
+  map_traveler.Traverse(_root);
+
+  // build CFG
+  WN_CFG_BUILD_ACTION<WN_CFG> cfg_helper(*this);
+  WN_CFG_TRAVERSE<WN_CFG_BUILD_ACTION<WN_CFG> > cfg_traveler(cfg_helper);
+  cfg_traveler.Traverse(_root);
+
+  // resolve the connectivity issue
+  CFG_UTIL::CFG_CONNECTIVITY<CFG_UTIL::WN_CFG> connectivity(*this);
+  connectivity.Perform();
+} 
+
+void
+WN_CFG::Verify() {
+  Is_True(_root != NULL, ("root wn is NULL"));
+
+  // verify parent map
+  PARENTMAP_VERIFY_ACTION<WN_CFG> map_helper(*this);
+  WN_TREE_TRAVERSE<PARENTMAP_VERIFY_ACTION<WN_CFG> > map_traveler(map_helper);
+  map_traveler.Traverse(_root);
+
+  // verify CFG
+  WN_CFG_VERIFY_ACTION<WN_CFG> cfg_helper(*this);
+  WN_CFG_TRAVERSE<WN_CFG_VERIFY_ACTION<WN_CFG> > cfg_traveler(cfg_helper);
+  cfg_traveler.Traverse(_root);
+}
+
 //===================================================================
 // Build_CFG
 //   Build CFG and parent map based on WHIRL tree
@@ -996,15 +1031,19 @@
   Add_stmt(cfg, _current_bb, wn);
   BB_NODE* condgoto_bb = _current_bb;
 
-  // connect the target of CONDGOTO if it's exist or push to list
-  LABEL_MAP::iterator lit = _label_map.find(WN_label_number(wn));
-  if (lit != _label_map.end()) {
-    cfg.Connect_predsucc(_current_bb, lit->second);
+  WN* next = WN_next(wn);
+  if (next == NULL || WN_operator(next) != OPR_LABEL ||
+      WN_label_number(wn) != WN_label_number(next)) {
+    // connect the target of CONDGOTO if it's exist or push to list
+    LABEL_MAP::iterator lit = _label_map.find(WN_label_number(wn));
+    if (lit != _label_map.end()) {
+      cfg.Connect_predsucc(_current_bb, lit->second);
+    }
+    else {
+      vector<BB_NODE*>& gotos = _goto_map[WN_label_number(wn)];
+      gotos.push_back(_current_bb);
+    }
   }
-  else {
-    vector<BB_NODE*>& gotos = _goto_map[WN_label_number(wn)];
-    gotos.push_back(_current_bb);
-  }
 
   // create and connect BB1
   _current_bb = cfg.Create_node();
=== osprey/be/com/wssa_update.cxx
==================================================================
--- osprey/be/com/wssa_update.cxx	(/mirror/open64-trunk)	(revision 2914)
+++ osprey/be/com/wssa_update.cxx	(/ssa-whirl)	(revision 2914)
@@ -391,6 +391,7 @@
     WN* stmt = succ->First_stmt();
     if (stmt != NULL && _ssa->WN_has_phi(stmt)) {
       INT pred_pos = succ->Pred_pos(pred);
+      Is_True(pred_pos != POS_INVALID, ("can not find pred"));
       Is_True(succ->Get_pred(pred_pos) == pred, ("pred succ mismatch"));
       for (WHIRL_SSA_MANAGER::phi_iterator pit = _ssa->WN_phi_begin(stmt);
            pit != _ssa->WN_phi_end(stmt);
@@ -833,6 +834,7 @@
     WN* stmt = succ->First_stmt();
     if (stmt != NULL && _ssa->WN_has_phi(stmt)) {
       INT pred_pos = succ->Pred_pos(pred);
+      Is_True(pred_pos != POS_INVALID, ("can not find pred"));
       Is_True(succ->Get_pred(pred_pos) == pred, ("pred succ mismatch"));
       for (WHIRL_SSA_MANAGER::phi_iterator pit = _ssa->WN_phi_begin(stmt);
            pit != _ssa->WN_phi_end(stmt);
=== osprey/be/com/wn_cfg_template.h
==================================================================
--- osprey/be/com/wn_cfg_template.h	(/mirror/open64-trunk)	(revision 2914)
+++ osprey/be/com/wn_cfg_template.h	(/ssa-whirl)	(revision 2914)
@@ -55,16 +55,30 @@
 namespace CFG_UTIL {
 
 //===================================================================
-// class PARENTMAP_BUILDER
+// class PARENTMAP_ACTION_BASE
+//  base class to build or verify the parent map
+//===================================================================
+template<typename _Tcfg>
+class PARENTMAP_ACTION_BASE {
+public:
+  void Initialize() {
+  }
+
+  void Finalize() {
+  }
+};
+
+//===================================================================
+// class PARENTMAP_BUILD_ACTION
 //  class to build the parent map
 //===================================================================
 template<typename _Tcfg>
-class PARENTIZE_ACTION {
+class PARENTMAP_BUILD_ACTION : public PARENTMAP_ACTION_BASE<_Tcfg> {
 private:
   _Tcfg& _cfg;
 
 public:
-  PARENTIZE_ACTION(_Tcfg& cfg) : _cfg(cfg) {
+  PARENTMAP_BUILD_ACTION(_Tcfg& cfg) : _cfg(cfg) {
   }
 
 public:
@@ -74,22 +88,22 @@
 };
 
 //===================================================================
-// class PARENTMAP_VERIFIER
+// class PARENTMAP_VERIFY_ACTION
 //  class to verfy the parent map
 //===================================================================
 template<typename _Tcfg>
-class PARENTIZE_VERIFIER {
+class PARENTMAP_VERIFY_ACTION : public PARENTMAP_ACTION_BASE<_Tcfg> {
 private:
   _Tcfg& _cfg;
 
 public:
-  PARENTIZE_VERIFIER(_Tcfg& cfg) : _cfg(cfg) {
+  PARENTMAP_VERIFY_ACTION(_Tcfg& cfg) : _cfg(cfg) {
   }
 
 public:
   void Process(WN* parent, WN* kid) const {
     Is_True(_cfg.Get_parent(kid) == parent, 
-            ("PARENTIZE_VERIFIER: parent mismatch"));
+            ("PARENTMAP VERIFY: parent and kid mismatch"));
   }
 };
 
@@ -106,24 +120,35 @@
   WN_TREE_TRAVERSE(_Ttraverser& traverser) : _traverser(traverser) {
   }
 
-public:
-  void Traverse(WN* wn) {
+private:
+  void Traverse_rec(WN* wn) {
     Is_True(wn != NULL && WN_operator(wn) != OPERATOR_UNKNOWN,
             ("invalid WHIRL node"));
 
     if (WN_operator(wn) == OPR_BLOCK) {
       for (WN* item = WN_first(wn); item != NULL; item = WN_next(item)) {
         _traverser.Process(wn, item);
-        Traverse(item);
+        Traverse_rec(item);
       }
     }
     else {
       for (INT i = 0; i < WN_kid_count(wn); ++i) {
         _traverser.Process(wn, WN_kid(wn, i));
-        Traverse(WN_kid(wn, i));
+        Traverse_rec(WN_kid(wn, i));
       }
     }
   }
+
+public:
+  void Traverse(WN* wn) {
+    Is_True(wn != NULL &&
+            (WN_operator(wn) == OPR_FUNC_ENTRY ||
+             WN_operator(wn) == OPR_REGION),
+            ("invalid WHIRL node"));
+    _traverser.Initialize();
+    Traverse_rec(wn);
+    _traverser.Finalize();
+  }
 };
 
 //===================================================================
@@ -176,6 +201,24 @@
   WN_CFG_BUILD_ACTION(_Tcfg& cfg) : WN_CFG_ACTION_BASE<_Tcfg> (cfg) {
   }
 
+  void Initialize() {
+  }
+
+  void Finalize() {
+#ifdef Is_True_On
+    Is_True(_goto_map.empty(), ("found unresolved GOTOs"));
+    for (typename LABEL_MAP::iterator it = _label_map.begin();
+         it != _label_map.end();
+         ++it) {
+      WN* stmt = it->second->First_stmt();
+      Is_True(stmt != NULL && WN_operator(stmt) == OPR_LABEL,
+              ("first stmt is not LABEL"));
+      Is_True(WN_label_number(stmt) == it->first,
+              ("LABEL number mismatch"));
+    }
+#endif    
+  }
+
 public:
   void Process_root(WN* root) {
     ACTION_BASE::_cfg.Set_wn_root(root);
@@ -251,9 +294,15 @@
     }
   }
 
-  BB_NODE* Create_node(WN* stmt) {
+  BB_NODE* Create_node(BB_NODE* node, WN* stmt) {
     return ACTION_BASE::_cfg.Create_node();
   }
+
+  BOOL Need_new_node(BB_NODE* node, WN* stmt) {
+    Is_True(node != NULL, ("node is NULL"));
+    return !node->Is_empty();
+  }
+
 };
 
 //===================================================================
@@ -264,57 +313,323 @@
 class WN_CFG_VERIFY_ACTION : public  WN_CFG_ACTION_BASE<_Tcfg> {
 public:
   typedef typename _Tcfg::BB_NODE BB_NODE;
+  typedef WN_CFG_ACTION_BASE<_Tcfg> ACTION_BASE;
 
 private:
-  _Tcfg& _cfg;
+  BB_NODE* _verify_node;
+  WN*      _verify_stmt;
+  typedef hash_set<INTPTR> NODE_SET;
+  vector<NODE_SET> _verify_preds;
+  vector<NODE_SET> _verify_succs;
 
+private:
+  BOOL Is_stmt_in_node(BB_NODE* node, WN* stmt) {
+    if (node == _verify_node && node->Next_stmt(_verify_stmt) == stmt) {
+      _verify_stmt = stmt;
+      return TRUE;
+    }
+    if (node->First_stmt() == stmt) {
+      _verify_node = node;
+      _verify_stmt = stmt;
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  BOOL Is_stmt_goto_label(WN* stmt, WN* label) {
+    OPERATOR opr = WN_operator(stmt);
+    FmtAssert(stmt != NULL &&
+              (opr == OPR_GOTO ||
+               opr == OPR_CASEGOTO ||
+               opr == OPR_TRUEBR ||
+               opr == OPR_FALSEBR ||
+               opr == OPR_REGION_EXIT ||
+               opr == OPR_SWITCH ||
+               opr == OPR_COMPGOTO),
+              ("stmt is not GOTO"));
+    FmtAssert(label != NULL &&
+              WN_operator(label) == OPR_LABEL,
+              ("label is not LABEL"));
+    if (opr == OPR_GOTO || opr == OPR_CASEGOTO ||
+        opr == OPR_TRUEBR || opr == OPR_FALSEBR ||
+        opr == OPR_REGION_EXIT) {
+      return WN_label_number(stmt) == WN_label_number(label);
+    }
+    else {
+      FmtAssert(opr == OPR_SWITCH || opr == OPR_COMPGOTO,
+                ("invalid opr"));
+      for (WN* goto_wn = WN_first(WN_switch_table(stmt));
+           goto_wn != NULL;
+           goto_wn = WN_next(goto_wn)) {
+        if (WN_label_number(goto_wn) == WN_label_number(label))
+          return TRUE;
+      }
+      if (WN_label_number(WN_switch_default(stmt)) == 
+          WN_label_number(label))
+        return TRUE;
+      else
+        return FALSE;
+    }
+  }
+
+  BOOL Is_kid_of_stmt(WN* stmt, WN* kid) {
+    FmtAssert(stmt != NULL &&
+              (WN_operator(stmt) == OPR_SWITCH ||
+               WN_operator(stmt) == OPR_COMPGOTO),
+              ("stmt is not SWITCH or COMPGOTO"));
+    FmtAssert(kid != NULL &&
+              (WN_operator(kid) == OPR_GOTO ||
+               WN_operator(kid) == OPR_CASEGOTO),
+              ("kid is not GOTO or CASEGOTO"));
+    for (WN* goto_wn = WN_first(WN_switch_table(stmt));
+         goto_wn != NULL;
+         goto_wn = WN_next(goto_wn)) {
+      if (goto_wn == kid)
+        return TRUE;
+    }
+    if (WN_switch_default(stmt) == kid)
+      return TRUE;
+    else
+      return FALSE;
+  }
+
+  BOOL Is_stmt_adjacent(WN* prev, WN* next) {
+    if (WN_next(prev) == NULL) {
+      do {
+        prev = ACTION_BASE::_cfg.Get_parent(prev);
+      } while (prev != NULL && WN_next(prev) == NULL);
+    }
+    if (WN_prev(next) == NULL) {
+      do {
+        next = ACTION_BASE::_cfg.Get_parent(next);
+      } while (next != NULL && WN_prev(next) == NULL);
+    }
+    FmtAssert(prev != NULL && next != NULL,
+              ("prev or next is NULL"));
+    if (WN_next(prev) == next) {
+      FmtAssert(WN_prev(next) == prev, ("invalid prev and next"));
+      return TRUE;
+    }
+    else {
+      return FALSE;
+    }
+  }
+
 public:
   WN_CFG_VERIFY_ACTION(_Tcfg& cfg) : WN_CFG_ACTION_BASE<_Tcfg> (cfg) {
+    _verify_node = NULL;
+    _verify_stmt = NULL;
   }
 
+  void Initialize() {
+    _verify_preds.resize(ACTION_BASE::_cfg.Get_max_id(), NODE_SET());
+    _verify_succs.resize(ACTION_BASE::_cfg.Get_max_id(), NODE_SET());
+  }
+
+  void Finalize() {
+    BB_NODE* dummy_exit = ACTION_BASE::Get_dummy_exit();
+    for (typename _Tcfg::bb_iterator bit = ACTION_BASE::_cfg.BB_begin();
+         bit != ACTION_BASE::_cfg.BB_end();
+         ++bit) {
+      UINT32 bb_id = (*bit)->Get_id();
+      if ((*bit)->Get_preds_count() != _verify_preds[bb_id].size()) {
+        if (dummy_exit != (*bit)) // we possibly add edges to dummy exit
+          FmtAssert(FALSE, ("WCFG VERIFY: missing edge"));
+      }
+      if ((*bit)->Get_succs_count() != _verify_succs[bb_id].size()) {
+        if ((*bit)->Succ_pos(dummy_exit) == POS_INVALID ||
+            (*bit)->Get_succs_count() != _verify_succs[bb_id].size() + 1)
+          FmtAssert(FALSE, ("WCFG VERIFY: missing edge"));
+      }
+    }
+  }
+
 public:
   void Process_root(WN* root) {
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(ACTION_BASE::_cfg.Get_wn_root() == root, 
+              ("WCFG VERIFY: root mismatch"));
+    FmtAssert(ACTION_BASE::_cfg.Get_dummy_entry()->First_stmt() == root,
+              ("WCFG VERIFY: root in dummy entry mismatch"));
   }
 
   void Process_rgn_level(REGION_LEVEL level) {
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(ACTION_BASE::_cfg.Get_rgn_level() == level, 
+              ("WCFG VERIFY: region level mismatch"));
   }
 
   void Process_stmt(BB_NODE* node, WN* stmt) {
-    Is_True(node != NULL, ("invalid WCFG node"));
-    Is_True(stmt != NULL && WN_operator(stmt) != OPERATOR_UNKNOWN,
-            ("invalid WHIRL node"));
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(node != NULL, ("invalid WCFG node"));
+    FmtAssert(stmt != NULL && WN_operator(stmt) != OPERATOR_UNKNOWN,
+              ("invalid WHIRL node"));
+    FmtAssert(ACTION_BASE::_cfg.Get_wn_node(stmt) == node, 
+              ("WCFG VERIFY: stmt to node mapping mismatch"));
+    FmtAssert(Is_stmt_in_node(node, stmt),
+              ("WCFG VERIFY: node to stmt mapping mismatch"));
   }
 
   void Process_predsucc(BB_NODE* pred, BB_NODE* succ) {
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(pred != NULL && succ != NULL, ("invalid WCFG node"));
+    INT32 succ_pos = pred->Succ_pos(succ);
+    FmtAssert(succ_pos != POS_INVALID &&
+              pred->Get_succ(succ_pos) == succ,
+              ("WCFG VERIFY: can not find succ"));
+    NODE_SET& succ_set = _verify_succs[pred->Get_id()];
+    FmtAssert(succ_set.find((INTPTR)succ) == succ_set.end(),
+              ("WCFG VERIFY: duplicated succ"));
+    succ_set.insert((INTPTR)succ);
+    INT32 pred_pos = succ->Pred_pos(pred);
+    FmtAssert(pred_pos != POS_INVALID &&
+              succ->Get_pred(pred_pos) == pred,
+              ("WCFG VERIFY: can not find pred"));
+    NODE_SET& pred_set = _verify_preds[succ->Get_id()];
+    FmtAssert(pred_set.find((INTPTR)pred) == pred_set.end(),
+              ("WCFG VERIFY: duplicated pred"));
+    pred_set.insert((INTPTR)pred);
   }
 
   void Process_entry_node(BB_NODE* entry) {
-    Is_True(entry != NULL, ("invalid entry node"));
-    Is_True(entry->Get_preds_count() == 1,
-            ("entry should only have 1 predecessor"));
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(entry != NULL, ("invalid entry node"));
+    FmtAssert(entry->Get_preds_count() == 1,
+              ("WCFG VERIFY: entry can only have 1 predecessor"));
+    BB_NODE* dummy_entry = ACTION_BASE::Get_dummy_entry();
+    FmtAssert(entry->Get_pred(0) == dummy_entry,
+              ("WCFG VERIFY: predecessor of entry node must be dummy entry"));
+    INT32 pos = dummy_entry->Succ_pos(entry);
+    FmtAssert(pos != POS_INVALID &&
+              dummy_entry->Get_succ(pos) == entry,
+              ("WCFG VERIFY: entry node is not connected to dummy entry"));
+    Process_predsucc(dummy_entry, entry);
   }
 
   void Process_exit_node(BB_NODE* exit) {
-    Is_True(exit != NULL, ("invalid node"));
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(exit != NULL, ("invalid exit node"));
+    FmtAssert(exit->Get_succs_count() == 1,
+              ("WCFG VERIFY: exit can only have 1 successor"));
+    BB_NODE* dummy_exit = ACTION_BASE::Get_dummy_exit();
+    FmtAssert(exit->Get_succ(0) == dummy_exit,
+              ("WCFG VERIFY: successor of exit node must be dummy exit"));
+    INT32 pos = dummy_exit->Pred_pos(exit);
+    FmtAssert(pos != POS_INVALID &&
+              dummy_exit->Get_pred(pos) == exit,
+              ("WCFG VERIFY: exit node is not connected to dummy exit"));
+    Process_predsucc(exit, dummy_exit);
   }
 
   void Process_goto(BB_NODE* node, WN* stmt) {
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(stmt != NULL &&
+              (WN_operator(stmt) == OPR_GOTO ||
+               WN_operator(stmt) == OPR_CASEGOTO ||
+               WN_operator(stmt) == OPR_TRUEBR ||
+               WN_operator(stmt) == OPR_FALSEBR ||
+               WN_operator(stmt) == OPR_REGION_EXIT),
+              ("stmt is not goto or casegoto"));
+    FmtAssert(node != NULL, ("node is NULL"));
+    FmtAssert(node->Last_stmt() == stmt ||
+              Is_kid_of_stmt(node->Last_stmt(), stmt),
+              ("WCFG VERIFY: stmt is not the last of node"));
+    INT32 label_number = WN_label_number(stmt);
+    BB_NODE* succ = ACTION_BASE::_cfg.Get_label_node(label_number);
+    FmtAssert(succ != NULL,
+              ("WCFG VERIFY: can not find label"));
+    WN* label_wn = succ->First_stmt();
+    FmtAssert(label_wn != NULL && WN_operator(label_wn) == OPR_LABEL &&
+              WN_label_number(label_wn) == WN_label_number(stmt),
+              ("WCFG VERIFY: invalid label for goto"));
+    Process_predsucc(node, succ);
   }
 
   void Process_label(BB_NODE* node, WN* stmt) {
-    FmtAssert(FALSE, ("TODO"));
+    FmtAssert(stmt != NULL && WN_operator(stmt) == OPR_LABEL,
+              ("stmt is not label"));
+    FmtAssert(node != NULL, ("node is NULL"));
+    WN* label_wn = node->First_stmt();
+    FmtAssert(label_wn == stmt,
+              ("WCFG VERIFY: invalid label for node"));
+    if (WN_Label_Is_Handler_Begin(stmt) ||
+        LABEL_target_of_goto_outer_block(WN_label_number(stmt))) {
+      BB_NODE* dummy_entry = ACTION_BASE::Get_dummy_entry();
+      INT32 succ_pos = dummy_entry->Succ_pos(node);
+      FmtAssert(succ_pos != POS_INVALID &&
+                dummy_entry->Get_succ(succ_pos) == node,
+                ("WCFG VERIFY: handler node is not connected to dummy entry"));
+      INT32 pred_pos = node->Pred_pos(dummy_entry);
+      FmtAssert(pred_pos != POS_INVALID &&
+                node->Get_pred(pred_pos) == dummy_entry,
+                ("WCFG VERIFY: handler node is not connected to dummy entry"));
+      return; 
+    }
+
+    for (typename BB_NODE::bb_iterator bit = node->Pred_begin();
+         bit != node->Pred_end();
+         ++bit) {
+      WN* last_stmt = (*bit)->Last_stmt();
+      switch (WN_operator(last_stmt)) {
+      case OPR_GOTO:
+      case OPR_CASEGOTO:
+      case OPR_REGION_EXIT:
+        FmtAssert(WN_label_number(last_stmt) == WN_label_number(stmt),
+                  ("WCFG VERIFY: invalid label for goto"));
+        break;
+      case OPR_TRUEBR:
+      case OPR_FALSEBR:
+        if (WN_label_number(last_stmt) != WN_label_number(stmt)) {
+          FmtAssert(Is_stmt_adjacent(last_stmt, stmt),
+                    ("WCFG VERIFY: invalid fall through node"));
+        }
+        break;
+      case OPR_COMPGOTO:
+      case OPR_SWITCH:
+        FmtAssert(Is_stmt_goto_label(last_stmt, stmt), 
+                  ("WCFG VERIFY: invalid label for goto"));
+        break;
+      default:
+        FmtAssert(Is_stmt_adjacent(last_stmt, stmt),
+                  ("WCFG VERIFY: invalid fall through node"));
+        break;
+      }
+    }
   }
 
-  BB_NODE* Create_node(WN* wn) {
-    FmtAssert(FALSE, ("TODO"));
+  BB_NODE* Create_node(BB_NODE* node, WN* stmt) {
+    if (stmt == NULL) {
+      FmtAssert(node != NULL, ("invalid node"));
+      UINT32 bb_id = node->Get_id();
+      for (typename BB_NODE::bb_iterator bit = node->Succ_begin();
+           bit != node->Succ_end();
+           ++bit) {
+        BB_NODE* succ = *bit;
+        if (_verify_succs[bb_id].find((INTPTR)succ) != _verify_succs[bb_id].end())
+          continue;
+        if (succ->Is_empty())
+          return succ;
+      }
+      FmtAssert(FALSE, ("WCFG VERIFY: can not verify node for stmt"));
+      return NULL;
+    }
+    else {
+      while (WN_operator(stmt) == OPR_REGION) {
+        stmt = WN_first(WN_region_body(stmt));
+        FmtAssert(stmt != NULL, ("TODO: stmt is NULL"));
+      }
+      FmtAssert(WN_operator(stmt) != OPR_BLOCK, ("invalid stmt"));
+      BB_NODE* new_node = ACTION_BASE::_cfg.Get_wn_node(stmt);
+      FmtAssert(new_node != NULL && new_node->First_stmt() == stmt,
+                ("WCFG VERIFY: invalid first stmt for node"));
+      return new_node;
+    }
   }
+
+  BOOL Need_new_node(BB_NODE* node, WN* stmt) {
+    FmtAssert(stmt != NULL, ("TODO: stmt is NULL"));
+    FmtAssert(node != NULL, ("node is NULL"));
+    while (WN_operator(stmt) == OPR_REGION) {
+      stmt = WN_first(WN_region_body(stmt));
+      FmtAssert(stmt != NULL, ("TODO: stmt is NULL"));
+    }
+    FmtAssert(WN_operator(stmt) != OPR_BLOCK, ("invalid stmt"));
+    return node->First_stmt() != stmt;
+  }
+
 };
 
 //===================================================================
@@ -342,12 +657,16 @@
     }
     Is_True(WN_operator(tree) == OPR_FUNC_ENTRY, ("tree is not FUNC_ENTRY"));
 
+    _action.Initialize();
+
     _action.Process_root(tree);
     RID *rid = REGION_get_rid(tree);
     _action.Process_rgn_level((REGION_LEVEL)(RID_level(rid) + 1));
 
     Is_True(_current_bb == NULL, ("invalud current node"));
     Process_entry(tree);
+
+    _action.Finalize();
   }
 
 public:
@@ -367,7 +686,7 @@
     WN* func_body = WN_func_body(wn);
     Is_True(func_body != NULL && WN_operator(func_body) == OPR_BLOCK,
             ("invalid BLOCK of function body"));
-    _current_bb = _action.Create_node(WN_first(func_body));
+    _current_bb = _action.Create_node(NULL, WN_first(func_body));
     _action.Process_entry_node(_current_bb);
     Process_stmt(_action.Get_dummy_entry(), wn);
     Process_block(func_body);
@@ -385,7 +704,7 @@
     Is_True(_current_bb != NULL, ("Current BB is NULL"));
     Is_True(_current_bb->Get_preds_count() == 0, ("Current BB has predecessors"));
 
-    _current_bb = _action.Create_node(wn);
+    _current_bb = _action.Create_node(NULL, wn);
     _action.Process_entry_node(_current_bb);
     Process_stmt(_current_bb, wn);
   }
@@ -412,7 +731,7 @@
     WN* then_block = WN_then(wn);
     Is_True(then_block != NULL && WN_operator(then_block) == OPR_BLOCK,
             ("invalid BLOCK of IF then"));
-    BB_NODE* then_bb = _action.Create_node(WN_first(then_block));
+    BB_NODE* then_bb = _action.Create_node(if_bb, WN_first(then_block));
     _action.Process_predsucc(if_bb, then_bb);
     Process_block(then_block);
 
@@ -420,12 +739,13 @@
     WN* else_block = WN_else(wn);
     Is_True(else_block != NULL && WN_operator(else_block) == OPR_BLOCK,
             ("invalid BLOCK of IF else"));
-    BB_NODE* else_bb = _action.Create_node(WN_first(else_block));
+    BB_NODE* else_bb = _action.Create_node(if_bb, WN_first(else_block));
     _action.Process_predsucc(if_bb, else_bb);
     Process_block(else_block);
 
     // connect THEN/ELSE block with BB3
-    _current_bb = _action.Create_node(WN_next(wn));
+    _current_bb = _action.Create_node(then_bb != NULL ? then_bb : else_bb, 
+                                      WN_next(wn));
     if (then_bb != NULL)
       _action.Process_predsucc(then_bb, _current_bb);
     if (else_bb != NULL)
@@ -454,7 +774,7 @@
     Process_stmt(init_bb, wn);
   
     // put COMP into BB1
-    BB_NODE* cmp_bb = _action.Create_node(WN_end(wn));
+    BB_NODE* cmp_bb = _action.Create_node(init_bb, WN_end(wn));
     _action.Process_predsucc(init_bb, cmp_bb);
     Process_stmt(cmp_bb, WN_end(wn));
   
@@ -462,7 +782,7 @@
     WN* body_block = WN_do_body(wn);
     Is_True(body_block != NULL && WN_operator(body_block) == OPR_BLOCK,
             ("invalid BLOCK for DO_LOOP body"));
-    BB_NODE* body_bb = _action.Create_node(WN_first(body_block));
+    BB_NODE* body_bb = _action.Create_node(cmp_bb, WN_first(body_block));
     _action.Process_predsucc(cmp_bb, body_bb);
     _current_bb = body_bb;
     Process_block(body_block);
@@ -470,7 +790,7 @@
     _action.Process_predsucc(_current_bb, cmp_bb);
   
     // connect with BB3
-    _current_bb = _action.Create_node(WN_next(wn));
+    _current_bb = _action.Create_node(cmp_bb, WN_next(wn));
     _action.Process_predsucc(cmp_bb, _current_bb);
   }
 
@@ -491,10 +811,10 @@
     Is_True(body_block != NULL && WN_operator(body_block) == OPR_BLOCK,
             ("invalid BLOCK for DO_WHILE body"));
     // put BODY into BB1
-    if (!_current_bb->Is_empty()) {
+    if (_action.Need_new_node(_current_bb, WN_first(body_block)) /*!_current_bb->Is_empty()*/) {
       // create new BB if current BB isn't empty
       BB_NODE* last_bb = _current_bb;
-      _current_bb = _action.Create_node(WN_first(body_block));
+      _current_bb = _action.Create_node(last_bb, WN_first(body_block));
       _action.Process_predsucc(last_bb, _current_bb);
     }
     BB_NODE* body_entry = _current_bb;
@@ -503,11 +823,11 @@
   
     if (_current_bb == NULL) {
       // there is a GOTO at the end of body
-      _current_bb = _action.Create_node(wn);
+      _current_bb = _action.Create_node(NULL, wn);
     }
     else if (_current_bb->Get_succs_count() > 0) {
       // can not put the COMP to BB1 in this case
-      _current_bb = _action.Create_node(wn);
+      _current_bb = _action.Create_node(body_exit, wn);
       _action.Process_predsucc(body_exit, _current_bb);
     }
     Process_stmt(_current_bb, wn);
@@ -516,7 +836,7 @@
     // connect BB2 and BB3
     if (WN_next(wn) != NULL) {
       BB_NODE* cmp_bb = _current_bb;
-      _current_bb = _action.Create_node(WN_next(wn));
+      _current_bb = _action.Create_node(cmp_bb, WN_next(wn));
       _action.Process_predsucc(cmp_bb, _current_bb);
     }
   }
@@ -535,10 +855,10 @@
   Is_True(_current_bb != NULL, ("Current BB is NULL"));
 
   // put COMP into BB1
-  if (!_current_bb->Is_empty()) {
+  if (_action.Need_new_node(_current_bb, wn) /*!_current_bb->Is_empty()*/) {
     // create new BB if current BB isn't empty
     BB_NODE* last_bb = _current_bb;
-    _current_bb = _action.Create_node(wn);
+    _current_bb = _action.Create_node(last_bb, wn);
     _action.Process_predsucc(last_bb, _current_bb);
   }
   BB_NODE* cmp_bb = _current_bb;
@@ -548,7 +868,7 @@
   WN* body_block = WN_while_body(wn);
   Is_True(body_block != NULL && WN_operator(body_block) == OPR_BLOCK,
           ("invalid BLOCK for WHILE_DO body"));
-  _current_bb = _action.Create_node(WN_first(body_block));
+  _current_bb = _action.Create_node(cmp_bb, WN_first(body_block));
   _action.Process_predsucc(cmp_bb, _current_bb);
   Process_block(body_block);
   if (_current_bb != NULL) {
@@ -557,7 +877,7 @@
   }
 
   // connect BB1 and BB3
-  _current_bb = _action.Create_node(WN_next(wn));
+  _current_bb = _action.Create_node(cmp_bb, WN_next(wn));
   _action.Process_predsucc(cmp_bb, _current_bb);
 }
 
@@ -593,7 +913,7 @@
   
     // create BB1
     if (WN_next(wn) != NULL)
-      _current_bb = _action.Create_node(WN_next(wn));
+      _current_bb = _action.Create_node(NULL, WN_next(wn));
     else
       _current_bb = NULL;    // no fall-through for compgoto
   }
@@ -630,7 +950,7 @@
   
     // create BB1
     if (WN_next(wn) != NULL)
-      _current_bb = _action.Create_node(WN_next(wn));
+      _current_bb = _action.Create_node(NULL, WN_next(wn));
     else
       _current_bb = NULL;    // no fall-through for switch
   }
@@ -647,9 +967,9 @@
     Is_True(_current_bb != NULL, ("Current BB is NULL"));
   
     BB_NODE* last_bb = _current_bb;
-    if (! last_bb->Is_empty()) {
+    if (_action.Need_new_node(_current_bb, wn) /*!_current_bb->Is_empty()*/) {
       // create new bb if current BB isn't empty
-      _current_bb = _action.Create_node(wn);
+      _current_bb = _action.Create_node(last_bb, wn);
     }
   
     Process_stmt(_current_bb, wn);
@@ -680,7 +1000,7 @@
   
     // create BB1
     if (WN_next(wn) != NULL)
-      _current_bb = _action.Create_node(WN_next(wn));
+      _current_bb = _action.Create_node(NULL, WN_next(wn));
     else
       _current_bb = NULL;    // no fall-through for goto
   }
@@ -714,10 +1034,15 @@
     // put CONDGOTO into BB0
     BB_NODE* condgoto_bb = _current_bb;
     Process_stmt(condgoto_bb, wn);
-    _action.Process_goto(condgoto_bb, wn);
+
+    WN* next = WN_next(wn);
+    if (next == NULL || WN_operator(next) != OPR_LABEL ||
+        WN_label_number(wn) != WN_label_number(next)) {
+      _action.Process_goto(condgoto_bb, wn);
+    }
   
     // create and connect BB1
-    _current_bb = _action.Create_node(WN_next(wn));
+    _current_bb = _action.Create_node(condgoto_bb, WN_next(wn));
     _action.Process_predsucc(condgoto_bb, _current_bb);
   }
   
@@ -806,10 +1131,10 @@
     WN* region_body = WN_region_body(wn);
     Is_True(region_body != NULL && WN_operator(region_body) == OPR_BLOCK,
             ("invalid BLOCK for REGION body")); 
-    if (!_current_bb->Is_empty()) {
+    if (_action.Need_new_node(_current_bb, WN_first(region_body)) /*!_current_bb->Is_empty()*/) {
       // Force new block if current BB isn't empty
       BB_NODE* last_bb = _current_bb;
-      _current_bb = _action.Create_node(WN_first(region_body));
+      _current_bb = _action.Create_node(last_bb, WN_first(region_body));
       _action.Process_predsucc(last_bb, _current_bb);
     }
     Process_block(region_body);
@@ -817,7 +1142,7 @@
   
     // create BB2
     if (WN_next(wn) != NULL) {
-      _current_bb = _action.Create_node(WN_next(wn));
+      _current_bb = _action.Create_node(rgn_body, WN_next(wn));
       if (rgn_body != NULL) {
         _action.Process_predsucc(rgn_body, _current_bb);
       }
@@ -841,7 +1166,7 @@
   
     // create BB1
     if (WN_next(wn) != NULL)
-      _current_bb = _action.Create_node(WN_next(wn));
+      _current_bb = _action.Create_node(NULL, WN_next(wn));
     else
       _current_bb = NULL;    // no fall-through for region_exit
   }
@@ -862,7 +1187,7 @@
       _action.Process_predsucc(_current_bb, _action.Get_dummy_exit());
       // create BB1
       if (WN_next(wn) != NULL)
-        _current_bb = _action.Create_node(WN_next(wn));
+        _current_bb = _action.Create_node(NULL, WN_next(wn));
       else
         _current_bb = NULL;    // no fall-through for the intrinsic
     }
@@ -893,7 +1218,7 @@
       _action.Process_exit_node(bb);
       // RETURN will end current bb
       if (WN_next(stmt) != NULL)
-        _current_bb = _action.Create_node(WN_next(stmt));
+        _current_bb = _action.Create_node(NULL, WN_next(stmt));
       else
         _current_bb = NULL;    // no fall-through for return
     }

