diff --git a/src/Bookkeeper.cpp b/src/Bookkeeper.cpp index 865a3b9c9..b1d8e8dcb 100644 --- a/src/Bookkeeper.cpp +++ b/src/Bookkeeper.cpp @@ -51,7 +51,7 @@ using namespace std; // counter for all levels of struct depth std::vector Bookkeeper::struct_depth_cnts; - +int Bookkeeper::union_var_cnt = 0; std::vector Bookkeeper::expr_depth_cnts; std::vector Bookkeeper::dereference_level_cnts; int Bookkeeper::address_taken_cnt = 0; @@ -136,7 +136,7 @@ Bookkeeper::output_stmts_statistics(std::ostream &out) void Bookkeeper::output_statistics(std::ostream &out) { - output_struct_statistics(out); + output_struct_union_statistics(out); out << endl; output_expr_statistics(out); out << endl; @@ -152,13 +152,14 @@ Bookkeeper::output_statistics(std::ostream &out) } void -Bookkeeper::output_struct_statistics(std::ostream &out) +Bookkeeper::output_struct_union_statistics(std::ostream &out) { formated_output(out, "max struct depth: ", (struct_depth_cnts.size()-1)); out << "breakdown:" << endl; for (size_t i=0; i struct_depth_cnts; + static std::vector struct_depth_cnts; + + static int union_var_cnt; static std::vector expr_depth_cnts; diff --git a/src/CGContext.cpp b/src/CGContext.cpp index 67f9201dc..d258d0e64 100644 --- a/src/CGContext.cpp +++ b/src/CGContext.cpp @@ -207,7 +207,7 @@ CGContext::check_read_var(const Variable *v, const std::vector& fac if (is_nonreadable(v)) { return false; } - if (effect_context.is_written(v) || effect_context.field_is_written(v)) { + if (effect_context.is_written_partially(v)) { return false; } if (v->is_volatile() && !effect_context.is_side_effect_free()) { @@ -329,10 +329,10 @@ CGContext::check_write_var(const Variable *v, const std::vector& fa if (is_nonwritable(v) || v->is_const()) { return false; } - if (effect_context.is_written(v) || effect_context.field_is_written(v)) { + if (effect_context.is_written_partially(v)) { return false; } - if (effect_context.is_read(v) || effect_context.field_is_read(v)) { + if (effect_context.is_read_partially(v)) { return false; } if (v->is_volatile() && !effect_context.is_side_effect_free()) { @@ -556,7 +556,7 @@ CGContext::in_conflict(const Effect& eff) const if (is_nonreadable(v)) { return true; } - if (effect_context.is_written(v) || effect_context.field_is_written(v)) { + if (effect_context.is_written_partially(v)) { return true; } // Yang: do we need to consider deref level here? @@ -570,10 +570,10 @@ CGContext::in_conflict(const Effect& eff) const if (is_nonwritable(v) || v->is_const()) { return true; } - if (effect_context.is_written(v) || effect_context.field_is_written(v)) { + if (effect_context.is_written_partially(v)) { return true; } - if (effect_context.is_read(v) || effect_context.field_is_read(v)) { + if (effect_context.is_read_partially(v)) { return true; } if (v->is_volatile() && !effect_context.is_side_effect_free()) { diff --git a/src/Effect.cpp b/src/Effect.cpp index 34af7709b..86bdd4fb2 100644 --- a/src/Effect.cpp +++ b/src/Effect.cpp @@ -434,6 +434,50 @@ Effect::field_is_written(const Variable *v) const return false; } +bool +Effect::sibling_field_is_read(const Variable *v) const +{ + // check other fields of union/struct + if (v->isFieldVarOf_) { + for (size_t j=0; jisFieldVarOf_->field_vars.size(); j++) { + Variable* field_var = v->isFieldVarOf_->field_vars[j]; + if (field_var == v) continue; + if (is_read(field_var) || field_is_read(field_var)) { + return true; + } + } + } + return false; +} + +bool +Effect::sibling_field_is_written(const Variable *v) const +{ + // check other fields of union/struct + if (v->isFieldVarOf_) { + for (size_t j=0; jisFieldVarOf_->field_vars.size(); j++) { + Variable* field_var = v->isFieldVarOf_->field_vars[j]; + if (field_var == v) continue; + if (is_written(field_var) || field_is_written(field_var)) { + return true; + } + } + } + return false; +} + +bool +Effect::is_read_partially(const Variable* v) const +{ + return is_read(v) || field_is_read(v) || (v->is_union_field() && sibling_field_is_read(v)); +} + +bool +Effect::is_written_partially(const Variable* v) const +{ + return is_written(v) || field_is_written(v) || (v->is_union_field() && sibling_field_is_written(v)); +} + /* * consolidate the read/write set */ diff --git a/src/Effect.h b/src/Effect.h index 3d0704f1f..2806a8e8b 100644 --- a/src/Effect.h +++ b/src/Effect.h @@ -65,6 +65,10 @@ class Effect bool is_written(std::string vname) const; bool field_is_read(const Variable *v) const; bool field_is_written(const Variable *v) const; + bool sibling_field_is_read(const Variable *v) const; + bool sibling_field_is_written(const Variable *v) const; + bool is_read_partially(const Variable* v) const; + bool is_written_partially(const Variable* v) const; bool has_race_with(const Effect &e) const; bool is_empty(void) const; void consolidate(void); diff --git a/src/Probabilities.cpp b/src/Probabilities.cpp index ed54637fc..478146f81 100644 --- a/src/Probabilities.cpp +++ b/src/Probabilities.cpp @@ -654,10 +654,6 @@ Probabilities::set_default_simple_types_prob() else { SET_SINGLE_NAME("long_long_prob", LongLong, 0); SET_SINGLE_NAME("ulong_long_prob", ULongLong, 0); - if (CGOptions::x86_64()) { - SET_SINGLE_NAME("long_prob", Long, 0); - SET_SINGLE_NAME("ulong_prob", ULong, 0); - } } set_group_prob(true, pSimpleTypesProb, m); diff --git a/src/Variable.h b/src/Variable.h index a4b550882..390373269 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -87,6 +87,7 @@ class Variable bool is_volatile_after_deref(int deref_level) const; bool has_field_var(const Variable* v) const; bool is_field_var(void) const { return isFieldVarOf_ != 0; }; + bool is_union_field(void) const { return isFieldVarOf_ != 0 && isFieldVarOf_->type->eType == eUnion; }; bool is_array_field(void) const; bool is_virtual(void) const; bool is_aggregate(void) const { return type && type->is_aggregate(); } diff --git a/src/VariableSelector.cpp b/src/VariableSelector.cpp index 4aa2eca5d..91e32c52f 100644 --- a/src/VariableSelector.cpp +++ b/src/VariableSelector.cpp @@ -225,10 +225,6 @@ VariableSelector::has_dereferenceable_var(const vector& vars, const bool VariableSelector::is_eligible_var(const Variable* var, int deref_level, Effect::Access access, const CGContext& cg_context) { - // JYTODO: integrate this into get_collective? - //if (var->isFieldVarOf_ && var->is_array_field()) { - // var = var->isFieldVarOf_->get_collective(); - //} const Variable* coll = var->get_collective(); if (coll != var) { CGContext cg_tmp(cg_context); @@ -256,7 +252,7 @@ VariableSelector::is_eligible_var(const Variable* var, int deref_level, Effect:: // We can neither read nor write a variable that is being written in // the current effect context. if (((access == Effect::READ) || (access == Effect::WRITE)) - && (effect_context.is_written(var) || effect_context.field_is_written(var))) { + && (effect_context.is_written_partially(var))) { return false; } // ISSUE: generating "strictly conforming" programs. @@ -264,7 +260,7 @@ VariableSelector::is_eligible_var(const Variable* var, int deref_level, Effect:: // We cannot write a variable that is being read in the current effect context. // JYTODO: this is too restrictive, with dereference, var is not the variable // being written, but the pointed variable. Nevertheless, we excluded var here - if ((access == Effect::WRITE && deref_level==0) && (effect_context.is_read(var) || effect_context.field_is_read(var))) { + if ((access == Effect::WRITE && deref_level==0) && effect_context.is_read_partially(var)) { return false; } // ISSUE: generating correct C programs. @@ -532,8 +528,6 @@ VariableSelector::GenerateNewGlobal(Effect::Access access, const CGContext &cg_c tmp_count++; Variable* var = create_and_initialize(access, cg_context, t, &var_qfer, 0, name); - Bookkeeper::record_vars_with_bitfields(t); - incr_counter(Bookkeeper::struct_depth_cnts, t->get_struct_depth()); GlobalList.push_back(var); // for DFA FactMgr* fm = get_fact_mgr(&cg_context); @@ -562,8 +556,6 @@ VariableSelector::GenerateNewNonArrayGlobal(Effect::Access access, const CGConte ERROR_GUARD(NULL); Variable *var = new_variable(name, t, init, qfer); - Bookkeeper::record_vars_with_bitfields(t); - incr_counter(Bookkeeper::struct_depth_cnts, t->get_struct_depth()); GlobalList.push_back(var); // for DFA FactMgr* fm = get_fact_mgr(&cg_context); @@ -927,9 +919,6 @@ VariableSelector::GenerateNewParentLocal(Block &block, string name = RandomLocalName(); Variable* var = create_and_initialize(access, cg_context, t, &var_qfer, blk, name); - - Bookkeeper::record_vars_with_bitfields(t); - incr_counter(Bookkeeper::struct_depth_cnts, t->get_struct_depth()); blk->local_vars.push_back(var); FactMgr* fm = get_fact_mgr(&cg_context); fm->add_new_local_var_fact(blk, var->get_collective()); @@ -1206,10 +1195,17 @@ VariableSelector::select(Effect::Access access, if (var && !cg_context.get_effect_context().is_side_effect_free()) { assert(!var->is_volatile()); } - if (var_created) { - Bookkeeper::use_new_var_cnt++; - } else { - Bookkeeper::use_old_var_cnt++; + // record statistics + if (var) { + if (var_created) { + const Type* t = var->type; + Bookkeeper::use_new_var_cnt++; + Bookkeeper::record_vars_with_bitfields(t); + incr_counter(Bookkeeper::struct_depth_cnts, t->get_struct_depth()); + if (t->eType == eUnion) Bookkeeper::union_var_cnt++; + } else { + Bookkeeper::use_old_var_cnt++; + } } return var; } @@ -1355,8 +1351,7 @@ VariableSelector::select_array(const CGContext &cg_context) ArrayVariable* av = dynamic_cast(vars[i]); assert(av); if (av->collective == 0) { - if (!cg_context.get_effect_context().is_read(av) && - !cg_context.get_effect_context().field_is_read(av) && + if (!cg_context.get_effect_context().is_read_partially(av) && !cg_context.get_effect_context().is_written(av) && (cg_context.get_effect_context().is_side_effect_free() || !av->is_volatile()) && !av->is_const() &&