Skip to content

Commit 2df6785

Browse files
committed
remove initializations of unused global variables
1 parent b7ed4c7 commit 2df6785

File tree

7 files changed

+228
-2
lines changed

7 files changed

+228
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
int x;
3+
int y;
4+
5+
int z;
6+
7+
int a[10];
8+
9+
typedef struct some_struct {
10+
int a;
11+
int b;
12+
} some_struct_t;
13+
14+
some_struct_t s1;
15+
some_struct_t s2;
16+
17+
void func1()
18+
{
19+
s1.a = 7;
20+
}
21+
22+
void func2()
23+
{
24+
s2.a = 7;
25+
}
26+
27+
void func3()
28+
{
29+
func3();
30+
}
31+
32+
int main()
33+
{
34+
z = 1;
35+
z = a[0];
36+
37+
func2();
38+
39+
func3();
40+
41+
return 0;
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--slice-global-inits --show-goto-functions
4+
z = 0;$
5+
a =
6+
s2 =
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
10+
x = 0;$
11+
y = 0;$
12+
s1 =
13+
^warning: ignoring

src/goto-instrument/goto_instrument_parse_options.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Author: Daniel Kroening, [email protected]
3232
#include <goto-programs/remove_asm.h>
3333
#include <goto-programs/remove_unused_functions.h>
3434
#include <goto-programs/parameter_assignments.h>
35+
#include <goto-programs/slice_global_inits.h>
3536

3637
#include <pointer-analysis/value_set_analysis.h>
3738
#include <pointer-analysis/goto_program_dereference.h>
@@ -1015,6 +1016,13 @@ void goto_instrument_parse_optionst::instrument_goto_program()
10151016
nondet_static(ns, goto_functions);
10161017
}
10171018

1019+
if(cmdline.isset("slice-global-inits"))
1020+
{
1021+
status() << "Slicing away initializations of unused global variables"
1022+
<< eom;
1023+
slice_global_inits(ns, goto_functions);
1024+
}
1025+
10181026
if(cmdline.isset("string-abstraction"))
10191027
{
10201028
status() << "String Abstraction" << eom;
@@ -1371,6 +1379,7 @@ void goto_instrument_parse_optionst::help()
13711379
" --reachability-slice slice away instructions that can't reach assertions\n"
13721380
" --full-slice slice away instructions that don't affect assertions\n"
13731381
" --property id slice with respect to specific property only\n"
1382+
" --slice-global-inits slice away initializations of unused global variables\n"
13741383
"\n"
13751384
"Further transformations:\n"
13761385
" --constant-propagator propagate constants and simplify expressions\n"

src/goto-instrument/goto_instrument_parse_options.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Author: Daniel Kroening, [email protected]
5050
"(custom-bitvector-analysis)" \
5151
"(show-struct-alignment)(interval-analysis)(show-intervals)" \
5252
"(show-uninitialized)(show-locations)" \
53-
"(full-slice)(reachability-slice)" \
53+
"(full-slice)(reachability-slice)(slice-global-inits)" \
5454
"(inline)(remove-function-pointers)" \
5555
"(show-claims)(show-properties)(property):" \
5656
"(show-symbol-table)(show-points-to)(show-rw-set)" \

src/goto-programs/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \
1616
remove_returns.cpp osx_fat_reader.cpp remove_complex.cpp \
1717
goto_trace.cpp xml_goto_trace.cpp vcd_goto_trace.cpp \
1818
graphml_witness.cpp remove_virtual_functions.cpp \
19-
class_hierarchy.cpp show_goto_functions.cpp get_goto_model.cpp
19+
class_hierarchy.cpp show_goto_functions.cpp get_goto_model.cpp \
20+
slice_global_inits.cpp
2021

2122
INCLUDES= -I ..
2223

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*******************************************************************\
2+
3+
Module: Remove initializations of unused global variables
4+
5+
Author: Daniel Poetzl
6+
7+
Date: December 2016
8+
9+
\*******************************************************************/
10+
11+
#include <analyses/call_graph.h>
12+
13+
#include <util/namespace.h>
14+
#include <util/std_expr.h>
15+
#include <util/cprover_prefix.h>
16+
#include <util/prefix.h>
17+
#include <util/hash_cont.h>
18+
19+
#include <goto-programs/goto_functions.h>
20+
#include <goto-programs/remove_skip.h>
21+
22+
#include "slice_global_inits.h"
23+
24+
/*******************************************************************\
25+
26+
Function: slice_global_inits
27+
28+
Inputs:
29+
30+
Outputs:
31+
32+
Purpose:
33+
34+
\*******************************************************************/
35+
36+
void slice_global_inits(
37+
const namespacet &ns,
38+
goto_functionst &goto_functions)
39+
{
40+
// gather all functions reachable from the entry point
41+
42+
call_grapht call_graph(goto_functions);
43+
const call_grapht::grapht &graph=call_graph.graph;
44+
45+
std::list<irep_idt> worklist;
46+
hash_set_cont<irep_idt, irep_id_hash> functions_reached;
47+
48+
const irep_idt entry_point=goto_functionst::entry_point();
49+
50+
goto_functionst::function_mapt::const_iterator e_it;
51+
e_it=goto_functions.function_map.find(entry_point);
52+
53+
if(e_it==goto_functions.function_map.end())
54+
throw "entry point not found";
55+
56+
worklist.push_back(entry_point);
57+
58+
do
59+
{
60+
const irep_idt id=worklist.front();
61+
worklist.pop_front();
62+
63+
functions_reached.insert(id);
64+
65+
const auto &p=graph.equal_range(id);
66+
67+
for(auto it=p.first; it!=p.second; it++)
68+
{
69+
const irep_idt callee=it->second;
70+
71+
if(functions_reached.find(callee)==functions_reached.end())
72+
worklist.push_back(callee);
73+
}
74+
} while(!worklist.empty());
75+
76+
const irep_idt initialize=CPROVER_PREFIX "initialize";
77+
functions_reached.erase(initialize);
78+
79+
// gather all symbols used by reachable functions
80+
81+
class symbol_collectort:public const_expr_visitort
82+
{
83+
public:
84+
virtual void operator()(const exprt &expr)
85+
{
86+
if(expr.id()==ID_symbol)
87+
{
88+
const symbol_exprt &symbol_expr=to_symbol_expr(expr);
89+
const irep_idt id=symbol_expr.get_identifier();
90+
symbols.insert(id);
91+
}
92+
}
93+
94+
hash_set_cont<irep_idt, irep_id_hash> symbols;
95+
};
96+
97+
symbol_collectort visitor;
98+
99+
assert(!functions_reached.empty());
100+
101+
for(const irep_idt &id : functions_reached)
102+
{
103+
const goto_functionst::goto_functiont &goto_function
104+
=goto_functions.function_map.at(id);
105+
const goto_programt &goto_program=goto_function.body;
106+
107+
forall_goto_program_instructions(i_it, goto_program)
108+
{
109+
const codet &code=i_it->code;
110+
code.visit(visitor);
111+
}
112+
}
113+
114+
const hash_set_cont<irep_idt, irep_id_hash> &symbols=visitor.symbols;
115+
116+
// now remove unnecessary initializations
117+
118+
goto_functionst::function_mapt::iterator f_it;
119+
f_it=goto_functions.function_map.find(initialize);
120+
assert(f_it!=goto_functions.function_map.end());
121+
122+
goto_programt &goto_program=f_it->second.body;
123+
124+
Forall_goto_program_instructions(i_it, goto_program)
125+
{
126+
if(i_it->is_assign())
127+
{
128+
const code_assignt &code_assign=to_code_assign(i_it->code);
129+
const symbol_exprt &symbol_expr=to_symbol_expr(code_assign.lhs());
130+
const irep_idt id=symbol_expr.get_identifier();
131+
132+
if(!has_prefix(id2string(id), CPROVER_PREFIX) &&
133+
symbols.find(id)==symbols.end())
134+
i_it->make_skip();
135+
}
136+
}
137+
138+
remove_skip(goto_functions);
139+
goto_functions.update();
140+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*******************************************************************\
2+
3+
Module: Remove initializations of unused global variables
4+
5+
Author: Daniel Poetzl
6+
7+
Date: December 2016
8+
9+
\*******************************************************************/
10+
11+
#ifndef CPROVER_GOTO_PROGRAMS_SLICE_GLOBAL_INITS_H
12+
#define CPROVER_GOTO_PROGRAMS_SLICE_GLOBAL_INITS_H
13+
14+
class goto_functionst;
15+
class namespacet;
16+
17+
void slice_global_inits(
18+
const namespacet &ns,
19+
goto_functionst &goto_functions);
20+
21+
#endif

0 commit comments

Comments
 (0)