da.cc: need_parametrization: check if potential sources can have executed
[ppn.git] / main.cc
blobd0d2b6c2bb3d64ecb9a2d62a9bbf10733e84bb8e
1 #include "suif_inc.h"
2 #include "for_normalize.h"
3 #include "domain.h"
4 #include "dump.h"
6 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*a))
8 static char **funcs;
9 static int verbose;
10 static int oldstyle;
11 static cmd_line_option my_options[] = {
12 { CLO_MULTI_STRING, "-func", "", &funcs },
13 { CLO_NOARG, "-verbose", "", &verbose },
14 { CLO_NOARG, "-oldstyle", "", &oldstyle },
17 static int m_argc;
18 static char **m_argv;
20 static void extract_context(tree_instr *ti, context_info *ci)
22 instruction *in = ti->instr();
23 operand cpy = in->src_op(0);
24 assert(cpy.is_expr());
25 operand op = cpy.instr()->src_op(0);
27 guard_constructor gc(ci->sa, 1, NULL);
28 assert(op.kind() == OPER_INSTR);
29 instruction * ins = op.instr();
30 gc.construct_guard(ins);
32 ci->ctx = new SRelation(*gc.s, ci->sa);
35 static context_info *handle_context(annote *ca, context_info *ctx)
37 immed_list *ims = ca->immeds();
38 if (ims->count() != 2)
39 return ctx;
40 immed val = (*ims)[1];
41 if (val.kind() != im_symbol)
42 return ctx;
43 sym_node *sym = val.symbol();
44 if (sym->kind() != SYM_PROC)
45 return ctx;
47 assert(ctx->ctx == NULL);
49 proc_sym *proc = static_cast<proc_sym *>(sym);
50 if (!proc->is_in_memory())
51 proc->read_proc();
52 ctx->tp = proc->block();
53 tree_node_list *tnl = ctx->tp->body();
54 tree_node_list_iter tnli(tnl);
55 for (int i = 0; !tnli.is_empty(); ++i) {
56 tree_node *tn = tnli.step();
57 switch (tn->kind()) {
58 case TREE_INSTR: {
59 tree_instr *in = (tree_instr*)tn;
60 switch (in->instr()->opcode()) {
61 case io_ret:
62 extract_context(in, ctx);
63 break;
64 case io_mrk:
65 break;
66 default:
67 assert(0);
69 break;
71 default:
72 assert(0);
74 if (ctx->ctx)
75 break;
77 return ctx;
80 static context_info *handle_parameter(annote *an, context_info *ctx)
82 immed_list *ims = an->immeds();
83 if (ims->count() != 3 && ims->count() != 4)
84 return ctx;
85 bool have_ub = ims->count() == 4;
86 immed val = (*ims)[1];
87 if (val.kind() != im_symbol)
88 return ctx;
89 sym_node *sym = val.symbol();
90 if (sym->kind() != SYM_VAR)
91 return ctx;
93 if ((*ims)[2].kind() != im_int)
94 return ctx;
95 int lb = (*ims)[2].integer();
97 if (have_ub && (*ims)[3].kind() != im_int)
98 return ctx;
100 var_sym* var = static_cast<var_sym*>(sym);
101 ctx->sa->add_var(var);
102 ctx->sa->vars[var]->lb = lb;
103 ctx->sa->vars[var]->lb_set = true;
104 Relation r(0);
105 GEQ_Handle e1 = r.and_with_GEQ();
106 e1.update_coef(r.get_local(ctx->sa->vars[var]), 1);
107 e1.update_const(-lb);
108 if (have_ub) {
109 int ub = (*ims)[3].integer();
110 GEQ_Handle e2 = r.and_with_GEQ();
111 e2.update_coef(r.get_local(ctx->sa->vars[var]), -1);
112 e2.update_const(ub);
114 SRelation *sr = new SRelation(r, ctx->sa);
115 if (!ctx->ctx)
116 ctx->ctx = sr;
117 else {
118 SRelation *r = ctx->ctx;
119 ctx->ctx = r->Intersection(sr);
120 delete sr;
121 delete r;
124 return ctx;
127 static context_info *handle_pragmas(tree_proc *tp)
129 context_info *ctx = new context_info;
130 const char *k_C_pragma = lexicon->enter("C pragma")->sp;;
131 annote_list_iter anli(tp->proc()->file()->annotes());
132 while (!anli.is_empty()) {
133 annote *an = anli.step();
134 if (an->name() != k_C_pragma)
135 continue;
136 immed_list *ims = an->immeds();
137 if (!(*ims)[0].is_string())
138 continue;
139 if (strcmp((*ims)[0].string(), "context") == 0)
140 ctx = handle_context(an, ctx);
141 if (strcmp((*ims)[0].string(), "parameter") == 0)
142 ctx = handle_parameter(an, ctx);
144 return ctx;
147 /* Ensure for loops have step +1.
149 * We use a modified version of SUIF's normalize_fors_on_proc,
150 * since we don't mind that the lower bound may not be zero.
152 * The normalization will introduce an assignment to the old
153 * iterator. We have to propagate this assignment to all
154 * the accesses so that they no longer reference the old iterator.
155 * Afterward, this assignment needs to be removed, but we can't
156 * just use proc_dead_code since that will remove all dead code,
157 * including assignments to scalars in a program that we want
158 * to analyze.
160 static void normalize_for_loops(tree_proc *tp)
162 instruction_list *normalized = normalized_fors_on_proc(tp);
163 if (!normalized)
164 return;
165 forward_propagate(tp, FPK_ALL);
166 fold_all_constants(tp);
167 while (!normalized->is_empty()) {
168 instruction *ass = normalized->pop();
169 tree_instr *parent = ass->parent();
170 parent->parent()->remove(parent->list_e());
171 delete parent->list_e();
172 delete parent;
174 delete normalized;
177 void do_proc(tree_proc * tp)
179 static context_info *ctx = NULL;
181 if (!ctx)
182 ctx = handle_pragmas(tp);
184 char **f;
185 proc_sym * psym = tp->proc();
186 //printf("=======%s======= \n", psym->name());
187 for (f = funcs; **f; ++f)
188 if (!strcmp(*f, psym->name()))
189 break;
190 if (f != funcs && **f == '\0')
191 return;
192 if (ctx && ctx->tp == tp)
193 return;
194 normalize_for_loops(tp);
195 fill_in_access(tp);
196 construct_domains(tp, verbose, oldstyle, ctx);
197 //tp->print();
198 dump(tp, ctx, m_argc, m_argv);
201 int main(int argc, char * argv[])
203 m_argc = argc;
204 m_argv = new char* [argc+1];
205 for (int i = 0; i < argc; ++i)
206 m_argv[i] = argv[i];
207 m_argv[argc] = NULL;
208 start_suif(argc, argv);
209 init_dead_code();
210 init_unused();
211 funcs = new char *[argc];
212 parse_cmd_line(argc, argv, my_options, ARRAY_SIZE(my_options));
213 init(argc, argv);
214 suif_proc_iter(argc, argv, do_proc, TRUE);
215 delete [] funcs;
216 delete [] m_argv;
217 return 0;