Hi,
Can the gatekeeper review the changes to WHIRL SSA and WHIRL CFG? This patch
includes:
* Some format change
* Add interface to CFG to update its statement list
* Add volatile support to WSSA
--
Regards,
Lai Jian-Xin
Index: be/com/wssa_wn.cxx
===================================================================
--- be/com/wssa_wn.cxx (revision 3402)
+++ be/com/wssa_wn.cxx (working copy)
@@ -50,8 +50,7 @@
//===================================================================
BOOL
-WN_has_node(const WN* wn, WSSA_NODE_KIND nkind)
-{
+WN_has_node(const WN* wn, WSSA_NODE_KIND nkind) {
switch (nkind) {
case WSSA_PHI:
return WN_has_phi(wn);
@@ -68,8 +67,7 @@
}
BOOL
-WN_has_phi(const WN* wn)
-{
+WN_has_phi(const WN* wn) {
OPERATOR opr = WN_operator(wn);
switch (opr) {
case OPR_IF:
@@ -84,8 +82,7 @@
}
BOOL
-WN_has_chi(const WN* wn)
-{
+WN_has_chi(const WN* wn) {
OPERATOR opr = WN_operator(wn);
switch (opr) {
case OPR_FUNC_ENTRY: // entry chi
@@ -118,8 +115,7 @@
}
BOOL
-WN_has_mu(const WN* wn)
-{
+WN_has_mu(const WN* wn) {
OPERATOR opr = WN_operator(wn);
switch (opr) {
case OPR_ASM_STMT:
@@ -145,8 +141,7 @@
}
BOOL
-WN_has_ver(const WN* wn)
-{
+WN_has_ver(const WN* wn) {
OPERATOR opr = WN_operator(wn);
switch (opr) {
case OPR_LDID:
@@ -160,8 +155,7 @@
}
BOOL
-WN_def_ver(const WN* wn)
-{
+WN_def_ver(const WN* wn) {
OPERATOR opr = WN_operator(wn);
switch (opr) {
case OPR_STID:
@@ -173,8 +167,7 @@
}
BOOL
-WN_use_ver(const WN* wn)
-{
+WN_use_ver(const WN* wn) {
OPERATOR opr = WN_operator(wn);
switch (opr) {
case OPR_LDID:
@@ -185,5 +178,34 @@
}
}
+BOOL
+WN_is_volatile(const WN* wn) {
+ if (WN_ty(wn) != 0 && TY_is_volatile(WN_ty(wn)))
+ return TRUE;
+ else if (WN_has_sym(wn) &&
+ WN_st(wn) != NULL &&
+ ST_class(WN_st(wn)) == CLASS_VAR &&
+ TY_is_volatile(ST_type(WN_st(wn))))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+BOOL
+Tree_is_volatile(const WN* tree) {
+ OPCODE opc = WN_opcode(tree);
+ Is_True(OPCODE_is_stmt(opc) || OPCODE_is_expression(opc),
+ ("opcode %s is not stmt or expr", OPCODE_name(opc)));
+
+ if (WN_is_volatile(tree)) {
+ return TRUE;
+ }
+ for (int i=0; i < WN_kid_count(tree); ++i) {
+ if (Tree_is_volatile(WN_kid(tree, i)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
} /* namespace WSSA */
Index: be/com/wssa_sym.cxx
===================================================================
--- be/com/wssa_sym.cxx (revision 3402)
+++ be/com/wssa_sym.cxx (working copy)
@@ -108,11 +108,9 @@
_def_wn(NULL), _def_type(WSSA_UNKNOWN), _ver_flags(0) {
}
-WST_Version_Entry::WST_Version_Entry(const WN* wn, WST_IDX wst_idx, UINT32 ver, WSSA_NODE_KIND type, BOOL zero_ver)
+WST_Version_Entry::WST_Version_Entry(WST_IDX wst_idx, UINT32 ver, const WN* wn, WSSA_NODE_KIND type)
: _wst_idx(wst_idx), _version(ver), _prev_ver(VER_INVALID),
_def_wn(wn), _def_type(type), _ver_flags(0) {
- if (zero_ver)
- Set_flag(VER_IS_ZERO);
}
void
Index: be/com/wn_cfg.h
===================================================================
--- be/com/wn_cfg.h (revision 3402)
+++ be/com/wn_cfg.h (working copy)
@@ -102,6 +102,11 @@
WN* Last_stmt() const;
BOOL Is_empty() const;
+ // update the stmt inside the Container
+ void Insert_before(WN* before, WN* stmt);
+ void Insert_after(WN* after, WN* stmt);
+ void Remove_stmt(WN* stmt);
+
// iterators to traverse the statements
iterator begin() { return iterator(First_stmt(), this); }
iterator end() { return iterator(NULL, this); }
Index: be/com/cfg_base.h
===================================================================
--- be/com/cfg_base.h (revision 3402)
+++ be/com/cfg_base.h (working copy)
@@ -98,8 +98,14 @@
STMT First_stmt() const { return _stmts.First_stmt(); }
STMT Last_stmt() const { return _stmts.Last_stmt(); }
BOOL Is_empty() const { return _stmts.Is_empty(); }
+ void Insert_before(STMT before, STMT stmt) {
+ _stmts.Insert_before(before, stmt);
+ }
+ void Insert_after(STMT after, STMT stmt) {
+ _stmts.Insert_after(after, stmt);
+ }
+ void Remove_stmt(STMT stmt) { _stmts.Remove_stmt(stmt); }
-
// preds/succs related methods
void Add_pred(BB_NODE* pred) { _preds.push_back(pred); }
void Add_succ(BB_NODE* succ) { _succs.push_back(succ); }
@@ -613,7 +619,11 @@
// node operations
BB_NODE* Create_node() { return _node_container.Create_node(_cfg_pool); }
- void Delete_node(BB_NODE* node) { _node_container.Delete_node(node, _cfg_pool); }
+ void Delete_node(BB_NODE* node) {
+ Disconnect_node(node); // remove all edges on the node
+ Disconnect_all_stmt_in_node(node); // disconnect all stmts in the node
+ _node_container.Delete_node(node, _cfg_pool); // delete the node
+ }
UINT32 Get_max_id() const { return _node_container.Get_max_id(); }
BB_NODE* Get_node(UINT32 id) { return _node_container.Get_node(id); }
BB_NODE* Get_dummy_entry() const { return _dummy_entry; }
@@ -676,6 +686,29 @@
return _stmt_mapper.Get_stmt_node(stmt);
}
+ // insert/delete stmt from node
+ void Insert_before(STMT before, STMT stmt) {
+ Is_True(before != NULL && stmt != NULL, ("insert point or stmt is null"));
+ BB_NODE* node = Get_stmt_node(before);
+ Is_True(node != NULL, ("can not find BB for insert point"));
+ node->Insert_before(before, stmt);
+ Connect_stmt_node(stmt, node);
+ }
+ void Insert_after(STMT after, STMT stmt) {
+ Is_True(after != NULL && stmt != NULL, ("insert point or stmt is null"));
+ BB_NODE* node = Get_stmt_node(after);
+ Is_True(node != NULL, ("can not find BB for insert point"));
+ node->Insert_after(after, stmt);
+ Connect_stmt_node(stmt, node);
+ }
+ void Remove_stmt(STMT stmt) {
+ Is_True(stmt != NULL, ("stmt is null"));
+ BB_NODE* node = Get_stmt_node(stmt);
+ Is_True(node != NULL, ("can not find BB for stmt"));
+ node->Remove_stmt(stmt);
+ Disconnect_stmt_node(stmt, node);
+ }
+
// DFS iterators
dfs_fwd_itrator Dfs_fwd_begin() { dfs_fwd_itrator it(Get_dummy_entry(), Get_max_id()); return it; }
dfs_fwd_itrator Dfs_fwd_end() { dfs_fwd_itrator it(NULL, 0); return it; }
Index: be/com/wn_cfg.cxx
===================================================================
--- be/com/wn_cfg.cxx (revision 3402)
+++ be/com/wn_cfg.cxx (working copy)
@@ -78,6 +78,87 @@
}
void
+WN_STMT_CONTAINER::Insert_before(WN* before, WN* stmt) {
+ Is_True(before != NULL, ("invalid before stmt"));
+ Is_True(stmt != NULL, ("invalid stmt"));
+ Is_True(OPERATOR_is_stmt(WN_operator(stmt)), ("invalid stmt"));
+ FmtAssert(before != _extra_stmt, ("TODO: support insert before extra stmt"));
+ FmtAssert(WN_operator(before) != OPR_LABEL, ("can not insert before label"));
+
+#ifdef Is_True_On
+ WN* wn = NULL;
+ for (wn = _first_stmt; wn != _last_stmt; wn = WN_next(wn)) {
+ if (wn == before)
+ break;
+ }
+ Is_True(before == wn, ("can not find insert position"));
+#endif
+
+ if (before == _first_stmt) {
+ _first_stmt = stmt;
+ }
+}
+
+void
+WN_STMT_CONTAINER::Insert_after(WN* after, WN* stmt) {
+ Is_True(after != NULL, ("invalid after stmt"));
+ Is_True(stmt != NULL, ("invalid stmt"));
+ Is_True(OPERATOR_is_stmt(WN_operator(stmt)), ("invalid stmt"));
+ Is_True(!OPERATOR_is_scf(WN_operator(after)), ("TODO: after is scf"));
+ Is_True(WN_operator(after) != OPR_TRUEBR &&
+ WN_operator(after) != OPR_FALSEBR &&
+ WN_operator(after) != OPR_GOTO &&
+ WN_operator(after) != OPR_AGOTO &&
+ WN_operator(after) != OPR_CASEGOTO &&
+ WN_operator(after) != OPR_COMPGOTO &&
+ WN_operator(after) != OPR_GOTO_OUTER_BLOCK &&
+ WN_operator(after) != OPR_RETURN &&
+ WN_operator(after) != OPR_RETURN_VAL &&
+ WN_operator(after) != OPR_XGOTO, ("TODO: after is jump"));
+ FmtAssert(after != _extra_stmt, ("TODO: support insert after extra stmt"));
+
+#ifdef Is_True_On
+ WN* wn = NULL;
+ for (wn = _first_stmt; wn != _last_stmt; wn = WN_next(wn)) {
+ if (wn == after)
+ break;
+ }
+ Is_True(after == wn, ("can not find insert position"));
+#endif
+
+ if (after == _last_stmt) {
+ _last_stmt = stmt;
+ }
+}
+
+void
+WN_STMT_CONTAINER::Remove_stmt(WN* stmt) {
+ Is_True(stmt != NULL, ("invalid stmt"));
+ FmtAssert(stmt != _extra_stmt, ("TODO: support remove extra stmt"));
+
+#ifdef Is_True_On
+ WN* wn = NULL;
+ for (wn = _first_stmt; wn != _last_stmt; wn = WN_next(wn)) {
+ if (wn == stmt)
+ break;
+ }
+ Is_True(stmt == wn, ("can not find wn"));
+#endif
+
+ if (_first_stmt != _last_stmt) {
+ if (stmt == _first_stmt)
+ _first_stmt = WN_next(_first_stmt);
+ if (stmt == _last_stmt)
+ _last_stmt = WN_prev(_last_stmt);
+ }
+ else {
+ FmtAssert(stmt == _first_stmt, ("can not find wn"));
+ FmtAssert(_extra_stmt == NULL, ("extra stmt is not NULL"));
+ _first_stmt = _last_stmt = NULL;
+ }
+}
+
+void
WN_STMT_CONTAINER::Print(FILE* fp, INT32 dump_flag) const {
if (dump_flag & DUMP_AIR) {
for (WN* wn = First_stmt(); wn != NULL; wn = Next_stmt(wn)) {
@@ -439,12 +520,15 @@
_current_bb = cfg.Create_node();
cfg.Add_entry_node(_current_bb);
Add_block(cfg, WN_func_body(wn));
+
+ // put FUNC_ENTRY into dummy entry
+ Add_stmt(cfg, cfg.Get_dummy_entry(), wn);
}
//===================================================================
// Add_altentry: handle ALTENTRY
// STMT0 --> BB0 (must be GOTO/RETURN)
-// FUNC_ENTRY --> BB1 (BB1 don't have other preds than dummy_entry
+// ALTENTRY --> BB1 (BB1 don't have other preds than dummy_entry
// [kid0..n-1] IDNAME --> ignore
//===================================================================
void
@@ -454,9 +538,12 @@
Is_True(_current_bb != NULL, ("Current BB is NULL"));
Is_True(_current_bb->Get_preds_count() == 0, ("Current BB has predecessors"));
- // put BODY into BB1
+ // create new BB for ALTENTRY, connect new bb with dummy entry
_current_bb = cfg.Create_node();
cfg.Add_entry_node(_current_bb);
+
+ // put ALTENTRY into _current_bb
+ Add_stmt(cfg, _current_bb, wn);
}
//===================================================================
@@ -913,7 +1000,13 @@
Is_True(stmt != NULL, ("wn is NULL"));
OPERATOR opr = WN_operator(stmt);
- Is_True(opr != OPR_FUNC_ENTRY && opr != OPR_ALTENTRY, ("stmt is ENTRY"));
+ if (opr == OPR_FUNC_ENTRY) {
+ Is_True(bb == cfg.Get_dummy_entry(), ("FUNC_ENTRY can only be in dummy entry"));
+ }
+ if (opr == OPR_ALTENTRY) {
+ Is_True(bb->Get_preds_count() == 1 &&
+ *(bb->Pred_begin()) == cfg.Get_dummy_entry(), ("ALTENTRY can only have the dummy entry as it pred."));
+ }
bb->Add_stmt(stmt);
cfg.Connect_stmt_node(stmt, bb);
Index: be/com/wssa_wn.h
===================================================================
--- be/com/wssa_wn.h (revision 3402)
+++ be/com/wssa_wn.h (working copy)
@@ -63,6 +63,13 @@
// return TRUE if the version can be used by the WN (LDID/LDBITS)
BOOL WN_use_ver(const WN* wn);
+// return TRUE if WN or ST used in WN node is volatile
+BOOL WN_is_volatile(const WN* wn);
+
+// return TRUE if WN or ST used in WN tree is volatile
+// tree must be statement or expression
+BOOL Tree_is_volatile(const WN* tree);
+
} /* namespace WSSA */
#endif /* wssa_wn_INCLUDED */
Index: be/com/wssa_sym.h
===================================================================
--- be/com/wssa_sym.h (revision 3402)
+++ be/com/wssa_sym.h (working copy)
@@ -207,7 +207,8 @@
// Version flag
enum VER_FLAG {
- VER_IS_ZERO = 0x1, // zero version
+ VER_IS_ZERO = 0x1, // zero version
+ VER_IS_VOLATILE = 0x2, // def or use is volatile
};
// WSSA version entry
@@ -226,6 +227,11 @@
};
// TODO: FSA, POINTS_TO
+private:
+ void Set_flag(VER_FLAG flag) { _ver_flags |= flag; }
+ void Reset_flag(VER_FLAG flag) { _ver_flags &= !flag; }
+ BOOL Is_flag_set(VER_FLAG flag) const { return (_ver_flags & flag) == flag; }
+
public:
// these routines are for IO only
void Set_flags(INT32 flags) { _flags = flags; }
@@ -233,8 +239,8 @@
public:
WST_Version_Entry();
- WST_Version_Entry(const WN* def_wn, WST_IDX wst_idx, UINT32 ver,
- WSSA_NODE_KIND def_type, BOOL zero_ver);
+ WST_Version_Entry(WST_IDX wst_idx, UINT32 ver,
+ const WN* def_wn, WSSA_NODE_KIND def_type);
public:
WST_IDX Get_wst() const { return _wst_idx; }
@@ -252,10 +258,14 @@
WSSA_NODE_KIND Get_def_type() const { return (WSSA_NODE_KIND)_def_type; }
void Set_def_type(WSSA_NODE_KIND type) { _def_type = type; }
- void Set_flag(VER_FLAG flag) { _ver_flags |= flag; }
- void Reset_flag(VER_FLAG flag) { _ver_flags &= !flag; }
- BOOL Is_flag_set(VER_FLAG flag) const { return (_ver_flags & flag) == flag; }
+ void Set_zero() { Set_flag(VER_IS_ZERO); }
+ void Reset_zero() { Reset_flag(VER_IS_ZERO); }
+ BOOL Is_zero() const { return Is_flag_set(VER_IS_ZERO); }
+ void Set_volatile() { Set_flag(VER_IS_VOLATILE); }
+ void Reset_volatile() { Reset_flag(VER_IS_VOLATILE); }
+ BOOL Is_volatile() const { return Is_flag_set(VER_IS_VOLATILE); }
+
public:
void Print(FILE* fp = stdout) const;
};
Index: be/com/wssa_mgr.cxx
===================================================================
--- be/com/wssa_mgr.cxx (revision 3402)
+++ be/com/wssa_mgr.cxx (working copy)
@@ -506,6 +506,9 @@
ST_IDX st_idx = 0;
switch (sym.Sym_type()) {
case WST_WHIRL:
+ case WST_PREG:
+ case WST_FIELD:
+ case WST_VSYM:
st_idx = sym.St_idx();
break;
default:
@@ -587,11 +590,15 @@
VER_IDX idx = (VER_IDX)_ver_table.size();
_ver_table.push_back(ver);
- if (ver.Get_def_wn() != NULL) {
- VER_IDX last_ver = wst.Last_ver();
+ VER_IDX last_ver = wst.Last_ver();
+ if (ver.Get_def_wn() != NULL || // musy def or may def
+ (last_ver != VER_INVALID && // previous def is volatile
+ _ver_table[last_ver].Is_volatile())) {
_ver_table[idx].Set_prev_ver(last_ver);
wst.Set_last_ver(idx);
}
Index: be/com/wssa_mgr.h
===================================================================
--- be/com/wssa_mgr.h (revision 3402)
+++ be/com/wssa_mgr.h (working copy)
@@ -353,6 +353,17 @@
const WST_Version_Entry& ver = _mgr->Get_ver(_cur_ver);
_def_type = ver.Get_def_type();
_def_wn = ver.Get_def_wn();
+ if (_def_wn == NULL) {
+ Is_True(_def_type == WSSA_UNKNOWN, ("invalid def type"));
+ // volatile use does not have def
+ // if the previous def is volatile, there is no def for current use
+ VER_IDX prev_ver = ver.Prev_ver();
+ Is_True(ver.Is_volatile() == TRUE ||
+ (prev_ver != VER_INVALID &&
+ _mgr->Get_ver(prev_ver).Is_volatile() == TRUE),
+ ("cur use or prev def is not volatile"));
+ continue;
+ }
Is_True(_def_wn != NULL && _def_type != WSSA_UNKNOWN, ("invalid def wn"));
if (_wn_visited[(INTPTR)_def_wn] == true)
------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1, ECMAScript5, and DOM L2 & L3.
Spend less time writing and rewriting code and more time creating great
experiences on the web. Be a part of the beta today
http://p.sf.net/sfu/msIE9-sfdev2dev
_______________________________________________
Open64-devel mailing list
Open64-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/open64-devel